121 lines
5.7 KiB
Python
121 lines
5.7 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=schemas.Image, status_code=201)
|
|
def upload_celebrity_image(celebrity_id: int, file: 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")
|
|
|
|
file_extension = file.filename.split('.')[-1]
|
|
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)
|
|
|
|
return crud.create_celebrity_image(db=db, celebrity_id=celebrity_id, file_path=unique_filename)
|
|
|
|
@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 |