from pathlib import Path from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Query from fastapi.responses import FileResponse, StreamingResponse from sqlalchemy.orm import Session from api.schemas import CleanupRequest, VideoCreate, VideoResponse from database.database import getDb from download.download_service import downloadAsync from model.video import Video from notify.notify_clients import notifyClients from stream.stream_service import streamAndSave router = APIRouter(prefix="/videos", tags=["videos"]) @router.post("", status_code=204) async def create(videoData: VideoCreate, db: Session = Depends(getDb)): title = videoData.title youtuber = videoData.youtuber thumbnailUrl = videoData.thumbnailUrl youtubeUrl = videoData.youtubeUrl profileId = videoData.profileId Video.deleteIfExists(db, youtubeUrl, profileId) Video.create(db, title, youtuber, thumbnailUrl, youtubeUrl, profileId) await notifyClients(profileId) @router.get("", response_model=list[VideoResponse]) def getAll(profileId: Optional[int] = Query(None), db: Session = Depends(getDb)): return Video.getAll(db, profileId=profileId) @router.get("/downloaded", response_model=list[VideoResponse]) def getDownloaded(profileId: Optional[int] = Query(None), db: Session = Depends(getDb)): return Video.getDownloaded(db, profileId=profileId) @router.post("/cleanup") def cleanup(request: CleanupRequest, db: Session = Depends(getDb)): profileId = request.profileId excludeIds = request.excludeIds count = Video.deleteNotDownloaded(db, profileId, excludeIds) return {"deleted": count} @router.post("/{videoId}/download") def download(videoId: int, db: Session = Depends(getDb)): video = Video.getById(db, videoId) if not video: raise HTTPException(404, "Video nicht gefunden") if video.filePath: return {"status": "already_downloaded"} downloadAsync(videoId, video.youtubeUrl) return {"status": "download_started"} @router.get("/{videoId}/stream") def stream(videoId: int, db: Session = Depends(getDb)): video = Video.getById(db, videoId) if not video: raise HTTPException(404, "Video nicht gefunden") if not video.filePath: return StreamingResponse(streamAndSave(videoId, video.youtubeUrl), media_type="video/mp4") path = Path(video.filePath) if not path.exists(): raise HTTPException(404, "Videodatei nicht gefunden") return FileResponse(path, media_type="video/mp4") @router.get("/{videoId}/file") def getFile(videoId: int, db: Session = Depends(getDb)): path, video = Video.getValidPath(db, videoId) if not path: raise HTTPException(404, "Video noch nicht heruntergeladen") return FileResponse(path, media_type="video/mp4", filename=f"{video.title}.mp4") @router.delete("/{videoId}/file") def deleteFile(videoId: int, db: Session = Depends(getDb)): if not Video.deleteServerFile(db, videoId): raise HTTPException(404, "Video nicht gefunden") return {"status": "deleted"}