fix(media): a film leaves the TV library only for a film it actually names

The first tvdb-grade plan handed 12 files to the movie library, and two of them
were wrong in a way the exceptions file could not show: an episode of the
documentary series `Russia 1985-1999: TraumaZone` was renamed to the 1963 Bond
film `From Russia with Love`, and `Gundam 00 Special Edition III - Return The
World` became `Special Edition I - Celestial Being`.

Two guards, each alone insufficient:

- `title_of` salvages a short query from a long release name ("russia", "mobile
  suit gundam 00"), and tmdb() took the FIRST search result. The call site then
  compared the provider's words against that salvaged query, so any title merely
  CONTAINING the query passed. The provider's title must now be a run of words the
  FILE itself states: `Special Edition I: Celestial Being` is not in a filename
  that says `Special Edition III - Return The World`.
- tmdb() read the year from `year`/`first_air_date`, which the MOVIE search does
  not return — it returns `release_date`. Every film answer therefore arrived
  year-less and the year guard at the call site could never fire. That is how a
  1963 answer survived a filename stating 1991.

Tests: a provider answer the file does not name parks, and nothing lands in the
movie library; an answer from another year is refused. The year-from-the-wire half
is proven by the live re-plan, which now dates every movie answer.
This commit is contained in:
Frank committed 2026-10-31 07:38:54 -07:00
1 parent 32b8901bff
commit c70f9b3f6d
2 files changed
+46 -4

No files matched your search

+14 -4
View File
@@ -278,9 +278,14 @@ def tmdb(kind, query):
CACHE[ck] = None
return None
top = found[0]
# The two search endpoints date their rows differently: movies carry
# `release_date`, tv carries `first_air_date`. Reading only one of them leaves
# every film answer year-less, and a year-less answer can never be refused by
# the year guard below.
when = str(top.get("year") or "") or \
str(top.get("release_date") or top.get("first_air_date") or "")[:4]
CACHE[ck] = {"name": (top.get("title") or top.get("name") or "").strip(),
"year": str(top.get("year") or "") or (top.get("first_air_date") or "")[:4],
"id": top.get("id")}
"year": when, "id": top.get("id")}
return CACHE[ck]
@@ -787,8 +792,13 @@ for r, name, kind in extras:
for r in films:
parsed, year = title_of(r["base"])
got = tmdb("movie", parsed)
words = eng.norm(got["name"]).split() if got else []
if not got or not eng.mentions(parsed.split(), words) \
# The provider's title must be a run of words the FILE itself states. The query
# is only what title_of could salvage from the name, and a short one ("russia")
# lets the top hit be a different work entirely: a 1963 Bond film is not a 1991
# documentary episode, and Special Edition I is not Special Edition III.
said = eng.norm(os.path.splitext(r["base"])[0]).split()
named = eng.norm(got["name"]).split() if got else []
if not got or not eng.mentions(named, said) \
or (year != "?" and got["year"] and got["year"] != year):
park(r, "long file with no episode evidence, and no movie provider names it")
continue