mirror of
https://github.com/plexguide/Huntarr.git
synced 2026-01-26 13:19:13 -06:00
123 lines
4.5 KiB
Python
123 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Missing Episode Processing
|
|
Handles searching for missing episodes in Sonarr
|
|
"""
|
|
|
|
import random
|
|
import time
|
|
from typing import List
|
|
from utils.logger import logger
|
|
from config import HUNT_MISSING_SHOWS, MONITORED_ONLY, RANDOM_SELECTION
|
|
from api import (
|
|
get_episodes_for_series,
|
|
refresh_series,
|
|
episode_search_episodes,
|
|
get_series_with_missing_episodes
|
|
)
|
|
from state import load_processed_ids, save_processed_id, truncate_processed_list, PROCESSED_MISSING_FILE
|
|
|
|
def process_missing_episodes() -> bool:
|
|
"""
|
|
Process shows that have missing episodes, but respect
|
|
unmonitored seasons/episodes. We'll fetch episodes for each show
|
|
and only search for episodes that are BOTH missing and monitored.
|
|
|
|
Returns:
|
|
True if any processing was done, False otherwise
|
|
"""
|
|
logger.info("=== Checking for Missing Episodes ===")
|
|
|
|
# Skip if HUNT_MISSING_SHOWS is set to 0
|
|
if HUNT_MISSING_SHOWS <= 0:
|
|
logger.info("HUNT_MISSING_SHOWS is set to 0, skipping missing content")
|
|
return False
|
|
|
|
# Get shows that have missing episodes directly - more efficient than checking all shows
|
|
shows_with_missing = get_series_with_missing_episodes()
|
|
if not shows_with_missing:
|
|
logger.info("No shows with missing episodes found.")
|
|
return False
|
|
|
|
logger.info(f"Found {len(shows_with_missing)} shows with missing episodes.")
|
|
|
|
# Optionally filter to only monitored shows (if MONITORED_ONLY==true)
|
|
if MONITORED_ONLY:
|
|
logger.info("MONITORED_ONLY=true => only fully monitored shows.")
|
|
shows_with_missing = [s for s in shows_with_missing if s.get("monitored") is True]
|
|
else:
|
|
logger.info("MONITORED_ONLY=false => all shows, even if unmonitored.")
|
|
|
|
if not shows_with_missing:
|
|
logger.info("No monitored shows with missing episodes found.")
|
|
return False
|
|
|
|
processed_missing_ids = load_processed_ids(PROCESSED_MISSING_FILE)
|
|
shows_processed = 0
|
|
processing_done = False
|
|
|
|
# Optionally randomize show order
|
|
if RANDOM_SELECTION:
|
|
random.shuffle(shows_with_missing)
|
|
|
|
for show in shows_with_missing:
|
|
if shows_processed >= HUNT_MISSING_SHOWS:
|
|
break
|
|
|
|
series_id = show.get("id")
|
|
if not series_id:
|
|
continue
|
|
|
|
# If we already processed this show ID, skip
|
|
if series_id in processed_missing_ids:
|
|
continue
|
|
|
|
show_title = show.get("title", "Unknown Show")
|
|
missing_count = show.get("missingEpisodeCount", 0)
|
|
missing_episodes = show.get("missingEpisodes", [])
|
|
|
|
logger.info(f"Processing '{show_title}' with {missing_count} missing episodes.")
|
|
|
|
# Filter missing episodes to find those that are monitored
|
|
monitored_missing_episodes = [
|
|
ep for ep in missing_episodes
|
|
if ep.get("monitored") is True
|
|
]
|
|
|
|
if not monitored_missing_episodes:
|
|
logger.info(f"No missing monitored episodes found for '{show_title}' — skipping.")
|
|
continue
|
|
|
|
logger.info(f"Found {len(monitored_missing_episodes)} missing monitored episode(s) for '{show_title}'.")
|
|
|
|
# Refresh the series
|
|
logger.info(f" - Refreshing series (ID: {series_id})...")
|
|
refresh_res = refresh_series(series_id)
|
|
if not refresh_res or "id" not in refresh_res:
|
|
logger.warning(f"WARNING: Refresh command failed for {show_title}. Skipping.")
|
|
time.sleep(5)
|
|
continue
|
|
|
|
logger.info(f"Refresh command accepted (ID: {refresh_res['id']}). Waiting 5s...")
|
|
time.sleep(5)
|
|
|
|
# Search specifically for these missing + monitored episodes
|
|
episode_ids = [ep["id"] for ep in monitored_missing_episodes]
|
|
logger.info(f" - Searching for {len(episode_ids)} missing episodes in '{show_title}'...")
|
|
search_res = episode_search_episodes(episode_ids)
|
|
if search_res and "id" in search_res:
|
|
logger.info(f"Search command accepted (ID: {search_res['id']}).")
|
|
processing_done = True
|
|
else:
|
|
logger.warning(f"WARNING: EpisodeSearch failed for show '{show_title}' (ID: {series_id}).")
|
|
continue
|
|
|
|
# Mark as processed
|
|
save_processed_id(PROCESSED_MISSING_FILE, series_id)
|
|
shows_processed += 1
|
|
logger.info(f"Processed {shows_processed}/{HUNT_MISSING_SHOWS} missing shows this cycle.")
|
|
|
|
# Truncate processed list if needed
|
|
truncate_processed_list(PROCESSED_MISSING_FILE)
|
|
|
|
return processing_done |