Files
Server-scripts/docker_compose/configure_indexers.py
T

222 lines
5.7 KiB
Python
Executable File

#!/usr/bin/env python3
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import requests
import re
import time
# ============================================================================
# CONFIG
# ============================================================================
ip_address = "192.168.0.4"
INSTANCES = [
{
"name": "radarr-de",
"url": f"http://{ip_address}:7879",
"api_key": "29f67f0ac8894357b22ea3f7fc1abfdf",
},
{
"name": "radarr-en",
"url": f"http://{ip_address}:7878",
"api_key": "4332aee075c748f2acee41aa26f06007",
},
{
"name": "sonarr",
"url": f"http://{ip_address}:8990",
"api_key": "707d4fcbb3d74822ba990c6a8b7278e9",
},
{
"name": "lidarr",
"url": f"http://{ip_address}:8686",
"api_key": "bb41cbf2b17e439290f90ecfaeb24dff",
},
# {
# "name": "listenarr",
# "url": f"http://{ip_address}:7878",
# "api_key": "READARR_API_KEY",
# },
]
PRIVATE_CLIENT = "qbittorrent-private"
PUBLIC_CLIENT = "qbittorrent-public"
PRIVATE_INDEXER_REGEX = re.compile(
r"(Bittorrentfiles|NordicQuality|funzone|SeedCore|The Brothers)",
re.IGNORECASE
)
DRY_RUN = False
# ============================================================================
session = requests.Session()
retry_strategy = Retry(
total=3,
connect=3,
read=3,
backoff_factor=2,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["GET", "PUT", "POST"],
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("http://", adapter)
session.mount("https://", adapter)
def get_api_version(base_url, api_key):
r = requests.get(
f"{base_url}/api",
headers={"X-Api-Key": api_key},
timeout=30,
)
r.raise_for_status()
return r.json()["current"]
def api_get(base_url, api_key, endpoint, retries=3):
last_error = None
for attempt in range(1, retries + 1):
try:
r = requests.get(
f"{base_url}{endpoint}",
headers={"X-Api-Key": api_key},
timeout=30,
)
r.raise_for_status()
return r.json()
except requests.HTTPError as e:
print("Status:", e.response.status_code)
print("Response:", e.response.text)
raise
except Exception as e:
last_error = e
print(f"GET failed ({attempt}/{retries}): {e}")
if attempt < retries:
time.sleep(2 ** attempt)
raise last_error
def api_put(base_url, api_key, endpoint, payload, retries=3):
last_error = None
for attempt in range(1, retries + 1):
try:
r = requests.put(
f"{base_url}{endpoint}",
headers={
"X-Api-Key": api_key,
"Content-Type": "application/json",
},
json=payload,
timeout=30,
)
r.raise_for_status()
return r.json() if r.content else None
except requests.HTTPError as e:
print("Status:", e.response.status_code)
print("Response:", e.response.text)
raise
except Exception as e:
last_error = e
print(f"PUT failed ({attempt}/{retries}): {e}")
if attempt < retries:
time.sleep(2 ** attempt)
raise last_error
def get_download_client_ids(base_url, endpoint,api_key):
clients = api_get(base_url, api_key, endpoint)
private_id = None
public_id = None
for client in clients:
if client["name"] == PRIVATE_CLIENT:
private_id = client["id"]
if client["name"] == PUBLIC_CLIENT:
public_id = client["id"]
return private_id, public_id
def process_instance(instance):
name = instance["name"]
url = instance["url"]
api_key = instance["api_key"]
print(f"\n{'=' * 80}")
print(f"Processing: {name}")
print(f"{'=' * 80}")
api_version = get_api_version(url, api_key)
endpoint_download = f"/api/{api_version}/downloadclient"
private_id, public_id = get_download_client_ids(url, endpoint_download, api_key)
if not private_id:
print(f"ERROR: '{PRIVATE_CLIENT}' not found")
return
if not public_id:
print(f"ERROR: '{PUBLIC_CLIENT}' not found")
return
print(f"{PRIVATE_CLIENT} id: {private_id}")
print(f"{PUBLIC_CLIENT} id: {public_id}")
indexers = api_get(url,api_key,f"/api/{api_version}/indexer")
for indexer in indexers:
idx_id = indexer["id"]
idx_name = indexer["name"]
print(idx_name)
if PRIVATE_INDEXER_REGEX.search(idx_name):
target_id = private_id
target_name = PRIVATE_CLIENT
else:
target_id = public_id
target_name = PUBLIC_CLIENT
current_id = indexer.get("downloadClientId")
if current_id == target_id:
print(f"SKIP {idx_name} -> {target_name}")
continue
indexer["downloadClientId"] = target_id
if DRY_RUN:
print(f"DRY {idx_name} -> {target_name}")
continue
endpoint_indexer = f"/api/{api_version}/indexer/{idx_id}?forceSave=true"
try:
api_put(
url,
api_key,
endpoint_indexer,
indexer,
)
print(f"SET {idx_name} -> {target_name}")
except Exception as e:
print(f"FAIL {idx_name}: {e}")
def main():
for instance in INSTANCES:
process_instance(instance)
if __name__ == "__main__":
main()