Files
beavergram/backend/src/api/routers/stories.py
T

49 lines
1.6 KiB
Python

from typing import Annotated
import asyncpg
from dishka.integrations.fastapi import DishkaRoute, FromDishka
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse
from utils.read import peers
from utils.read.models import DEFAULT_LIMIT, Page, StoryView
from utils.storage import ContentAddressedStorage
router = APIRouter(prefix="/api", tags=["stories"], route_class=DishkaRoute)
AccountId = Annotated[int, Query()]
_STORY_MIME = {"photo": "image/jpeg", "video": "video/mp4"}
@router.get("/stories")
async def list_stories(
pool: FromDishka[asyncpg.Pool],
account_id: AccountId,
peer_id: Annotated[int | None, Query()] = None,
limit: Annotated[int, Query()] = DEFAULT_LIMIT,
offset: Annotated[int, Query()] = 0,
) -> list[StoryView]:
return await peers.get_stories(
pool, account_id, Page(limit=limit, offset=offset), peer_id=peer_id
)
@router.get("/stories/{peer_id}/{story_id}/media")
async def serve_story_media(
pool: FromDishka[asyncpg.Pool],
storage: FromDishka[ContentAddressedStorage],
peer_id: int,
story_id: int,
account_id: AccountId,
) -> FileResponse:
story = await peers.get_story(pool, account_id, peer_id, story_id)
if story is None:
raise HTTPException(status_code=404, detail="story not found")
if not story.downloaded or story.storage_key is None:
raise HTTPException(status_code=409, detail="story media not downloaded")
return FileResponse(
storage.url(story.storage_key),
media_type=_STORY_MIME.get(story.media_kind or "", "application/octet-stream"),
)