Adding a Ruby example, exporting list of all pages for use in CSV/Excel

This commit is contained in:
Nick Gorbikoff 2024-04-26 17:47:16 -05:00
commit b43b5c61ee

View file

@ -0,0 +1,3 @@
BS_URL=<your_bookstack_url>
BS_TOKEN_ID=<your_api_token_id>
BS_TOKEN_SECRET=<your_api_token_secret>

View file

@ -0,0 +1,5 @@
source 'https://rubygems.org'
gem 'httparty'
gem 'dotenv'
gem 'logger'

View file

@ -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=<your_bookstack_url>
BS_TOKEN_ID=<your_api_token_id>
BS_TOKEN_SECRET=<your_api_token_secret>
```
Replace `<your_bookstack_url>`, `<your_api_token_id>`, and `<your_api_token_secret>` 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.

View file

@ -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