feat(indexing): emit and accept TVDB ids so Sonarr can match by id - #69
Merged
Conversation
…follow-up) PR 1 of the Sonarr/Radarr matching work. Sonarr previously had to identify every release by parsing our title string against Mediathek naming — the exact problem MediathekArr and RundfunkArr spend most of their effort on. A tvdbid attribute short-circuits it: Sonarr trusts the id over the string. - Release carries TvdbId, projected from Show.TvdbId by the Mapperly mapper. - NewznabXml emits <newznab:attr name="tvdbid"> when the show is mapped, and nothing when it is not — a wrong id would be far worse than none, since Sonarr trusts the id over the title and would silently attach releases to the wrong series. - caps advertises supportedParams="q,tvdbid,season,ep". This matters: Sonarr reads caps and only sends what we advertise, so without listing tvdbid it would keep falling back to title-only searches no matter what we accept. - The endpoint binds tvdbid; SearchReleasesQuery carries it; a search by id answers from IEpisodeRepository.GetByTvdbIdAsync rather than re-parsing titles. Fallback behaviour is deliberate. An id we have not mapped is *our* gap, not proof the show is absent, so an unknown id falls through to the title search when Sonarr also sent one. With no title it returns empty rather than inventing a match. Correcting my own earlier claim: season and episode attributes were already being emitted. Only tvdbid was missing. Note Show.TvdbId is still populated by nothing, so today every release is emitted without an id and behaviour is unchanged — this is the plumbing that makes PR 3 (show mapping) worth having. Verified both directions so the unmapped case is known-good, not assumed. Verified against a running host with a mapped show (extra 3, tvdb 255986 — a real id found during the research) and an unmapped one (Panorama): caps -> supportedParams="q,tvdbid,season,ep" q=extra 3 (mapped) -> item carries tvdbid = 255986 q=Panorama (unmapped) -> item carries no tvdbid attr at all tvdbid=255986 -> 1 item, answered by id tvdbid=999999 (unmapped, no title) -> 0 items tvdbid=999999&q=Panorama -> 1 item, and the *right* show q= / no params -> title search and RSS feed unchanged Tests: App 117 / Arch 11 / Infra 102 green, 0 warnings. Plan: docs/plans/2026-07-28 - sonarr-radarr-integration.md — which also records the matching research: TVDB stores German titles as translations/aliases (its search indexes them), and Wikidata's P4835 offers a keyless title->tvdbid bridge that covers only 16.3% of German public-TV series, so a manual tail is unavoidable. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR 1 of the matching work. Sonarr previously had to identify every release by parsing our title string against Mediathek naming — the exact problem MediathekArr and RundfunkArr pour most of their effort into. A
tvdbidattribute short-circuits it: Sonarr trusts the id over the string.What changed
ReleasecarriesTvdbId, projected fromShow.TvdbIdby the Mapperly mapper.NewznabXmlemits<newznab:attr name="tvdbid">when the show is mapped, and nothing when it isn't — a wrong id is far worse than none, since Sonarr trusts the id over the title and would silently attach releases to the wrong series.capsadvertisessupportedParams="q,tvdbid,season,ep". This is the part that's easy to miss: Sonarr reads caps and only sends what we advertise, so without listingtvdbidit would keep doing title-only searches no matter what the endpoint accepts.tvdbid; a search by id answers fromIEpisodeRepository.GetByTvdbIdAsyncinstead of re-parsing titles.Fallback behaviour is deliberate
An id we haven't mapped is our gap, not proof the show is absent. So an unknown id falls through to the title search when Sonarr also sent one; with no title it returns empty rather than inventing a match.
Two corrections to my own earlier claims
seasonandepisodewere already being emitted. I'd said "notvdbid, noseason, noepisode" when I first read the code — wrong on two of three. Onlytvdbidwas missing.Show.TvdbIdis still populated by nothing, so today every release goes out without an id and observable behaviour is unchanged. This is the plumbing that makes PR 3 (show mapping) worth having. I verified both directions so the unmapped case is known-good rather than assumed.Verified against a running host
Seeded a mapped show (
extra 3, tvdb 255986 — a real id from the research) and an unmapped one (Panorama):t=capssupportedParams="q,tvdbid,season,ep"q=extra 3(mapped)tvdbid = 255986q=Panorama(unmapped)tvdbidattr at alltvdbid=255986tvdbid=999999(unmapped, no title)tvdbid=999999&q=Panoramaq=/ no paramsTests: App 117 / Arch 11 / Infra 102 green, 0 warnings.
Research recorded in the plan
The plan now carries the matching research, since it changes how PR 3 should be built:
P4835maps German title (label or alias) → TVDB id, with broadcaster for disambiguation. Measured live: 16.3% coverage (ZDF 14.6%, Das Erste 15.3%, KiKA 48.5%). Good first pass, not a complete answer.extra 3's network is NDR, not "Das Erste" — filtering on Das Erste would silently miss it.PR 3 will use
TvdbClient(Chrison-dev/TvdbApi) rather than a hand-rolled client.Plan:
docs/plans/2026-07-28 - sonarr-radarr-integration.md🤖 Generated with Claude Code