new event ID lookup

This commit is contained in:
2025-09-08 14:38:17 -04:00
parent 134fb0c5c3
commit 157ba581b7
3 changed files with 71 additions and 113 deletions
+5
View File
@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
## [Unreleased] ## [Unreleased]
## [0.3.8] - 2025-09-08
### Changed
- Use Radarr's numeric EventType (3="Imported") for more accurate import date detection
- Simplified history processing logic
## [0.3.7] - 2025-09-08 ## [0.3.7] - 2025-09-08
### Changed ### Changed
- Improved import date detection by tracking grab dates as fallback - Improved import date detection by tracking grab dates as fallback
+1 -1
View File
@@ -1 +1 @@
0.3.7 0.3.8
+43 -90
View File
@@ -11,6 +11,8 @@ from urllib.parse import urlencode, urljoin
from urllib.request import Request as UrlRequest, urlopen from urllib.request import Request as UrlRequest, urlopen
from urllib.error import URLError, HTTPError from urllib.error import URLError, HTTPError
from .logging import _log
# Import path mapper for proper path handling # Import path mapper for proper path handling
try: try:
from ..core.path_mapper import path_mapper from ..core.path_mapper import path_mapper
@@ -26,11 +28,6 @@ except ImportError:
path_mapper = DummyPathMapper() path_mapper = DummyPathMapper()
def _log(level: str, msg: str):
"""Placeholder logging function - replace with your actual logger"""
print(f"[{datetime.now().isoformat()}] {level}: {msg}")
class RadarrClient: class RadarrClient:
"""Enhanced Radarr API client with improved import date detection""" """Enhanced Radarr API client with improved import date detection"""
@@ -274,26 +271,13 @@ class RadarrClient:
except Exception: except Exception:
pass pass
# For import/download events, handle specially # Get imported path from Data field
# Grab date of first download/grab event as fallback
if event_type == "grabbed" and not earliest_grab_date:
earliest_grab_date = datetime.fromisoformat(event["date"].replace("Z", "+00:00")).astimezone(timezone.utc).isoformat(timespec="seconds")
_log("DEBUG", f"Found first grab event at {earliest_grab_date}")
if event_type not in ["moviefileimported", "downloadFolderImported"]:
continue
imported_path = None imported_path = None
# Try different sources for the path try:
if event_type == "moviefileimported": data = json.loads(event.get("data", "{}"))
imported_path = (event.get("data", {}).get("importedPath", "") or imported_path = data.get("importedPath", "").lower()
event.get("data", {}).get("path", "") or except (json.JSONDecodeError, AttributeError):
event.get("importedPath", "") or pass
event.get("sourcePath", "")).lower()
elif event_type == "downloadFolderImported":
imported_path = (event.get("data", {}).get("path", "") or
event.get("sourcePath", "") or
event.get("downloadPath", "")).lower()
if not imported_path: if not imported_path:
continue continue
@@ -302,6 +286,7 @@ class RadarrClient:
movie_title = (movie_info.get("title", "") or "").lower() movie_title = (movie_info.get("title", "") or "").lower()
movie_year = str(movie_info.get("year", "")) movie_year = str(movie_info.get("year", ""))
# First try IMDb ID match
# First try IMDb ID match # First try IMDb ID match
if movie_imdb and ( if movie_imdb and (
f"[imdb-{movie_imdb}]" in imported_path or f"[imdb-{movie_imdb}]" in imported_path or
@@ -440,84 +425,45 @@ class RadarrClient:
"""Get the earliest import date from Radarr history.""" """Get the earliest import date from Radarr history."""
_log("INFO", f"Finding earliest import for movie_id {movie_id}") _log("INFO", f"Finding earliest import for movie_id {movie_id}")
# Get full movie history
earliest_real_import = None earliest_real_import = None
earliest_grab_date = None earliest_grab_date = None
page = 1 page = 1
page_size = 50 page_size = 50
total_events = 0 total_events = 0
# Get full movie history
while True: while True:
# Get page of history # Get page of history
history_data = self._get_movie_history_page(movie_id, page, page_size) history_data = self._get_movie_history_page(movie_id, page, page_size)
if not history_data:
break
# Process events on this page # Process events on this page
for event in history_data: for event in history_data:
event_type = event.get("eventType", "").lower() event_type = event.get("eventType")
if not event_type:
continue
# Track earliest grab date as fallback # Parse event date
if event_type == "grabbed" and not earliest_grab_date: event_date = datetime.fromisoformat(event["date"].replace("Z", "+00:00")).astimezone(timezone.utc).isoformat(timespec="seconds")
earliest_grab_date = datetime.fromisoformat(event["date"].replace("Z", "+00:00")).astimezone(timezone.utc).isoformat(timespec="seconds")
# Track earliest grab date as fallback (EventType 1)
if event_type == 1 and not earliest_grab_date:
earliest_grab_date = event_date
_log("DEBUG", f"Found first grab event at {earliest_grab_date}") _log("DEBUG", f"Found first grab event at {earliest_grab_date}")
# Only process import events
if event_type not in ["moviefileimported", "downloadFolderImported"]:
continue continue
# Try different sources for the path # Look for import events (EventType 3)
imported_path = None if event_type == 3:
if event_type == "moviefileimported": try:
imported_path = (event.get("data", {}).get("importedPath", "") or data = json.loads(event.get("data", "{}"))
event.get("data", {}).get("path", "") or if data.get("importedPath"):
event.get("importedPath", "") or _log("INFO", f"✅ FOUND IMPORT at {event_date}")
event.get("sourcePath", "")).lower() earliest_real_import = event_date
elif event_type == "downloadFolderImported": break
imported_path = (event.get("data", {}).get("path", "") or except (json.JSONDecodeError, AttributeError):
event.get("sourcePath", "") or
event.get("downloadPath", "")).lower()
if not imported_path:
continue continue
movie_imdb = (movie_info.get("imdbId", "") or "").lower()
movie_title = (movie_info.get("title", "") or "").lower()
movie_year = str(movie_info.get("year", ""))
# First try IMDb ID match
if movie_imdb and (
f"[imdb-{movie_imdb}]" in imported_path or
f"[{movie_imdb}]" in imported_path or
movie_imdb in imported_path
):
_log("INFO", f"Found potential IMDb match in {event_type} event: {imported_path}")
date_iso = datetime.fromisoformat(event["date"].replace("Z", "+00:00")).astimezone(timezone.utc).isoformat(timespec="seconds")
_log("INFO", f"✅ FOUND IMPORT at {date_iso}")
earliest_real_import = date_iso
break
# Then try title/year match with fuzzy path cleaning
if movie_title and movie_year:
# Clean strings for comparison by replacing common separators
clean_title = movie_title.replace(" ", ".").replace(":", ".").replace("-", ".").replace("_", ".").lower()
clean_path = imported_path.replace(" ", ".").replace("-", ".").replace("_", ".").replace("[", "").replace("]", "").lower()
# Remove common words for better matching
for word in ["the", "a", "an"]:
clean_title = clean_title.replace(f".{word}.", ".").replace(f"{word}.", "").replace(f".{word}", "")
clean_path = clean_path.replace(f".{word}.", ".").replace(f"{word}.", "").replace(f".{word}", "")
# Look for both title and year in the path
if clean_title in clean_path and movie_year in clean_path:
date_iso = datetime.fromisoformat(event["date"].replace("Z", "+00:00")).astimezone(timezone.utc).isoformat(timespec="seconds")
_log("INFO", f"Found potential title/year match in {event_type} event: {clean_title} ({movie_year})")
_log("INFO", f"✅ FOUND IMPORT at {date_iso}")
earliest_real_import = date_iso
break
# Break if no more pages
if not history_data:
break
# Break if we found an import # Break if we found an import
if earliest_real_import: if earliest_real_import:
break break
@@ -525,15 +471,22 @@ class RadarrClient:
total_events += len(history_data) total_events += len(history_data)
page += 1 page += 1
_log("INFO", f"Processed {total_events} events across {page-1} pages") _log("INFO", f"Processed {total_events} events across {page}")
# Return earliest real import if found
if earliest_real_import: if earliest_real_import:
return earliest_real_import return earliest_real_import
# Fall back to earliest grab date if available
if earliest_grab_date: if earliest_grab_date:
_log("WARNING", f"⚠️ No real imports found, using grab date: {earliest_grab_date}") _log("WARNING", f"⚠️ No EventType 3 (import) found, using grab date: {earliest_grab_date}")
return earliest_grab_date return earliest_grab_date
return None return None
def _get_movie_history_page(self, movie_id: int, page: int, page_size: int) -> List[Dict[str, Any]]:
"""Get a page of movie history."""
data = self._get("/api/v3/history", {
"movieId": str(movie_id),
"page": page,
"pageSize": page_size,
"sortKey": "date",
"sortDirection": "ascending"
})
return data if isinstance(data, list) else data.get("records", [])