Add TMDB search and media detail pages, HDHive resource ingestion flow, unified error handling, Docker single-container runtime, and project docs/config updates for local deployment. Co-authored-by: Cursor <cursoragent@cursor.com>
74 lines
2.3 KiB
Python
74 lines
2.3 KiB
Python
from adapters.hdhive_adapter import normalize_resource, search_resource, unlock_link
|
|
from adapters.tmdb_adapter import get_media_detail, search_media
|
|
from error_handling import AppServiceError
|
|
|
|
|
|
def search_media_by_keyword(query, media_type):
|
|
result = search_media(query, media_type)
|
|
raw_items = result.get("items") or []
|
|
items = []
|
|
for item in raw_items:
|
|
items.append(
|
|
{
|
|
"id": item.get("id"),
|
|
"type": media_type,
|
|
"title": item.get("title") or item.get("name"),
|
|
"overview": item.get("overview") or "",
|
|
"posterPath": item.get("poster_path") or "",
|
|
"releaseDate": item.get("release_date") or item.get("first_air_date") or "",
|
|
"voteAverage": item.get("vote_average"),
|
|
}
|
|
)
|
|
return {"items": items}
|
|
|
|
|
|
def get_media_resources(media_type, tmdb_id):
|
|
detail = get_media_detail(tmdb_id, media_type)
|
|
hdhive = search_resource(media_type, tmdb_id)
|
|
search_data = hdhive.get("data") or []
|
|
if isinstance(search_data, dict):
|
|
search_data = search_data.get("items") or []
|
|
|
|
resources = []
|
|
for item in search_data:
|
|
slug = (item or {}).get("slug")
|
|
unlock_data = {}
|
|
unlock_error = None
|
|
if slug:
|
|
try:
|
|
unlock = unlock_link(slug)
|
|
unlock_data = unlock.get("data") or {}
|
|
except Exception as error:
|
|
unlock_error = str(error)
|
|
normalized = normalize_resource(item, unlock_data)
|
|
normalized["unlockError"] = unlock_error
|
|
resources.append(normalized)
|
|
|
|
return {
|
|
"media": detail.get("normalized"),
|
|
"resources": resources,
|
|
}
|
|
|
|
|
|
def validate_media_query(query, media_type):
|
|
if not query:
|
|
raise AppServiceError(
|
|
"query is required",
|
|
category="validation",
|
|
code="INVALID_INPUT",
|
|
status=400,
|
|
provider="api",
|
|
)
|
|
validate_media_type(media_type)
|
|
|
|
|
|
def validate_media_type(media_type):
|
|
if media_type not in ("movie", "tv"):
|
|
raise AppServiceError(
|
|
"type must be movie or tv",
|
|
category="validation",
|
|
code="INVALID_INPUT",
|
|
status=400,
|
|
provider="api",
|
|
)
|