import json from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form, Request from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from sqlalchemy.orm import Session from sqlalchemy.exc import IntegrityError from core.db import get_db, Poster, PosterLike from core.crypt import decode_jwt, is_admin from core.file import get_upload_dir, save_file, get_poster_dir, generate_file_url from pydantic import BaseModel, EmailStr from datetime import datetime router = APIRouter() security = HTTPBearer() @router.get("/getallposter") async def get_all_poster( db: Session = Depends(get_db), ): posters = db.query(Poster).all() if not posters: raise HTTPException(status_code=404, detail="Постеры не найдены.") return { "posters": [ { "id": poster.id, "title": poster.title, "description": (poster.description[:250] + "...") if poster.description and len(poster.description) > 250 else poster.description, "image": poster.image, "date": poster.date.isoformat() if poster.date else None, "price": poster.price, "like": poster.like, } for poster in posters ] } @router.post("/postercreate") def create_poster( title: str = Form(...), description: str = Form(...), price: int = Form(...), date: datetime = Form(...), file: UploadFile = File(...), db: Session = Depends(get_db), credentials: HTTPAuthorizationCredentials = Depends(security), request: Request = None, ): token = credentials.credentials decoded_data = decode_jwt(token) user_id = decoded_data.get("user_id") if not is_admin(user_id, db): raise HTTPException(status_code=403, detail="Недостаточно прав для выполнения этого действия.") if not file: raise HTTPException(status_code=400, detail="Файл не был загружен.") if not file.filename.endswith(('.jpg', '.jpeg', '.png')): raise HTTPException(status_code=400, detail="Недопустимый формат файла. Допустимые форматы: .jpg, .jpeg, .png.") try: poster_id = db.query(Poster).count() + 1 upload_dir = get_poster_dir(poster_id) file_path = save_file(file, upload_dir) file_url = generate_file_url(request, file_path) new_poster = Poster( title=title, description=description, date=date, price=price, like=0, datecreation=datetime.utcnow(), image=str(file_url), ) db.add(new_poster) db.commit() db.refresh(new_poster) except Exception as e: db.rollback() raise HTTPException(status_code=500, detail=f"Ошибка при загрузке файла: {str(e)}") return {"message": "Постер успешно создан.", "poster": new_poster} @router.post("/posterupdate") def update_poster( poster_id: int = Form(...), title: str = Form(...), description: str = Form(...), price: int = Form(...), date: datetime = Form(...), file: UploadFile = File(None), db: Session = Depends(get_db), credentials: HTTPAuthorizationCredentials = Depends(security), request: Request = None, ): token = credentials.credentials decoded_data = decode_jwt(token) user_id = decoded_data.get("user_id") if not is_admin(user_id, db): raise HTTPException(status_code=403, detail="Недостаточно прав для выполнения этого действия.") poster = db.query(Poster).filter(Poster.id == poster_id).first() if not poster: raise HTTPException(status_code=404, detail="Постер не найден.") if file: if not file.filename.endswith(('.jpg', '.jpeg', '.png')): raise HTTPException(status_code=400, detail="Недопустимый формат файла. Допустимые форматы: .jpg, .jpeg, .png.") try: upload_dir = get_poster_dir(poster_id) file_path = save_file(file, upload_dir) file_url = generate_file_url(request, file_path) poster.image = str(file_url) except Exception as e: db.rollback() raise HTTPException(status_code=500, detail=f"Ошибка при загрузке файла: {str(e)}") poster.title = title poster.description = description poster.date = date poster.price = price try: db.commit() db.refresh(poster) except IntegrityError: db.rollback() raise HTTPException(status_code=400, detail="Ошибка при обновлении постера.") return {"message": "Постер успешно обновлен.", "poster": poster} @router.post("/setlike") def set_like( poster_id: int = Form(...), like: int = Form(...), db: Session = Depends(get_db), credentials: HTTPAuthorizationCredentials = Depends(security), ): token = credentials.credentials decoded_data = decode_jwt(token) user_id = decoded_data.get("user_id") if not user_id: raise HTTPException(status_code=401, detail="Пользователь не авторизован.") # Проверка существования постера poster = db.query(Poster).filter(Poster.id == poster_id).first() if not poster: raise HTTPException(status_code=404, detail="Постер не найден.") # Валидация значения like if like not in [1, -1]: raise HTTPException(status_code=400, detail="Значение like должно быть 1 или -1.") try: # Проверка на существующий лайк existing_like = db.query(PosterLike).filter( PosterLike.poster_id == poster_id, PosterLike.user_id == user_id ).first() if like == 1: # Пользователь хочет поставить лайк if existing_like: # Лайк уже есть - ничего не делаем return { "message": "Вы уже оценили этот постер.", "poster": { "id": poster.id, "title": poster.title, "like": poster.like, "image": poster.image, "price": poster.price, "date": poster.date.isoformat(), "description": poster.description } } else: # Добавляем лайк new_like = PosterLike(poster_id=poster_id, user_id=user_id) db.add(new_like) poster.like += 1 else: # Пользователь хочет убрать лайк if existing_like: # Удаляем запись о лайке db.delete(existing_like) poster.like -= 1 else: # Лайка не было - ничего не делаем return { "message": "Вы еще не ставили лайк этому постеру.", "poster": { "id": poster.id, "title": poster.title, "like": poster.like, "image": poster.image, "price": poster.price, "date": poster.date.isoformat(), "description": poster.description } } db.commit() db.refresh(poster) return { "message": "Лайк успешно обновлен.", "poster": { "id": poster.id, "title": poster.title, "like": poster.like, "image": poster.image, "price": poster.price, "date": poster.date.isoformat(), "description": poster.description } } except IntegrityError as e: db.rollback() print(f"Ошибка IntegrityError: {str(e)}") raise HTTPException(status_code=400, detail="Ошибка при обновлении лайка постера.") except Exception as e: db.rollback() print(f"Неожиданная ошибка: {str(e)}") raise HTTPException(status_code=500, detail=f"Произошла ошибка: {str(e)}") @router.get("/getposter/{poster_id}") async def get_poster( poster_id: int, db: Session = Depends(get_db), ): poster = db.query(Poster).filter(Poster.id == poster_id).first() if not poster: raise HTTPException(status_code=404, detail="Постер не найден.") return { "id": poster.id, "title": poster.title, "description": poster.description, "image": poster.image, "date": poster.date.isoformat() if poster.date else None, "price": poster.price, "like": poster.like, }