Skip to main content

Bookstack


---
version: "3.3"
services:
  bookstack:
    image: lscr.io/linuxserver/bookstack
    container_name: bookstack
    environment:
      - PUID=998
      - PGID=100
      - APP_URL=https://your.domain.com
      - DB_HOST=bookstack_db
      - DB_USER=bookstack
      - DB_PASS=xxxxxx
      - DB_DATABASE=bookstackapp
    volumes:
      - /srv/path/Files/Bookstack/config:/config
    ports:
      - 6875:80
    restart: unless-stopped
    depends_on:
      - bookstack_db
  bookstack_db:
    image: lscr.io/linuxserver/mariadb
    container_name: bookstack_db
    environment:
      - PUID=998
      - PGID=100
      - MYSQL_ROOT_PASSWORD=xxxxxx
      - TZ=Europe/Paris
      - MYSQL_DATABASE=bookstackapp
      - MYSQL_USER=bookstack
      - MYSQL_PASSWORD=xxxxxx
    volumes:
      - /srv/path/Files/Bookstack/db:/config
    restart: unless-stopped

Export All Books

This script will export all books in your preferred format (PDF, HTML or TXT).

Requirements

You will need php (~7.1+) installed on the machine you want to run this script on. 

apt install php

You will also need BookStack API credentials (TOKEN_ID & TOKEN_SECRET) at the ready.

Edit profile > create token > copy tokens

Running

# Downloading the script
curl https://raw.githubusercontent.com/BookStackApp/api-scripts/main/php-export-all-books/export-books.php > export-books.php

# Setup
# ALTERNATIVELY: Open the script and edit the variables at the top.
$apiUrl = getenv('BS_URL') ?: 'http://192.168.1.103:6875'; // http://bookstack.local/
$clientId = getenv('BS_TOKEN_ID') ?: 'token';
$clientSecret = getenv('BS_TOKEN_SECRET') ?: 'token';

# Running the script
php export-books.php <format> <output_dir>
Raw script
#!/usr/bin/env php
<?php

// API Credentials
// You can either provide them as environment variables
// or hard-code them in the empty strings below.
$apiUrl = getenv('BS_URL') ?: ''; // http://bookstack.local/
$clientId = getenv('BS_TOKEN_ID') ?: '';
$clientSecret = getenv('BS_TOKEN_SECRET') ?: '';

// Export Format & Location
// Can be provided as a arguments when calling the script
// or be hard-coded as strings below.
$exportFormat = $argv[1] ?? 'pdf';
$exportLocation = $argv[2] ?? './';

// Script logic
////////////////

$books = getAllBooks();
$outDir = realpath($exportLocation);

$extensionByFormat = [
    'pdf' => 'pdf',
    'html' => 'html',
    'plaintext' => 'txt',
];

foreach ($books as $book) {
    $id = $book['id'];
    $extension = $extensionByFormat[$exportFormat] ?? $exportFormat;
    $content = apiGet("api/books/{$id}/export/{$exportFormat}");
    $outPath = $outDir  . "/{$book['slug']}.{$extension}";
    file_put_contents($outPath, $content);
}

/**
 * Get all books from the system API.
 */
function getAllBooks() {
    $count = 100;
    $offset = 0;
    $total = 0;
    $allBooks = [];

    do {
        $endpoint = 'api/books?' . http_build_query(['count' => $count, 'offset' => $offset]);
        $resp = apiGetJson($endpoint);

        // Only set total on first request, due to API bug:
        // https://github.com/BookStackApp/BookStack/issues/2043
        if ($offset == 0) {
            $total = $resp['total'] ?? 0;
        }

        $newBooks = $resp['data'] ?? [];
        array_push($allBooks, ...$newBooks);
        $offset += $count;
    } while ($offset < $total);

    return $allBooks;
}

/**
 * Make a simple GET HTTP request to the API.
 */
function apiGet(string $endpoint): string {
    global $apiUrl, $clientId, $clientSecret;
    $url = rtrim($apiUrl, '/') . '/' . ltrim($endpoint, '/');
    $opts = ['http' => ['header' => "Authorization: Token {$clientId}:{$clientSecret}"]];
    $context = stream_context_create($opts);
    return file_get_contents($url, false, $context);
}

/**
 * Make a simple GET HTTP request to the API &
 * decode the JSON response to an array.
 */
function apiGetJson(string $endpoint): array {
    $data = apiGet($endpoint);
    return json_decode($data, true);
}

/**
 * DEBUG: Dump out the given variables and exit.
 */
function dd(...$args) {
    foreach ($args as $arg) {
        var_dump($arg);
    }
    exit(1);
}

 

Examples

# Export as plaintext to an existing "out" directory
php export-books.php plaintext ./out

# Export as pdf to the current directory
php export-books.php pdf ./

# Export as HTML to an existing "html" directory
php export-books.php html ./html

# Export as HTML to an existing "bookstackPDFexport" directory
php /home/scripts/bookstack/export-books.php html /home/bookstackPDFexport/

You can schedule using cron

crontab -e

30 5 * * * rm -rf /home/bookstackexport/* #clear folder at 5:30
0 6 * * * php /home/scripts/bookstack/export-books.php html /home/bookstackexport/ #export to folder at 6:00