5 require 'bundler/setup'
7 Bundler.require(:default)
9 logger = Logger.new('bookstack.log')
13 base_uri ENV['BS_URL']
14 headers 'Authorization' => "Token #{ENV['BS_TOKEN_ID']}:#{ENV['BS_TOKEN_SECRET']}"
17 def self.get(path, options = {})
18 url = "#{base_uri}#{path}"
19 ::Logger.new(STDOUT).info("Making GET request to: #{url}")
20 ::Logger.new(STDOUT).info("Query parameters: #{options[:query]}")
21 response = super(path, options)
22 ::Logger.new(STDOUT).info("Response status: #{response.code}")
27 def get_all_items(path)
34 sleep(0.5) if offset > 0
36 response = BookStackAPI.get(path, query: { count: page_size, offset: offset })
37 total = response['total']
40 results.concat(response['data'])
43 ::Logger.new(STDOUT).info("Retrieved #{results.count} items from #{path}")
47 def generate_csv(pages, books, shelves)
48 book_map = books.map { |book| [book['id'], book] }.to_h
49 shelf_map = shelves.map { |shelf| [shelf['id'], shelf] }.to_h
51 CSV.open('bookstack_data.csv', 'w') do |csv|
52 csv << ['Type', 'ID', 'Name', 'URL', 'Book ID', 'Book Name', 'Book URL', 'Shelf Name', 'Date Modified', 'Date Created']
55 book = book_map[page['book_id']]
56 shelf_name = shelf_map[book['shelf_id']]['name'] if book && shelf_map[book['shelf_id']]
61 "=HYPERLINK(\"#{ENV['BS_URL']}/books/#{page['book_id']}/page/#{page['id']}\")",
63 book ? book['name'] : '',
64 "=HYPERLINK(\"#{ENV['BS_URL']}/books/#{page['book_id']}\")",
72 shelf_name = shelf_map[book['shelf_id']]['name'] if shelf_map[book['shelf_id']]
77 "=HYPERLINK(\"#{ENV['BS_URL']}/books/#{book['id']}\")",
90 logger.info('Started generating BookStack data CSV')
91 logger.info("BookStack URL: #{ENV['BS_URL']}")
93 pages = get_all_items('/api/pages')
94 books = get_all_items('/api/books')
95 shelves = get_all_items('/api/shelves')
97 generate_csv(pages, books, shelves)
99 logger.info('CSV file generated: bookstack_data.csv')
100 rescue StandardError => e
101 logger.error("Error: #{e.message}")
102 logger.error(e.backtrace.join("\n"))