E5 S2: TMDB enrichment engine (Plex catalog)
Matches each mirrored Plex movie/show to TMDB by its stored canonical guid, fetches once (append_to_response), and PERSISTS the enrichment onto the row — served from the DB, never a live TMDB call at serve time. Additive: the Plex-sourced imdb_rating/rating are untouched; tmdb_rating is the distinct TMDb community score (ratings scope = TMDb + Plex's IMDb/audience, no OMDb/RT). - config.py: tmdb_api_key + api_base/language/interval/batch defaults. - sysconfig SPECS: tmdb_api_key (secret, Fernet) + tmdb_language, auto-rendered in the admin Config page; read like the Plex token. - migration 0071 (ADD-only nullable, reversible): plex_items + plex_shows gain tmdb_id / tmdb_enriched_at (watermark) / tmdb_rating / tmdb_vote_count / budget / revenue / keywords / crew / studios / production_countries / recommendations / backdrops; plex_people gains tmdb_person_id (the S2 foundation for S6 person bios). No watermark reset needed. - app/plex/tmdb.py: TmdbClient (mirrors PlexClient; throttled; 404->None, transient->TmdbError), parse_tmdb / apply_tmdb_detail (one-parser rule), guid_to_tmdb_id (tmdb: direct, imdb:/tvdb: via /find), enrich_batch (movies then shows, transient error leaves the watermark NULL to retry, definitive no-match still stamps so it isn't re-fetched), _link_people (upserts tmdb_person_id by name), serve_block (recommendations resolved to library rows by guid), run_enrich (no-op without a key). - scheduler: tmdb_enrich nightly job (default 120 min, no YouTube quota), runtime-tunable + "run now" from the Scheduler dashboard. - detail endpoints emit `tmdb` (movies + shows) so it's curl-verifiable now; the FE render lands in S5. Note: _link_people inserts plex_people rows for TMDB cast/crew; unreferenced crew (composers etc., not in cast_names/directors) get pruned by the orphan sweep — acceptable, the person page is cast-driven and cast rows survive. Gate: ruff + py_compile green; backend test lane FULL suite 387 passed (incl. migration drift downgrade->re-upgrade + test_plex_tmdb 9 tests). Frontend unchanged since S1. Not merged (epic branch, stacks on S1).
This commit is contained in:
@@ -102,6 +102,11 @@ SPECS: tuple[ConfigSpec, ...] = (
|
||||
ConfigSpec("plex_max_transcodes", "int", "plex", "plex_max_transcodes", min=0, max=16),
|
||||
# NOTE: plex_watch_sync_interval_min is a config.py default read by the watch-sync scheduler job
|
||||
# (scheduler.py); it is intentionally NOT a runtime admin knob, so it stays out of SPECS.
|
||||
# --- TMDB enrichment (E5 S2; optional) — the API key is the only secret ---
|
||||
ConfigSpec("tmdb_api_key", "str", "tmdb", "tmdb_api_key", secret=True),
|
||||
ConfigSpec("tmdb_language", "str", "tmdb", "tmdb_language"),
|
||||
# (tmdb_enrich_interval_min is a scheduler job, tuned from the Scheduler dashboard; tmdb_enrich_batch
|
||||
# is a config.py default — both stay out of SPECS, like plex_sync_interval_min.)
|
||||
)
|
||||
|
||||
_BY_KEY: dict[str, ConfigSpec] = {s.key: s for s in SPECS}
|
||||
|
||||
Reference in New Issue
Block a user