#!/usr/bin/env python3 """Declarative quality profile initialization for Jellyseerr. Resolves profile names to IDs by querying Radarr/Sonarr APIs, then patches Jellyseerr's settings.json so new requests default to the correct quality profiles. """ import json import os import subprocess import sys import requests as http from common import load_config, read_api_key_xml, wait_for_api def resolve_profile_id(base_url, api_key, profile_name, app_name): """Query a Servarr app for quality profiles and resolve a name to an ID.""" resp = http.get( f"{base_url}/qualityprofile", headers={"X-Api-Key": api_key}, timeout=30, ) resp.raise_for_status() profiles = resp.json() for profile in profiles: if profile["name"] == profile_name: print(f"Resolved {app_name} profile '{profile_name}' -> ID {profile['id']}") return profile["id"] available = [p["name"] for p in profiles] print( f"Profile '{profile_name}' not found in {app_name}. " f"Available: {available}", file=sys.stderr, ) sys.exit(1) def main(): cfg = load_config() settings_path = os.path.join(cfg["configDir"], "settings.json") if not os.path.isfile(settings_path): print(f"{settings_path} not found, skipping (Jellyseerr not yet initialized)") return timeout = cfg["apiTimeout"] # Resolve Radarr profile radarr_cfg = cfg["radarr"] radarr_key = read_api_key_xml(f"{radarr_cfg['dataDir']}/config.xml") radarr_bind = radarr_cfg.get("bindAddress", "127.0.0.1") radarr_base = f"http://{radarr_bind}:{radarr_cfg['port']}/api/v3" wait_for_api(radarr_base, radarr_key, timeout, "Radarr") radarr_profile_id = resolve_profile_id( radarr_base, radarr_key, radarr_cfg["profileName"], "Radarr", ) # Resolve Sonarr profiles sonarr_cfg = cfg["sonarr"] sonarr_key = read_api_key_xml(f"{sonarr_cfg['dataDir']}/config.xml") sonarr_bind = sonarr_cfg.get("bindAddress", "127.0.0.1") sonarr_base = f"http://{sonarr_bind}:{sonarr_cfg['port']}/api/v3" wait_for_api(sonarr_base, sonarr_key, timeout, "Sonarr") sonarr_profile_id = resolve_profile_id( sonarr_base, sonarr_key, sonarr_cfg["profileName"], "Sonarr", ) sonarr_anime_profile_id = resolve_profile_id( sonarr_base, sonarr_key, sonarr_cfg["animeProfileName"], "Sonarr (anime)", ) # Patch settings.json with open(settings_path) as f: settings = json.load(f) changed = False for entry in settings.get("radarr", []): if ( entry.get("activeProfileId") != radarr_profile_id or entry.get("activeProfileName") != radarr_cfg["profileName"] ): entry["activeProfileId"] = radarr_profile_id entry["activeProfileName"] = radarr_cfg["profileName"] changed = True print( f"Radarr '{entry.get('name', '?')}': " f"set profile to {radarr_cfg['profileName']} (ID {radarr_profile_id})" ) for entry in settings.get("sonarr", []): updates = {} if ( entry.get("activeProfileId") != sonarr_profile_id or entry.get("activeProfileName") != sonarr_cfg["profileName"] ): updates["activeProfileId"] = sonarr_profile_id updates["activeProfileName"] = sonarr_cfg["profileName"] if ( entry.get("activeAnimeProfileId") != sonarr_anime_profile_id or entry.get("activeAnimeProfileName") != sonarr_cfg["animeProfileName"] ): updates["activeAnimeProfileId"] = sonarr_anime_profile_id updates["activeAnimeProfileName"] = sonarr_cfg["animeProfileName"] if updates: entry.update(updates) changed = True print( f"Sonarr '{entry.get('name', '?')}': " f"set profile to {sonarr_cfg['profileName']} (ID {sonarr_profile_id})" ) if not changed: print("Jellyseerr profiles already correct, no changes needed") return with open(settings_path, "w") as f: json.dump(settings, f, indent=2) print("Updated settings.json, restarting Jellyseerr...") result = subprocess.run( ["systemctl", "restart", "jellyseerr.service"], capture_output=True, text=True, ) if result.returncode != 0: print( f"Failed to restart Jellyseerr: {result.stderr.strip()}", file=sys.stderr, ) sys.exit(1) print("Jellyseerr init complete") if __name__ == "__main__": main()