Skip to content

nenadom/booker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Booker

Do you have an ever-growing list of books to read, but can't stand the tedium of buying, downloading and sending to device? Well, not anymore.

Automated reading list to e-reader pipeline. Watches an Obsidian markdown reading list, resolves book metadata, downloads EPUBs from online book collections, adds them to Calibre, and emails them to your e-reader. Available as a CLI or a desktop GUI.

Pipeline

Reading list (.md) → Parse entries → Resolve metadata (Google Books / Open Library)
→ Search book collections → Download EPUB → Validate → Add to Calibre → Email to e-reader

Each book is tracked through these statuses:

pending → resolved → downloading → downloaded → in_calibre → sending → sent
                                                                    ↘ failed

State lives in SQLite at ~/.booker/booker.db. The reading list is never modified.

Install

Pre-built binaries

Download the latest release for your platform from Releases. Available for macOS and Windows.

From source

Requires Python 3.12+ and Calibre installed at /Applications/calibre.app (optional — can be disabled).

git clone https://github.com/nenadom/booker.git && cd booker
python3 -m venv .venv
source .venv/bin/activate

# CLI only
pip install -e .

# CLI + GUI
pip install -e ".[gui]"

Create ~/.booker/.env:

KINDLE_EMAIL=you@example.com
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=you@gmail.com
SMTP_PASSWORD=xxxx xxxx xxxx xxxx

The SMTP password is a Gmail App Password (requires 2FA). Your Gmail address must be approved in your e-reader's email settings (e.g. for Kindle: Amazon's Approved Personal Document Email List).

GUI users can configure all settings from the Settings tab instead of editing .env manually.

Usage

# Preview what the parser sees (no DB writes)
booker parse

# Dry run — parse + resolve metadata, no downloads
booker run --dry-run

# Single full pipeline run
booker run --once

# Continuous mode (runs every 2 hours)
booker run

# Check book statuses
booker status
booker status --filter=failed

# Re-queue a failed book
booker retry <id>

# Skip a book permanently
booker skip <id>

Background service (macOS)

# Install launchd plist (runs every 2 hours)
booker service install

# Check logs
booker service logs

# Remove service
booker service uninstall

GUI

Launch the desktop interface:

booker-gui
# or
python -m booker.gui

The GUI has four tabs:

  • Reading List — view and edit your reading list markdown file
  • Status — run the pipeline, monitor progress, and manage book statuses (retry, skip)
  • Settings — configure all options (paths, email, Calibre, run interval) without editing .env
  • Logs — live-scrolling pipeline log output

The app minimizes to the system tray on close. A welcome tutorial walks through first-time setup on launch.

Reading list format

Booker parses Obsidian checklist entries in many formats:

- [ ] Deep Learning, Ian Goodfellow
- [ ] _Piranesi_ by Susanna Clarke
- [ ] the listeners - jordan tannahill
- [ ] thinking in systems
- [ ] [how to take over the world](https://amazon.com/.../059319201X)
- [x] the algebra of wealth, scott galloway   ← skipped (done)
- [ ] iain banks culture series                ← flagged for manual review

Amazon ASINs and Goodreads IDs are extracted from URLs. Title/author swaps are detected and corrected during metadata resolution.

Configuration

All config is via environment variables in ~/.booker/.env:

Variable Default Description
KINDLE_EMAIL Your e-reader email address
SMTP_HOST smtp.gmail.com SMTP server
SMTP_PORT 587 SMTP port
SMTP_USER Gmail address
SMTP_PASSWORD Gmail App Password
READING_LIST_PATH ~/.booker/reading_list.md Path to reading list
DOWNLOAD_DIR ~/Books Where EPUBs are saved
CALIBRE_LIBRARY ~/Calibre Library Calibre library path
CALIBRE_ENABLED true Set to false to skip Calibre import
RUN_INTERVAL_MINUTES 120 Minutes between pipeline runs in continuous/GUI mode

Project structure

src/booker/
├── cli.py          # Click CLI commands
├── config.py       # Environment and path configuration
├── models.py       # BookStatus enum, ParsedEntry, ResolvedBook, BookRecord
├── parser.py       # Obsidian markdown → ParsedEntry list
├── resolver.py     # Google Books API + Open Library fallback
├── downloader.py   # Book collection search + multi-mirror EPUB download
├── validator.py    # EPUB integrity checks (ZIP, mimetype, size, traversal)
├── calibre.py      # calibredb add wrapper
├── sender.py       # Gmail SMTP to e-reader email
├── notifier.py     # macOS notifications via osascript
├── pipeline.py     # Orchestrator tying all steps together
├── db.py           # SQLite schema + CRUD
└── gui/
    ├── app.py            # QApplication entry point
    ├── main_window.py    # Tabbed main window + system tray
    ├── editor_view.py    # Reading list editor tab
    ├── status_view.py    # Pipeline status + controls tab
    ├── settings_view.py  # Configuration form tab
    ├── log_view.py       # Live log viewer tab
    ├── scheduler.py      # Periodic pipeline runner
    ├── workers.py        # QThread workers for pipeline execution
    ├── tray.py           # System tray icon + menu
    └── welcome.py        # First-run tutorial dialog

Tests

pytest

60 tests covering parsing, metadata resolution, EPUB validation, retry logic, concurrent DB access, and file deduplication.

About

Automated reading list to e-reader pipeline

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors