This commit is contained in:
2025-09-09 10:59:45 -04:00
parent 49a2c1788a
commit 4a9aecbc22
12 changed files with 81 additions and 4121 deletions
+56 -3
View File
@@ -287,8 +287,8 @@ class ExternalClientManager:
self.omdb = OMDbClient()
self.jellyseerr = JellyseerrClient()
def get_release_date_by_priority(self, imdb_id: str, priority_order: List[str]) -> Optional[Tuple[str, str]]:
"""Get release date using configurable priority order"""
def get_release_date_by_priority(self, imdb_id: str, priority_order: List[str], enable_smart_validation: bool = True) -> Optional[Tuple[str, str]]:
"""Get release date using configurable priority order with smart date validation"""
# Get all possible release dates
release_options = {}
@@ -326,13 +326,66 @@ class ExternalClientManager:
earliest_jellyseerr = min(jellyseerr_dates)
release_options["digital"] = (earliest_jellyseerr, "jellyseerr:digital")
# Return first available option according to priority
# Smart date validation: Check if priority order makes sense given the actual dates
if enable_smart_validation and len(release_options) > 1:
validated_choice = self._validate_date_choice(release_options, priority_order)
if validated_choice:
return validated_choice
# Return first available option according to priority (fallback behavior)
for priority in priority_order:
if priority in release_options:
return release_options[priority]
return None
def _validate_date_choice(self, release_options: Dict[str, Tuple[str, str]], priority_order: List[str]) -> Optional[Tuple[str, str]]:
"""Validate date choice and prefer theatrical if digital/physical are unreasonably late"""
from datetime import datetime, timezone
import os
# Get configuration for maximum gap (default: 10 years)
max_reasonable_gap_years = int(os.environ.get("MAX_RELEASE_DATE_GAP_YEARS", "10"))
# Parse all available dates
parsed_dates = {}
for release_type, (date_str, source) in release_options.items():
try:
parsed_dates[release_type] = (datetime.fromisoformat(date_str.replace('Z', '+00:00')), source)
except Exception:
continue
if not parsed_dates or "theatrical" not in parsed_dates:
return None # No smart validation possible without theatrical date
theatrical_date, theatrical_source = parsed_dates["theatrical"]
# Check each priority option against theatrical date
for priority in priority_order:
if priority == "theatrical":
continue # Skip theatrical in this validation
if priority in parsed_dates:
priority_date, priority_source = parsed_dates[priority]
# Calculate the gap in years
gap = (priority_date - theatrical_date).days / 365.25
# If the gap is too large, skip this priority and continue
if gap > max_reasonable_gap_years:
print(f"[SMART VALIDATION] {priority} date {priority_date.strftime('%Y-%m-%d')} is {gap:.1f} years after theatrical {theatrical_date.strftime('%Y-%m-%d')}, preferring theatrical")
continue
# This priority option is reasonable, use it
return (priority_date.isoformat(timespec="seconds"), f"{priority_source} (validated)")
# If all priority options are unreasonable, fall back to theatrical
if "theatrical" in release_options:
theatrical_date_str, theatrical_source = release_options["theatrical"]
return (theatrical_date_str, f"{theatrical_source} (smart fallback)")
return None
def get_digital_release_candidates(self, imdb_id: str) -> List[Tuple[str, str]]:
"""Get digital release date candidates from all sources (legacy method)"""
candidates = []