This commit is contained in:
Admin9705
2025-04-06 00:27:54 -04:00
parent 7d76b096e6
commit 2a6967dcaa
2 changed files with 92 additions and 28 deletions

63
api.py
View File

@@ -105,4 +105,65 @@ def get_cutoff_unmet_total_pages() -> int:
def get_episodes_for_series(series_id: int) -> Optional[List[Dict]]:
"""Get all episodes for a specific series"""
return sonarr_request(f"episode?seriesId={series_id}", method="GET")
return sonarr_request(f"episode?seriesId={series_id}", method="GET")
def get_missing_episodes(pageSize: int = 1000) -> Optional[Dict]:
"""
GET /api/v3/wanted/missing?pageSize=<pageSize>&includeSeriesInformation=true
Returns JSON with a "records" array of missing episodes and "totalRecords".
"""
endpoint = f"wanted/missing?pageSize={pageSize}&includeSeriesInformation=true"
return sonarr_request(endpoint, method="GET")
def get_series_with_missing_episodes() -> List[Dict]:
"""
Fetch all shows that have missing episodes using the wanted/missing endpoint.
Returns a list of series objects with an additional 'missingEpisodes' field
containing the list of missing episodes for that series.
"""
missing_data = get_missing_episodes()
if not missing_data or "records" not in missing_data:
return []
# Group missing episodes by series ID
series_with_missing = {}
for episode in missing_data.get("records", []):
series_id = episode.get("seriesId")
series_title = None
# Try to get series info from the episode record
if "series" in episode and isinstance(episode["series"], dict):
series_info = episode["series"]
series_title = series_info.get("title")
if series_id not in series_with_missing:
# Initialize the series entry if it doesn't exist
if series_title:
# We have the series info from the episode
series_with_missing[series_id] = {
"id": series_id,
"title": series_title,
"monitored": series_info.get("monitored", False),
"missingEpisodes": [episode]
}
else:
# We need to fetch the series info
series_info = sonarr_request(f"series/{series_id}", method="GET")
if series_info:
series_with_missing[series_id] = {
"id": series_id,
"title": series_info.get("title", "Unknown Show"),
"monitored": series_info.get("monitored", False),
"missingEpisodes": [episode]
}
else:
# Add the episode to the existing series entry
series_with_missing[series_id]["missingEpisodes"].append(episode)
# Convert to list and add count for convenience
result = []
for series_id, series_data in series_with_missing.items():
series_data["missingEpisodeCount"] = len(series_data["missingEpisodes"])
result.append(series_data)
return result

View File

@@ -9,7 +9,12 @@ 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_series, get_episodes_for_series, refresh_series, episode_search_episodes
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:
@@ -28,35 +33,37 @@ def process_missing_episodes() -> bool:
logger.info("HUNT_MISSING_SHOWS is set to 0, skipping missing content")
return False
shows = get_series()
if not shows:
logger.error("ERROR: Unable to retrieve series data from Sonarr.")
# 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 = [s for s in shows if s.get("monitored") is True]
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:
logger.info("No shows to process.")
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
indices = list(range(len(shows)))
# Optionally randomize show order
if RANDOM_SELECTION:
random.shuffle(indices)
random.shuffle(shows_with_missing)
for idx in indices:
for show in shows_with_missing:
if shows_processed >= HUNT_MISSING_SHOWS:
break
show = shows[idx]
series_id = show.get("id")
if not series_id:
continue
@@ -66,26 +73,22 @@ def process_missing_episodes() -> bool:
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.")
# Fetch the episodes for this show
episode_list = get_episodes_for_series(series_id)
if not episode_list:
logger.warning(f"WARNING: Could not retrieve episodes for series ID={series_id}. Skipping.")
continue
# Find all episodes that are monitored and missing a file
missing_monitored_eps = [
e for e in episode_list
if e.get("monitored") is True
and e.get("hasFile") is False
# 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 missing_monitored_eps:
# This show has no missing monitored episodes, skip
logger.info(f"No missing monitored episodes for '{show_title}' — skipping.")
if not monitored_missing_episodes:
logger.info(f"No missing monitored episodes found for '{show_title}' — skipping.")
continue
logger.info(f"Found {len(missing_monitored_eps)} missing monitored episode(s) for '{show_title}'.")
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})...")
@@ -99,7 +102,7 @@ def process_missing_episodes() -> bool:
time.sleep(5)
# Search specifically for these missing + monitored episodes
episode_ids = [ep["id"] for ep in missing_monitored_eps]
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: