57 lines
1.9 KiB
Python
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"
|
|
)
|