from flask import Flask, jsonify, request from flask_cors import CORS from config import Config from error_handling import AppServiceError, normalize_exception from services.media_service import ( get_media_resources, search_media_by_keyword, validate_media_query, validate_media_type, ) from services.orchestrator import run_ingest_task from storage import init_db, list_logs, list_tasks def create_app(): def error_response(error, fallback_status=400): normalized = normalize_exception(error) status = normalized.status or fallback_status return jsonify({"error": normalized.to_dict()}), status app = Flask(__name__) CORS(app) init_db() @app.get("/api/health") def health(): return jsonify({"ok": True}) @app.post("/api/tasks") def create_task(): data = request.get_json(silent=True) or {} tmdb_id = str(data.get("tmdbId", "")).strip() media_type = data.get("type", "movie") keyword = str(data.get("keyword", "")).strip() if not tmdb_id: return error_response( AppServiceError( "tmdbId is required", category="validation", code="INVALID_INPUT", status=400, provider="api", ), 400, ) if media_type not in ("movie", "tv"): return error_response( AppServiceError( "type must be movie or tv", category="validation", code="INVALID_INPUT", status=400, provider="api", ), 400, ) task = run_ingest_task( { "tmdbId": tmdb_id, "type": media_type, "keyword": keyword, "slug": str(data.get("slug", "")).strip(), } ) return jsonify(task) @app.get("/api/media/search") def search_media_handler(): query = str(request.args.get("query", "")).strip() media_type = str(request.args.get("type", "movie")).strip() try: validate_media_query(query, media_type) return jsonify(search_media_by_keyword(query, media_type)) except Exception as error: return error_response(error) @app.get("/api/media//") def media_detail_handler(media_type, tmdb_id): try: validate_media_type(media_type) return jsonify(get_media_resources(media_type, str(tmdb_id))) except Exception as error: return error_response(error) @app.get("/api/tasks") def get_tasks(): return jsonify({"items": list_tasks()}) @app.get("/api/tasks//logs") def get_task_logs(task_id): return jsonify({"items": list_logs(task_id)}) return app app = create_app() if __name__ == "__main__": app.run(host="0.0.0.0", port=Config.FLASK_RUN_PORT, debug=Config.FLASK_DEBUG)