fix(radarr): improve event type parsing and grab event validation
- Fix string-based event type parsing (grabbed, downloadFolderImported, etc.) - Filter grab events to only count actual downloads with metadata - Fix JSON parsing errors for dict-type event data - Enhanced chronological processing for accurate import date detection - Validate grab events require sourceTitle or indexer info Fixes issue where library addition events were mistaken for download grabs, ensuring only real download timestamps are used for
This commit is contained in:
+15
-1
@@ -4,7 +4,21 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.4.0] - 2025-09-08
|
||||
# Changelog
|
||||
|
||||
## [0.4.1] - 2025-01-09
|
||||
|
||||
### Fixed
|
||||
- **Radarr Client**: Fixed event type parsing for string-based event types (grabbed, downloadFolderImported, etc.)
|
||||
- **Radarr Client**: Improved grab event detection to filter out library addition events and only count actual download grabs
|
||||
- **Radarr Client**: Fixed JSON parsing errors when handling event data that's already a dictionary
|
||||
- **Radarr Client**: Enhanced validation of grab events to require download metadata (sourceTitle or indexer)
|
||||
|
||||
### Improved
|
||||
- **Radarr Client**: Better chronological event processing to find earliest actual download dates
|
||||
- **Radarr Client**: More accurate import date detection by validating grab events have real download information
|
||||
|
||||
## [0.4.0] - 2025-01-08
|
||||
### Changed
|
||||
- Switched to using Radarr's numeric event types for more reliable import detection
|
||||
- Added constants for EVENT_TYPE_GRABBED (1), IMPORTED (3), etc.
|
||||
|
||||
+30
-14
@@ -278,39 +278,55 @@ class RadarrClient:
|
||||
_log("DEBUG", f"Unknown event type: {event_type}")
|
||||
continue
|
||||
|
||||
# Check for grab events (type 1)
|
||||
# Check for grab events (type 1) - but validate it's a real download
|
||||
if event_type == self.EVENT_TYPE_GRABBED and not first_grab:
|
||||
if event.get("date"):
|
||||
try:
|
||||
first_grab = datetime.fromisoformat(event["date"].replace("Z", "+00:00")).astimezone(timezone.utc).isoformat(timespec="seconds")
|
||||
_log("DEBUG", f"Found grab event (type {self.EVENT_TYPE_GRABBED}) at {first_grab}")
|
||||
except Exception:
|
||||
pass
|
||||
# Get event data to check if this is a real grab with download info
|
||||
event_data = event.get("data", {})
|
||||
if isinstance(event_data, str):
|
||||
try:
|
||||
event_data = json.loads(event_data)
|
||||
except (json.JSONDecodeError, AttributeError):
|
||||
event_data = {}
|
||||
|
||||
# Track the first grab event we find
|
||||
if event_type == self.EVENT_TYPE_GRABBED and not first_grab:
|
||||
if event.get("date"):
|
||||
try:
|
||||
# Check if this grab has actual download/indexer info
|
||||
source_title = event_data.get("sourceTitle", "")
|
||||
indexer = event_data.get("indexer", "")
|
||||
|
||||
# Only count grabs that have actual download metadata
|
||||
if source_title or indexer:
|
||||
first_grab = datetime.fromisoformat(event["date"].replace("Z", "+00:00")).astimezone(timezone.utc).isoformat(timespec="seconds")
|
||||
_log("DEBUG", f"Found first grab event at {first_grab}")
|
||||
_log("DEBUG", f"Found real grab event with source '{source_title}' from '{indexer}' at {first_grab}")
|
||||
else:
|
||||
_log("DEBUG", f"Skipping grab event without download info at {event.get('date')}")
|
||||
except Exception:
|
||||
pass
|
||||
continue
|
||||
|
||||
# Only process import events (type 3)
|
||||
if event_type != self.EVENT_TYPE_IMPORTED:
|
||||
continue
|
||||
|
||||
# Get imported path from event data
|
||||
imported_path = None
|
||||
event_data = event.get("data", {})
|
||||
|
||||
# Handle both string and dict data
|
||||
if isinstance(event_data, str):
|
||||
try:
|
||||
data = json.loads(event.get("data", "{}"))
|
||||
imported_path = data.get("importedPath", "").lower()
|
||||
event_data = json.loads(event_data)
|
||||
except (json.JSONDecodeError, AttributeError) as e:
|
||||
_log("DEBUG", f"Failed to get imported path: {e}")
|
||||
_log("DEBUG", f"Failed to parse event data JSON: {e}")
|
||||
continue
|
||||
elif not isinstance(event_data, dict):
|
||||
continue
|
||||
|
||||
imported_path = event_data.get("importedPath", "")
|
||||
if not imported_path:
|
||||
continue
|
||||
|
||||
imported_path = imported_path.lower()
|
||||
|
||||
movie_imdb = (movie_info.get("imdbId", "") or "").lower()
|
||||
movie_title = (movie_info.get("title", "") or "").lower()
|
||||
movie_year = str(movie_info.get("year", ""))
|
||||
|
||||
Reference in New Issue
Block a user