fix video scan
This commit is contained in:
@@ -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.
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user