updates
This commit is contained in:
+132
-24
@@ -348,23 +348,28 @@ class RadarrClient:
|
||||
imdb_id = imdb_id if imdb_id.startswith("tt") else f"tt{imdb_id}"
|
||||
_log("DEBUG", f"Radarr API: Looking up movie by IMDb ID: {imdb_id}")
|
||||
|
||||
# Radarr's IMDb filtering is unreliable, so fetch all movies and filter client-side
|
||||
res = self._get("/api/v3/movie")
|
||||
if isinstance(res, list):
|
||||
# Filter results to find exact IMDb ID match
|
||||
# Try direct movie search with IMDb filter (even if unreliable)
|
||||
res = self._get("/api/v3/movie", {"imdbId": imdb_id})
|
||||
if isinstance(res, list) and len(res) > 0:
|
||||
# CRITICAL: Validate that returned movie actually matches requested IMDb ID
|
||||
for movie in res:
|
||||
if movie.get("imdbId") == imdb_id:
|
||||
movie_imdb = movie.get("imdbId", "").lower()
|
||||
if movie_imdb == imdb_id.lower():
|
||||
_log("DEBUG", f"Radarr API: Found exact match: {movie.get('title')} (ID: {movie.get('id')})")
|
||||
return movie
|
||||
_log("WARNING", f"Radarr API: Searched {len(res)} movies but none match IMDb {imdb_id}")
|
||||
|
||||
# Fallback: Try lookup endpoint
|
||||
# Log the mismatch for debugging
|
||||
returned_ids = [m.get("imdbId", "None") for m in res[:3]] # Show first 3
|
||||
_log("ERROR", f"Radarr API returned WRONG movies for {imdb_id}! Got: {returned_ids}")
|
||||
_log("DEBUG", f"Will reject mismatched results and try lookup endpoint")
|
||||
|
||||
# Fallback: Try lookup endpoint which might be more reliable
|
||||
res = self._get("/api/v3/movie/lookup/imdb", {"imdbId": imdb_id})
|
||||
if isinstance(res, dict) and res.get("id") and res.get("imdbId") == imdb_id:
|
||||
if isinstance(res, dict) and res.get("imdbId", "").lower() == imdb_id.lower():
|
||||
_log("DEBUG", f"Radarr API: Found movie via lookup: {res.get('title')} (ID: {res.get('id')})")
|
||||
return res
|
||||
|
||||
_log("DEBUG", f"Radarr API: No movie found for IMDb ID: {imdb_id}")
|
||||
_log("WARNING", f"Radarr API: No valid movie found for IMDb ID: {imdb_id}")
|
||||
return None
|
||||
|
||||
def movie_files(self, movie_id: int) -> List[Dict[str, Any]]:
|
||||
@@ -394,6 +399,8 @@ class RadarrClient:
|
||||
page = 1
|
||||
page_size = 1000
|
||||
|
||||
_log("INFO", f"Starting history lookup for movie_id {movie_id}")
|
||||
|
||||
while True:
|
||||
data = self._get("/api/v3/history", {
|
||||
"movieId": movie_id, "page": page, "pageSize": page_size,
|
||||
@@ -419,11 +426,23 @@ class RadarrClient:
|
||||
_log("WARNING", f"Stopped pagination at page 10 for movie_id {movie_id} - may have missed some history")
|
||||
break
|
||||
|
||||
_log("DEBUG", f"Found {len(all_items)} total history items across {page} pages for movie_id {movie_id}")
|
||||
items = all_items
|
||||
_log("INFO", f"Found {len(all_items)} total history items across {page} pages for movie_id {movie_id}")
|
||||
|
||||
# Log ALL events first for debugging
|
||||
_log("INFO", f"=== COMPLETE HISTORY ANALYSIS for movie_id {movie_id} ===")
|
||||
for i, it in enumerate(all_items):
|
||||
ev = (it.get("eventType") or it.get("type") or "").lower()
|
||||
date_str = it.get("date", "NO_DATE")
|
||||
event_data = it.get('data', {})
|
||||
source_path = event_data.get('sourcePath', '') or event_data.get('path', '') or event_data.get('sourceTitle', '')
|
||||
|
||||
_log("INFO", f"Event #{i+1}: type='{ev}', date='{date_str}', sourcePath='{source_path}'")
|
||||
_log("DEBUG", f" Full data: {json.dumps(event_data, indent=2) if event_data else 'No data'}")
|
||||
|
||||
first_grab = None
|
||||
for it in items:
|
||||
earliest_real_import = None
|
||||
|
||||
for it in all_items:
|
||||
ev = (it.get("eventType") or it.get("type") or "").lower()
|
||||
date_iso = None
|
||||
if it.get("date"):
|
||||
@@ -432,8 +451,6 @@ class RadarrClient:
|
||||
except Exception:
|
||||
date_iso = None
|
||||
|
||||
_log("DEBUG", f"History event: type='{ev}', date={date_iso}, data={it.get('data', {})}")
|
||||
|
||||
# Expanded event types for Radarr v4/v5 compatibility
|
||||
import_events = {
|
||||
"downloadfolderimported", "moviefileimported", "imported",
|
||||
@@ -443,27 +460,41 @@ class RadarrClient:
|
||||
if ev in import_events:
|
||||
# Check if this is a real import (from downloads) vs existing file rename
|
||||
event_data = it.get('data', {})
|
||||
source_path = event_data.get('sourcePath', '') or event_data.get('path', '')
|
||||
source_path = event_data.get('sourcePath', '') or event_data.get('path', '') or event_data.get('sourceTitle', '')
|
||||
|
||||
_log("INFO", f"Analyzing import event '{ev}' with source: '{source_path}'")
|
||||
|
||||
# Real imports typically come from download folders
|
||||
is_real_import = any(download_indicator in source_path.lower() for download_indicator in [
|
||||
download_indicators = [
|
||||
'/downloads/', '/download/', '/completed/', '/nzbs/', '/torrents/',
|
||||
'sabnzbd', 'nzbget', 'deluge', 'qbittorrent', 'transmission'
|
||||
])
|
||||
'sabnzbd', 'nzbget', 'deluge', 'qbittorrent', 'transmission',
|
||||
'/radarr/', 'completed/' # Add more specific patterns
|
||||
]
|
||||
|
||||
is_real_import = any(indicator in source_path.lower() for indicator in download_indicators)
|
||||
|
||||
_log("INFO", f"Import analysis: is_real_import={is_real_import}, date={date_iso}")
|
||||
|
||||
if is_real_import and date_iso:
|
||||
_log("INFO", f"Found REAL import event '{ev}' from downloads at {date_iso} (source: {source_path})")
|
||||
return date_iso
|
||||
_log("INFO", f"✅ FOUND REAL IMPORT EVENT '{ev}' from downloads at {date_iso} (source: {source_path})")
|
||||
if earliest_real_import is None:
|
||||
earliest_real_import = date_iso
|
||||
elif date_iso:
|
||||
_log("DEBUG", f"Skipping non-import event '{ev}' (rename/existing file) from {source_path}")
|
||||
if ev == "grabbed" and date_iso and first_grab is None:
|
||||
_log("INFO", f"⚠️ Skipping non-download import '{ev}' from {source_path}")
|
||||
|
||||
elif ev == "grabbed" and date_iso and first_grab is None:
|
||||
first_grab = date_iso
|
||||
_log("INFO", f"Found grab event at {date_iso}")
|
||||
|
||||
if earliest_real_import:
|
||||
_log("INFO", f"✅ USING EARLIEST REAL IMPORT DATE: {earliest_real_import}")
|
||||
return earliest_real_import
|
||||
|
||||
if first_grab:
|
||||
_log("INFO", f"Using grab date {first_grab} as fallback for movie_id {movie_id}")
|
||||
_log("INFO", f"⚠️ Using grab date {first_grab} as fallback for movie_id {movie_id}")
|
||||
return first_grab
|
||||
|
||||
_log("WARNING", f"No real import/grab events found for movie_id {movie_id} (only renames/existing files)")
|
||||
_log("ERROR", f"❌ No real import/grab events found for movie_id {movie_id}")
|
||||
return None
|
||||
|
||||
# ---------------------------
|
||||
@@ -1650,6 +1681,83 @@ async def get_stats():
|
||||
async def get_batch_status():
|
||||
return batcher.get_status()
|
||||
|
||||
@app.get("/debug/movie/{imdb_id}")
|
||||
async def debug_movie_import_date(imdb_id: str):
|
||||
"""Debug endpoint to analyze movie import date detection"""
|
||||
try:
|
||||
if not imdb_id.startswith("tt"):
|
||||
imdb_id = f"tt{imdb_id}"
|
||||
|
||||
_log("INFO", f"=== DEBUG MOVIE IMPORT DATE: {imdb_id} ===")
|
||||
|
||||
if not (config.radarr_url and config.radarr_api_key):
|
||||
return {
|
||||
"error": "Radarr not configured",
|
||||
"imdb_id": imdb_id,
|
||||
"radarr_configured": False
|
||||
}
|
||||
|
||||
# Create Radarr client
|
||||
rc = RadarrClient(config.radarr_url, config.radarr_api_key, config.radarr_timeout, config.radarr_retries)
|
||||
|
||||
# Look up movie
|
||||
movie_obj = rc.movie_by_imdb(imdb_id)
|
||||
if not movie_obj:
|
||||
return {
|
||||
"error": f"Movie not found in Radarr for IMDb ID {imdb_id}",
|
||||
"imdb_id": imdb_id,
|
||||
"radarr_configured": True,
|
||||
"movie_found": False
|
||||
}
|
||||
|
||||
movie_id = movie_obj.get("id")
|
||||
movie_title = movie_obj.get("title")
|
||||
|
||||
_log("INFO", f"Found movie: {movie_title} (Radarr ID: {movie_id})")
|
||||
|
||||
# Get import history with detailed logging
|
||||
import_date = rc.earliest_import_event(movie_id)
|
||||
|
||||
# Get movie files for additional context
|
||||
movie_files = rc.movie_files(movie_id)
|
||||
file_dates = []
|
||||
for f in movie_files:
|
||||
file_dates.append({
|
||||
"id": f.get("id"),
|
||||
"relativePath": f.get("relativePath"),
|
||||
"dateAdded": f.get("dateAdded"),
|
||||
"quality": f.get("quality", {}).get("quality", {}).get("name", "Unknown")
|
||||
})
|
||||
|
||||
return {
|
||||
"imdb_id": imdb_id,
|
||||
"radarr_configured": True,
|
||||
"movie_found": True,
|
||||
"movie_title": movie_title,
|
||||
"movie_id": movie_id,
|
||||
"detected_import_date": import_date,
|
||||
"movie_files": file_dates,
|
||||
"analysis": {
|
||||
"import_date_found": import_date is not None,
|
||||
"expected_july_7_2025": "2025-07-07" in (import_date or ""),
|
||||
"method_used": "radarr:history.import" if import_date else "none"
|
||||
},
|
||||
"debug_info": {
|
||||
"radarr_url": config.radarr_url,
|
||||
"movie_digital_release": movie_obj.get("digitalRelease"),
|
||||
"movie_in_cinemas": movie_obj.get("inCinemas"),
|
||||
"movie_physical_release": movie_obj.get("physicalRelease")
|
||||
}
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
_log("ERROR", f"Debug endpoint error for {imdb_id}: {e}")
|
||||
return {
|
||||
"error": str(e),
|
||||
"imdb_id": imdb_id,
|
||||
"success": False
|
||||
}
|
||||
|
||||
# ---------------------------
|
||||
# Manual scans
|
||||
# ---------------------------
|
||||
|
||||
Reference in New Issue
Block a user