"""Scheduler API Routes - Manage scheduled tasks.""" import logging from typing import Optional, List, Dict, Any from fastapi import APIRouter, Form from fastapi.responses import JSONResponse from core.scheduler import add_job, remove_job, get_jobs logger = logging.getLogger("syllabus") router = APIRouter(prefix="/api/schedule", tags=["Scheduler"]) @router.post("/add", description="Add a scheduled task") async def add_scheduled_task( job_id: str = Form(...), task: str = Form(...), cron: str = Form(...), show: Optional[str] = Form(None), season: Optional[int] = Form(None), specials: bool = Form(False) ) -> JSONResponse: """ Add a scheduled task. **Tasks:** - `download_show`: Download specific show/season (requires: show, season) - `download_latest`: Download latest season (requires: show) - `update_series`: Update series list (no params needed) - `update_posters`: Force re-download all show posters (no params needed) **Cron Format:** (minute hour day month day_of_week) - `0 2 * * *` = Daily at 2 AM - `0 */6 * * *` = Every 6 hours - `0 0 * * 0` = Weekly on Sunday at midnight """ try: # Validate task type valid_tasks = ["download_show", "download_latest", "update_series", "update_posters"] if task not in valid_tasks: return JSONResponse( status_code=400, content={"status": "error", "message": f"Invalid task. Must be one of: {valid_tasks}"} ) # Build kwargs based on task kwargs = {} if task == "download_show": if not show or season is None: return JSONResponse( status_code=400, content={"status": "error", "message": "download_show requires 'show' and 'season'"} ) kwargs = {"show": show, "season": season, "specials": specials} elif task == "download_latest": if not show: return JSONResponse( status_code=400, content={"status": "error", "message": "download_latest requires 'show'"} ) kwargs = {"show": show} # Add the job success = add_job(job_id, task, cron, kwargs) if success: return JSONResponse( status_code=201, content={ "status": "success", "message": f"Job '{job_id}' scheduled", "job_id": job_id, "task": task, "cron": cron } ) else: return JSONResponse( status_code=500, content={"status": "error", "message": "Failed to add job"} ) except Exception as e: logger.error(f"Error adding scheduled task: {e}") return JSONResponse( status_code=500, content={"status": "error", "message": str(e)} ) @router.delete("/remove/{job_id}", description="Remove a scheduled task") async def remove_scheduled_task(job_id: str) -> JSONResponse: """Remove a scheduled task by ID.""" try: success = remove_job(job_id) if success: return JSONResponse( status_code=200, content={"status": "success", "message": f"Job '{job_id}' removed"} ) else: return JSONResponse( status_code=404, content={"status": "error", "message": f"Job '{job_id}' not found"} ) except Exception as e: logger.error(f"Error removing scheduled task: {e}") return JSONResponse( status_code=500, content={"status": "error", "message": str(e)} ) @router.get("/list", description="List all scheduled tasks") async def list_scheduled_tasks() -> JSONResponse: """Get list of all scheduled tasks.""" try: jobs = get_jobs() return JSONResponse( status_code=200, content={ "status": "success", "count": len(jobs), "jobs": jobs } ) except Exception as e: logger.error(f"Error listing scheduled tasks: {e}") return JSONResponse( status_code=500, content={"status": "error", "message": str(e)} )