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

57 lines
1.9 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.jobs import enqueue
from utils.read.avatars import avatar_by_unique_id, avatar_history, current_avatar
from utils.read.models import AvatarHistoryView
from utils.storage import ContentAddressedStorage
router = APIRouter(prefix="/api/avatars", tags=["avatars"], route_class=DishkaRoute)
@router.get("/{owner_kind}/{owner_id}/history")
async def serve_avatar_history(
pool: FromDishka[asyncpg.Pool],
owner_kind: str, # noqa: ARG001
owner_id: int,
account_id: Annotated[int, Query()],
) -> list[AvatarHistoryView]:
return await avatar_history(pool, account_id, owner_id)
@router.get("/{owner_kind}/{owner_id}")
async def serve_avatar(
pool: FromDishka[asyncpg.Pool],
storage: FromDishka[ContentAddressedStorage],
owner_kind: str,
owner_id: int,
account_id: Annotated[int, Query()],
unique_id: Annotated[str | None, Query()] = None,
) -> FileResponse:
avatar = (
await avatar_by_unique_id(pool, account_id, owner_id, unique_id)
if unique_id is not None
else await current_avatar(pool, account_id, owner_kind, owner_id)
)
if avatar is None:
raise HTTPException(status_code=404, detail="avatar not found")
if not avatar.downloaded or avatar.storage_key is None:
await enqueue(
pool,
account_id,
"fetch_avatar",
{
"owner_kind": owner_kind,
"owner_id": owner_id,
"unique_id": avatar.unique_id,
},
)
raise HTTPException(status_code=409, detail="avatar not downloaded; fetching")
return FileResponse(
storage.url(avatar.storage_key), media_type=avatar.mime or "image/jpeg"
)