from __future__ import annotations import json import pathlib from typing import Any import aiosqlite from server.settings import settings SCHEMA_PATH = str(pathlib.Path(__file__).resolve().parents[1] / "tools" / "schema.sql") async def get_db() -> aiosqlite.Connection: pathlib.Path(settings.db_path).parent.mkdir(parents=True, exist_ok=True) db = await aiosqlite.connect(settings.db_path) db.row_factory = aiosqlite.Row await db.execute("PRAGMA foreign_keys = ON;") return db async def ensure_schema(db: aiosqlite.Connection) -> None: schema = pathlib.Path(SCHEMA_PATH).read_text(encoding="utf-8") await db.executescript(schema) await db.commit() def row_to_recap(row: aiosqlite.Row) -> dict[str, Any]: data = dict(row) data["sections"] = json.loads(data.pop("sections_json")) return data async def get_recap(db: aiosqlite.Connection, video_id: str) -> dict[str, Any] | None: cur = await db.execute("SELECT * FROM recaps WHERE video_id = ?", (video_id,)) row = await cur.fetchone() await cur.close() return row_to_recap(row) if row else None async def list_recaps(db: aiosqlite.Connection, *, limit: int = 20, offset: int = 0) -> list[dict[str, Any]]: cur = await db.execute( """ SELECT video_id, title, channel, thumbnail_url, duration_sec, language, tldr, vibe_check, watch_verdict, goldfish_note, created_at, updated_at FROM recaps ORDER BY created_at DESC LIMIT ? OFFSET ? """, (limit, offset), ) rows = await cur.fetchall() await cur.close() return [dict(row) for row in rows] async def count_recaps(db: aiosqlite.Connection) -> int: cur = await db.execute("SELECT COUNT(*) FROM recaps") row = await cur.fetchone() await cur.close() return int(row[0]) if row else 0 async def upsert_recap(db: aiosqlite.Connection, recap: dict[str, Any]) -> None: await db.execute( """ INSERT INTO recaps ( video_id, title, channel, thumbnail_url, duration_sec, language, tldr, vibe_check, watch_verdict, goldfish_note, sections_json, transcript_hash, model, created_at, updated_at ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(video_id) DO UPDATE SET title = excluded.title, channel = excluded.channel, thumbnail_url = excluded.thumbnail_url, duration_sec = excluded.duration_sec, language = excluded.language, tldr = excluded.tldr, vibe_check = excluded.vibe_check, watch_verdict = excluded.watch_verdict, goldfish_note = excluded.goldfish_note, sections_json = excluded.sections_json, transcript_hash = excluded.transcript_hash, model = excluded.model, updated_at = excluded.updated_at """, ( recap["video_id"], recap["title"], recap.get("channel"), recap.get("thumbnail_url"), recap.get("duration_sec"), recap.get("language"), recap["tldr"], recap.get("vibe_check"), recap["watch_verdict"], recap.get("goldfish_note"), json.dumps(recap["sections"], ensure_ascii=False), recap.get("transcript_hash"), recap.get("model"), recap["created_at"], recap["updated_at"], ), ) await db.commit()