c2f9e9cc0829dd72c1bdbb94179f93cb15781201
7
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e3fd8c67d4 |
feat: switch pixiv off — unregistered, unreachable, and refused at dispatch (406 phase 1)
Milestone 406 retires pixiv (rule 171) in two phases at the operator's explicit ask: switch it off, then later delete its code. This is the switch-off. Steps 2 and 3 ship together because each is a half-state of the other: unregistered but still in the extension, pixiv creator pages would offer a button the backend then refuses. Reachability removed, never gated (rule 22 - no flag, no `if platform == "pixiv"`): - platforms registry: pixiv unregistered, so /api/platforms, the source validator and quick-add all refuse it through their existing unknown-platform paths. - NATIVE_INGESTER_PLATFORMS: pixiv removed. - extension_service: pixiv's quick-add URL pattern removed (the Python half of the JS mirror). - extension: pixiv's host permissions, content-script match, platform entry and artist pattern removed; popup's pixiv branches removed; and the whole pixiv PKCE OAuth flow cut out of background.js. That last one could not wait for phase 2 - a webRequest listener on a host the manifest no longer grants is at best dead and at worst a startup failure for the entire background script. On startup the extension now also removes any pixiv refresh token a browser still holds in storage, for the same reason as the server-side credential cleanup (3980). - frontend: the extension card stops listing pixiv; SourceActions' copy of the native list drops it. platformColor keeps rendering a pixiv key so existing pixiv posts do not look broken. The guard, and why a registry change alone was not enough. A source outlives its platform: the live instance still had one ENABLED pixiv source (step 1). Tracing it: the scheduler only selects enabled rows and every platform lookup uses .get(), so a disabled row is inert - but re-enabling it and pressing Check would have routed pixiv, no longer native, straight into the gallery-dl branch, which still has a pixiv extractor. And a worker can pick up a still-enabled row before a deploy's migration runs. So run_download and verify_source_credential - the two functions every download and credential probe pass through - now refuse any platform not in the registry: an unsupported_url failure for downloads, and an inconclusive (None, not False) verify, since nothing was probed so nothing was rejected. Generic by registration, so it covers deviantart's leftovers too. Positive-controlled: a supported gallery-dl platform must still reach gallery-dl, or a guard that refused everything would pass (rule 167). Migration 0097 disables sources on retired platforms (pixiv, deviantart) and clears their failure state exactly as disabling through the app does (1285), so the stale row stops being scheduled and stops showing as failing. Nothing is deleted: removing a source can collide with uq_post_artist_external_id_null_source on real data, which is phase 2's step 6 to check. No post or image is touched. Tests: the known-platform lists drop pixiv and gain retirement assertions beside deviantart's; pixiv's positive extension cases become negative guards; the pixiv sidecar post-URL test is deleted with the behaviour it tested; quick-add rejects a pixiv URL. The pixiv client/downloader/ingester suites stay - that code stays until phase 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SHQB1YukL3VyvMK8rcbmV9 |
||
|
|
0bbcdee3bd |
feat(pixiv): flip dispatch to the native ingester (#129 step 4)
pixiv joins NATIVE_INGESTER_PLATFORMS: download/verify/preview and the recover/recapture UI actions now route through PixivIngester. Campaign id is parsed straight from the source URL (numeric user id — no network resolver), with a platform-aware resolution-failure message. auth_token now rides the uniform adapter construction (token platforms use it, cookie platforms accept-and-ignore), and the preview endpoint fetches/threads it. The legacy gallery-dl pixiv path is fully removed (PLATFORM_DEFAULTS entry + the refresh-token config branches in download/verify) per no-legacy policy; gallery-dl keeps hentaifoundry/discord/deviantart until they migrate/retire. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CDgx8bQS5YrGRK76v8HUnM |
||
|
|
d8d8ecd78f |
feat(subscribestar): flip dispatch to the native ingester (#893, Step 5)
SubscribeStar now downloads + verifies through the native core ingester instead of gallery-dl — the go-live switch for milestone #71. - download_backends: subscribestar added to NATIVE_INGESTER_PLATFORMS; a _NATIVE_INGESTERS registry + _resolve_native_campaign_id make _run_native_ingester / preview_source / verify_source_credential platform-aware. SubscribeStar's campaign_id IS the creator URL (no resolver); Patreon still resolves the vanity. preview now catches the shared NativeIngestError (covers both platforms). - platform_lock: subscribestar serialized (one paced walk at a time). - gallery_dl: subscribestar entry removed from PLATFORM_DEFAULTS (rule 22 — no fallback once native works). - frontend SourceActions: isPatreon → isNative (patreon|subscribestar) so the recover/recapture actions show for subscribestar; download_service's cursor/mode/post_first + the preview endpoint already key on uses_native_ingester, so backfill/recovery/recapture/preview light up for free. - tests: download_backends (subscribestar native), platform_lock (serialized), and three gallery-dl-sample tests repointed to hentaifoundry (api_credentials verify, gallery_dl_service skip-value, api_sources arm-no-preflight). post_is_gated stays best-effort (can't cause junk downloads); not gating this. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
65ec29ba9b |
feat(ingest): Recapture mode — re-grab post bodies/links + localize on-disk inline images (#830)
A plain backfill gates post-body capture on the seen-ledger, so a post whose media is already on disk AND whose post key is already seen never gets its body recaptured (operator-flagged: Industrial Lust description missing). Recovery recaptures unconditionally but re-downloads the whole source. New 'recapture' walk mode (4th beside tick/backfill/recovery): bypasses the post-record gate so EVERY post's body + external links are re-captured (detail-fetching empty bodies) WITHOUT re-downloading on-disk media; and surfaces already-present media via a separate non-deleting relink channel so the importer backfills ImageRecord.source_filehash for inline-image localization. - ingest_core: recapture mode + recapture_records gate bypass + relink collect - patreon_downloader: recapture surfaces seen-on-disk as skipped_disk(path), never refetches seen-missing media, still downloads genuinely-new - importer.relink_source_filehash: NULL-only sha256 backfill, never unlinks - download_service: mode derivation + phase-3 relink loop + lifecycle clear - source_service/api: start_recapture + backfill_recapture field + action - frontend: Recapture kebab action + 'Recapturing' badge across SourceActions/ Row/Card/SubscriptionsTab + sources store - tests across ingester/downloader/importer/source_service/api/download_service Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
c774042a85 |
refactor(ui): consolidate 7 hand-rolled kebabs into one KebabMenu (DRY pattern sweep)
First pattern-consistency DRY pass (process #594). The overflow kebab was hand-rolled 7 ways in two divergent activator strategies — Pattern A (#activator + v-bind) which silently breaks inside the teleported image modal (#711), and Pattern B (manual v-model + activator=parent + open-on-click=false + z-index 2400) the modal kebabs needed as a workaround. New <KebabMenu> (components/common) bakes in the modal-safe strategy UNIVERSALLY, so every kebab works in modal and non-modal contexts — folding the latent #711-class bug fix into all five Pattern-A sites. Menu items go in the default slot; variations (size/variant/location/label/min-width) are props. Adopted across all 7: TagChip, SuggestionItem, TagCard, SeriesView card, SeriesManageView, BackupRunsTable, SourceActions. Exhaustiveness (§8b): mdi-dots-vertical now lives only in KebabMenu. Labeled dropdowns / nav menus / filter popovers are a different concept and left alone. Seeded the pattern catalog so new code reuses the primitive. Test: KebabMenu renders slot items + trigger label/glyph + presentational props. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e4e35163ab |
feat(subs): subscriptions UX batch — error reasons, single-source rows, health sort, bulk backfill
Operator-requested follow-ups: - #1 Failure reason on hover: the red error-count chip now shows source.last_error in a tooltip (desktop row + mobile card), so the cause (e.g. the new "vanity=cw" message) is visible without opening Downloads. - #2 Collapse the single-source case: a subscription with exactly one source now shows that source's URL + its own actions (Check / Backfill / ⋮ / Edit) inline on the artist row — no expand needed for the common case. Multi-source keeps the artist-level actions + expandable per-source table. - #3 Sort by health: the Health column is sortable on a numeric rank (never/ok/warn/fail) and the table defaults to worst-first, name as tiebreak. - #4 Drop Preview: removed the low-value bounded-peek action from the menu and all its wiring (backend endpoint + store fn left in place, unused). - #5 Backfill selected: a "Backfill" button in the bulk bar arms a run-until-done backfill on every enabled, not-already-running source in the selection. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
b7d07324ee |
fix(subs): stop the lock/reload on source actions + regroup the row buttons
Lock/reload: every inline source action (check / backfill / recover / toggle / remove) ended by refetching the WHOLE subscription list (store.loadAll / refresh), which blocked the UI and re-rendered the table — collapsing the expanded row, which read as "locks then resets." The action APIs already return the updated source, so the store now patches that one row in place (_patchSource / _dropSource); the post-action loadAll/refresh calls are gone. Toggling enabled, starting/stopping a backfill, recovering, and removing are now instant and leave the expansion intact. Button regroup (operator-flagged: tiny, mis-clickable, not grouped by function): - New shared SourceActions.vue used by desktop SourceRow + mobile SourceCard. - Frequent actions stay as size="small" buttons: Check, Backfill/Stop. - Low-frequency / destructive actions move into a labelled overflow (⋮) menu — Preview backfill, Recover dropped near-duplicates, Remove source — so they can't be fat-fingered, and the labels spell out recover-vs-backfill. - Edit moves next to the source URL (its identity), out of the action cluster where it sat beside Remove. - Single-source Remove now confirms (it had no guard before). Tests: store patches/drops in place without dropping the cache. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |