Skip to content

Releases: mavrovde/bookvault

v1.2.0 — Linux installer (AppImage)

Choose a tag to compare

@mavrovde mavrovde released this 14 Jul 19:07
ec204d0

Adds a Linux AppImage, completing the desktop trio (macOS / Windows / Linux).
Built with PyInstaller + appimagetool on an ubuntu-latest runner, with a
headless smoke test (xvfb) that boots the frozen app to prove the GTK/WebKit
binding works, then attaches the .AppImage to each release.

Added

  • Linux .AppImage. chmod +x and run it. It bundles the app + the gi
    bindings/typelib; WebKitGTK 4.1 is a host runtime dependency (WebKit's
    multiprocess helpers use compile-time absolute paths that can't live inside an
    AppImage) — one apt line covers it on Ubuntu 24.04+
    (libwebkit2gtk-4.1-0 gir1.2-webkit2-4.1 gir1.2-gtk-3.0). Chromium is fetched
    on first run; app data lives in ~/.local/share/BookVault/.
  • CI (.github/workflows/desktop-linux.yml) builds + smoke-tests the AppImage on
    ubuntu-latest on every tag and attaches it to the GitHub Release.

v1.1.0 — Windows installer (Setup.exe)

Choose a tag to compare

@mavrovde mavrovde released this 14 Jul 18:59
b6b681c

Adds a native Windows installer, built the same way as macOS: a PyInstaller
onedir app wrapped by Inno Setup into Setup.exe, with Chromium fetched on first
run. Built on a windows-latest CI runner and attached to each release.

Added

  • Windows Setup.exe. Download it from the release and run it (unsigned, so
    SmartScreen → More info → Run anyway); BookVault installs to Program Files
    with a Start-menu shortcut. Requires the WebView2 runtime (present on Windows
    11 and up-to-date Windows 10). App data lives in %LOCALAPPDATA%\BookVault;
    Chromium caches in %LOCALAPPDATA%\ms-playwright (shared, survives reinstall).
  • CI (.github/workflows/desktop-windows.yml) builds Setup.exe on
    windows-latest on every tag and attaches it to the GitHub Release, and runs
    as a build check on PRs touching the Windows packaging.

v1.0.1 — Fix: macOS app couldn't launch its browser

Choose a tag to compare

@mavrovde mavrovde released this 14 Jul 18:49
4fe68af

The downloadable macOS app failed at login with an "Internal server error".
Inside a frozen .app, Playwright resolved Chromium to a path inside the
read-only bundle and could neither install nor launch it, so every login died at
chromium.launch(). Fixed by pinning the browser cache (and the app's data dir)
to the standard writable per-OS locations.

Fixed

  • Desktop app login on the packaged macOS build. chromium.launch() failed
    with Executable doesn't exist at …/BookVault.app/…/.local-browsers/… because
    a frozen Playwright defaults its browsers path relative to the (read-only)
    bundle. The launcher now sets PLAYWRIGHT_BROWSERS_PATH to the standard
    ~/Library/Caches/ms-playwright cache — writable, persistent, and shared with
    any normal Playwright install on the machine.

Changed

  • The frozen entry point moved to a single cross-platform packaging/entry.py
    (per-user data dir + browsers path chosen by OS), shared by all packaged
    builds.

v1.0.0 — BookVault 1.0: now a native desktop app, too

Choose a tag to compare

@mavrovde mavrovde released this 14 Jul 17:58
063aa63

BookVault reaches 1.0 with a third way to run it: a native desktop app for
macOS, Windows, and Linux, alongside the local web app and the MCP server. All
three are front-ends over the same backend -- the desktop app embeds the exact
bookvault-web server and shows it in a native window, with no browser tab or
terminal needed.

Added

  • bookvault-desktop -- a native desktop app. A
    pywebview shell that starts the FastAPI web
    app on a private 127.0.0.1 port in a background thread and shows it in a
    native OS window (WKWebView on macOS, WebView2 on Windows, WebKitGTK on
    Linux). It reuses bookvault-web verbatim -- the backend is imported, not
    duplicated -- so the web app, the MCP server, and their Docker images are
    unchanged. A splash is shown while a saved session restores (which drives a
    real headless Chromium), then the live app loads; closing the window cleanly
    stops the backend and the Playwright/Chromium session (bounded graceful
    shutdown, so the browser is never orphaned).

    .venv/bin/pip install -e ./core -e ./web -e ./desktop
    .venv/bin/bookvault-desktop

Notes

  • The desktop app currently runs from a source checkout; packaged installers
    (.dmg / .msi / .AppImage) and package-manager channels (Homebrew /
    winget / AUR) are the next step.
  • tests/test_desktop.py skips itself unless the desktop package is
    installed, so the released web/MCP CI is unaffected.

v0.12.0 — Shared state across browsers, a results view, and your name in the header

Choose a tag to compare

@mavrovde mavrovde released this 14 Jul 16:38
5689c82

The web app's selection and format choices now live on the server, so every
browser, tab, and device pointed at the app shows the same ticked books, the
same formats, and the same live progress. The header shows your account
email/name instead of a generic "Signed in", and a new results view makes a
failed download easy to find among hundreds of successes.

Added

  • Server-side shared UI state. Which books are selected and your preferred
    ebook/audiobook formats now live on the backend (GET / POST /prefs, and
    folded into the /activity poll every browser already makes) instead of each
    browser's localStorage/sessionStorage. Open the app in a second browser
    mid-download and it shows the same selection and progress. Persisted to
    LITRES_STATE_FILE (defaults onto the Docker /data volume), so it also
    survives a restart.
  • Account identity in the header. A cookie-only session (e.g. in Docker,
    where there's no OS keychain to remember the login name) now recovers your
    email/login from litres.ru's /users/me, so the header shows who you are
    rather than a generic "Signed in".
  • Results view with a status filter. After a build, a summary shows
    All N · ✓ done · ! skipped · ✗ failed as clickable pills -- one click
    filters the log to just the failures, so a single rights-limited title no
    longer hides among hundreds of successes.
  • End-to-end / smoke tests. An offline e2e suite (real server boot + full
    login → build → download flow + the MCP tool flow) plus an opt-in
    pytest -m live suite that smoke-tests a running instance.

Fixed

  • The results and the download link survive a page reload. The cache-only
    size-check that runs on every page load used to wipe the finished build's
    per-book results and its zip download link. Both are now kept until the
    next build starts, so you can reload to inspect failures and still download
    the zip.
  • A build where every selected title failed no longer offers an empty zip.

Changed

  • New LITRES_STATE_FILE setting (default .litres_state.json; /data/...
    in Docker) holds the shared UI state; it's git-ignored like the session and
    cache files.

0.11.1 — Faster release builds

Choose a tag to compare

@mavrovde mavrovde released this 14 Jul 14:55
b75b98d

Patch release: the Docker publish workflow now uses a registry-backed build cache (a per-image buildcache tag in GHCR) instead of the per-ref GitHub Actions cache, so releases reuse unchanged layers (the ~2.5GB Playwright base + dependency install) instead of rebuilding from scratch. CI-only change — no application code. This first run populates the cache; the next release will be noticeably faster.

Full notes: CHANGELOG.md.

0.11.0 — Renamed to BookVault

Choose a tag to compare

@mavrovde mavrovde released this 14 Jul 14:44
b158da1

The project is now BookVaultown the books you bought. Renamed so the identity no longer leads with a third-party trademark, with clear non-affiliation notices.

Changed (breaking)

  • Renamed the whole product identity: repo → mavrovde/bookvault; distributions → bookvault-core/-web/-mcp; modules → bookvault_core/_web/_mcp; commands → bookvault-web / bookvault-mcp; Docker images → ghcr.io/mavrovde/bookvault/{web,mcp}; OS-keychain + MCP server id → bookvault.
  • Kept as nominative references to the litres.ru service: the LITRES_* env vars, the LitresClient class, litres.ru URLs, and the .litres_session.json / .litres_cache.json files.

Added

  • TRADEMARKS.md + non-affiliation notices in README, MCP README, and LICENSE. "LitRes"/"ЛитРес"/"litres.ru" are trademarks of ООО «ЛитРес»; BookVault is independent and unofficial, uses the name only nominatively, and uses none of LitRes's logos/branding. Links to the official LitRes sites included.
  • LICENSE now states it covers this project's own code only and grants no trademark rights.

Migration

pip install -e ./core -e ./web -e ./mcp     # reinstall renamed packages
bookvault-web                                # was: litres-web
docker pull ghcr.io/mavrovde/bookvault/web:0.11.0

If the web app shows logged-out after upgrading (the keychain service id changed), just log in once more.

Full notes: CHANGELOG.md.

0.10.1 — Multi-arch Docker images

Choose a tag to compare

@mavrovde mavrovde released this 14 Jul 14:14
f9936ea

Patch release fixing the Docker images published in 0.10.0.

Fixed

  • Images are now multi-arch (linux/amd64 + linux/arm64). 0.10.0 built amd64 only, so docker pull / docker compose up failed on Apple Silicon (arm64) with no matching manifest for linux/arm64. The publish workflow now sets up QEMU and builds both, so ghcr.io/mavrovde/litres-assistant/{web,mcp} run natively on Intel and Apple Silicon.

Changed

  • Bumped the publish workflow's docker actions to their Node 24 releases (build-push-action@v7, login-action@v4, metadata-action@v6, setup-buildx-action@v4, setup-qemu-action@v4), clearing the "Node.js 20 is deprecated" warnings.

No application code changed since 0.10.0.

0.10.0 — Docker images (web + MCP)

Choose a tag to compare

@mavrovde mavrovde released this 14 Jul 14:07
36a9047

Both entry points now ship as container images, and docker compose up -d starts and controls both.

Two images (Playwright base, Chromium included), published to GHCR with this release, tagged 0.10.0 + latest:

  • ghcr.io/mavrovde/litres-assistant/web
  • ghcr.io/mavrovde/litres-assistant/mcp

Added

  • docker-compose.yml runs both services sharing one named volume (/data) — logging in via the web app authenticates the MCP server too (shared session cookies); cache + downloads persist. Ports publish to 127.0.0.1 only, preserving the localhost-only design.
  • MCP streamable-http transport (LITRES_MCP_TRANSPORT) so the container runs a long-lived networked MCP service Compose can control (http://127.0.0.1:8421/mcp). Stdio stays the default for direct/Claude-Desktop use.
  • CI workflow builds + pushes both images on every v* tag.
  • New env vars: LITRES_APP_HOST, LITRES_RELOAD, LITRES_MCP_TRANSPORT, LITRES_MCP_HOST, LITRES_MCP_PORT.
  • LICENSE — MIT with an attribution requirement (credit the author + link the source).

Changed

  • credentials degrades gracefully with no OS keychain (headless container): falls back to session-only instead of crashing login. No password written to the container — the saved session (on the volume) keeps you logged in; re-login via the web form once it lapses.
  • README overhaul — TOC, badges, features, clearer quick-starts, Docker guide, and a Legal & fair use section (personal backups of fairly-bought books only; no DRM circumvention, no redistribution).

Quick start

git clone https://github.com/mavrovde/litres-assistant.git
cd litres-assistant && docker compose up -d
# open http://127.0.0.1:8420

Full notes: CHANGELOG.md.

0.9.0 — Don't provoke DDoS-Guard

Choose a tag to compare

@mavrovde mavrovde released this 14 Jul 13:35
a8d65af

Makes this low-volume personal backup tool behave like one, so it stops tripping DDoS-Guard's false-positive checks. Diagnosed and hardened from real block logs.

Fixed

  • Downloads carry the browser's TLS fingerprint. Downloads must stream (audiobook bundles ~2GB) over a separate client from the Chromium API calls; plain httpx has a Python JA3/JA4 that can be re-challenged even with valid __ddg* cookies. download_file now streams via curl_cffi impersonating Chrome (measured: JA3 + JA4 both differ from httpx; negotiates HTTP/2 like Chrome). Falls back to httpx if unavailable.
  • Auto-fallback to the subscription download endpoint. litres serves purchases from download_book and subscription/abonement titles from download_book_subscr. On a plain (non-anti-bot) 403 the client now tries the other endpoint automatically before giving up — so subscription titles that used to fail just download.

Added

  • Retry with backoff + cookie re-warm on transient blocks (DDoS-Guard 403 / 429 / 503): honor Retry-After, jittered exponential backoff, re-warm __ddg* cookies via a page visit, retry — for downloads and API GETs. Interruptible by Stop. Genuine rights-403s aren't retried.
  • Instrumentation: failures log the response Server header, so an anti-bot block is distinguishable from a litres app error.
  • New env vars: LITRES_MAX_RETRIES, LITRES_RETRY_BASE_DELAY, LITRES_RETRY_MAX_DELAY.

Changed

  • Opening the app no longer sweeps every book's size — the on-load sweep is cache-only (zero litres.ru calls); live size fetches happen only on explicit Refresh.
  • Jittered pacing between live fetches and library pages.
  • Honest failure messages: persistent anti-bot block → "wait a few minutes"; both endpoints 403 → likely subscription-only/region-locked/preview-only (no more "retry this book").

Full notes: see CHANGELOG.md.