web: updates to populate
Local Docker Build (Dev) / build-dev (push) Successful in 6s

This commit is contained in:
2025-11-03 11:03:27 -05:00
parent c91c33e9b2
commit 099ec12560
4 changed files with 138 additions and 7 deletions
+1 -1
View File
@@ -1 +1 @@
2.8.1-populate-fix 2.8.2-populate-fix2
+132 -1
View File
@@ -5,12 +5,16 @@ Provides endpoints for the web-based database manipulation interface
import json import json
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import List, Optional, Dict, Any from typing import List, Optional, Dict, Any
from fastapi import HTTPException, Query from fastapi import HTTPException, Query, BackgroundTasks
from pathlib import Path from pathlib import Path
from api.models import * from api.models import *
# Global status tracking for database population
_populate_status = {"running": False, "completed": False}
def map_source_to_description(source: str) -> str: def map_source_to_description(source: str) -> str:
"""Map technical source codes to user-friendly descriptions""" """Map technical source codes to user-friendly descriptions"""
if not source or source == "no_valid_date_source": if not source or source == "no_valid_date_source":
@@ -1242,6 +1246,111 @@ async def get_episode_date_options(dependencies: dict, imdb_id: str, season: int
} }
async def populate_database(background_tasks: BackgroundTasks, media_type: str = "both", dependencies: dict = None):
"""
Populate NFOGuard database from Radarr/Sonarr sources
Args:
background_tasks: FastAPI background tasks
media_type: Type of media to populate ("movies", "tv", or "both")
dependencies: Dictionary with db, radarr_client, sonarr_client
Returns:
Status message indicating population has started
"""
from core.database_populator import DatabasePopulator
db = dependencies["db"]
config = dependencies["config"]
# Get Radarr and Sonarr clients
from clients.radarr_client import RadarrClient
from clients.sonarr_client import SonarrClient
radarr_client = RadarrClient(config)
sonarr_client = SonarrClient(config)
if media_type not in ["both", "movies", "tv"]:
raise HTTPException(status_code=400, detail="media_type must be 'both', 'movies', or 'tv'")
# Create global status tracking
populate_status = {
"running": True,
"media_type": media_type,
"start_time": datetime.now().isoformat(),
"movies": {"status": "pending", "stats": None},
"tv": {"status": "pending", "stats": None},
"completed": False,
"error": None
}
# Store status globally so it can be queried
global _populate_status
_populate_status = populate_status
async def run_population():
"""Background task to populate the database"""
try:
populator = DatabasePopulator(db, radarr_client, sonarr_client)
print(f"INFO: Starting database population: {media_type}")
if media_type == "movies":
populate_status["movies"]["status"] = "running"
movie_stats = populator.populate_movies()
populate_status["movies"]["status"] = "completed"
populate_status["movies"]["stats"] = movie_stats
print(f"INFO: Movie population completed: {movie_stats}")
elif media_type == "tv":
populate_status["tv"]["status"] = "running"
tv_stats = populator.populate_tv_episodes()
populate_status["tv"]["status"] = "completed"
populate_status["tv"]["stats"] = tv_stats
print(f"INFO: TV population completed: {tv_stats}")
elif media_type == "both":
populate_status["movies"]["status"] = "running"
movie_stats = populator.populate_movies()
populate_status["movies"]["status"] = "completed"
populate_status["movies"]["stats"] = movie_stats
print(f"INFO: Movie population completed: {movie_stats}")
populate_status["tv"]["status"] = "running"
tv_stats = populator.populate_tv_episodes()
populate_status["tv"]["status"] = "completed"
populate_status["tv"]["stats"] = tv_stats
print(f"INFO: TV population completed: {tv_stats}")
populate_status["completed"] = True
populate_status["running"] = False
print("INFO: Database population completed successfully")
except Exception as e:
print(f"ERROR: Database population failed: {e}")
populate_status["error"] = str(e)
populate_status["running"] = False
populate_status["completed"] = True
# Add task to background
background_tasks.add_task(run_population)
print(f"INFO: Database population started for: {media_type}")
return {
"status": "started",
"media_type": media_type,
"message": f"Database population started for {media_type}"
}
async def get_populate_status():
"""Get the current status of database population"""
global _populate_status
if '_populate_status' not in globals():
return {"running": False, "completed": False}
return _populate_status
def register_web_routes(app, dependencies): def register_web_routes(app, dependencies):
"""Register all web API routes with FastAPI app""" """Register all web API routes with FastAPI app"""
from fastapi import Request, Response from fastapi import Request, Response
@@ -1944,6 +2053,28 @@ def register_database_admin_routes(app, dependencies):
"""Get schedule execution history""" """Get schedule execution history"""
return await get_schedule_executions(dependencies, schedule_id) return await get_schedule_executions(dependencies, schedule_id)
# Database population endpoints
print("🔧 DEBUG: Registering /admin/populate-database endpoint...")
@app.post("/admin/populate-database")
async def api_populate_database(request: Request, background_tasks: BackgroundTasks):
"""Populate database from Radarr/Sonarr"""
print(f"🔥 DEBUG: populate-database endpoint called!")
try:
data = await request.json()
media_type = data.get("media_type", "both")
except Exception:
# Fallback to query parameter if JSON parsing fails
media_type = request.query_params.get("media_type", "both")
return await populate_database(background_tasks, media_type, dependencies)
print("✅ DEBUG: /admin/populate-database registered")
@app.get("/api/populate/status")
async def api_populate_status():
"""Get database population status"""
return await get_populate_status()
# Scheduled Scans Functions # Scheduled Scans Functions
+3 -3
View File
@@ -4,7 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NFOGuard - Database Management</title> <title>NFOGuard - Database Management</title>
<link rel="stylesheet" href="/static/css/styles.css?v=2.8.1-populate-fix"> <link rel="stylesheet" href="/static/css/styles.css?v=2.8.2-populate-fix2">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet"> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
</head> </head>
<body> <body>
@@ -12,7 +12,7 @@
<!-- Header --> <!-- Header -->
<header class="app-header"> <header class="app-header">
<div class="header-content"> <div class="header-content">
<h1><i class="fas fa-shield-alt"></i> NFOGuard <span style="font-size: 0.5em; color: #888;">v2.8.1-populate-fix</span></h1> <h1><i class="fas fa-shield-alt"></i> NFOGuard <span style="font-size: 0.5em; color: #888;">v2.8.2-populate-fix2</span></h1>
<p>Database Management & Reporting</p> <p>Database Management & Reporting</p>
</div> </div>
<div class="auth-status" id="auth-status" style="display: none;"> <div class="auth-status" id="auth-status" style="display: none;">
@@ -711,6 +711,6 @@
<!-- Toast Notifications --> <!-- Toast Notifications -->
<div class="toast-container" id="toast-container"></div> <div class="toast-container" id="toast-container"></div>
<script src="/static/js/app.js?v=2.8.1-populate-fix"></script> <script src="/static/js/app.js?v=2.8.2-populate-fix2"></script>
</body> </body>
</html> </html>
+2 -2
View File
@@ -29,7 +29,7 @@ def create_web_app() -> FastAPI:
app = FastAPI( app = FastAPI(
title="NFOGuard Web Interface", title="NFOGuard Web Interface",
description="Web interface for NFOGuard media database management", description="Web interface for NFOGuard media database management",
version="2.7.0-web", version="2.8.2-populate-fix2",
docs_url=None, # Disable docs in production docs_url=None, # Disable docs in production
redoc_url=None redoc_url=None
) )
@@ -94,7 +94,7 @@ def setup_static_files(app: FastAPI) -> None:
"status": "healthy", "status": "healthy",
"service": "nfoguard-web", "service": "nfoguard-web",
"timestamp": time.time(), "timestamp": time.time(),
"version": "2.8.0-web" "version": "2.8.2-populate-fix2"
} }
except Exception as e: except Exception as e:
from fastapi import HTTPException from fastapi import HTTPException