feat: TMDB year fallback + PUID/PGID support
Docker / docker (push) Successful in 2m58s

- tmdb.py: store release_date year in cache, expose as tmdb_year
- main.py + app.js: use tmdb_year when subtitle has no year
- Dockerfile: add gosu + abc user for PUID/PGID runtime privilege drop
- entrypoint.sh: new entrypoint handling PUID/PGID ownership of /app/data

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
dev
2026-05-05 18:02:18 +02:00
parent 9cc8bb771d
commit 0866a875ba
6 changed files with 45 additions and 14 deletions
+19 -11
View File
@@ -33,9 +33,14 @@ def _init_db():
tmdb_id INTEGER,
poster TEXT,
backdrop TEXT,
year INTEGER,
cached_at TEXT NOT NULL
)
""")
try:
conn.execute("ALTER TABLE tmdb_cache ADD COLUMN year INTEGER")
except Exception:
pass
def _search(query: str) -> list[dict]:
@@ -72,39 +77,42 @@ def lookup(arte_id: str, title: str, subtitle: str) -> dict | None:
cutoff = (datetime.now() - timedelta(days=_CACHE_DAYS)).isoformat()
with sqlite3.connect(_DB) as conn:
row = conn.execute(
"SELECT tmdb_id, poster, backdrop FROM tmdb_cache WHERE arte_id=? AND cached_at>?",
"SELECT tmdb_id, poster, backdrop, year FROM tmdb_cache WHERE arte_id=? AND cached_at>?",
(arte_id, cutoff),
).fetchone()
if row is not None:
tmdb_id, poster, backdrop = row
tmdb_id, poster, backdrop, year = row
if tmdb_id is None:
return None # cached "no match"
return _build(tmdb_id, poster, backdrop)
return _build(tmdb_id, poster, backdrop, year)
# Query TMDB
query = f"{title} {subtitle}".strip()
results = _search(query) or (_search(title) if subtitle else [])
match = _best_match(results, title, subtitle)
tmdb_id = match["id"] if match else None
poster = match.get("poster_path") if match else None
backdrop = match.get("backdrop_path") if match else None
tmdb_id = match["id"] if match else None
poster = match.get("poster_path") if match else None
backdrop = match.get("backdrop_path") if match else None
rd = (match.get("release_date") or "")[:4] if match else ""
year = int(rd) if rd.isdigit() else None
with sqlite3.connect(_DB) as conn:
conn.execute(
"INSERT OR REPLACE INTO tmdb_cache VALUES (?,?,?,?,?)",
(arte_id, tmdb_id, poster, backdrop, datetime.now().isoformat()),
"INSERT OR REPLACE INTO tmdb_cache VALUES (?,?,?,?,?,?)",
(arte_id, tmdb_id, poster, backdrop, year, datetime.now().isoformat()),
)
return _build(tmdb_id, poster, backdrop) if tmdb_id else None
return _build(tmdb_id, poster, backdrop, year) if tmdb_id else None
def _build(tmdb_id: int, poster: str | None, backdrop: str | None) -> dict:
def _build(tmdb_id: int, poster: str | None, backdrop: str | None, year: int | None = None) -> dict:
return {
"tmdb_id": tmdb_id,
"tmdb_id": tmdb_id,
"tmdb_poster": f"{_IMG_BASE}/w500{poster}" if poster else None,
"tmdb_backdrop": f"{_IMG_BASE}/w1280{backdrop}" if backdrop else None,
"tmdb_year": year,
}