import os import uuid from typing import List, Optional from fastapi import APIRouter, Depends, File, HTTPException, Query, UploadFile, status from sqlmodel import Session, select from app.config import UPLOAD_DIR from app.database import get_session from app.models.media import Attachment, Media router = APIRouter(tags=["media"]) def _save_webp(data: bytes, max_px: int) -> str: try: from PIL import Image import io img = Image.open(io.BytesIO(data)).convert("RGB") img.thumbnail((max_px, max_px)) name = f"{uuid.uuid4()}.webp" path = os.path.join(UPLOAD_DIR, name) img.save(path, "WEBP", quality=85) return name except Exception: name = f"{uuid.uuid4()}.bin" path = os.path.join(UPLOAD_DIR, name) with open(path, "wb") as f: f.write(data) return name @router.post("/upload") async def upload_file(file: UploadFile = File(...)): os.makedirs(UPLOAD_DIR, exist_ok=True) data = await file.read() ct = file.content_type or "" if ct.startswith("image/"): name = _save_webp(data, 1200) thumb = _save_webp(data, 300) return {"url": f"/uploads/{name}", "thumbnail_url": f"/uploads/{thumb}"} else: name = f"{uuid.uuid4()}_{file.filename}" path = os.path.join(UPLOAD_DIR, name) with open(path, "wb") as f: f.write(data) return {"url": f"/uploads/{name}", "thumbnail_url": None} @router.get("/media/all", response_model=List[Media]) def list_all_media( entity_type: Optional[str] = Query(default=None), session: Session = Depends(get_session), ): """Retourne tous les médias, filtrés optionnellement par entity_type.""" q = select(Media).order_by(Media.created_at.desc()) if entity_type: q = q.where(Media.entity_type == entity_type) return session.exec(q).all() @router.get("/media", response_model=List[Media]) def list_media( entity_type: str = Query(...), entity_id: int = Query(...), session: Session = Depends(get_session), ): return session.exec( select(Media).where( Media.entity_type == entity_type, Media.entity_id == entity_id ) ).all() @router.post("/media", response_model=Media, status_code=status.HTTP_201_CREATED) def create_media(m: Media, session: Session = Depends(get_session)): session.add(m) session.commit() session.refresh(m) return m @router.delete("/media/{id}", status_code=status.HTTP_204_NO_CONTENT) def delete_media(id: int, session: Session = Depends(get_session)): m = session.get(Media, id) if not m: raise HTTPException(404, "Media introuvable") session.delete(m) session.commit() @router.get("/attachments", response_model=List[Attachment]) def list_attachments( entity_type: str = Query(...), entity_id: int = Query(...), session: Session = Depends(get_session), ): return session.exec( select(Attachment).where( Attachment.entity_type == entity_type, Attachment.entity_id == entity_id, ) ).all() @router.post("/attachments", response_model=Attachment, status_code=status.HTTP_201_CREATED) def create_attachment(a: Attachment, session: Session = Depends(get_session)): session.add(a) session.commit() session.refresh(a) return a