Add Plex Sonarr integration script and testing framework
- 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.
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
"""
|
||||
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.")
|
||||
Reference in New Issue
Block a user