feat(stats): add TMDB metadata for live-action dramas in the Library

Anime covers come from AniList, which has no live-action titles, so dramas
and movies showed blank cards with no description and split across season
folders. Library entries now carry a media kind plus a TMDB link, and the
cover-art fetcher falls back to TMDB when AniList has no match, accepting
only a Japanese non-animated title whose TMDB names match the parsed title
exactly. Entries that resolve to the same TMDB title merge into one card
regardless of season, and a Link to TMDB action in the detail view covers
anything the automatic match missed.

Release builds bundle a project-owned TMDB key injected from the
SUBMINER_TMDB_API_KEY secret at build time; tmdb.apiKey/apiKeyCommand
override it and are required when running from source.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-18 23:31:35 -07:00
co-authored by Claude Fable 5.1
parent dd76782d30
commit 2b33d32879
68 changed files with 2339 additions and 68 deletions
@@ -34,6 +34,9 @@ export function getAnimeLibrary(db: DatabaseSync): AnimeLibraryRow[] {
a.anime_id AS animeId,
a.canonical_title AS canonicalTitle,
a.anilist_id AS anilistId,
a.media_kind AS mediaKind,
a.tmdb_id AS tmdbId,
a.tmdb_type AS tmdbType,
COALESCE(lm.total_sessions, 0) AS totalSessions,
COALESCE(lm.total_active_ms, 0) AS totalActiveMs,
COALESCE(lm.total_cards, 0) AS totalCards,
@@ -64,6 +67,9 @@ export function getAnimeDetail(db: DatabaseSync, animeId: number): AnimeDetailRo
a.anime_id AS animeId,
a.canonical_title AS canonicalTitle,
a.anilist_id AS anilistId,
a.media_kind AS mediaKind,
a.tmdb_id AS tmdbId,
a.tmdb_type AS tmdbType,
a.title_romaji AS titleRomaji,
a.title_english AS titleEnglish,
a.title_native AS titleNative,