"""Public (unauthenticated) endpoint for sharing generated shorts. Resolves a share_token to video metadata and a presigned download URL. No auth dependency — anyone with the token can access the short. """ from __future__ import annotations import logging from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload from database import get_session from models import GeneratedShort, HighlightCandidate, ShortStatus, SourceVideo logger = logging.getLogger("chrysopedia.shorts_public") router = APIRouter(prefix="/public/shorts", tags=["shorts-public"]) class PublicShortResponse(BaseModel): """Public metadata for a shared short — no internal IDs exposed.""" format_preset: str width: int height: int duration_secs: float | None creator_name: str highlight_title: str download_url: str @router.get("/{share_token}", response_model=PublicShortResponse) async def get_public_short( share_token: str, db: AsyncSession = Depends(get_session), ): """Resolve a share token to short metadata and a presigned download URL.""" stmt = ( select(GeneratedShort) .where(GeneratedShort.share_token == share_token) .options( selectinload(GeneratedShort.highlight_candidate) .selectinload(HighlightCandidate.key_moment), selectinload(GeneratedShort.highlight_candidate) .selectinload(HighlightCandidate.source_video) .selectinload(SourceVideo.creator), ) ) result = await db.execute(stmt) short = result.scalar_one_or_none() if short is None: raise HTTPException(status_code=404, detail="Short not found") if short.status != ShortStatus.complete: raise HTTPException(status_code=404, detail="Short not found") if not short.minio_object_key: raise HTTPException( status_code=500, detail="Short is complete but has no storage key", ) highlight = short.highlight_candidate key_moment = highlight.key_moment source_video = highlight.source_video creator = source_video.creator from minio_client import generate_download_url try: url = generate_download_url(short.minio_object_key) except Exception as exc: logger.error( "Failed to generate download URL for share_token=%s: %s", share_token, exc, ) raise HTTPException( status_code=503, detail="Failed to generate download URL", ) from exc return PublicShortResponse( format_preset=short.format_preset.value, width=short.width, height=short.height, duration_secs=short.duration_secs, creator_name=creator.name, highlight_title=key_moment.title, download_url=url, )