From 5e870d0e8b3660e72dd43a56a70f16d7e620e31f Mon Sep 17 00:00:00 2001 From: rope Date: Wed, 24 Jun 2026 21:35:37 +0100 Subject: [PATCH] arr-interconnect: auto-add Jellyfin library-refresh notification to Sonarr/Radarr Co-Authored-By: Claude Opus 4.8 --- services/arr-interconnect.nix | 83 ++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/services/arr-interconnect.nix b/services/arr-interconnect.nix index 66440df..7e8293e 100644 --- a/services/arr-interconnect.nix +++ b/services/arr-interconnect.nix @@ -2,7 +2,7 @@ let interconnectScript = pkgs.writeShellScript "arr-interconnect" '' set -euo pipefail - PATH="${lib.makeBinPath [ pkgs.curl pkgs.jq pkgs.gnused pkgs.gnugrep pkgs.coreutils pkgs.systemd ]}:$PATH" + PATH="${lib.makeBinPath [ pkgs.curl pkgs.jq pkgs.gnused pkgs.gnugrep pkgs.coreutils pkgs.systemd pkgs.sqlite ]}:$PATH" BASE="http://127.0.0.1" @@ -30,6 +30,14 @@ let SABNZBD_KEY=$(grep -oP '^api_key\s*=\s*\K\S+' /var/lib/sabnzbd/sabnzbd.ini | head -n1 || true) fi + # Jellyfin has no config.xml api key; any AccessToken in its db works as + # an API key. Reuse the first one (create one in the Jellyfin UI once if + # the table is empty — same first-run caveat as SAB above). + JELLYFIN_KEY="" + if [ -f "/var/lib/jellyfin/data/jellyfin.db" ]; then + JELLYFIN_KEY=$(sqlite3 /var/lib/jellyfin/data/jellyfin.db "SELECT AccessToken FROM ApiKeys LIMIT 1;" 2>/dev/null || true) + fi + # --- Helpers --- wait_for() { local name="$1" url="$2" key="$3" @@ -341,6 +349,79 @@ let fi fi + ########################################################################## + # Sonarr → Jellyfin (refresh library on import so new shows appear + # without waiting for Jellyfin's flaky filesystem watcher / full scan) + ########################################################################## + if [ -n "$SONARR_KEY" ] && [ -n "$JELLYFIN_KEY" ]; then + if ! exists_by_name "$BASE:8989/api/v3/notification" "$SONARR_KEY" "Jellyfin"; then + echo "Adding Jellyfin notification to Sonarr..." + curl -sf -X POST \ + -H "Content-Type: application/json" \ + -H "X-Api-Key: $SONARR_KEY" \ + "$BASE:8989/api/v3/notification" \ + -d "$(jq -n --arg key "$JELLYFIN_KEY" '{ + name: "Jellyfin", + implementation: "MediaBrowser", + configContract: "MediaBrowserSettings", + implementationName: "Emby / Jellyfin", + onDownload: true, + onUpgrade: true, + onRename: true, + onSeriesDelete: true, + onEpisodeFileDelete: true, + onEpisodeFileDeleteForUpgrade: true, + fields: [ + {name: "host", value: "localhost"}, + {name: "port", value: 8096}, + {name: "useSsl", value: false}, + {name: "apiKey", value: $key}, + {name: "notify", value: false}, + {name: "updateLibrary", value: true} + ], + tags: [] + }')" > /dev/null && echo " done" || echo " failed" + else + echo "Sonarr → Jellyfin already configured" + fi + fi + + ########################################################################## + # Radarr → Jellyfin (refresh library on import) + ########################################################################## + if [ -n "$RADARR_KEY" ] && [ -n "$JELLYFIN_KEY" ]; then + if ! exists_by_name "$BASE:7878/api/v3/notification" "$RADARR_KEY" "Jellyfin"; then + echo "Adding Jellyfin notification to Radarr..." + curl -sf -X POST \ + -H "Content-Type: application/json" \ + -H "X-Api-Key: $RADARR_KEY" \ + "$BASE:7878/api/v3/notification" \ + -d "$(jq -n --arg key "$JELLYFIN_KEY" '{ + name: "Jellyfin", + implementation: "MediaBrowser", + configContract: "MediaBrowserSettings", + implementationName: "Emby / Jellyfin", + onDownload: true, + onUpgrade: true, + onRename: true, + onMovieDelete: true, + onMovieFileDelete: true, + onMovieFileDeleteForUpgrade: true, + fields: [ + {name: "host", value: "localhost"}, + {name: "port", value: 8096}, + {name: "useSsl", value: false}, + {name: "apiKey", value: $key}, + {name: "notify", value: false}, + {name: "updateLibrary", value: true} + ], + tags: [] + }')" > /dev/null && echo " done" || echo " failed" + else + echo "Radarr → Jellyfin already configured" + fi + fi + ########################################################################## # Prowlarr auth — trust localhost so Authelia is the only gate. Other # *arr apps default to this; Prowlarr does not.