Files
twimg-backend/app/routers/videos.py
2025-07-13 12:56:16 -04:00

116 lines
4.4 KiB
Python

import os
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 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():
"""
Scans the video directory and adds new video documents to the 'videos' collection in Firestore.
"""
new_videos_count = 0
if not os.path.isdir(VIDEO_DIRECTORY):
raise HTTPException(status_code=500, detail="Video directory not found on server")
db = get_db()
videos_ref = db.collection('videos')
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
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():
"""
Retrieves a random, unvoted video document from Firestore.
"""
db = get_db()
videos_stream = db.collection('videos').where('has_been_voted', '==', False).stream()
unvoted_videos = [doc.to_dict() for doc in videos_stream]
if not unvoted_videos:
raise HTTPException(status_code=404, detail="No more videos to vote on!")
random_video_data = random.choice(unvoted_videos)
return Video(**random_video_data)
@router.post("/{video_id}/vote", status_code=status.HTTP_201_CREATED)
async def submit_vote(video_id: str, vote_data: VoteCreate, current_user: dict = Depends(is_user)):
"""
Submits a vote, creating a 'vote' document and updating the video document in Firestore.
"""
db = get_db()
video_ref = db.collection('videos').document(video_id)
video_doc = video_ref.get()
if not video_doc.exists:
raise HTTPException(status_code=404, detail="Video not found")
if video_doc.to_dict().get("has_been_voted"):
raise HTTPException(status_code=400, detail="This video has already been voted on")
new_vote_ref = db.collection('votes').document()
new_vote_ref.set({
"id": new_vote_ref.id, "video_id": video_id, "user_id": current_user['uid'],
"decision": vote_data.decision, "reason": vote_data.reason,
"recommended_game": vote_data.recommended_game
})
update_data = {"has_been_voted": True}
if vote_data.recommended_game:
update_data["game"] = vote_data.recommended_game
video_ref.update(update_data)
return {"message": "Vote submitted successfully"}
@router.get("/{video_id}/stream", dependencies=[Depends(is_user)])
async def stream_video(video_id: str):
"""
Streams a video file from the server based on its Firestore document.
"""
db = get_db()
video_doc = db.collection('videos').document(video_id).get()
if not video_doc.exists:
raise HTTPException(status_code=404, detail="Video not found")
full_path = os.path.join(VIDEO_DIRECTORY, video_doc.to_dict()["file_path"])
if not os.path.exists(full_path):
raise HTTPException(status_code=404, detail="Video file not found on disk")
return FileResponse(full_path, media_type="video/mp4")
@router.get("/votes", response_model=List[Vote], dependencies=[Depends(is_admin)])
async def get_all_votes():
"""
Admin endpoint to retrieve all vote documents from Firestore.
"""
db = get_db()
votes_stream = db.collection('votes').stream()
return [Vote(**doc.to_dict()) for doc in votes_stream]