Skip to content

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.