487b28e682
- Implemented a Python script for integrating Plex Media Server with Sonarr to manage TV show seasons based on viewing habits. - Added features for automated season management, exclusion list support, and detailed logging. - Created a requirements.txt file to include necessary packages: plexapi, requests, pytest, pytest-mock, and requests-mock. - Developed unit tests for the API verification function using pytest and requests_mock. - Included a standalone script to unmonitor excluded shows in Sonarr. - Added a test script for manual API verification with mock and real API tests.
117 lines
4.4 KiB
Python
117 lines
4.4 KiB
Python
"""
|
|
Standalone script to unmonitor all excluded shows in Sonarr
|
|
"""
|
|
from plexapi.server import PlexServer
|
|
import requests
|
|
|
|
# Configuration
|
|
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"
|
|
|
|
# Initialize Plex connection
|
|
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 verify_sonarr_api():
|
|
"""Check if Sonarr API is alive and the token is correct"""
|
|
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.")
|
|
return True
|
|
except requests.exceptions.RequestException as e:
|
|
print(f"❌ Failed to verify Sonarr API: {e}")
|
|
return False
|
|
|
|
def get_tvdb_id(show):
|
|
"""Extract TVDB ID from Plex show metadata"""
|
|
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_series_id_from_tvdb(tvdb_id):
|
|
"""Get Sonarr series ID from 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}")
|
|
|
|
def mark_season_unmonitored(series_id, season_number):
|
|
"""Mark a season 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()
|
|
|
|
for season in series['seasons']:
|
|
if season['seasonNumber'] == season_number:
|
|
season['monitored'] = False
|
|
|
|
response = requests.put(url, json=series)
|
|
response.raise_for_status()
|
|
print(f" ✅ Season {season_number} marked as unmonitored for series ID {series_id}")
|
|
|
|
def unmonitor_all_excluded_shows():
|
|
"""Unmonitor all seasons of shows in the exclude list"""
|
|
print("🚀 Starting to unmonitor all excluded shows...")
|
|
print("=" * 60)
|
|
|
|
success_count = 0
|
|
error_count = 0
|
|
|
|
for show_title in exclude_shows:
|
|
try:
|
|
print(f"\n📺 Processing: {show_title}")
|
|
show = tv_shows.get(title=show_title)
|
|
print(f" Found in Plex: {show.title}")
|
|
|
|
tvdb_id = get_tvdb_id(show)
|
|
print(f" TVDB ID: {tvdb_id}")
|
|
|
|
series_id = get_series_id_from_tvdb(tvdb_id)
|
|
print(f" Sonarr Series ID: {series_id}")
|
|
|
|
seasons = show.seasons()
|
|
print(f" Found {len(seasons)} seasons")
|
|
|
|
for season in seasons:
|
|
mark_season_unmonitored(series_id, season.index)
|
|
|
|
print(f"✅ All seasons of '{show_title}' have been marked as unmonitored.")
|
|
success_count += 1
|
|
|
|
except Exception as e:
|
|
print(f"❌ Error processing '{show_title}': {e}")
|
|
error_count += 1
|
|
|
|
print("\n" + "=" * 60)
|
|
print(f"🎉 Processing complete!")
|
|
print(f"✅ Successfully processed: {success_count} shows")
|
|
print(f"❌ Errors encountered: {error_count} shows")
|
|
|
|
if __name__ == "__main__":
|
|
print("🔍 Verifying Sonarr API connection...")
|
|
if verify_sonarr_api():
|
|
print("\n🎯 Ready to unmonitor excluded shows")
|
|
user_input = input("Do you want to proceed? (y/n): ").lower().strip()
|
|
|
|
if user_input in ['y', 'yes']:
|
|
unmonitor_all_excluded_shows()
|
|
else:
|
|
print("❌ Operation cancelled by user.")
|
|
else:
|
|
print("❌ Cannot proceed - Sonarr API verification failed.")
|