This commit is contained in:
+163
-23
@@ -2579,6 +2579,9 @@ def register_routes(app, dependencies: dict):
|
|||||||
print("🔍 Looking up dateadded values from database for missing items...")
|
print("🔍 Looking up dateadded values from database for missing items...")
|
||||||
|
|
||||||
# Enhance episodes with database data
|
# Enhance episodes with database data
|
||||||
|
episodes_with_dates = 0
|
||||||
|
episodes_missing_db = 0
|
||||||
|
|
||||||
for episode in missing_items["episodes"]:
|
for episode in missing_items["episodes"]:
|
||||||
if episode["imdb_id"] != "unknown":
|
if episode["imdb_id"] != "unknown":
|
||||||
try:
|
try:
|
||||||
@@ -2595,12 +2598,47 @@ def register_routes(app, dependencies: dict):
|
|||||||
if result:
|
if result:
|
||||||
episode["dateadded"] = result["dateadded"]
|
episode["dateadded"] = result["dateadded"]
|
||||||
episode["source"] = result.get("source", "database")
|
episode["source"] = result.get("source", "database")
|
||||||
|
episodes_with_dates += 1
|
||||||
|
print(f"✅ Found database date for {episode['imdb_id']} S{episode['season']:02d}E{episode['episode']:02d}: {result['dateadded']}")
|
||||||
else:
|
else:
|
||||||
print(f"⚠️ No database entry for {episode['imdb_id']} S{episode['season']:02d}E{episode['episode']:02d}")
|
episodes_missing_db += 1
|
||||||
|
# Try to find other episodes from same series to estimate date
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT dateadded, season, episode
|
||||||
|
FROM episodes
|
||||||
|
WHERE imdb_id = %s AND dateadded IS NOT NULL
|
||||||
|
ORDER BY season DESC, episode DESC
|
||||||
|
LIMIT 3
|
||||||
|
""", (episode["imdb_id"],))
|
||||||
|
|
||||||
|
similar_episodes = cursor.fetchall()
|
||||||
|
if similar_episodes:
|
||||||
|
latest_date = similar_episodes[0]["dateadded"]
|
||||||
|
episode["dateadded"] = latest_date
|
||||||
|
episode["source"] = f"estimated_from_series_latest"
|
||||||
|
print(f"🔮 Estimated date for {episode['imdb_id']} S{episode['season']:02d}E{episode['episode']:02d} from latest episode: {latest_date}")
|
||||||
|
else:
|
||||||
|
# Use NFO file modification time as fallback
|
||||||
|
try:
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
if os.path.exists(episode["nfo_path"]):
|
||||||
|
file_mtime = os.path.getmtime(episode["nfo_path"])
|
||||||
|
file_date = datetime.fromtimestamp(file_mtime)
|
||||||
|
episode["dateadded"] = file_date
|
||||||
|
episode["source"] = "nfo_file_mtime"
|
||||||
|
print(f"📅 Using NFO file date for {episode['imdb_id']} S{episode['season']:02d}E{episode['episode']:02d}: {file_date}")
|
||||||
|
else:
|
||||||
|
print(f"❌ No fallback date available for {episode['imdb_id']} S{episode['season']:02d}E{episode['episode']:02d}")
|
||||||
|
except Exception as fallback_error:
|
||||||
|
print(f"⚠️ Fallback date lookup failed for {episode['imdb_id']}: {fallback_error}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ Database lookup failed for episode {episode['imdb_id']}: {e}")
|
print(f"⚠️ Database lookup failed for episode {episode['imdb_id']}: {e}")
|
||||||
|
|
||||||
# Enhance movies with database data
|
# Enhance movies with database data
|
||||||
|
movies_with_dates = 0
|
||||||
|
movies_missing_db = 0
|
||||||
|
|
||||||
for movie in missing_items["movies"]:
|
for movie in missing_items["movies"]:
|
||||||
if movie["imdb_id"] != "unknown":
|
if movie["imdb_id"] != "unknown":
|
||||||
try:
|
try:
|
||||||
@@ -2617,11 +2655,34 @@ def register_routes(app, dependencies: dict):
|
|||||||
if result:
|
if result:
|
||||||
movie["dateadded"] = result["dateadded"]
|
movie["dateadded"] = result["dateadded"]
|
||||||
movie["source"] = result.get("source", "database")
|
movie["source"] = result.get("source", "database")
|
||||||
|
movies_with_dates += 1
|
||||||
|
print(f"✅ Found database date for movie {movie['imdb_id']}: {result['dateadded']}")
|
||||||
else:
|
else:
|
||||||
print(f"⚠️ No database entry for movie {movie['imdb_id']}")
|
movies_missing_db += 1
|
||||||
|
# Use NFO file modification time as fallback for movies
|
||||||
|
try:
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
if os.path.exists(movie["nfo_path"]):
|
||||||
|
file_mtime = os.path.getmtime(movie["nfo_path"])
|
||||||
|
file_date = datetime.fromtimestamp(file_mtime)
|
||||||
|
movie["dateadded"] = file_date
|
||||||
|
movie["source"] = "nfo_file_mtime"
|
||||||
|
print(f"📅 Using NFO file date for movie {movie['imdb_id']}: {file_date}")
|
||||||
|
else:
|
||||||
|
print(f"❌ No fallback date available for movie {movie['imdb_id']}")
|
||||||
|
except Exception as fallback_error:
|
||||||
|
print(f"⚠️ Fallback date lookup failed for movie {movie['imdb_id']}: {fallback_error}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ Database lookup failed for movie {movie['imdb_id']}: {e}")
|
print(f"⚠️ Database lookup failed for movie {movie['imdb_id']}: {e}")
|
||||||
|
|
||||||
|
# Print summary statistics
|
||||||
|
total_episodes = len(missing_items["episodes"])
|
||||||
|
total_movies = len(missing_items["movies"])
|
||||||
|
print(f"📊 Database lookup summary:")
|
||||||
|
print(f" Episodes: {episodes_with_dates}/{total_episodes} found in DB, {episodes_missing_db} missing from DB")
|
||||||
|
print(f" Movies: {movies_with_dates}/{total_movies} found in DB, {movies_missing_db} missing from DB")
|
||||||
|
|
||||||
total_missing = len(missing_items["episodes"]) + len(missing_items["movies"])
|
total_missing = len(missing_items["episodes"]) + len(missing_items["movies"])
|
||||||
print(f"✅ NFO repair scan complete: {total_missing} items missing dateadded elements")
|
print(f"✅ NFO repair scan complete: {total_missing} items missing dateadded elements")
|
||||||
|
|
||||||
@@ -2707,18 +2768,52 @@ def register_routes(app, dependencies: dict):
|
|||||||
# Write back to file
|
# Write back to file
|
||||||
tree.write(nfo_path, encoding='utf-8', xml_declaration=True)
|
tree.write(nfo_path, encoding='utf-8', xml_declaration=True)
|
||||||
|
|
||||||
fixed_count += 1
|
# VERIFY the write was successful by re-reading the file
|
||||||
results.append({
|
try:
|
||||||
"type": "episode",
|
verify_tree = ET.parse(nfo_path)
|
||||||
"imdb_id": episode["imdb_id"],
|
verify_root = verify_tree.getroot()
|
||||||
"season": episode["season"],
|
verify_dateadded = verify_root.find("dateadded")
|
||||||
"episode": episode["episode"],
|
|
||||||
"nfo_path": nfo_path,
|
|
||||||
"dateadded": nfo_dateadded,
|
|
||||||
"status": "fixed"
|
|
||||||
})
|
|
||||||
|
|
||||||
print(f"✅ Fixed episode {episode['imdb_id']} S{episode['season']:02d}E{episode['episode']:02d}")
|
if verify_dateadded is not None and verify_dateadded.text and verify_dateadded.text.strip():
|
||||||
|
# Verification successful
|
||||||
|
fixed_count += 1
|
||||||
|
results.append({
|
||||||
|
"type": "episode",
|
||||||
|
"imdb_id": episode["imdb_id"],
|
||||||
|
"season": episode["season"],
|
||||||
|
"episode": episode["episode"],
|
||||||
|
"nfo_path": nfo_path,
|
||||||
|
"dateadded": nfo_dateadded,
|
||||||
|
"verified_dateadded": verify_dateadded.text.strip(),
|
||||||
|
"status": "fixed_and_verified"
|
||||||
|
})
|
||||||
|
print(f"✅ Fixed and verified episode {episode['imdb_id']} S{episode['season']:02d}E{episode['episode']:02d}")
|
||||||
|
else:
|
||||||
|
# Verification failed - dateadded missing after write
|
||||||
|
failed_count += 1
|
||||||
|
results.append({
|
||||||
|
"type": "episode",
|
||||||
|
"imdb_id": episode["imdb_id"],
|
||||||
|
"season": episode["season"],
|
||||||
|
"episode": episode["episode"],
|
||||||
|
"nfo_path": nfo_path,
|
||||||
|
"dateadded": nfo_dateadded,
|
||||||
|
"status": "write_failed_verification"
|
||||||
|
})
|
||||||
|
print(f"❌ Write verification FAILED for episode {episode['imdb_id']} S{episode['season']:02d}E{episode['episode']:02d} - dateadded not found after write")
|
||||||
|
except Exception as verify_error:
|
||||||
|
# Verification failed due to parse error
|
||||||
|
failed_count += 1
|
||||||
|
results.append({
|
||||||
|
"type": "episode",
|
||||||
|
"imdb_id": episode["imdb_id"],
|
||||||
|
"season": episode["season"],
|
||||||
|
"episode": episode["episode"],
|
||||||
|
"nfo_path": nfo_path,
|
||||||
|
"status": "verification_parse_error",
|
||||||
|
"error": str(verify_error)
|
||||||
|
})
|
||||||
|
print(f"❌ Verification parse error for episode {episode['imdb_id']} S{episode['season']:02d}E{episode['episode']:02d}: {verify_error}")
|
||||||
else:
|
else:
|
||||||
failed_count += 1
|
failed_count += 1
|
||||||
print(f"❌ NFO file not found: {nfo_path}")
|
print(f"❌ NFO file not found: {nfo_path}")
|
||||||
@@ -2759,17 +2854,49 @@ def register_routes(app, dependencies: dict):
|
|||||||
# Write back to file
|
# Write back to file
|
||||||
tree.write(nfo_path, encoding='utf-8', xml_declaration=True)
|
tree.write(nfo_path, encoding='utf-8', xml_declaration=True)
|
||||||
|
|
||||||
fixed_count += 1
|
# VERIFY the write was successful by re-reading the file
|
||||||
results.append({
|
try:
|
||||||
"type": "movie",
|
verify_tree = ET.parse(nfo_path)
|
||||||
"imdb_id": movie["imdb_id"],
|
verify_root = verify_tree.getroot()
|
||||||
"title": movie["title"],
|
verify_dateadded = verify_root.find("dateadded")
|
||||||
"nfo_path": nfo_path,
|
|
||||||
"dateadded": nfo_dateadded,
|
|
||||||
"status": "fixed"
|
|
||||||
})
|
|
||||||
|
|
||||||
print(f"✅ Fixed movie {movie['imdb_id']} ({movie['title']})")
|
if verify_dateadded is not None and verify_dateadded.text and verify_dateadded.text.strip():
|
||||||
|
# Verification successful
|
||||||
|
fixed_count += 1
|
||||||
|
results.append({
|
||||||
|
"type": "movie",
|
||||||
|
"imdb_id": movie["imdb_id"],
|
||||||
|
"title": movie["title"],
|
||||||
|
"nfo_path": nfo_path,
|
||||||
|
"dateadded": nfo_dateadded,
|
||||||
|
"verified_dateadded": verify_dateadded.text.strip(),
|
||||||
|
"status": "fixed_and_verified"
|
||||||
|
})
|
||||||
|
print(f"✅ Fixed and verified movie {movie['imdb_id']} ({movie['title']})")
|
||||||
|
else:
|
||||||
|
# Verification failed - dateadded missing after write
|
||||||
|
failed_count += 1
|
||||||
|
results.append({
|
||||||
|
"type": "movie",
|
||||||
|
"imdb_id": movie["imdb_id"],
|
||||||
|
"title": movie["title"],
|
||||||
|
"nfo_path": nfo_path,
|
||||||
|
"dateadded": nfo_dateadded,
|
||||||
|
"status": "write_failed_verification"
|
||||||
|
})
|
||||||
|
print(f"❌ Write verification FAILED for movie {movie['imdb_id']} ({movie['title']}) - dateadded not found after write")
|
||||||
|
except Exception as verify_error:
|
||||||
|
# Verification failed due to parse error
|
||||||
|
failed_count += 1
|
||||||
|
results.append({
|
||||||
|
"type": "movie",
|
||||||
|
"imdb_id": movie["imdb_id"],
|
||||||
|
"title": movie["title"],
|
||||||
|
"nfo_path": nfo_path,
|
||||||
|
"status": "verification_parse_error",
|
||||||
|
"error": str(verify_error)
|
||||||
|
})
|
||||||
|
print(f"❌ Verification parse error for movie {movie['imdb_id']} ({movie['title']}): {verify_error}")
|
||||||
else:
|
else:
|
||||||
failed_count += 1
|
failed_count += 1
|
||||||
print(f"❌ NFO file not found: {nfo_path}")
|
print(f"❌ NFO file not found: {nfo_path}")
|
||||||
@@ -2780,11 +2907,24 @@ def register_routes(app, dependencies: dict):
|
|||||||
|
|
||||||
print(f"✅ NFO repair fix complete: {fixed_count} fixed, {failed_count} failed")
|
print(f"✅ NFO repair fix complete: {fixed_count} fixed, {failed_count} failed")
|
||||||
|
|
||||||
|
# Final summary with detailed statistics
|
||||||
|
verification_summary = {
|
||||||
|
"fixed_and_verified": sum(1 for r in results if r.get("status") == "fixed_and_verified"),
|
||||||
|
"write_failed_verification": sum(1 for r in results if r.get("status") == "write_failed_verification"),
|
||||||
|
"verification_parse_error": sum(1 for r in results if r.get("status") == "verification_parse_error")
|
||||||
|
}
|
||||||
|
|
||||||
|
print(f"📊 Final summary: {fixed_count} fixed, {failed_count} failed")
|
||||||
|
print(f" ✅ Verified successful: {verification_summary['fixed_and_verified']}")
|
||||||
|
print(f" ❌ Write verification failed: {verification_summary['write_failed_verification']}")
|
||||||
|
print(f" ⚠️ Verification parse errors: {verification_summary['verification_parse_error']}")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": "success",
|
"status": "success",
|
||||||
"total_processed": total_episodes + total_movies,
|
"total_processed": total_episodes + total_movies,
|
||||||
"fixed_count": fixed_count,
|
"fixed_count": fixed_count,
|
||||||
"failed_count": failed_count,
|
"failed_count": failed_count,
|
||||||
|
"verification_summary": verification_summary,
|
||||||
"results": results[:20] # Show first 20 for UI
|
"results": results[:20] # Show first 20 for UI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user