This commit is contained in:
+107
-104
@@ -2278,71 +2278,63 @@ def register_routes(app, dependencies: dict):
|
|||||||
#
|
#
|
||||||
# Web interface available on separate container port 8081
|
# Web interface available on separate container port 8081
|
||||||
@app.get("/admin/nfo-repair-scan")
|
@app.get("/admin/nfo-repair-scan")
|
||||||
async def nfo_repair_scan(dependencies: dict):
|
async def _nfo_repair_scan():
|
||||||
"""Scan filesystem for episodes/movies missing dateadded elements in NFO files"""
|
return await nfo_repair_scan(dependencies)
|
||||||
from nfoguard.utils.db_utils import get_db_connection
|
|
||||||
import os
|
|
||||||
import xml.etree.ElementTree as ET
|
|
||||||
|
|
||||||
logger = dependencies.get("logger")
|
async def nfo_repair_scan(dependencies: dict):
|
||||||
config = dependencies.get("config")
|
"""Scan filesystem for episodes/movies missing dateadded elements in NFO files"""
|
||||||
|
from nfoguard.utils.db_utils import get_db_connection
|
||||||
|
import os
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
if not logger or not config:
|
logger = dependencies.get("logger")
|
||||||
raise HTTPException(status_code=500, detail="Dependencies not available")
|
config = dependencies.get("config")
|
||||||
|
|
||||||
logger.info("🔧 Starting NFO repair scan from core container")
|
if not logger or not config:
|
||||||
|
raise HTTPException(status_code=500, detail="Dependencies not available")
|
||||||
|
|
||||||
missing_items = {
|
logger.info("🔧 Starting NFO repair scan from core container")
|
||||||
"episodes": [],
|
|
||||||
"movies": []
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
missing_items = {
|
||||||
# Get database connection
|
"episodes": [],
|
||||||
db_conn = get_db_connection(config)
|
"movies": []
|
||||||
if not db_conn:
|
}
|
||||||
raise HTTPException(status_code=500, detail="Database connection failed")
|
|
||||||
|
|
||||||
# Scan episodes
|
try:
|
||||||
logger.info("📺 Scanning episodes for missing dateadded elements")
|
# Get database connection
|
||||||
episode_query = """
|
db_conn = get_db_connection(config)
|
||||||
SELECT DISTINCT imdb_id, season, episode, series_name, episode_name, dateadded
|
if not db_conn:
|
||||||
FROM episodes
|
raise HTTPException(status_code=500, detail="Database connection failed")
|
||||||
WHERE dateadded IS NOT NULL
|
|
||||||
ORDER BY imdb_id, season, episode
|
|
||||||
"""
|
|
||||||
|
|
||||||
episodes = db_conn.fetch_all(episode_query)
|
# Scan episodes
|
||||||
logger.info(f"📊 Found {len(episodes)} episodes in database")
|
logger.info("📺 Scanning episodes for missing dateadded elements")
|
||||||
|
episode_query = """
|
||||||
|
SELECT DISTINCT imdb_id, season, episode, series_name, episode_name, dateadded
|
||||||
|
FROM episodes
|
||||||
|
WHERE dateadded IS NOT NULL
|
||||||
|
ORDER BY imdb_id, season, episode
|
||||||
|
"""
|
||||||
|
|
||||||
for episode in episodes:
|
episodes = db_conn.fetch_all(episode_query)
|
||||||
# Build NFO path
|
logger.info(f"📊 Found {len(episodes)} episodes in database")
|
||||||
nfo_path = os.path.join(
|
|
||||||
config.tv_library_path,
|
|
||||||
episode["series_name"],
|
|
||||||
f"Season {episode['season']:02d}",
|
|
||||||
f"S{episode['season']:02d}E{episode['episode']:02d}.nfo"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check if NFO file exists and has dateadded
|
for episode in episodes:
|
||||||
if os.path.exists(nfo_path):
|
# Build NFO path
|
||||||
try:
|
nfo_path = os.path.join(
|
||||||
tree = ET.parse(nfo_path)
|
config.tv_library_path,
|
||||||
root = tree.getroot()
|
episode["series_name"],
|
||||||
dateadded_elem = root.find("dateadded")
|
f"Season {episode['season']:02d}",
|
||||||
|
f"S{episode['season']:02d}E{episode['episode']:02d}.nfo"
|
||||||
|
)
|
||||||
|
|
||||||
if dateadded_elem is None or not dateadded_elem.text:
|
# Check if NFO file exists and has dateadded
|
||||||
missing_items["episodes"].append({
|
if os.path.exists(nfo_path):
|
||||||
"imdb_id": episode["imdb_id"],
|
try:
|
||||||
"season": episode["season"],
|
tree = ET.parse(nfo_path)
|
||||||
"episode": episode["episode"],
|
root = tree.getroot()
|
||||||
"series_name": episode["series_name"],
|
dateadded_elem = root.find("dateadded")
|
||||||
"episode_name": episode["episode_name"],
|
|
||||||
"dateadded": episode["dateadded"],
|
if dateadded_elem is None or not dateadded_elem.text:
|
||||||
"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"],
|
||||||
@@ -2350,70 +2342,81 @@ def register_routes(app, 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
|
||||||
"""
|
"""
|
||||||
|
|
||||||
movies = db_conn.fetch_all(movie_query)
|
movies = db_conn.fetch_all(movie_query)
|
||||||
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)}"
|
||||||
|
})
|
||||||
|
|
||||||
db_conn.close()
|
db_conn.close()
|
||||||
|
|
||||||
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)}")
|
||||||
|
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
# Core API - No Web Interface
|
# Core API - No Web Interface
|
||||||
|
|||||||
Reference in New Issue
Block a user