playreel/backend/routers/archive.py

82 lines
3.0 KiB
Python

"""/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, "아카이브에 없는 항목입니다")