"""/api/archive — 완료된 잡을 한 목록으로 보여준다 별도 저장소를 두지 않는다. 두 잡 테이블에서 끝난 것만 골라 그때그때 만든다. 필드는 web/lib/api.ts 의 ArchiveEntry 와 맞춘다. """ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from models.nol import NolMeta from pipelines.gate import period_text from pipelines.playreel import thumbnail_url from pipelines.runner import DONE from routers.view import UNNAMED from tables.task import PlayreelTask, PosterAliveTask from utils.database import get_session # 완성본 구경은 로그인 없이 연다 router = APIRouter(prefix="/api/archive", tags=["archive"]) def poster_alive_entry(task: PosterAliveTask) -> dict: return { "slug": task.id, "kind": "f1", "name": task.name or UNNAMED, "source": None, "metadata": task.poster_metadata, "narration": task.narration_lines, "poster_url": task.poster_url, "video_url": task.video_url, "thumbnail_url": task.thumbnail_url, "version": None, "credits_used": task.credits_used, "f2_variants": [], "created_at": task.created_at.timestamp(), } def playreel_entry(task: PlayreelTask) -> dict: meta = NolMeta.model_validate(task.nol_meta) if task.nol_meta else None return { "slug": task.id, "kind": "playreel", "name": task.name or UNNAMED, "source": {"url": task.source_url, "goods_id": task.goods_id, "slug": task.slug}, "metadata": None if meta is None else { "event_name": meta.goods_name or "", "date_text": period_text(meta), "place": meta.place_name or "", "category": meta.genre_name or "", "keywords": [], }, "narration": [line["text"] for line in task.narration_lines or []] or None, "poster_url": task.upscaled_poster_url or task.poster_url, "video_url": task.video_url, "thumbnail_url": thumbnail_url(task), "version": task.version, "credits_used": task.credits_used, "f2_variants": [], "created_at": task.created_at.timestamp(), } @router.get("") async def list_entries(session: AsyncSession = Depends(get_session)): entries = [playreel_entry(task) for task in await session.scalars( select(PlayreelTask).where(PlayreelTask.status == DONE))] entries += [poster_alive_entry(task) for task in await session.scalars( select(PosterAliveTask).where(PosterAliveTask.status == DONE))] return sorted(entries, key=lambda entry: entry["created_at"], reverse=True) @router.get("/{slug}") async def get_entry(slug: str, session: AsyncSession = Depends(get_session)): playreel = await session.get(PlayreelTask, slug) if playreel is not None: return playreel_entry(playreel) poster_alive = await session.get(PosterAliveTask, slug) if poster_alive is not None: return poster_alive_entry(poster_alive) raise HTTPException(404, "아카이브에 없는 항목입니다")