Skip to content

About

Mirror KOReader reading progress from sync.koreader.rocks into Calibre-Web-Automated

Resources

Stars

4 stars

Watchers

0 watching

Forks

Repository files navigation

kosync-cwa-bridge

Mirror your KOReader reading progress from sync.koreader.rocks into Calibre-Web-Automated — so your CWA web UI shows where you actually are in each book, without installing any extra plugin on your KOReader devices.

CI License: MIT

What this is

KOReader's built-in Progress Sync plugin syncs reading position between devices via sync.koreader.rocks — the free public KOSync server run by the KOReader team. That works great for device-to-device sync, but the data lives in someone else's Redis and never reaches your Calibre-Web-Automated instance, so the CWA web UI has no idea what you're reading.

This bridge runs alongside CWA as a small Python sidecar. It periodically polls sync.koreader.rocks for each book in your CWA library and writes any new progress into CWA via its existing /kosync HTTP endpoint. Result: your CWA web UI starts reflecting current reading position, the "Read" checkmark flips when you finish a book, and CWA integrations (Hardcover, Kobo sync) get notified — all without installing any extra plugin on your e-readers.

What this is NOT

  • Not a replacement for sync.koreader.rocks. Your devices keep using it as their primary sync server. If the bridge is down or you stop running it, device-to-device sync still works.
  • Not a KOSync server itself. It doesn't accept incoming sync requests. It's a one-way poll-and-write daemon.
  • Not the cwasync plugin. That plugin (shipped by CWA) requires installing on every KOReader device. This bridge runs once on your server and works for all your devices automatically — and keeps your KOReader UI uncluttered.

Architecture

KOReader devices ←──→ sync.koreader.rocks        (unchanged primary sync)
                              ▲
                              │ GET /syncs/progress/<hash>
                              │ (your kosync.rocks credentials)
                              │
                       kosync-cwa-bridge
                       (Python, Docker)
                              │
                              │ PUT /kosync/syncs/progress
                              │ (CWA credentials via HTTP Basic)
                              ▼
                            CWA

The bridge knows which document hashes to poll for by reading CWA's metadata.db (read-only) — specifically the book_format_checksums table that CWA already maintains. So a book has to be in your CWA library to be tracked.

Quickstart (Docker Compose)

  1. Get a kosync.rocks account. If your KOReader devices are already syncing progress, you already have one — same username and password you set up in KOReader's Progress Sync settings.

  2. Get a CWA account. This is your normal CWA login. For better security, create an app password from the CWA profile page (/me → App Passwords) — it's revocable without changing your main password. See CWA PR #1269 for details.

  3. Compute the MD5 of your kosync.rocks password:

    echo -n 'your_kosync_password' | md5sum
    # PowerShell
    [System.BitConverter]::ToString(
      [System.Security.Cryptography.MD5]::Create().ComputeHash(
        [System.Text.Encoding]::UTF8.GetBytes('your_kosync_password'))
    ).Replace('-','').ToLower()
  4. Create config.yml (start from config.example.yml):

    kosync_rocks:
      url: https://sync.koreader.rocks
      username: your_kosync_rocks_username
      password_md5: 5f4dcc3b5aa765d61d8327deb882cf99
    cwa:
      url: http://calibre-web-automated:8083
      username: admin
      password: ${CWA_PASSWORD}
    metadata_db_path: /calibre-library/metadata.db
    cache_db_path: /data/bridge_cache.db
    poll_interval_seconds: 300
  5. Add to your Docker Compose (see docker-compose.example.yml):

    services:
      kosync-cwa-bridge:
        image: ghcr.io/ericchansen/kosync-cwa-bridge:latest
        restart: unless-stopped
        environment:
          CWA_PASSWORD: ${CWA_PASSWORD}
        volumes:
          - ./config.yml:/config/config.yml:ro
          - /your/calibre-library:/calibre-library:ro
          - bridge-data:/data
    volumes:
      bridge-data:
  6. Start it:

    CWA_PASSWORD='your_cwa_password' docker compose up -d kosync-cwa-bridge
    docker compose logs -f kosync-cwa-bridge

    You should see something like:

    INFO __main__: checking kosync.rocks auth...
    INFO __main__: checking CWA auth...
    INFO __main__: preflight ok
    INFO kosync_cwa_bridge.poller: forwarded checksum=8f13037c percentage=0.5125 device=tokay
    INFO kosync_cwa_bridge.poller: cycle complete: checked=341 hits=2 forwarded=2 cache_skips=0 errors=0
    
  7. Watch CWA's web UI. Books you're reading on your devices should now show up with progress.

Configuration Reference

Field Required Default Description
kosync_rocks.url yes — KOSync server URL (almost always https://sync.koreader.rocks)
kosync_rocks.username yes — Your kosync.rocks username (same as KOReader Progress Sync)
kosync_rocks.password_md5 yes — MD5 hex digest of your kosync.rocks password
cwa.url yes — Base URL of your CWA instance (no trailing /kosync)
cwa.username yes — CWA username
cwa.password yes — CWA cleartext password (or app password — preferred)
metadata_db_path yes — Path to CWA's Calibre metadata.db (in container)
cache_db_path yes — Path for the bridge's local cache SQLite file
poll_interval_seconds no 300 How often to poll kosync.rocks for changes
request_delay_seconds no 0.2 Delay between per-book requests (be polite)
log_level no INFO DEBUG, INFO, WARNING, ERROR

Any ${ENV_VAR} references in the YAML are substituted at load time. Missing env vars cause a fast-fail on startup.

CLI Usage

# Long-running daemon (default)
python -m kosync_cwa_bridge --config /path/to/config.yml

# One cycle and exit (useful for testing or cron)
python -m kosync_cwa_bridge --config /path/to/config.yml --once

# Help
python -m kosync_cwa_bridge --help

The KOSYNC_CWA_BRIDGE_CONFIG environment variable can replace --config. Inside the Docker image it defaults to /config/config.yml.

Development

git clone https://github.com/ericchansen/kosync-cwa-bridge
cd kosync-cwa-bridge
python -m venv .venv
.venv/bin/pip install -e ".[dev]"

# Run unit tests
.venv/bin/pytest -q

# Run lint
.venv/bin/ruff check src tests

# Run integration tests (requires live CWA + kosync.rocks creds via env vars)
KSR_USER=... KSR_PASS=... CWA_URL=... CWA_USER=... CWA_PASS=... \
  CWA_METADATA_DB=... .venv/bin/pytest -m integration

How it works (under the hood)

The bridge is a stateless poll loop:

while True:
    for (book_id, format, checksum) in cwa.read_book_checksums():
        progress = kosync_rocks.get_progress(checksum)
        if progress and progress.timestamp > cache.get(checksum):
            cwa.update_progress(progress)
            cache.set(checksum, progress.timestamp)
    sleep(poll_interval)

Key points:

  • Reads are direct SQLite reads against CWA's metadata.db opened with ?mode=ro URI — safe alongside a running CWA.
  • Writes to CWA go through its proper /kosync/syncs/progress HTTP endpoint, so all CWA side-effects (Read status flip at ≥99%, Hardcover sync, Kobo state cascading updates) happen automatically.
  • The local cache is purely an optimization — delete bridge_cache.db and the bridge will re-push everything on next cycle.

Limitations

  • Polling means there's a lag between reading something on your device and seeing it in CWA — by default 5 minutes. Lower poll_interval_seconds if you want faster updates (but be polite to sync.koreader.rocks).
  • Only books in your CWA library are tracked. Sideloaded books on your devices that aren't in CWA won't appear in CWA's progress (which is correct — there's no library entry to attach progress to).
  • Single user. v0.1 supports one kosync.rocks account ↔ one CWA account mapping. Multi-user is on the roadmap.
  • One-way sync. Progress flows kosync.rocks → CWA. If you mark a book as Read in CWA's web UI, that change is not propagated back to KOReader.

License

MIT — see LICENSE

Acknowledgements

About

Mirror KOReader reading progress from sync.koreader.rocks into Calibre-Web-Automated

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages