Merge dev → main: #830 rich post capture + external-host downloads (+ #768/#789/#739) #102
Reference in New Issue
Block a user
Delete Branch "dev"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Promotes accumulated
devwork tomainso the runtime image rebuilds. Primary driver: this build bakesmegatools+gdowninto the image (Dockerfile+requirements.txt) — required to actually run the off-platform downloaders from #830 Phase 4.What lands
#830 — rich post capture + faithful render + external-host downloads (all phases 0–5)
external_linktable (0049), per-host Settings toggles (0050).external_fetch.py(gdown for Drive,megatools dlfor mega) +tasks/external.pyworker (claim, per-host lock, attach-in-place, dead-letter/recovery/retention) on thedownloadqueue.#768 — normalized
image_predictiontable; dropped the 100 GBtagger_predictionsTOAST (0045/0046).#789 — flat series sequence + cosmetic chapter dividers + global page numbering + pending staging (0047/0048).
#739 — DB-backup hardening: split stall threshold (40 min), local tempfile dump + bounded-kill,
-Fcdumps.Plus tag-alias raw-key fix, browse/series UX polish, DRY sweeps.
Migration head: 0051.
Deploy / test after merge
maintriggersbuild.yml→ publishes:main+:latestwith megatools/gdown.:lateston the services (a moved tag does NOT auto re-pull) — thedownloadworker especially.CI is green on
devhead (5e16553/96c29c3).The feed endpoint (/api/posts) returns `content` empty for many posts, so post bodies — their formatting, inline <img>, and external <a href> links — were never captured (the post showed "(no description)"). Enrich an empty feed body from the per-post detail endpoint (/api/posts/{id}) before writing the importer sidecar, memoized by mutating the shared post dict so a multi-image post fetches detail exactly once and fully-seen posts (no fresh download) pay nothing. Best-effort by design: a body we can't fetch returns None and never fails the walk. No-doubling and no-clobber-of-populated-body already hold (post upsert is keyed on external_post_id; an empty body parses to None and isn't applied). First slice of milestone #64 (rich post capture + faithful rendering + external-host downloads). Refs FC #830. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Shared, reusable fetchers for the 5 off-platform hosts behind one signature (fetch_external(host, url, dest_dir, ...) -> FetchResult): - dropbox : force dl=1 + stream GET - pixeldrain : GET /api/file/{id} - mediafire : scrape the download page for the direct link + stream GET - gdrive : gdown (confirm-token + virus-scan interstitial); added to reqs - mega : MEGAcmd `mega-get` subprocess (public link incl. #key) HTTP/gdown/subprocess go through module seams so unit tests run without network/gdown/MEGAcmd. fetch_external never raises — every backend failure (transport, non-200, scrape miss, subprocess error, stop) is captured on .error so the worker (next slice) records it and moves on. mega's binary lands in the runtime image in a later slice; the code is complete + tested now. Refs FC #830 (Phase 4a). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>