49 lines
1.6 KiB
Python
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"),
|
|
)
|