from typing import List, Optional from aiogram.types import BufferedInputFile from fastapi import APIRouter, UploadFile, File, Form from fastapi.openapi.models import MediaType from starlette.exceptions import HTTPException from starlette.requests import Request from starlette.responses import Response, JSONResponse from models.Asset import Asset, AssetType from repos.dao import DAO router = APIRouter(prefix="/api/assets", tags=["Assets"]) @router.get("/{asset_id}") async def get_asset(asset_id: str, request: Request) -> Response: dao = request.app.state.dao asset = await dao.assets.get_asset(asset_id) # 2. Проверка на существование if not asset: raise HTTPException(status_code=404, detail="Asset not found") headers = { # Кэшировать на 1 год (31536000 сек) "Cache-Control": "public, max-age=31536000, immutable" } return Response(content=asset.data, media_type="image/png", headers=headers) @router.get("") async def get_assets(request: Request) -> List[Asset]: dao: DAO = request.app.state.dao assets = await dao.assets.get_assets() return assets @router.post("/upload", response_model=Asset) async def upload_asset( request: Request, # Файл обязателен file: UploadFile = File(...), # Остальные поля принимаем как Form-data (не JSON!) name: str = Form(...), type: AssetType = Form(...), linked_char_id: Optional[str] = Form(None) ): """ Загружает файл, отправляет его в ТГ (для получения ID) и сохраняет в БД. """ # 1. Читаем байты файла file_content = await file.read() if not file_content: raise HTTPException(status_code=400, detail="File is empty") # 2. Получаем необходимые зависимости из state bot = request.app.state.bot # Бот нужен, чтобы получить tg_file_id admin_id = request.app.state.admin_id # Куда отправлять файл "на хранение" dao = request.app.state.assets_dao # 3. Отправляем файл в Telegram, чтобы получить tg_doc_file_id # (Это обязательно, так как ваша модель требует этот ID) try: tg_msg = await bot.send_document( chat_id=admin_id, document=BufferedInputFile(file_content, filename=file.filename), caption=f"📥 Uploaded via API: {name}" ) # Получаем ID документа из ответа ТГ tg_doc_id = tg_msg.document.file_id # Если это картинка, можно попытаться достать и photo_id (для превью) # Но send_document обычно возвращает именно документ. except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to upload to Telegram: {e}") # 4. Создаем объект Asset # Pydantic сам подставит created_at и вычислит link new_asset = Asset( name=name, type=type, linked_char_id=linked_char_id, data=file_content, # Сохраняем байты в БД tg_doc_file_id=tg_doc_id # ID из телеграма ) # 5. Сохраняем через DAO saved_asset = await dao.save_asset(new_asset) return saved_asset