62 lines
1.8 KiB
Python
62 lines
1.8 KiB
Python
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")),
|
|
}
|