0.9.0 — Don't provoke DDoS-Guard
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
httpxhas a Python JA3/JA4 that can be re-challenged even with valid__ddg*cookies.download_filenow streams viacurl_cffiimpersonating Chrome (measured: JA3 + JA4 both differ from httpx; negotiates HTTP/2 like Chrome). Falls back tohttpxif unavailable. - Auto-fallback to the subscription download endpoint. litres serves purchases from
download_bookand subscription/abonement titles fromdownload_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
Serverheader, 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.