diff --git a/ruby-generate-csv-list-of-all-pages/.env b/ruby-generate-csv-list-of-all-pages/.env new file mode 100644 index 0000000..798716a --- /dev/null +++ b/ruby-generate-csv-list-of-all-pages/.env @@ -0,0 +1,3 @@ +BS_URL= +BS_TOKEN_ID= +BS_TOKEN_SECRET= diff --git a/ruby-generate-csv-list-of-all-pages/Gemfile b/ruby-generate-csv-list-of-all-pages/Gemfile new file mode 100644 index 0000000..7173b60 --- /dev/null +++ b/ruby-generate-csv-list-of-all-pages/Gemfile @@ -0,0 +1,5 @@ +source 'https://rubygems.org' + +gem 'httparty' +gem 'dotenv' +gem 'logger' diff --git a/ruby-generate-csv-list-of-all-pages/README.md b/ruby-generate-csv-list-of-all-pages/README.md new file mode 100644 index 0000000..ae9d79b --- /dev/null +++ b/ruby-generate-csv-list-of-all-pages/README.md @@ -0,0 +1,78 @@ +# BookStack Data Exporter + +This Ruby script allows you to export data from a BookStack instance into a CSV file. The exported data includes information about pages, books, and shelves, along with their respective URLs and modification dates. + +## Prerequisites + +Before running the script, make sure you have the following: + +- Ruby installed on your system +- Access to a BookStack instance with API enabled +- BookStack API token ID and token secret + +## Installation + +1. Clone this repository or download the script file. +2. Install the required dependencies by running the following command: + + ``` + bundle install + ``` + +3. Create a `.env` file in the same directory as the script and provide the following environment variables: + + ``` + BS_URL= + BS_TOKEN_ID= + BS_TOKEN_SECRET= + ``` + + Replace ``, ``, and `` with your actual BookStack URL, API token ID, and API token secret, respectively. + +## Usage + +To run the script and export the data, execute the following command: + +``` +ruby export_bookstack_data.rb +``` + +The script will retrieve data from your BookStack instance and generate a CSV file named `bookstack_data.csv` in the same directory. + +## CSV Output + +The generated CSV file will have the following columns: + +- Type: Indicates whether the row represents a page or a book. +- ID: The unique identifier of the page or book. +- Name: The name of the page or book. +- URL: The URL of the page or book, formatted as an Excel hyperlink. +- Book ID: The ID of the book to which the page belongs (applicable only for pages). +- Book Name: The name of the book to which the page belongs (applicable only for pages). +- Book URL: The URL of the book, formatted as an Excel hyperlink (applicable only for pages). +- Shelf Name: The name of the shelf to which the book belongs. +- Date Modified: The last modification date of the page or book. + +The URLs in the 'URL' and 'Book URL' columns are wrapped in the `=HYPERLINK()` function, allowing you to easily access the respective pages and books directly from the CSV file when opened in Excel. +HYPERLINK() - is an Excel shortcut to make URL clickable, feel free to remove, if you don't use Excel. + +## Logging + +Logging to STDOUT, but can be adjusted to a file. + +## Example + +Here's an example of how the generated CSV file might look. + +``` +Type,ID,Name,URL,Book ID,Book Name,Book URL,Shelf Name,Date Modified +Page,1,Introduction,=HYPERLINK("https://example.com/books/1/page/1"),1,User Guide,=HYPERLINK("https://example.com/books/1"),Getting Started,2023-05-01T10:00:00.000000Z +Page,2,Installation,=HYPERLINK("https://example.com/books/1/page/2"),1,User Guide,=HYPERLINK("https://example.com/books/1"),Getting Started,2023-05-02T11:30:00.000000Z +Book,1,User Guide,=HYPERLINK("https://example.com/books/1"),,,,Getting Started,2023-05-01T09:00:00.000000Z +``` + +## License + +This script is released under the [MIT License](LICENSE). + +Feel free to customize and adapt the script to suit your specific requirements. diff --git a/ruby-generate-csv-list-of-all-pages/export_pages.rb b/ruby-generate-csv-list-of-all-pages/export_pages.rb new file mode 100644 index 0000000..5b0298f --- /dev/null +++ b/ruby-generate-csv-list-of-all-pages/export_pages.rb @@ -0,0 +1,103 @@ +require 'csv' +require 'httparty' +require 'dotenv/load' +require 'logger' +require 'bundler/setup' + +Bundler.require(:default) + +logger = Logger.new('bookstack.log') + +class BookStackAPI + include HTTParty + base_uri ENV['BS_URL'] + headers 'Authorization' => "Token #{ENV['BS_TOKEN_ID']}:#{ENV['BS_TOKEN_SECRET']}" + format :json + + def self.get(path, options = {}) + url = "#{base_uri}#{path}" + ::Logger.new(STDOUT).info("Making GET request to: #{url}") + ::Logger.new(STDOUT).info("Query parameters: #{options[:query]}") + response = super(path, options) + ::Logger.new(STDOUT).info("Response status: #{response.code}") + response + end +end + +def get_all_items(path) + results = [] + page_size = 500 + offset = 0 + total = 1 + + while offset < total + sleep(0.5) if offset > 0 + + response = BookStackAPI.get(path, query: { count: page_size, offset: offset }) + total = response['total'] + offset += page_size + + results.concat(response['data']) + end + + ::Logger.new(STDOUT).info("Retrieved #{results.count} items from #{path}") + results +end + +def generate_csv(pages, books, shelves) + book_map = books.map { |book| [book['id'], book] }.to_h + shelf_map = shelves.map { |shelf| [shelf['id'], shelf] }.to_h + + CSV.open('bookstack_data.csv', 'w') do |csv| + csv << ['Type', 'ID', 'Name', 'URL', 'Book ID', 'Book Name', 'Book URL', 'Shelf Name', 'Date Modified', 'Date Created'] + + pages.each do |page| + book = book_map[page['book_id']] + shelf_name = shelf_map[book['shelf_id']]['name'] if book && shelf_map[book['shelf_id']] + csv << [ + 'Page', + page['id'], + page['name'], + "=HYPERLINK(\"#{ENV['BS_URL']}/books/#{page['book_id']}/page/#{page['id']}\")", + page['book_id'], + book ? book['name'] : '', + "=HYPERLINK(\"#{ENV['BS_URL']}/books/#{page['book_id']}\")", + shelf_name || '', + page['updated_at'], + page['created_at'] + ] + end + + books.each do |book| + shelf_name = shelf_map[book['shelf_id']]['name'] if shelf_map[book['shelf_id']] + csv << [ + 'Book', + book['id'], + book['name'], + "=HYPERLINK(\"#{ENV['BS_URL']}/books/#{book['id']}\")", + '', + '', + '', + shelf_name || '', + book['updated_at'], + page['created_at'] + ] + end + end +end + +begin + logger.info('Started generating BookStack data CSV') + logger.info("BookStack URL: #{ENV['BS_URL']}") + + pages = get_all_items('/api/pages') + books = get_all_items('/api/books') + shelves = get_all_items('/api/shelves') + + generate_csv(pages, books, shelves) + + logger.info('CSV file generated: bookstack_data.csv') +rescue StandardError => e + logger.error("Error: #{e.message}") + logger.error(e.backtrace.join("\n")) +end