Files
2026-04-29 16:01:20 +00:00

89 lines
2.9 KiB
Python

"""TMDB API client. Uses v3 API with api_key query param."""
import requests
from typing import List, Dict, Optional
BASE = "https://api.themoviedb.org/3"
IMG = "https://image.tmdb.org/t/p"
def _img(path: Optional[str], size: str = "w500") -> str:
if not path:
return ""
return f"{IMG}/{size}{path}"
def search_movies(api_key: str, query: str) -> List[Dict]:
if not api_key or not query.strip():
return []
r = requests.get(f"{BASE}/search/movie", params={"api_key": api_key, "query": query}, timeout=15)
r.raise_for_status()
data = r.json().get("results", []) or []
out = []
for m in data[:20]:
year = None
if m.get("release_date"):
try: year = int(m["release_date"].split("-")[0])
except Exception: pass
out.append({
"tmdb_id": m["id"],
"title": m.get("title") or m.get("name") or "",
"year": year,
"overview": m.get("overview") or "",
"poster_url": _img(m.get("poster_path"), "w500"),
"backdrop_url": _img(m.get("backdrop_path"), "original"),
})
return out
def get_movie(api_key: str, tmdb_id: int) -> Dict:
"""Return rich movie details with cast/crew."""
r = requests.get(
f"{BASE}/movie/{tmdb_id}",
params={"api_key": api_key, "append_to_response": "credits"},
timeout=15,
)
r.raise_for_status()
m = r.json()
year = None
if m.get("release_date"):
try: year = int(m["release_date"].split("-")[0])
except Exception: pass
credits = m.get("credits", {}) or {}
cast = [c["name"] for c in (credits.get("cast") or [])[:8] if c.get("name")]
crew = credits.get("crew") or []
director = next((c["name"] for c in crew if c.get("job") == "Director"), "")
genres = [g["name"] for g in (m.get("genres") or []) if g.get("name")]
# Map TMDB certifications to our rating scale (best effort, US fallback)
rating = "NR"
try:
rel = requests.get(
f"{BASE}/movie/{tmdb_id}/release_dates",
params={"api_key": api_key}, timeout=10,
).json()
for r_country in rel.get("results", []):
if r_country.get("iso_3166_1") == "US":
for d in r_country.get("release_dates", []) or []:
cert = (d.get("certification") or "").strip()
if cert:
rating = cert
break
break
except Exception:
pass
return {
"tmdb_id": m["id"],
"title": m.get("title") or "",
"year": year,
"description": m.get("overview") or "",
"duration_minutes": m.get("runtime") or 0,
"rating": rating or "NR",
"genres": genres,
"cast": cast,
"director": director,
"poster_url": _img(m.get("poster_path"), "w500"),
"backdrop_url": _img(m.get("backdrop_path"), "original"),
}