dev #18
@@ -13,6 +13,7 @@ from core.episode_nfo_manager import EpisodeNFOManager
|
||||
from core.nfo_manager import NFOManager
|
||||
from core.path_mapper import PathMapper
|
||||
from clients.sonarr_client import SonarrClient
|
||||
from clients.external_clients import ExternalClientManager
|
||||
from core.logging import _log, convert_utc_to_local
|
||||
|
||||
|
||||
@@ -26,6 +27,7 @@ class TVSeriesProcessor:
|
||||
self.episode_nfo_manager = EpisodeNFOManager()
|
||||
self.path_mapper = path_mapper
|
||||
self.sonarr = sonarr_client
|
||||
self.external_manager = ExternalClientManager()
|
||||
|
||||
def process_series_manual_scan(self, series_path: Path) -> bool:
|
||||
"""Process a TV series during manual scan"""
|
||||
@@ -228,6 +230,13 @@ class TVSeriesProcessor:
|
||||
except Exception as e:
|
||||
_log("ERROR", f"Sonarr API error for S{season_num:02d}E{episode_num:02d}: {e}")
|
||||
|
||||
# Try external APIs for episode airdate
|
||||
_log("INFO", f"Trying external APIs for episode S{season_num:02d}E{episode_num:02d} airdate")
|
||||
aired, source = self._get_episode_airdate_from_external_apis(imdb_id, season_num, episode_num)
|
||||
if aired:
|
||||
dateadded = convert_utc_to_local(aired)
|
||||
return aired, dateadded, source
|
||||
|
||||
_log("ERROR", f"Could not get any date information for S{season_num:02d}E{episode_num:02d}")
|
||||
return aired, dateadded, source
|
||||
|
||||
@@ -251,6 +260,62 @@ class TVSeriesProcessor:
|
||||
|
||||
return None, None
|
||||
|
||||
def _get_episode_airdate_from_external_apis(self, imdb_id: str, season_num: int, episode_num: int) -> Tuple[Optional[str], str]:
|
||||
"""Get episode airdate from external APIs (TMDB, OMDb) as fallback"""
|
||||
# Try TMDB first
|
||||
if self.external_manager.tmdb.enabled:
|
||||
try:
|
||||
_log("DEBUG", f"Trying TMDB for episode S{season_num:02d}E{episode_num:02d} airdate")
|
||||
|
||||
# First convert IMDb to TMDB TV ID
|
||||
tv_search = self.external_manager.tmdb._get(f"/find/{imdb_id}", {"external_source": "imdb_id"})
|
||||
if tv_search and tv_search.get("tv_results"):
|
||||
tv_id = tv_search["tv_results"][0].get("id")
|
||||
if tv_id:
|
||||
_log("DEBUG", f"Found TMDB TV ID {tv_id} for {imdb_id}")
|
||||
|
||||
# Get episode details
|
||||
episode_data = self.external_manager.tmdb._get(f"/tv/{tv_id}/season/{season_num}/episode/{episode_num}")
|
||||
if episode_data and episode_data.get("air_date"):
|
||||
airdate = episode_data["air_date"]
|
||||
# Convert to ISO format with UTC timezone
|
||||
iso_airdate = f"{airdate}T00:00:00Z"
|
||||
_log("INFO", f"Found TMDB airdate for S{season_num:02d}E{episode_num:02d}: {iso_airdate}")
|
||||
return iso_airdate, "tmdb:episode.air_date"
|
||||
except Exception as e:
|
||||
_log("WARNING", f"TMDB episode lookup failed for S{season_num:02d}E{episode_num:02d}: {e}")
|
||||
|
||||
# Try OMDb as fallback
|
||||
if self.external_manager.omdb.enabled:
|
||||
try:
|
||||
_log("DEBUG", f"Trying OMDb for episode S{season_num:02d}E{episode_num:02d} airdate")
|
||||
episode_dates = self.external_manager.omdb.get_tv_season_episodes(imdb_id, season_num)
|
||||
if episode_num in episode_dates:
|
||||
airdate = episode_dates[episode_num]
|
||||
# Convert to ISO format
|
||||
from datetime import datetime, timezone
|
||||
try:
|
||||
# Try to parse OMDb date format (usually DD MMM YYYY)
|
||||
dt = datetime.strptime(airdate, "%d %b %Y").replace(tzinfo=timezone.utc)
|
||||
iso_airdate = dt.isoformat(timespec="seconds")
|
||||
_log("INFO", f"Found OMDb airdate for S{season_num:02d}E{episode_num:02d}: {iso_airdate}")
|
||||
return iso_airdate, "omdb:episode.released"
|
||||
except ValueError:
|
||||
# Try other common formats
|
||||
for fmt in ["%Y-%m-%d", "%d %B %Y"]:
|
||||
try:
|
||||
dt = datetime.strptime(airdate, fmt).replace(tzinfo=timezone.utc)
|
||||
iso_airdate = dt.isoformat(timespec="seconds")
|
||||
_log("INFO", f"Found OMDb airdate for S{season_num:02d}E{episode_num:02d}: {iso_airdate}")
|
||||
return iso_airdate, "omdb:episode.released"
|
||||
except ValueError:
|
||||
continue
|
||||
except Exception as e:
|
||||
_log("WARNING", f"OMDb episode lookup failed for S{season_num:02d}E{episode_num:02d}: {e}")
|
||||
|
||||
_log("WARNING", f"No external API airdate found for S{season_num:02d}E{episode_num:02d}")
|
||||
return None, "no_external_data"
|
||||
|
||||
def _create_series_nfos(self, series_path: Path, imdb_id: str):
|
||||
"""Create tvshow.nfo and season.nfo files"""
|
||||
# Create tvshow.nfo
|
||||
|
||||
Reference in New Issue
Block a user