web: more nfo scan debugs
Local Docker Build (Dev) / build-dev (push) Successful in 4s

This commit is contained in:
2025-10-26 12:43:12 -04:00
parent 0b27fc1c65
commit 483bcc9d25
+109 -108
View File
@@ -2277,63 +2277,71 @@ def register_routes(app, dependencies: dict):
# - Health checks (/health) # - Health checks (/health)
# #
# Web interface available on separate container port 8081 # Web interface available on separate container port 8081
@app.get("/admin/nfo-repair-scan")
async def _nfo_repair_scan():
return await nfo_repair_scan(dependencies)
async def nfo_repair_scan(dependencies: dict): async def nfo_repair_scan():
"""Scan filesystem for episodes/movies missing dateadded elements in NFO files""" """Scan filesystem for episodes/movies missing dateadded elements in NFO files"""
import os import os
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
logger = dependencies.get("logger") logger = dependencies.get("logger")
config = dependencies.get("config") config = dependencies.get("config")
db = dependencies.get("db") db = dependencies.get("db")
if not logger or not config or not db: if not logger or not config or not db:
raise HTTPException(status_code=500, detail="Dependencies not available") raise HTTPException(status_code=500, detail="Dependencies not available")
logger.info("🔧 Starting NFO repair scan from core container") logger.info("🔧 Starting NFO repair scan from core container")
missing_items = { missing_items = {
"episodes": [], "episodes": [],
"movies": [] "movies": []
} }
try: try:
# Scan episodes # Scan episodes
logger.info("📺 Scanning episodes for missing dateadded elements") logger.info("📺 Scanning episodes for missing dateadded elements")
episode_query = """ episode_query = """
SELECT DISTINCT imdb_id, season, episode, series_name, episode_name, dateadded SELECT DISTINCT imdb_id, season, episode, series_name, episode_name, dateadded
FROM episodes FROM episodes
WHERE dateadded IS NOT NULL WHERE dateadded IS NOT NULL
ORDER BY imdb_id, season, episode ORDER BY imdb_id, season, episode
""" """
with db.get_connection() as conn: with db.get_connection() as conn:
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute(episode_query) cursor.execute(episode_query)
episodes = [dict(row) for row in cursor.fetchall()] episodes = [dict(row) for row in cursor.fetchall()]
logger.info(f"📊 Found {len(episodes)} episodes in database") logger.info(f"📊 Found {len(episodes)} episodes in database")
for episode in episodes: for episode in episodes:
# Build NFO path # Build NFO path
nfo_path = os.path.join( nfo_path = os.path.join(
config.tv_library_path, config.tv_library_path,
episode["series_name"], episode["series_name"],
f"Season {episode['season']:02d}", f"Season {episode['season']:02d}",
f"S{episode['season']:02d}E{episode['episode']:02d}.nfo" f"S{episode['season']:02d}E{episode['episode']:02d}.nfo"
) )
# Check if NFO file exists and has dateadded # Check if NFO file exists and has dateadded
if os.path.exists(nfo_path): if os.path.exists(nfo_path):
try: try:
tree = ET.parse(nfo_path) tree = ET.parse(nfo_path)
root = tree.getroot() root = tree.getroot()
dateadded_elem = root.find("dateadded") dateadded_elem = root.find("dateadded")
if dateadded_elem is None or not dateadded_elem.text: if dateadded_elem is None or not dateadded_elem.text:
missing_items["episodes"].append({
"imdb_id": episode["imdb_id"],
"season": episode["season"],
"episode": episode["episode"],
"series_name": episode["series_name"],
"episode_name": episode["episode_name"],
"dateadded": episode["dateadded"],
"nfo_path": nfo_path
})
except ET.ParseError as e:
logger.warning(f"⚠️ Could not parse NFO file {nfo_path}: {e}")
missing_items["episodes"].append({ missing_items["episodes"].append({
"imdb_id": episode["imdb_id"], "imdb_id": episode["imdb_id"],
"season": episode["season"], "season": episode["season"],
@@ -2341,83 +2349,76 @@ async def nfo_repair_scan(dependencies: dict):
"series_name": episode["series_name"], "series_name": episode["series_name"],
"episode_name": episode["episode_name"], "episode_name": episode["episode_name"],
"dateadded": episode["dateadded"], "dateadded": episode["dateadded"],
"nfo_path": nfo_path "nfo_path": nfo_path,
"error": f"Parse error: {str(e)}"
}) })
except ET.ParseError as e:
logger.warning(f"⚠️ Could not parse NFO file {nfo_path}: {e}")
missing_items["episodes"].append({
"imdb_id": episode["imdb_id"],
"season": episode["season"],
"episode": episode["episode"],
"series_name": episode["series_name"],
"episode_name": episode["episode_name"],
"dateadded": episode["dateadded"],
"nfo_path": nfo_path,
"error": f"Parse error: {str(e)}"
})
# Scan movies # Scan movies
logger.info("🎬 Scanning movies for missing dateadded elements") logger.info("🎬 Scanning movies for missing dateadded elements")
movie_query = """ movie_query = """
SELECT DISTINCT imdb_id, title, dateadded SELECT DISTINCT imdb_id, title, dateadded
FROM movies FROM movies
WHERE dateadded IS NOT NULL WHERE dateadded IS NOT NULL
ORDER BY title ORDER BY title
""" """
with db.get_connection() as conn: with db.get_connection() as conn:
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute(movie_query) cursor.execute(movie_query)
movies = [dict(row) for row in cursor.fetchall()] movies = [dict(row) for row in cursor.fetchall()]
logger.info(f"📊 Found {len(movies)} movies in database") logger.info(f"📊 Found {len(movies)} movies in database")
for movie in movies: for movie in movies:
# Build NFO path # Build NFO path
nfo_path = os.path.join( nfo_path = os.path.join(
config.movie_library_path, config.movie_library_path,
movie["title"], movie["title"],
f"{movie['title']}.nfo" f"{movie['title']}.nfo"
) )
# Check if NFO file exists and has dateadded # Check if NFO file exists and has dateadded
if os.path.exists(nfo_path): if os.path.exists(nfo_path):
try: try:
tree = ET.parse(nfo_path) tree = ET.parse(nfo_path)
root = tree.getroot() root = tree.getroot()
dateadded_elem = root.find("dateadded") dateadded_elem = root.find("dateadded")
if dateadded_elem is None or not dateadded_elem.text: if dateadded_elem is None or not dateadded_elem.text:
missing_items["movies"].append({
"imdb_id": movie["imdb_id"],
"title": movie["title"],
"dateadded": movie["dateadded"],
"nfo_path": nfo_path
})
except ET.ParseError as e:
logger.warning(f"⚠️ Could not parse NFO file {nfo_path}: {e}")
missing_items["movies"].append({ missing_items["movies"].append({
"imdb_id": movie["imdb_id"], "imdb_id": movie["imdb_id"],
"title": movie["title"], "title": movie["title"],
"dateadded": movie["dateadded"], "dateadded": movie["dateadded"],
"nfo_path": nfo_path "nfo_path": nfo_path,
"error": f"Parse error: {str(e)}"
}) })
except ET.ParseError as e:
logger.warning(f"⚠️ Could not parse NFO file {nfo_path}: {e}")
missing_items["movies"].append({
"imdb_id": movie["imdb_id"],
"title": movie["title"],
"dateadded": movie["dateadded"],
"nfo_path": nfo_path,
"error": f"Parse error: {str(e)}"
})
total_missing = len(missing_items["episodes"]) + len(missing_items["movies"]) total_missing = len(missing_items["episodes"]) + len(missing_items["movies"])
logger.info(f"✅ NFO repair scan complete: {total_missing} items missing dateadded elements") logger.info(f"✅ NFO repair scan complete: {total_missing} items missing dateadded elements")
return { return {
"status": "success", "status": "success",
"total_missing": total_missing, "total_missing": total_missing,
"episodes_missing": len(missing_items["episodes"]), "episodes_missing": len(missing_items["episodes"]),
"movies_missing": len(missing_items["movies"]), "movies_missing": len(missing_items["movies"]),
"missing_items": missing_items "missing_items": missing_items
} }
except Exception as e: except Exception as e:
logger.error(f"❌ Error during NFO repair scan: {str(e)}") logger.error(f"❌ Error during NFO repair scan: {str(e)}")
raise HTTPException(status_code=500, detail=f"NFO repair scan failed: {str(e)}") raise HTTPException(status_code=500, detail=f"NFO repair scan failed: {str(e)}")
@app.get("/admin/nfo-repair-scan")
async def _nfo_repair_scan():
return await nfo_repair_scan()
# --------------------------- # ---------------------------
# Core API - No Web Interface # Core API - No Web Interface