"""Daemon config & manual trigger API routes.""" from __future__ import annotations from fastapi import APIRouter, Depends from pydantic import BaseModel from api.deps import get_admin_user from core.db import conn from core import cache router = APIRouter() class DaemonConfigUpdate(BaseModel): scan_enabled: bool | None = None scan_interval_min: int | None = None process_enabled: bool | None = None process_interval_min: int | None = None process_limit: int | None = None @router.get("/config") def get_config(): """Get daemon config (read-only for all authenticated users).""" with conn() as c: cur = c.cursor() cur.execute( "SELECT scan_enabled, scan_interval_min, process_enabled, process_interval_min, " "process_limit, last_scan_at, last_process_at, updated_at " "FROM daemon_config WHERE id = 1" ) row = cur.fetchone() if not row: return {} return { "scan_enabled": bool(row[0]), "scan_interval_min": row[1], "process_enabled": bool(row[2]), "process_interval_min": row[3], "process_limit": row[4], "last_scan_at": str(row[5]) if row[5] else None, "last_process_at": str(row[6]) if row[6] else None, "updated_at": str(row[7]) if row[7] else None, } @router.put("/config") def update_config(body: DaemonConfigUpdate, _admin: dict = Depends(get_admin_user)): """Update daemon schedule config (admin only).""" sets = [] params: dict = {} if body.scan_enabled is not None: sets.append("scan_enabled = :se") params["se"] = 1 if body.scan_enabled else 0 if body.scan_interval_min is not None: sets.append("scan_interval_min = :si") params["si"] = body.scan_interval_min if body.process_enabled is not None: sets.append("process_enabled = :pe") params["pe"] = 1 if body.process_enabled else 0 if body.process_interval_min is not None: sets.append("process_interval_min = :pi") params["pi"] = body.process_interval_min if body.process_limit is not None: sets.append("process_limit = :pl") params["pl"] = body.process_limit if not sets: return {"ok": True} sets.append("updated_at = SYSTIMESTAMP") sql = f"UPDATE daemon_config SET {', '.join(sets)} WHERE id = 1" with conn() as c: c.cursor().execute(sql, params) return {"ok": True} @router.post("/run/scan") def run_scan(_admin: dict = Depends(get_admin_user)): """Manually trigger channel scan (admin only).""" from core.youtube import scan_all_channels new_count = scan_all_channels() with conn() as c: c.cursor().execute("UPDATE daemon_config SET last_scan_at = SYSTIMESTAMP WHERE id = 1") if new_count > 0: cache.flush() return {"ok": True, "new_videos": new_count} @router.post("/run/process") def run_process(limit: int = 10, _admin: dict = Depends(get_admin_user)): """Manually trigger video processing (admin only).""" from core.pipeline import process_pending rest_count = process_pending(limit=limit) with conn() as c: c.cursor().execute("UPDATE daemon_config SET last_process_at = SYSTIMESTAMP WHERE id = 1") if rest_count > 0: cache.flush() return {"ok": True, "restaurants_extracted": rest_count}