+48
-42
@@ -908,66 +908,72 @@ class TVProcessor:
|
|||||||
|
|
||||||
def _get_webhook_episode_date(self, imdb_id: str, season_num: int, episode_num: int, series_metadata: Optional[Dict[str, Any]] = None) -> Tuple[Optional[str], Optional[str], str]:
|
def _get_webhook_episode_date(self, imdb_id: str, season_num: int, episode_num: int, series_metadata: Optional[Dict[str, Any]] = None) -> Tuple[Optional[str], Optional[str], str]:
|
||||||
"""
|
"""
|
||||||
Get episode date for webhook processing with correct priority:
|
Get episode date for webhook processing - avoid treating webhook as gospel.
|
||||||
1. Check existing NFOGuard database entry (preserve previous import dates)
|
|
||||||
2. Check Sonarr import history - if old history exists, prefer air date
|
Logic:
|
||||||
3. If no history, use current time (webhook = new download)
|
1. Check Sonarr import history FIRST (any history = show has existed for a while)
|
||||||
|
2. If ANY import history exists → Use air date (webhook is likely upgrade/rename)
|
||||||
|
3. If NO import history → Use webhook date (truly new show)
|
||||||
|
|
||||||
|
This prevents upgrades from overriding dates for shows you've had for months/years.
|
||||||
"""
|
"""
|
||||||
# Check if we already have this episode in our database (preserve existing dates)
|
# Get aired date and episode ID from Sonarr
|
||||||
existing = self.db.get_episode_date(imdb_id, season_num, episode_num)
|
|
||||||
if existing and existing.get('dateadded'):
|
|
||||||
_log("DEBUG", f"Found existing database entry for S{season_num:02d}E{episode_num:02d}: {existing['dateadded']}")
|
|
||||||
return existing.get('aired'), existing.get('dateadded'), existing.get('source', 'nfoguard:database')
|
|
||||||
|
|
||||||
# Get aired date from Sonarr if available
|
|
||||||
aired = None
|
aired = None
|
||||||
if series_metadata and 'episodes' in series_metadata:
|
|
||||||
episode_data = series_metadata['episodes'].get((season_num, episode_num))
|
|
||||||
if episode_data:
|
|
||||||
aired = episode_data.get('airDate')
|
|
||||||
_log("DEBUG", f"Got aired date from Sonarr for S{season_num:02d}E{episode_num:02d}: {aired}")
|
|
||||||
|
|
||||||
# NEW: Check Sonarr import history to detect if this is an existing show
|
|
||||||
episode_id = None
|
episode_id = None
|
||||||
if series_metadata and 'episodes' in series_metadata:
|
if series_metadata and 'episodes' in series_metadata:
|
||||||
episode_data = series_metadata['episodes'].get((season_num, episode_num))
|
episode_data = series_metadata['episodes'].get((season_num, episode_num))
|
||||||
if episode_data:
|
if episode_data:
|
||||||
|
aired = episode_data.get('airDate')
|
||||||
episode_id = episode_data.get('id')
|
episode_id = episode_data.get('id')
|
||||||
|
_log("DEBUG", f"Got aired date from Sonarr for S{season_num:02d}E{episode_num:02d}: {aired}")
|
||||||
|
|
||||||
|
# STEP 1: Check Sonarr import history FIRST (this is the key check)
|
||||||
|
_log("INFO", f"Checking Sonarr import history for S{season_num:02d}E{episode_num:02d} to detect import vs rename events")
|
||||||
|
|
||||||
if episode_id and hasattr(self, 'sonarr'):
|
if episode_id and hasattr(self, 'sonarr'):
|
||||||
try:
|
try:
|
||||||
|
_log("DEBUG", f"Calling get_episode_import_history for episode_id: {episode_id}")
|
||||||
import_history = self.sonarr.get_episode_import_history(episode_id)
|
import_history = self.sonarr.get_episode_import_history(episode_id)
|
||||||
|
_log("DEBUG", f"Import history result: {import_history}")
|
||||||
|
|
||||||
if import_history:
|
if import_history:
|
||||||
from datetime import datetime as dt
|
# Found actual import event - use this date
|
||||||
from dateutil import parser
|
_log("INFO", f"Found real import event for S{season_num:02d}E{episode_num:02d}: {import_history}")
|
||||||
|
_log("INFO", f"Using first import date (not webhook): {import_history}")
|
||||||
|
return aired, import_history, "sonarr:import_history"
|
||||||
|
else:
|
||||||
|
# No import events found - this means only renames/moves exist in history
|
||||||
|
# The episode was already in Sonarr, just being managed/renamed
|
||||||
|
_log("INFO", f"No import events found for S{season_num:02d}E{episode_num:02d} - only renames/moves in history")
|
||||||
|
|
||||||
# Parse the import history date
|
if aired:
|
||||||
history_date = parser.parse(import_history)
|
_log("INFO", f"Using air date for existing episode (rename-only history): {aired}")
|
||||||
current_time = dt.now(history_date.tzinfo)
|
return aired, aired + "T20:00:00", "airdate"
|
||||||
time_diff = current_time - history_date
|
|
||||||
|
|
||||||
# If import history is more than 24 hours old, this is likely a re-download/upgrade
|
|
||||||
# In this case, prefer air date over webhook date
|
|
||||||
if time_diff.days > 0:
|
|
||||||
_log("INFO", f"Found old import history for S{season_num:02d}E{episode_num:02d} ({import_history}), using air date instead of webhook date")
|
|
||||||
if aired:
|
|
||||||
# Use air date for shows with existing history
|
|
||||||
return aired, aired + "T20:00:00", "airdate"
|
|
||||||
else:
|
|
||||||
# Fallback to import history if no air date
|
|
||||||
return aired, import_history, "sonarr:import_history"
|
|
||||||
else:
|
else:
|
||||||
# Recent import, use the import date
|
_log("DEBUG", f"No air date available for rename-only episode S{season_num:02d}E{episode_num:02d}")
|
||||||
_log("DEBUG", f"Found recent import history for S{season_num:02d}E{episode_num:02d}: {import_history}")
|
|
||||||
return aired, import_history, "sonarr:import_history"
|
|
||||||
except Exception as e:
|
|
||||||
_log("DEBUG", f"Error checking Sonarr import history for S{season_num:02d}E{episode_num:02d}: {e}")
|
|
||||||
|
|
||||||
# For webhook processing with no history, use current time as dateadded (new download)
|
except Exception as e:
|
||||||
|
_log("ERROR", f"Error checking Sonarr import history for S{season_num:02d}E{episode_num:02d}: {e}")
|
||||||
|
import traceback
|
||||||
|
_log("ERROR", traceback.format_exc())
|
||||||
|
else:
|
||||||
|
if not episode_id:
|
||||||
|
_log("DEBUG", f"No episode_id found for S{season_num:02d}E{episode_num:02d}")
|
||||||
|
if not hasattr(self, 'sonarr'):
|
||||||
|
_log("DEBUG", f"No sonarr client available")
|
||||||
|
|
||||||
|
# STEP 2: No import history found - this is likely a genuinely new show
|
||||||
|
# Check our database to avoid duplicates
|
||||||
|
existing = self.db.get_episode_date(imdb_id, season_num, episode_num)
|
||||||
|
if existing and existing.get('dateadded'):
|
||||||
|
_log("INFO", f"Episode S{season_num:02d}E{episode_num:02d} already exists in our database: {existing['dateadded']}")
|
||||||
|
return existing.get('aired'), existing.get('dateadded'), existing.get('source', 'nfoguard:database')
|
||||||
|
|
||||||
|
# STEP 3: Truly new episode - use webhook date
|
||||||
dateadded = datetime.now().isoformat()
|
dateadded = datetime.now().isoformat()
|
||||||
source = "sonarr:webhook"
|
source = "sonarr:webhook"
|
||||||
|
|
||||||
_log("DEBUG", f"Using webhook date for S{season_num:02d}E{episode_num:02d}: {dateadded}")
|
_log("INFO", f"No import history and not in database - using webhook date for genuinely new episode S{season_num:02d}E{episode_num:02d}: {dateadded}")
|
||||||
|
|
||||||
return aired, dateadded, source
|
return aired, dateadded, source
|
||||||
|
|
||||||
|
|||||||
@@ -245,6 +245,24 @@ function updateMoviesTable(data) {
|
|||||||
} else if (movie.source === 'no_valid_date_source') {
|
} else if (movie.source === 'no_valid_date_source') {
|
||||||
dateType = 'No Valid Source';
|
dateType = 'No Valid Source';
|
||||||
dateTypeBadge = 'badge-danger';
|
dateTypeBadge = 'badge-danger';
|
||||||
|
} else if (movie.source && movie.source.toLowerCase().includes('tmdb:theatrical')) {
|
||||||
|
dateType = 'TMDB Theatrical';
|
||||||
|
dateTypeBadge = 'badge-primary';
|
||||||
|
} else if (movie.source && movie.source.toLowerCase().includes('tmdb:digital')) {
|
||||||
|
dateType = 'TMDB Digital';
|
||||||
|
dateTypeBadge = 'badge-primary';
|
||||||
|
} else if (movie.source && movie.source.toLowerCase().includes('tmdb:physical')) {
|
||||||
|
dateType = 'TMDB Physical';
|
||||||
|
dateTypeBadge = 'badge-primary';
|
||||||
|
} else if (movie.source && movie.source.toLowerCase().includes('tmdb:')) {
|
||||||
|
dateType = 'TMDB Release';
|
||||||
|
dateTypeBadge = 'badge-primary';
|
||||||
|
} else if (movie.source && movie.source.toLowerCase().includes('omdb:')) {
|
||||||
|
dateType = 'OMDb Release';
|
||||||
|
dateTypeBadge = 'badge-info';
|
||||||
|
} else if (movie.source && movie.source.toLowerCase().includes('webhook:')) {
|
||||||
|
dateType = 'Webhook/API';
|
||||||
|
dateTypeBadge = 'badge-warning';
|
||||||
}
|
}
|
||||||
|
|
||||||
return `
|
return `
|
||||||
|
|||||||
Reference in New Issue
Block a user