Spaces:
Building
Building
from fastapi import APIRouter, UploadFile, Form, HTTPException, Depends | |
from sqlalchemy.ext.asyncio import AsyncSession | |
from sqlalchemy.future import select | |
from app.database import get_db | |
from app.models import VideoUpload | |
from .utils.s3 import upload_to_s3, delete_s3_key, key_from_url | |
from app.auth import get_current_user | |
from app.models import User | |
from sqlalchemy import delete as sqldelete | |
import uuid | |
import os | |
router = APIRouter() | |
# Accept any video file | |
ALLOWED_VIDEO_MIME_TYPES = { | |
"video/mp4", | |
"video/x-matroska", # mkv | |
"video/quicktime", # mov | |
"video/x-msvideo", # avi | |
"video/webm", | |
"video/mpeg", | |
} | |
async def upload_video( | |
user_id: int = Form(...), | |
file: UploadFile = Form(...), | |
db: AsyncSession = Depends(get_db), | |
): | |
if file.content_type not in ALLOWED_VIDEO_MIME_TYPES: | |
raise HTTPException( | |
status_code=400, detail=f"Unsupported file type: {file.content_type}" | |
) | |
try: | |
uid = str(uuid.uuid4()) | |
s3_key = f"videos/{uid}/{file.filename}" | |
video_url = upload_to_s3(file, s3_key) | |
new_video = VideoUpload( | |
user_id=user_id, | |
video_url=video_url, | |
pdf_url="", # will be set after analysis | |
status="pending", | |
) | |
db.add(new_video) | |
await db.commit() | |
await db.refresh(new_video) | |
return {"status": "uploaded", "video_url": video_url, "video_id": new_video.id} | |
except Exception as e: | |
await db.rollback() | |
raise HTTPException(status_code=500, detail=str(e)) | |
async def delete_uploaded_video(video_id: int, | |
current_user: User = Depends(get_current_user), | |
db: AsyncSession = Depends(get_db)): | |
result = await db.execute(select(VideoUpload).where(VideoUpload.id == video_id)) | |
video: VideoUpload | None = result.scalar_one_or_none() | |
if not video: | |
raise HTTPException(status_code=404, detail="Video not found") | |
if video.user_id != current_user.id: | |
raise HTTPException(status_code=403, detail="Not allowed") | |
# Delete from S3 if present | |
v_key = key_from_url(video.video_url) | |
p_key = key_from_url(video.pdf_url) | |
try: | |
if v_key: | |
delete_s3_key(v_key) | |
if p_key: | |
delete_s3_key(p_key) | |
except Exception: | |
pass | |
# Delete DB row | |
try: | |
await db.delete(video) | |
await db.commit() | |
return {"message": "Upload deleted"} | |
except Exception as e: | |
await db.rollback() | |
raise HTTPException(status_code=500, detail=str(e)) | |
async def delete_uploaded_pdf(video_id: int, | |
current_user: User = Depends(get_current_user), | |
db: AsyncSession = Depends(get_db)): | |
result = await db.execute(select(VideoUpload).where(VideoUpload.id == video_id)) | |
video: VideoUpload | None = result.scalar_one_or_none() | |
if not video: | |
raise HTTPException(status_code=404, detail="Upload not found") | |
if video.user_id != current_user.id: | |
raise HTTPException(status_code=403, detail="Not allowed") | |
p_key = key_from_url(video.pdf_url) | |
if not p_key: | |
return {"message": "No PDF to delete"} | |
try: | |
delete_s3_key(p_key) | |
except Exception: | |
pass | |
# Clear pdf_url field | |
video.pdf_url = "" | |
try: | |
await db.commit() | |
await db.refresh(video) | |
return {"message": "PDF deleted", "video_id": video.id} | |
except Exception as e: | |
await db.rollback() | |
raise HTTPException(status_code=500, detail=str(e)) | |