import json import re import urllib.error import urllib.parse import urllib.request from envfile import env_value IMDB_ID_PATTERN = re.compile(r"tt\d{7,9}") OMDB_URL = "https://www.omdbapi.com/" OMDB_DEMO_URL = "http://www.omdbapi.com/demo.aspx/" RATE_LIMITED_STATUS = 401 MISSING_VALUE = "N/A" def imdb_id(text: str) -> str | None: match = IMDB_ID_PATTERN.search(text) return match.group(0) if match else None def title_url(identifier: str) -> str: return f"https://www.imdb.com/title/{identifier}/" def request_json(url: str, parameters: dict) -> dict: with urllib.request.urlopen(f"{url}?{urllib.parse.urlencode(parameters)}", timeout=10) as response: return json.load(response) def lookup(identifier: str) -> dict | None: api_key = env_value("OMDB_API_KEY") if not api_key: return None try: try: result = request_json(OMDB_URL, {"apikey": api_key, "i": identifier}) except urllib.error.HTTPError as error: if error.code != RATE_LIMITED_STATUS: raise result = request_json(OMDB_DEMO_URL, {"i": identifier, "token": "demo"}) except (OSError, ValueError): return None return result if result.get("Response") == "True" else None def present(value: str | None) -> str | None: return value if value and value != MISSING_VALUE else None def details(identifier: str) -> dict: result = lookup(identifier) if not result: raise ValueError(f"Could not look up {identifier} on OMDb. Check OMDB_API_KEY in .env") return { "name": present(result.get("Title")), "year": present(result.get("Year")), "genre": present(result.get("Genre")), "runtime": present(result.get("Runtime")), "plot": present(result.get("Plot")), "posterSource": present(result.get("Poster")), }