fix video scan

This commit is contained in:
Logan Cusano
2025-07-13 19:47:55 -04:00
parent 6f91da738e
commit 0f6b375d92

View File

@@ -3,48 +3,90 @@ import random
from fastapi import APIRouter, Depends, HTTPException, status from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.responses import FileResponse from fastapi.responses import FileResponse
from typing import List from typing import List
from ..models import Video, Vote, VoteCreate from ..models import Vote, VoteCreate, Video
from ..security import is_user, is_admin from ..security import is_admin, is_user
from ..firebase_config import get_db from ..firebase_config import get_db, auth
from dotenv import load_dotenv from dotenv import load_dotenv
load_dotenv() load_dotenv()
router = APIRouter() router = APIRouter()
VIDEO_DIRECTORY = os.environ.get("VIDEO_DIRECTORY") VIDEO_DIRECTORY = os.environ.get("VIDEO_DIRECTORY")
@router.post("/scan", status_code=status.HTTP_201_CREATED, dependencies=[Depends(is_admin)]) @router.post("/scan", status_code=status.HTTP_201_CREATED)
async def scan_videos_directory(): 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 new_videos_count = 0
if not os.path.isdir(VIDEO_DIRECTORY): if not VIDEO_DIRECTORY or not os.path.isdir(VIDEO_DIRECTORY):
raise HTTPException(status_code=500, detail="Video directory not found on server") raise HTTPException(status_code=500, detail="Video directory not found or not configured on server")
db = get_db() 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): for person_name in os.listdir(VIDEO_DIRECTORY):
# ... (directory scanning logic remains the same) ... person_path = os.path.join(VIDEO_DIRECTORY, person_name)
# Simplified for brevity; assuming inner loop logic here if not os.path.isdir(person_path):
file_path = os.path.join(person_name, "some_clip.mp4") # Placeholder continue
# Check if video already exists by file_path # Second-level items can be 'game' directories or clips
existing_videos = videos_ref.where('file_path', '==', file_path).limit(1).get() for item_name in os.listdir(person_path):
if not existing_videos: item_path = os.path.join(person_path, item_name)
new_video_ref = videos_ref.document() game_name = None
video_data = {
"id": new_video_ref.id, "file_path": file_path, "person": person_name, # Structure 1: /person/game/clip.mkv
"game": None, "has_been_voted": False if os.path.isdir(item_path):
} game_name = item_name
new_video_ref.set(video_data) # Third-level items must be clips
new_videos_count += 1 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."} return {"message": f"Scan complete. Added {new_videos_count} new videos."}
@router.get("/vote-next", response_model=Video, dependencies=[Depends(is_user)]) @router.get("/vote-next", response_model=Video)
async def get_random_unvoted_video(): async def get_random_unvoted_video(current_user: dict = Depends(is_user)):
""" """
Retrieves a random, unvoted video document from Firestore. 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"} return {"message": "Vote submitted successfully"}
@router.get("/{video_id}/stream", dependencies=[Depends(is_user)]) @router.get("/{video_id}/stream")
async def stream_video(video_id: str): 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. 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") return FileResponse(full_path, media_type="video/mp4")
@router.get("/votes", response_model=List[Vote], dependencies=[Depends(is_admin)]) @router.get("/votes", response_model=List[Vote])
async def get_all_votes(): async def get_all_votes(current_user: dict = Depends(is_admin)):
""" """
Admin endpoint to retrieve all vote documents from Firestore. Admin endpoint to retrieve all vote documents from Firestore.
""" """