From 5dceec973d80b8210e2f6ed72352eb784156f086 Mon Sep 17 00:00:00 2001 From: sbcrumb Date: Fri, 10 Oct 2025 10:39:00 -0400 Subject: [PATCH] fix: Add targeted mode for rename webhooks using Sonarr history API - Rename webhooks don't include episodeFile data from Sonarr - Added fallback to query recent episodeFileRenamed events from history - Uses 1-hour window to find most recent rename for targeted processing - Prevents full series processing on single episode renames --- VERSION | 2 +- api/routes.py | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 82bd22f..3d45b5c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.13 +2.0.14 diff --git a/api/routes.py b/api/routes.py index 2da719b..4d4b846 100644 --- a/api/routes.py +++ b/api/routes.py @@ -3,6 +3,7 @@ FastAPI routes for NFOGuard - extracted from main nfoguard.py for modular archit """ import os import json +import requests from pathlib import Path from datetime import datetime, timezone from fastapi import HTTPException, BackgroundTasks, Request @@ -100,6 +101,63 @@ async def sonarr_webhook(request: Request, background_tasks: BackgroundTasks, de else: print(f"DEBUG: Missing season/episode numbers in episodeFile for {webhook.eventType}") + # Special handling for Rename events - Sonarr doesn't include episodeFile for renames + # Try to find recently renamed episodes using Sonarr history API + if not episodes_data and webhook.eventType == "Rename": + print(f"DEBUG: Attempting to find recently renamed episode for series {imdb_id}") + try: + # Get series info from Sonarr to find series ID + series_lookup_url = f"{config.sonarr_base_url}/api/v3/series/lookup?term=imdbid:{imdb_id}" + print(f"DEBUG: Sonarr lookup for rename: {series_lookup_url}") + + response = requests.get(series_lookup_url, headers={"X-Api-Key": config.sonarr_api_key}, timeout=10) + if response.status_code == 200: + series_results = response.json() + if series_results: + series_id = series_results[0].get("id") + print(f"DEBUG: Found series ID {series_id} for rename lookup") + + # Get recent history for episodefilerenamed events (last 24 hours) + from datetime import datetime, timedelta + since_date = (datetime.utcnow() - timedelta(hours=1)).strftime('%Y-%m-%dT%H:%M:%SZ') + history_url = f"{config.sonarr_base_url}/api/v3/history?seriesId={series_id}&eventType=episodeFileRenamed&since={since_date}&pageSize=10" + print(f"DEBUG: Checking recent rename history: {history_url}") + + history_response = requests.get(history_url, headers={"X-Api-Key": config.sonarr_api_key}, timeout=10) + if history_response.status_code == 200: + history_data = history_response.json() + recent_renames = history_data.get("records", []) + print(f"DEBUG: Found {len(recent_renames)} recent rename events") + + if recent_renames: + # Take the most recent rename event + latest_rename = recent_renames[0] + episode_info = latest_rename.get("episode", {}) + season_num = episode_info.get("seasonNumber") + episode_num = episode_info.get("episodeNumber") + + if season_num and episode_num: + episodes_data = [{ + "seasonNumber": season_num, + "episodeNumber": episode_num, + "id": episode_info.get("id"), + "title": episode_info.get("title") + }] + print(f"INFO: Found recently renamed episode from history: S{season_num:02d}E{episode_num:02d}") + else: + print(f"DEBUG: Recent rename event missing season/episode data") + else: + print(f"DEBUG: No recent rename events found in last hour") + else: + print(f"DEBUG: Failed to get rename history: {history_response.status_code}") + else: + print(f"DEBUG: No series found for IMDb {imdb_id}") + else: + print(f"DEBUG: Series lookup failed: {response.status_code}") + except Exception as e: + print(f"DEBUG: Error finding renamed episode: {e}") + # Continue with series processing as fallback + # Force targeted mode for single-episode webhooks to prevent full series processing processing_mode = config.tv_webhook_processing_mode if episodes_data and len(episodes_data) <= 3: # Single episode or small batch