#!/bin/bash # ============================================================================================== # ========================= Arr Profile Enforcer ============================================== # ============================================================================================== # # PURPOSE # ───────────────────────────────────────────────────────────────────────────── # Ensures every series/movie in Sonarr and Radarr is on the correct quality # profile based on its root folder. Safe to re-run — only touches items whose # current profile is wrong. # # RULES # ───────────────────────────────────────────────────────────────────────────── # Root folder path contains "kids" OR "anime" → kids profile # All other root folders → default profile # # Profile names are looked up by name from the API at runtime, so profile IDs # do not need to be hardcoded and work across hosts. # # ============================================================================================== # OPERATIONAL SAFEGUARDS # ============================================================================================== # # Idempotent — only touches items whose current profile is wrong # API-only — no file system changes; profile ID looked up by name at runtime # --dry-run mode — reports what would change without applying any updates # # ============================================================================================== # CONFIGURATION # ============================================================================================== # # master.conf # # ARR_KIDS_PROFILE_NAME — profile name for kids/anime (default: "Kids shows") # ARR_SONARR_DEFAULT_PROFILE — default Sonarr profile name (default: "Any") # ARR_RADARR_DEFAULT_PROFILE — default Radarr profile name (default: "Any (mine)") # # ============================================================================================== # RUNTIME MODES # ============================================================================================== # # arr_profile_enforcer.sh # Enforce profiles in both Sonarr and Radarr. # # arr_profile_enforcer.sh --dry-run # Show which items would be updated without making changes. # # arr_profile_enforcer.sh --sonarr-only # Run only Sonarr enforcement. # # arr_profile_enforcer.sh --radarr-only # Run only Radarr enforcement. # # ============================================================================================== DRY_RUN=false RUN_SONARR=true RUN_RADARR=true for arg in "$@"; do case "$arg" in --dry-run) DRY_RUN=true ;; --sonarr-only) RUN_RADARR=false ;; --radarr-only) RUN_SONARR=false ;; esac done SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../load_config.sh" detect_hosts KIDS_PROFILE_NAME="${ARR_KIDS_PROFILE_NAME:-Kids shows}" SONARR_DEFAULT="${ARR_SONARR_DEFAULT_PROFILE:-Any}" RADARR_DEFAULT="${ARR_RADARR_DEFAULT_PROFILE:-Any (mine)}" # ── Helpers ────────────────────────────────────────────────────────────────── _arr_get() { local url="$1" key="$2" endpoint="$3" curl -sf --max-time 30 -H "X-Api-Key: $key" "$url/api/v3/$endpoint" } _arr_put() { local url="$1" key="$2" endpoint="$3" body="$4" curl -sf --max-time 60 -X PUT \ -H "X-Api-Key: $key" \ -H "Content-Type: application/json" \ -d "$body" \ "$url/api/v3/$endpoint" } _profile_id_by_name() { local profiles_json="$1" name="$2" php -r ' $profiles = json_decode(file_get_contents("php://stdin"), true); $name = $argv[1]; foreach ($profiles as $p) { if (strcasecmp($p["name"], $name) === 0) { echo $p["id"]; exit; } } exit(1); ' "$name" <<< "$profiles_json" } _is_kids_path() { local path="$1" local dir dir=$(basename "$(dirname "$path")") [[ "$dir" == *kids* || "$dir" == *anime* ]] } # ── Core enforcer ───────────────────────────────────────────────────────────── # _enforce