feat: Add AniList, TVDB v4 integrations, provider priority ordering & BYOK custom keys - #495
Conversation
9eeda35 to
5d802c2
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bc41cb7033
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| case "metadata": | ||
| return <MetadataSection settings={settings} set={set} />; |
There was a problem hiding this comment.
Wire metadata settings into the web fetch paths
In the web app context I checked, adding this visible section only persists values: MetadataDispatcher is not imported anywhere, and existing search/details/catalog flows still call web/lib/tmdb.ts directly, so none of customTmdbApiKey, customTvdbApiKey, or the provider-order fields affect requests. Users can enter keys and see “TVDB enabled”, but metadata remains on the previous TMDB path until this section is wired into the fetchers.
Useful? React with 👍 / 👎.
| private static resolvers: Record<string, MetadataResolver> = { | ||
| anilist: aniListResolver, | ||
| tvdb: tvdbResolver | ||
| }; |
There was a problem hiding this comment.
Register TMDB before returning it as a default
When a caller uses the new dispatcher, the default priority list includes tmdb for all movie lookups and as the TV/anime fallback, but this resolver table only contains AniList and TVDB. Because the dispatch loop silently skips missing resolvers, movie getDetails/search returns null/[] and TV/anime never reach the displayed TMDB fallback unless a TMDB resolver is registered here.
Useful? React with 👍 / 👎.
ProdigyV21
left a comment
There was a problem hiding this comment.
Thanks Himanth — the direction here is right (AniList for anime, TVDB as an opt-in BYOK provider, priority fallback), the per-file code is clean, and both builds pass. TVDB being hard-disabled without a user key is exactly the right call.
The blocker: nothing is wired up yet, so merging this would ship a settings page for a feature that doesn't exist. Concretely:
-
No call sites.
MetadataDispatcher(web and Android), the resolvers, and the AniZip mapper are never referenced outside the new files — this PR adds no consumers either. Details, search and episodes still go 100% through the existing TMDB path on both platforms, so the ~840 added lines are unreachable at runtime. -
The anime chain can't trigger.
MediaTypeis"movie" | "tv"(web/lib/types.ts) and nothing anywhere produces or detects"anime"— the"anime" as anycasts paper over this. The feature needs a real anime media type or detection (e.g. TMDB genre 16 + origin country JP, or an AniList-id source) before a priority chain for it means anything. -
The dispatcher's terminal fallback doesn't exist.
dispatcher.tsonly registersanilistandtvdbin its resolver map — there is no TMDB resolver. As-is, movies (chain["tmdb"]) resolve tonullfor everyone, and TV without a TVDB key also dead-ends. Wiring the dispatcher into the app in this state would break details for all non-BYOK users. -
customTmdbApiKeyis stored but never read. The real TMDB fetch path (web/lib/tmdb.ts→/api/tmdbproxy) doesn't consult it, so the BYOK TMDB field does nothing. -
The settings page overstates reality. "Active chain: AniList → TVDB → TMDB" reads as live status, but nothing consults
metadataAnimeProviders/metadataTvProviders/metadataMovieProviders. A user can enter a key and see "Active — TVDB enabled" while zero requests ever hit TVDB.
Smaller points for the next revision:
- The web TVDB token cache (
cachedTokenintvdb.ts) isn't invalidated when the key/PIN changes — log in with key A, switch to key B, and requests keep riding A's token for up to 23h. - Android's
getAnimeDetails(query)searches by name only and ignores the priority config — the KotlinMetadataDispatcherhas no actual fallback chain despite the name. - The settings UI uses inline
style={{…}}throughout; the rest of the app styles via classes inglobals.css. convertAniListToTmdbEpisodeis exactly what playback needs for absolute-numbered anime episodes — it just needs a call site in the episode/stream resolution flow to earn its place.
What would make this mergeable: land one vertical slice end-to-end instead of scaffolding everywhere. Suggested shape, web-only first:
- Add anime detection (or an explicit anime type) for titles.
- Register a TMDB resolver as the terminal fallback so today's behavior is the guaranteed worst case.
- Route
getDetails/getEpisodesfor detected anime through the dispatcher. - Use the AniZip mapping when resolving episode streams (that's where it pays off).
- Only then surface the settings UI for keys/priorities, reflecting what's actually consulted.
Android can follow the same shape once the web slice proves out. Happy to review that version quickly.
- Extend MediaType to include 'anime' - Add tmdbResolver as terminal fallback MetadataResolver - Register tmdb resolver in dispatcher with anime priority support - Route getDetails/getSeasonEpisodes through MetadataDispatcher - Add isAnime() helper and customTmdbApiKey support in tmdb.ts - Wire AniZip mapping for anime episode stream resolution in store - Invalidate TVDB token cache on key/PIN change - Remove unsafe 'as any' casts in anilist.ts - Propagate MediaType union to sync, trakt, mdblist, imdbRatings - Fix type predicate widening errors with NonNullable generics - Clean up MetadataSection settings UI to use standard CSS classes
|
Thanks for the detailed review! All 5 blockers and the smaller points have been addressed in commit Blockers addressed
Smaller points fixed
Verification
Android vertical slice will follow once this web slice is validated. Ready for re-review! |
Summary
Introduces AniList GraphQL and TVDB v4 REST metadata integrations across both the Android Application (
app/) and Web Application (web/), with provider fallback priority ordering and Bring Your Own Key (BYOK) custom key management.Key Changes
AniListApi.kt(Retrofit GraphQL) in Android app andweb/lib/metadata/anilist.tsin Web app for full anime metadata support.web/lib/metadata/anizip.ts(AniZip ID mapper) for cross-referencing AniList IDs to TMDB/TVDB/IMDb.TvdbApiV4.ktin Android andweb/lib/metadata/tvdb.tsin Web.MetadataDispatcheron Android (MetadataDispatcher.kt) and Web (dispatcher.ts) for priority fallback routing:AniList → TVDB → TMDBTVDB → TMDBTMDBVerification
npx tsc --noEmitpassed with 0 errors../gradlew :app:compileSideloadDebugKotlinpassed with BUILD SUCCESSFUL.