Backend (FastAPI + Oracle ADB), Frontend (Next.js), daemon worker. Features: channel/video/restaurant management, semantic search, Google OAuth, user reviews. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
53 lines
1.4 KiB
Python
53 lines
1.4 KiB
Python
"""Video API routes."""
|
|
|
|
from fastapi import APIRouter, Query
|
|
|
|
from core.db import conn
|
|
from core.pipeline import process_pending
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("")
|
|
def list_videos(
|
|
status: str | None = None,
|
|
limit: int = Query(50, le=200),
|
|
offset: int = Query(0, ge=0),
|
|
):
|
|
conditions = []
|
|
params: dict = {"lim": limit, "off": offset}
|
|
if status:
|
|
conditions.append("v.status = :st")
|
|
params["st"] = status
|
|
|
|
where = ("WHERE " + " AND ".join(conditions)) if conditions else ""
|
|
sql = f"""
|
|
SELECT v.id, v.video_id, v.title, v.url, v.status,
|
|
v.published_at, c.channel_name
|
|
FROM videos v
|
|
JOIN channels c ON c.id = v.channel_id
|
|
{where}
|
|
ORDER BY v.published_at DESC NULLS LAST
|
|
OFFSET :off ROWS FETCH NEXT :lim ROWS ONLY
|
|
"""
|
|
with conn() as c:
|
|
cur = c.cursor()
|
|
cur.execute(sql, params)
|
|
cols = [d[0].lower() for d in cur.description]
|
|
rows = cur.fetchall()
|
|
|
|
results = []
|
|
for row in rows:
|
|
d = dict(zip(cols, row))
|
|
if d.get("published_at"):
|
|
d["published_at"] = d["published_at"].isoformat()
|
|
results.append(d)
|
|
return results
|
|
|
|
|
|
@router.post("/process")
|
|
def trigger_processing(limit: int = Query(5, le=20)):
|
|
"""Manually trigger processing of pending videos."""
|
|
count = process_pending(limit)
|
|
return {"restaurants_extracted": count}
|