from plexapi.server import PlexServer import requests PLEX_TOKEN = "gsyJxRUczrTPsyvopP6k" PLEX_SERVER_URL = "http://192.168.50.111:32400" SONARR_API_KEY = "2537de37fded4874ae83da9cf3c14f34" SONARR_SERVER_URL = "http://192.168.50.111:8989" plex = PlexServer(PLEX_SERVER_URL, PLEX_TOKEN) tv_shows = plex.library.section('TV Shows') # List of TV show titles to exclude exclude_shows = ["Stargate SG-1", "Space Sheriff Gavan", "Spider-Man and His Amazing Friends","Super Sentai", "Superman & Lois", "UFO Robot Grendizer","Zorro", "Saved by the Bell: The College Years","Saber Rider and the Star Sheriffs","Prison Break","Power Rangers","The Outer Limits (1995)","MacGyver","Knight Rider", "Chuck","Breaking Bad","Amazing Stories (1985)","Airwolf","The Adventures of Superboy (1988)", "The Amazing Race"] def unmonitor_all_excluded_shows(): for show_title in exclude_shows: show = tv_shows.get(title=show_title) print(f"Unmonitor Title: {show.title}") tvdb_id = get_tvdb_id(show) series_id = get_series_id_from_tvdb(tvdb_id) seasons = show.seasons() for season in seasons: mark_season_unmonitored(series_id, season.index) print(f"All seasons of '{show_title}' have been marked as unmonitored.") # Function to check if the last 3 episodes of a season are watched def last_3_episodes_watched(season): episodes = sorted(season.episodes(), key=lambda ep: ep.index) return all(ep.isWatched for ep in episodes[-3:]) # Function to check if the last 5 episodes of a show are watched, if not unmonitor the show def check_last_5_episodes_and_unmonitor(show): """ Check if the last 5 episodes of a show are watched. If not, mark the entire show as unmonitored in Sonarr. """ try: # Get all episodes from all seasons all_episodes = [] for season in show.seasons(): all_episodes.extend(season.episodes()) # Sort episodes by air date or episode index all_episodes = sorted(all_episodes, key=lambda ep: (ep.seasonNumber, ep.index)) if len(all_episodes) < 5: print(f" āš ļø Show has less than 5 episodes total. Skipping check.") return True # Get the last 5 episodes last_5_episodes = all_episodes[-5:] watched_count = sum(1 for ep in last_5_episodes if ep.isWatched) print(f" šŸ“Š Last 5 episodes: {watched_count}/5 watched") if watched_count >= 1: print(f" āœ… At least 1 of last 5 episodes watched. Continuing normal processing...") return True elif watched_count == 0: print(f" āŒ None of last 5 episodes watched. Marking show as unmonitored...") tvdb_id = get_tvdb_id(show) series_id = get_series_id_from_tvdb(tvdb_id) mark_show_unmonitored(series_id) return False else: print(f" āœ… Show remains monitored.") return True except Exception as e: print(f" āŒ Error checking episodes: {e}") return True # Function to check if Sonarr API is alive and the token is correct def verify_sonarr_api(): url = f"{SONARR_SERVER_URL}/api/v3/system/status?apikey={SONARR_API_KEY}" try: response = requests.get(url) response.raise_for_status() print("Sonarr API is alive and the token is correct.") except requests.exceptions.RequestException as e: print(f"Failed to verify Sonarr API: {e}") raise # Function to get the series ID from the TVDB ID def get_series_id_from_tvdb(tvdb_id): print(f"Fetching series ID for TVDB ID: {tvdb_id}") url = f"{SONARR_SERVER_URL}/api/v3/series/lookup?term=tvdb:{tvdb_id}&apikey={SONARR_API_KEY}" response = requests.get(url) response.raise_for_status() series = response.json() if series: print(f"Series found: {series[0]['title']} (ID: {series[0]['id']})") return series[0]['id'] else: raise ValueError(f"No series found for TVDB ID: {tvdb_id}") def get_series_id_from_tvdb(tvdb_id): url = f"{SONARR_SERVER_URL}/api/v3/series/lookup?term=tvdb:{tvdb_id}&apikey={SONARR_API_KEY}" response = requests.get(url) response.raise_for_status() series = response.json() if series: return series[0]['id'] else: raise ValueError(f"No series found for TVDB ID: {tvdb_id}") # Function to mark a season as unmonitored in Sonarr v4 def mark_season_unmonitored_bak(series_id, season_number): url = f"{SONARR_SERVER_URL}/api/v3/series/{series_id}/season/{season_number}?apikey={SONARR_API_KEY}" response = requests.put(url, json={"monitored": False}) response.raise_for_status() def mark_season_unmonitored(series_id, season_number): url = f"{SONARR_SERVER_URL}/api/v3/series/{series_id}?apikey={SONARR_API_KEY}" response = requests.get(url) # print(f"GET Response Status Code: {response.status_code}") # print(f"GET Response Content: {response.content}") response.raise_for_status() series = response.json() for season in series['seasons']: if season['seasonNumber'] == season_number: if season['monitored'] == False: # print(f"Season {season_number} is already unmonitored for series ID {series_id}. Skipping.") return season['monitored'] = False break response = requests.put(url, json=series) # print(f"PUT Response Status Code: {response.status_code}") # print(f"PUT Response Content: {response.content}") response.raise_for_status() # print(f"Season {season_number} marked as unmonitored for series ID {series_id}.") def mark_show_unmonitored(series_id): """Mark an entire show as unmonitored in Sonarr""" url = f"{SONARR_SERVER_URL}/api/v3/series/{series_id}?apikey={SONARR_API_KEY}" response = requests.get(url) response.raise_for_status() series = response.json() if series['monitored'] == False: print(f" ā„¹ļø Show is already unmonitored in Sonarr. Skipping.") return # Mark the entire series as unmonitored series['monitored'] = False response = requests.put(url, json=series) response.raise_for_status() print(f" āœ… Show marked as unmonitored in Sonarr (Series ID: {series_id})") def get_tvdb_id(show): for guid in reversed(show.guids): if guid.id.startswith("tvdb"): return guid.id.split("://")[1] raise ValueError(f"No series found for TVDB ID: {show.title}") # Verify Sonarr API before proceeding verify_sonarr_api() # Call this function after processing the main shows # unmonitor_all_excluded_shows() # Iterate over all TV shows and apply the deletion rules for show in tv_shows.all(): if show.title not in exclude_shows: #print(f"TV Show: {show}") print(f"\nšŸ“ŗ {show.title}") print(f" šŸ“… Year: {show.year if show.year else 'Unknown'}") print(f" ⭐ Rating: {show.rating if show.rating else 'N/A'}/10") print(f" šŸŽ¬ Seasons: {show.childCount}") print(" " + "─" * 40) # Check if last 5 episodes are watched, if not unmonitor the show if not check_last_5_episodes_and_unmonitor(show): continue # Skip further processing if show was unmonitored #print(f"Summary: {show.summary}") #print(f"Studio: {show.studio}") # print(f"Actors: {', '.join(actor.tag for actor in show.actors)}") #print(f"Views: {show.viewCount}") #print(f"Guid: {show.guid}") #print("="*40) seasons = sorted(show.seasons(), key=lambda s: s.index) if len(seasons) > 1: # Ensure there is a previous season to delete latest_season = seasons[-1] if len(latest_season.episodes()) >= 3 and last_3_episodes_watched(latest_season): # tvdb_id = show.guid.split('/')[-1] tvdb_id = get_tvdb_id(show) print(f"TVDB ID: {tvdb_id}") series_id = get_series_id_from_tvdb(tvdb_id) for season in seasons[:-1]: # Excluding the latest season # Mark the season as unmonitored in Sonarr v4 before deleting mark_season_unmonitored(series_id, season.index) print(f" - Marking Season {season.index} as unmonitored and ready to delete") # season.delete() else: for episode in latest_season.episodes(): if episode.isWatched: print(f" - Watched Episode: {episode.title}")