All checks were successful
Docker / docker (push) Successful in 1m22s
Poster 110×165px (w342 TMDB), grid et padding agrandis. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
66 lines
2.4 KiB
Python
66 lines
2.4 KiB
Python
import asyncio
|
|
import httpx
|
|
|
|
|
|
class TMDBClient:
|
|
BASE_URL = "https://api.themoviedb.org/3"
|
|
POSTER_BASE = "https://image.tmdb.org/t/p/w342"
|
|
|
|
def __init__(self, api_key: str):
|
|
self.api_key = api_key
|
|
|
|
async def _fetch(self, client: httpx.AsyncClient, path: str, params: dict) -> dict | None:
|
|
try:
|
|
r = await client.get(f"{self.BASE_URL}{path}", params={"api_key": self.api_key, **params}, timeout=10)
|
|
if r.status_code == 200:
|
|
return r.json()
|
|
except Exception:
|
|
pass
|
|
return None
|
|
|
|
async def get_movie_details(self, client: httpx.AsyncClient, movie: dict) -> dict:
|
|
tmdb_id = movie.get("tmdb_id")
|
|
imdb_id = movie.get("imdb_id")
|
|
|
|
# Resolve TMDB ID from IMDB if needed
|
|
if not tmdb_id and imdb_id:
|
|
data = await self._fetch(client, f"/find/{imdb_id}", {"external_source": "imdb_id"})
|
|
if data:
|
|
results = data.get("movie_results", [])
|
|
if results:
|
|
tmdb_id = results[0]["id"]
|
|
movie["tmdb_id"] = tmdb_id
|
|
|
|
if not tmdb_id:
|
|
movie.update({"title_fr": movie["title"], "overview": "", "poster": None})
|
|
return movie
|
|
|
|
# Fetch French details
|
|
details = await self._fetch(client, f"/movie/{tmdb_id}", {"language": "fr-FR"})
|
|
|
|
# Fallback to English overview if French is empty
|
|
if details and not details.get("overview"):
|
|
en = await self._fetch(client, f"/movie/{tmdb_id}", {"language": "en-US"})
|
|
if en:
|
|
details["overview"] = en.get("overview", "")
|
|
|
|
if details:
|
|
poster = details.get("poster_path")
|
|
movie.update({
|
|
"title_fr": details.get("title") or movie["title"],
|
|
"overview": details.get("overview") or "",
|
|
"poster": f"{self.POSTER_BASE}{poster}" if poster else None,
|
|
})
|
|
else:
|
|
movie.update({"title_fr": movie["title"], "overview": "", "poster": None})
|
|
|
|
return movie
|
|
|
|
async def enrich_movies(self, movies: list) -> list:
|
|
sem = asyncio.Semaphore(5)
|
|
async with httpx.AsyncClient() as client:
|
|
async def fetch_one(movie):
|
|
async with sem:
|
|
return await self.get_movie_details(client, movie)
|
|
return list(await asyncio.gather(*[fetch_one(m) for m in movies]))
|