diff --git a/app/routers/videos.py b/app/routers/videos.py index a037dbd..a1adff1 100644 --- a/app/routers/videos.py +++ b/app/routers/videos.py @@ -3,48 +3,90 @@ import random from fastapi import APIRouter, Depends, HTTPException, status from fastapi.responses import FileResponse from typing import List -from ..models import Video, Vote, VoteCreate -from ..security import is_user, is_admin -from ..firebase_config import get_db +from ..models import Vote, VoteCreate, Video +from ..security import is_admin, is_user +from ..firebase_config import get_db, auth from dotenv import load_dotenv load_dotenv() router = APIRouter() VIDEO_DIRECTORY = os.environ.get("VIDEO_DIRECTORY") -@router.post("/scan", status_code=status.HTTP_201_CREATED, dependencies=[Depends(is_admin)]) -async def scan_videos_directory(): +@router.post("/scan", status_code=status.HTTP_201_CREATED) +async def scan_videos_directory(current_user: dict = Depends(is_admin)): """ - Scans the video directory and adds new video documents to the 'videos' collection in Firestore. + Scans the video directory for new clips and adds them to the database. + Handles structures: + - /videos/person/game/clip[.mp4|.mkv] + - /videos/person/clip[.mp4|.mkv] """ new_videos_count = 0 - if not os.path.isdir(VIDEO_DIRECTORY): - raise HTTPException(status_code=500, detail="Video directory not found on server") + if not VIDEO_DIRECTORY or not os.path.isdir(VIDEO_DIRECTORY): + raise HTTPException(status_code=500, detail="Video directory not found or not configured on server") db = get_db() - videos_ref = db.collection('videos') + videos_collection = db.collection('videos') + # Top-level items should be 'person' directories for person_name in os.listdir(VIDEO_DIRECTORY): - # ... (directory scanning logic remains the same) ... - # Simplified for brevity; assuming inner loop logic here - file_path = os.path.join(person_name, "some_clip.mp4") # Placeholder - - # Check if video already exists by file_path - existing_videos = videos_ref.where('file_path', '==', file_path).limit(1).get() - if not existing_videos: - new_video_ref = videos_ref.document() - video_data = { - "id": new_video_ref.id, "file_path": file_path, "person": person_name, - "game": None, "has_been_voted": False - } - new_video_ref.set(video_data) - new_videos_count += 1 - + person_path = os.path.join(VIDEO_DIRECTORY, person_name) + if not os.path.isdir(person_path): + continue + + # Second-level items can be 'game' directories or clips + for item_name in os.listdir(person_path): + item_path = os.path.join(person_path, item_name) + game_name = None + + # Structure 1: /person/game/clip.mkv + if os.path.isdir(item_path): + game_name = item_name + # Third-level items must be clips + for clip_name in os.listdir(item_path): + clip_path = os.path.join(item_path, clip_name) + if os.path.isfile(clip_path) and clip_name.lower().endswith(('.mp4', '.mkv')): + # Construct relative path for DB: person/game/clip.mkv + relative_path = os.path.join(person_name, game_name, clip_name) + + # Check for duplicates + existing = videos_collection.where('file_path', '==', relative_path).limit(1).get() + if not existing: + new_video_ref = videos_collection.document() + video_data = { + "id": new_video_ref.id, + "file_path": relative_path, + "person": person_name, + "game": game_name, + "has_been_voted": False + } + new_video_ref.set(video_data) + new_videos_count += 1 + + # Structure 2: /person/clip.mp4 + elif os.path.isfile(item_path) and item_name.lower().endswith(('.mp4', '.mkv')): + clip_name = item_name + # Construct relative path for DB: person/clip.mp4 + relative_path = os.path.join(person_name, clip_name) + + # Check for duplicates + existing = videos_collection.where('file_path', '==', relative_path).limit(1).get() + if not existing: + new_video_ref = videos_collection.document() + video_data = { + "id": new_video_ref.id, + "file_path": relative_path, + "person": person_name, + "game": None, # No game in this structure + "has_been_voted": False + } + new_video_ref.set(video_data) + new_videos_count += 1 + return {"message": f"Scan complete. Added {new_videos_count} new videos."} -@router.get("/vote-next", response_model=Video, dependencies=[Depends(is_user)]) -async def get_random_unvoted_video(): +@router.get("/vote-next", response_model=Video) +async def get_random_unvoted_video(current_user: dict = Depends(is_user)): """ Retrieves a random, unvoted video document from Firestore. """ @@ -88,8 +130,8 @@ async def submit_vote(video_id: str, vote_data: VoteCreate, current_user: dict = return {"message": "Vote submitted successfully"} -@router.get("/{video_id}/stream", dependencies=[Depends(is_user)]) -async def stream_video(video_id: str): +@router.get("/{video_id}/stream") +async def stream_video(video_id: str, current_user: dict = Depends(is_user)): """ Streams a video file from the server based on its Firestore document. """ @@ -106,8 +148,8 @@ async def stream_video(video_id: str): return FileResponse(full_path, media_type="video/mp4") -@router.get("/votes", response_model=List[Vote], dependencies=[Depends(is_admin)]) -async def get_all_votes(): +@router.get("/votes", response_model=List[Vote]) +async def get_all_votes(current_user: dict = Depends(is_admin)): """ Admin endpoint to retrieve all vote documents from Firestore. """