163 lines
5.3 KiB
Python
163 lines
5.3 KiB
Python
"""
|
|
System API endpoints
|
|
"""
|
|
|
|
import logging
|
|
from typing import Dict, Any, List
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from pydantic import BaseModel
|
|
from sqlalchemy import func
|
|
from sqlalchemy.orm import Session
|
|
|
|
from ..core.database import get_db
|
|
from ..core.scheduler import scheduler_manager
|
|
from ..services.metube_client import MeTubeClient
|
|
from ..models.playlist import PlaylistSubscription
|
|
from ..models.video import VideoRecord, VideoStatus
|
|
from ..core.config import settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
# Pydantic models for API responses
|
|
class SystemStatus(BaseModel):
|
|
"""System status response"""
|
|
total_playlists: int
|
|
active_playlists: int
|
|
total_videos: int
|
|
pending_downloads: int
|
|
active_downloads: int
|
|
completed_downloads: int
|
|
failed_downloads: int
|
|
skipped_downloads: int
|
|
metube_status: Dict[str, Any]
|
|
|
|
|
|
class SchedulerStatus(BaseModel):
|
|
"""Scheduler status response"""
|
|
running: bool
|
|
jobs: List[Dict[str, Any]]
|
|
|
|
|
|
class SyncResponse(BaseModel):
|
|
"""Sync response"""
|
|
status: str
|
|
synced_videos: int
|
|
message: str
|
|
|
|
|
|
@router.get("/status", response_model=SystemStatus)
|
|
async def get_system_status(db: Session = Depends(get_db)):
|
|
"""Get overall system status"""
|
|
try:
|
|
# Get playlist statistics
|
|
total_playlists = db.query(PlaylistSubscription).count()
|
|
active_playlists = db.query(PlaylistSubscription).filter(
|
|
PlaylistSubscription.enabled == True
|
|
).count()
|
|
|
|
# Get video statistics
|
|
total_videos = db.query(VideoRecord).count()
|
|
pending_downloads = db.query(VideoRecord).filter(
|
|
VideoRecord.status == VideoStatus.PENDING
|
|
).count()
|
|
active_downloads = db.query(VideoRecord).filter(
|
|
VideoRecord.status == VideoStatus.DOWNLOADING
|
|
).count()
|
|
completed_downloads = db.query(VideoRecord).filter(
|
|
VideoRecord.status == VideoStatus.COMPLETED
|
|
).count()
|
|
failed_downloads = db.query(VideoRecord).filter(
|
|
VideoRecord.status == VideoStatus.FAILED
|
|
).count()
|
|
skipped_downloads = db.query(VideoRecord).filter(
|
|
VideoRecord.status == VideoStatus.SKIPPED
|
|
).count()
|
|
|
|
# Check MeTube connection
|
|
metube_status = {
|
|
"connected": False,
|
|
"error": None
|
|
}
|
|
|
|
try:
|
|
# Create a temporary MeTube client for health check
|
|
client = MeTubeClient(settings.METUBE_URL)
|
|
await client.connect()
|
|
metube_status["connected"] = await client.health_check()
|
|
await client.disconnect()
|
|
except Exception as e:
|
|
metube_status["error"] = str(e)
|
|
logger.error(f"Error checking MeTube status: {e}")
|
|
|
|
return SystemStatus(
|
|
total_playlists=total_playlists,
|
|
active_playlists=active_playlists,
|
|
total_videos=total_videos,
|
|
pending_downloads=pending_downloads,
|
|
active_downloads=active_downloads,
|
|
completed_downloads=completed_downloads,
|
|
failed_downloads=failed_downloads,
|
|
skipped_downloads=skipped_downloads,
|
|
metube_status=metube_status
|
|
)
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error getting system status: {e}")
|
|
raise HTTPException(status_code=500, detail=f"Error getting system status: {str(e)}")
|
|
|
|
|
|
@router.get("/scheduler/status", response_model=SchedulerStatus)
|
|
async def get_scheduler_status():
|
|
"""Get scheduler status and jobs"""
|
|
try:
|
|
running = scheduler_manager.scheduler and scheduler_manager.scheduler.running
|
|
jobs = scheduler_manager.get_all_jobs() if running else []
|
|
|
|
return SchedulerStatus(
|
|
running=running,
|
|
jobs=jobs
|
|
)
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error getting scheduler status: {e}")
|
|
raise HTTPException(status_code=500, detail=f"Error getting scheduler status: {str(e)}")
|
|
|
|
|
|
@router.post("/sync-metube", response_model=SyncResponse)
|
|
async def sync_with_metube(db: Session = Depends(get_db)):
|
|
"""Manually sync video status with MeTube"""
|
|
try:
|
|
from ..services.video_service import VideoService
|
|
|
|
service = VideoService(db)
|
|
synced_count = await service.sync_with_metube()
|
|
|
|
return SyncResponse(
|
|
status="ok",
|
|
synced_videos=synced_count,
|
|
message=f"Successfully synced {synced_count} videos with MeTube"
|
|
)
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error syncing with MeTube: {e}")
|
|
raise HTTPException(status_code=500, detail=f"Error syncing with MeTube: {str(e)}")
|
|
|
|
|
|
@router.get("/health")
|
|
async def health_check():
|
|
"""Simple health check endpoint"""
|
|
try:
|
|
# Basic health check - just return OK
|
|
# More detailed health checks are done in the main app's health endpoint
|
|
return {
|
|
"status": "healthy",
|
|
"service": "playlist-monitor",
|
|
"version": "0.1.0"
|
|
}
|
|
except Exception as e:
|
|
logger.error(f"Health check failed: {e}")
|
|
raise HTTPException(status_code=503, detail="Service unhealthy") |