import os from dotenv import load_dotenv from plexapi.server import PlexServer import requests import logging # Load environment variables from .env file load_dotenv() LOG_ENABLED= False PLEX_TOKEN = os.getenv("PLEX_TOKEN") PLEX_SERVER_URL = os.getenv("PLEX_SERVER_URL") SONARR_API_KEY = os.getenv("SONARR_API_KEY") SONARR_SERVER_URL = os.getenv("SONARR_SERVER_URL") TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN") TELEGRAM_CHAT_ID = os.getenv("TELEGRAM_CHAT_ID") # Set up logging if LOG_ENABLED: logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') else: logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') #logging.getLogger().setLevel(logging.CRITICAL) PLEX_TOKEN = "uZn42JMVkQpyb_duFsvT" 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)"] def unmonitor_all_excluded_shows(): for show_title in exclude_shows: show = tv_shows.get(title=show_title) if LOG_ENABLED: logging.info(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) logging.info(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 first 3 episodes of a season are watched def first_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 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() if LOG_ENABLED: logging.info("Sonarr API is alive and the token is correct.") except requests.exceptions.RequestException as e: logging.error(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): 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: if LOG_ENABLED: logging.info(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}") # Function to mark a season as unmonitored in Sonarr v4 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) response.raise_for_status() series = response.json() for season in series['seasons']: if season['seasonNumber'] == season_number: season['monitored'] = False response = requests.put(url, json=series) response.raise_for_status() logging.info(f"Season {season_number} marked as unmonitored for 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 TVDB ID found for show: {show.title}") def get_total_seasons(show): return len(show.seasons()) def verify_total_seasons_from_tvdb(show, series_id): url = f"{SONARR_SERVER_URL}/api/v3/series/{series_id}?apikey={SONARR_API_KEY}" response = requests.get(url) response.raise_for_status() series_data = response.json() # logging.info(series_data) season_count = series_data.get('statistics', {}).get('seasonCount') if LOG_ENABLED: logging.info(f"Total seasons for {show.title} from TVDB ({season_count}) instead Available on Plex ({len(show.seasons())})") # 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(): try: if show.title not in exclude_shows: logging.info(f"Processing TV Show: {show.title}") # Verify total seasons from TVDB tvdb_id = get_tvdb_id(show) series_id = get_series_id_from_tvdb(tvdb_id) verify_total_seasons_from_tvdb(show, series_id) 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 first_3_episodes_watched(latest_season): logging.info(f"TVDB ID: {tvdb_id}") for season in seasons[:-1]: # Excluding the latest season mark_season_unmonitored(series_id, season.index) logging.info(f" - Marking Season {season.index} as unmonitored and ready to delete") else: for episode in latest_season.episodes(): if episode.isWatched: logging.info(f" - Watched Episode: {episode.title} (Episode Number: {episode.episodeNumber})") except Exception as e: logging.error(f"Error processing show '{show.title}': {e}") #break # Send a report message with the list of TV series and movies being processed """ report_message = "TV Series and Movies Being Processed:\n\n" report_message += "* Number of Shows: {}\n".format(len(tv_shows.all())) for show in tv_shows.all(): report_message += "- {} (Last Season)\n".format(show.title) logging.info("Sending Telegram message with the report...") response = requests.post( "https://api.telegram.org/bot{}/sendMessage".format(TELEGRAM_BOT_TOKEN), data={ 'chat_id': TELEGRAM_CHAT_ID, 'text': report_message } ) if response.status_code == 200: logging.info("Telegram message sent successfully.") else: logging.error("Failed to send Telegram message.") """