Files
anotherboobsdirectory/packages/backend/app/routers/celebrities.py
2025-10-10 20:57:02 +02:00

140 lines
6.6 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, File, UploadFile
from sqlalchemy.orm import Session
from typing import List
import uuid
import shutil
from .. import crud, models, schemas
from ..database import get_db
router = APIRouter(
prefix="/api/celebrities",
tags=["celebrities"],
responses={404: {"description": "Not found"}},
)
@router.post("/", response_model=schemas.Celebrity, status_code=201)
def create_celebrity(celebrity: schemas.CelebrityCreate, db: Session = Depends(get_db)):
# Qui potresti aggiungere un check per vedere se una celebrità con lo stesso nome esiste già
return crud.create_celebrity(db=db, celebrity=celebrity)
@router.get("/", response_model=List[schemas.Celebrity])
def read_celebrities(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
celebrities = crud.get_celebrities(db, skip=skip, limit=limit)
return celebrities
@router.get("/{celebrity_id}", response_model=schemas.Celebrity)
def read_celebrity(celebrity_id: int, db: Session = Depends(get_db)):
db_celebrity = crud.get_celebrity(db, celebrity_id=celebrity_id)
if db_celebrity is None:
raise HTTPException(status_code=404, detail="Celebrity not found")
return db_celebrity
@router.put("/{celebrity_id}", response_model=schemas.Celebrity)
def update_celebrity(celebrity_id: int, celebrity: schemas.CelebrityUpdate, db: Session = Depends(get_db)):
db_celebrity = crud.update_celebrity(db, celebrity_id=celebrity_id, celebrity_update=celebrity)
if db_celebrity is None:
raise HTTPException(status_code=404, detail="Celebrity not found")
return db_celebrity
@router.delete("/{celebrity_id}", response_model=schemas.Celebrity)
def delete_celebrity(celebrity_id: int, db: Session = Depends(get_db)):
db_celebrity = crud.delete_celebrity(db, celebrity_id=celebrity_id)
if db_celebrity is None:
raise HTTPException(status_code=404, detail="Celebrity not found")
return db_celebrity
# --- NUOVI ENDPOINT PER LE IMMAGINI ---
@router.post("/{celebrity_id}/images", response_model=List[schemas.Image], status_code=201)
def upload_celebrity_images(celebrity_id: int, files: List[UploadFile] = File(...), db: Session = Depends(get_db)):
db_celebrity = crud.get_celebrity(db, celebrity_id=celebrity_id)
if db_celebrity is None:
raise HTTPException(status_code=404, detail="Celebrity not found")
created_images = []
for file in files:
try:
file_extension = file.filename.split('.')[-1]
if not file_extension: # Gestisce file senza estensione
file_extension = "jpg" # Default
unique_filename = f"{uuid.uuid4()}.{file_extension}"
file_location = f"uploads/{unique_filename}"
with open(file_location, "wb+") as file_object:
shutil.copyfileobj(file.file, file_object)
db_image = crud.create_celebrity_image(db=db, celebrity_id=celebrity_id, file_path=unique_filename)
created_images.append(db_image)
except Exception as e:
# Se un file fallisce, potremmo voler continuare con gli altri,
# ma per ora lanciamo un'eccezione per l'intero batch.
# In un'app di produzione, si potrebbe restituire una risposta parziale.
print(f"Failed to upload file {file.filename}: {e}")
raise HTTPException(status_code=500, detail=f"Could not upload file: {file.filename}")
if not created_images:
raise HTTPException(status_code=400, detail="No files were successfully uploaded.")
return created_images
@router.post("/{celebrity_id}/images/from-url", response_model=schemas.Image, status_code=201)
async def add_image_from_url(celebrity_id: int, request: schemas.ImageUrlRequest, db: Session = Depends(get_db)):
db_celebrity = crud.get_celebrity(db, celebrity_id=celebrity_id)
if not db_celebrity:
raise HTTPException(status_code=404, detail="Celebrity not found")
url = str(request.url)
try:
async with httpx.AsyncClient() as client:
# Eseguiamo prima una richiesta HEAD per controllare il tipo e la dimensione
head_response = await client.head(url, follow_redirects=True, timeout=10)
head_response.raise_for_status()
content_type = head_response.headers.get('content-type')
if not content_type or not content_type.startswith('image/'):
raise HTTPException(status_code=400, detail="URL does not point to a valid image.")
# Limite di dimensione (es. 10MB)
content_length = int(head_response.headers.get('content-length', 0))
if content_length > 10 * 1024 * 1024:
raise HTTPException(status_code=400, detail="Image size exceeds 10MB limit.")
# Scarica l'immagine
get_response = await client.get(url, follow_redirects=True, timeout=30)
get_response.raise_for_status()
# Determina l'estensione del file
file_extension = content_type.split('/')[-1]
if file_extension == 'jpeg': file_extension = 'jpg'
unique_filename = f"{uuid.uuid4()}.{file_extension}"
file_location = f"uploads/{unique_filename}"
with open(file_location, "wb") as file_object:
file_object.write(get_response.content)
return crud.create_celebrity_image(db=db, celebrity_id=celebrity_id, file_path=unique_filename)
except httpx.RequestError as exc:
raise HTTPException(status_code=400, detail=f"Failed to fetch image from URL: {exc}")
except Exception as e:
raise HTTPException(status_code=500, detail=f"An internal error occurred: {e}")
@router.put("/{celebrity_id}/profile-image", response_model=schemas.Celebrity)
def set_celebrity_profile_image(celebrity_id: int, request: schemas.SetProfileImageRequest, db: Session = Depends(get_db)):
updated_celebrity = crud.set_profile_image(db, celebrity_id=celebrity_id, image_id=request.image_id)
if updated_celebrity is None:
raise HTTPException(status_code=404, detail="Celebrity or Image not found, or image does not belong to celebrity.")
return updated_celebrity
# NOTA: Un approccio pi├╣ RESTful sarebbe /api/images/{image_id} in un router dedicato.
# Per semplicità, lo inseriamo qui.
@router.delete("/images/{image_id}", response_model=schemas.Image)
def delete_image(image_id: int, db: Session = Depends(get_db)):
db_image = crud.delete_image(db, image_id=image_id)
if db_image is None:
raise HTTPException(status_code=404, detail="Image not found")
return db_image