From adb69d57c15259a0625e8ef0462ed7dba68fa522 Mon Sep 17 00:00:00 2001 From: Chris Rosenhain Date: Tue, 24 Feb 2026 09:51:16 +1030 Subject: [PATCH 1/4] Extract arr config elements with xq -x and the XPath expression --- lidarr/PlexNotify.bash | 2 +- radarr/Extras.bash | 6 +++--- radarr/PlexNotify.bash | 4 ++-- readarr/PlexNotify.bash | 4 ++-- sonarr/PlexNotify.bash | 4 ++-- universal/functions.bash | 8 ++++---- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lidarr/PlexNotify.bash b/lidarr/PlexNotify.bash index 7b47028e..05e60b25 100644 --- a/lidarr/PlexNotify.bash +++ b/lidarr/PlexNotify.bash @@ -34,7 +34,7 @@ plexConnectionError () { # Validate connection if curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq . &>/dev/null; then - plexVersion=$(curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq . | jq -r '.MediaContainer."@version"') + plexVersion=$(curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq -x //MediaContainer/@version) if [ "$plexVersion" == "null" ]; then # Error out if version is null, indicates bad token plexConnectionError diff --git a/radarr/Extras.bash b/radarr/Extras.bash index 07a02d7b..05aaf09d 100644 --- a/radarr/Extras.bash +++ b/radarr/Extras.bash @@ -34,14 +34,14 @@ fi if [ -z "$arrUrl" ] || [ -z "$arrApiKey" ]; then - arrUrlBase="$(cat /config/config.xml | xq | jq -r .Config.UrlBase)" + arrUrlBase="$(cat /config/config.xml | xq -x //Config/UrlBase)" if [ "$arrUrlBase" == "null" ]; then arrUrlBase="" else arrUrlBase="/$(echo "$arrUrlBase" | sed "s/\///g")" fi - arrApiKey="$(cat /config/config.xml | xq | jq -r .Config.ApiKey)" - arrPort="$(cat /config/config.xml | xq | jq -r .Config.Port)" + arrApiKey="$(cat /config/config.xml | xq -x //Config/ApiKey)" + arrPort="$(cat /config/config.xml | xq -x //Config/Port)" arrUrl="http://127.0.0.1:${arrPort}${arrUrlBase}" fi diff --git a/radarr/PlexNotify.bash b/radarr/PlexNotify.bash index 34ef90fc..87c3bc3e 100644 --- a/radarr/PlexNotify.bash +++ b/radarr/PlexNotify.bash @@ -57,8 +57,8 @@ PlexConnectionError () { } # Validate connection -if curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq . &>/dev/null; then - plexVersion=$(curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq . | jq -r '.MediaContainer."@version"') +if curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq &>/dev/null; then + plexVersion=$(curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq -x //MediaContainer/@version) if [ "$plexVersion" == "null" ]; then # Error out if version is null, indicates bad token PlexConnectionError diff --git a/readarr/PlexNotify.bash b/readarr/PlexNotify.bash index 995d4f85..dab24235 100644 --- a/readarr/PlexNotify.bash +++ b/readarr/PlexNotify.bash @@ -33,8 +33,8 @@ plexConnectionError () { } # Validate connection -if curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq . &>/dev/null; then - plexVersion=$(curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq . | jq -r '.MediaContainer."@version"') +if curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq &>/dev/null; then + plexVersion=$(curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq -x //MediaContainer//@version) if [ "$plexVersion" == "null" ]; then # Error out if version is null, indicates bad token plexConnectionError diff --git a/sonarr/PlexNotify.bash b/sonarr/PlexNotify.bash index 10aedf76..7a5feea6 100644 --- a/sonarr/PlexNotify.bash +++ b/sonarr/PlexNotify.bash @@ -57,8 +57,8 @@ plexConnectionError () { } # Validate connection -if curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq . &>/dev/null; then - plexVersion=$(curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq . | jq -r '.MediaContainer."@version"') +if curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq &>/dev/null; then + plexVersion=$(curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq -x //MediaContainer/@version) if [ "$plexVersion" == "null" ]; then # Error out if version is null, indicates bad token plexConnectionError diff --git a/universal/functions.bash b/universal/functions.bash index ed3df173..20dbdec7 100644 --- a/universal/functions.bash +++ b/universal/functions.bash @@ -21,15 +21,15 @@ logfileSetup () { getArrAppInfo () { # Get Arr App information if [ -z "$arrUrl" ] || [ -z "$arrApiKey" ]; then - arrUrlBase="$(cat /config/config.xml | xq | jq -r .Config.UrlBase)" + arrUrlBase="$(cat /config/config.xml | xq -x //Config/UrlBase)" if [ "$arrUrlBase" == "null" ]; then arrUrlBase="" else arrUrlBase="/$(echo "$arrUrlBase" | sed "s/\///")" fi - arrName="$(cat /config/config.xml | xq | jq -r .Config.InstanceName)" - arrApiKey="$(cat /config/config.xml | xq | jq -r .Config.ApiKey)" - arrPort="$(cat /config/config.xml | xq | jq -r .Config.Port)" + arrName="$(cat /config/config.xml | xq -x //Config/InstanceName)" + arrApiKey="$(cat /config/config.xml | xq -x //Config/ApiKey)" + arrPort="$(cat /config/config.xml | xq -x //Config/Port)" arrUrl="http://127.0.0.1:${arrPort}${arrUrlBase}" fi } From bf152549cda2a20a40562e64886972c2be9cb0e1 Mon Sep 17 00:00:00 2001 From: Chris Rosenhain Date: Tue, 24 Feb 2026 10:01:25 +1030 Subject: [PATCH 2/4] Use xq to parse XML into JSON, then use jq to do the rest since it can do more --- lidarr/PlexNotify.bash | 16 ++++++++-------- radarr/PlexNotify.bash | 10 +++++----- readarr/PlexNotify.bash | 14 +++++++------- sonarr/PlexNotify.bash | 10 +++++----- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/lidarr/PlexNotify.bash b/lidarr/PlexNotify.bash index 05e60b25..7b487fbf 100644 --- a/lidarr/PlexNotify.bash +++ b/lidarr/PlexNotify.bash @@ -33,7 +33,7 @@ plexConnectionError () { } # Validate connection -if curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq . &>/dev/null; then +if curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq &>/dev/null; then plexVersion=$(curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq -x //MediaContainer/@version) if [ "$plexVersion" == "null" ]; then # Error out if version is null, indicates bad token @@ -42,17 +42,17 @@ if curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq . &>/dev/null; then log "Plex Connection Established, version: $plexVersion" fi else - # Error out if error in curl | xq . command output + # Error out if error in curl | xq command output plexConnectionError fi plexLibraries="$(curl -s "$plexUrl/library/sections?X-Plex-Token=$plexToken")" -if echo "$plexLibraries" | xq ".MediaContainer.Directory | select(.\"@type\"==\"artist\")" &>/dev/null; then - plexKeys=($(echo "$plexLibraries" | xq ".MediaContainer.Directory | select(.\"@type\"==\"artist\")" | jq -r '."@key"')) - plexLibraryData=$(echo "$plexLibraries" | xq ".MediaContainer.Directory | select(.\"@type\"==\"artist\")") -elif echo "$plexLibraries" | xq ".MediaContainer.Directory[] | select(.\"@type\"==\"artist\")" &>/dev/null; then - plexKeys=($(echo "$plexLibraries" | xq ".MediaContainer.Directory[] | select(.\"@type\"==\"artist\")" | jq -r '."@key"')) - plexLibraryData=$(echo "$plexLibraries" | xq ".MediaContainer.Directory[] | select(.\"@type\"==\"artist\")") +if echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory | select(.\"@type\"==\"artist\")" &>/dev/null; then + plexKeys=($(echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory | select(.\"@type\"==\"artist\")" | jq -r '."@key"')) + plexLibraryData=$(echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory | select(.\"@type\"==\"artist\")") +elif echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory[] | select(.\"@type\"==\"artist\")" &>/dev/null; then + plexKeys=($(echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory[] | select(.\"@type\"==\"artist\")" | jq -r '."@key"')) + plexLibraryData=$(echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory[] | select(.\"@type\"==\"artist\")") else log "ERROR: No Plex Music Type libraries found" log "ERROR: Exiting..." diff --git a/radarr/PlexNotify.bash b/radarr/PlexNotify.bash index 87c3bc3e..c18ea32d 100644 --- a/radarr/PlexNotify.bash +++ b/radarr/PlexNotify.bash @@ -66,17 +66,17 @@ if curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq &>/dev/null; then log "Plex Connection Established, version: $plexVersion" fi else - # Error out if error in curl | xq . command output + # Error out if error in curl | xq command output PlexConnectionError fi plexLibraries="$(curl -s "$plexUrl/library/sections?X-Plex-Token=$plexToken")" -plexLibraryData=$(echo "$plexLibraries" | xq ".MediaContainer.Directory") +plexLibraryData=$(echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory") if echo "$plexLibraryData" | grep "^\[" | read; then - plexLibraryData=$(echo "$plexLibraries" | xq ".MediaContainer.Directory[]") - plexKeys=($(echo "$plexLibraries" | xq ".MediaContainer.Directory[]" | jq -r '."@key"')) + plexLibraryData=$(echo "$plexLibraries" | jq ".MediaContainer.Directory[]") + plexKeys=($(echo "$plexLibraries" | jq ".MediaContainer.Directory[]" | jq -r '."@key"')) else - plexKeys=($(echo "$plexLibraries" | xq ".MediaContainer.Directory" | jq -r '."@key"')) + plexKeys=($(echo "$plexLibraries" | jq ".MediaContainer.Directory" | jq -r '."@key"')) fi if echo "$plexLibraryData" | grep "\"@path\": \"$arrRootFolderPath" | read; then diff --git a/readarr/PlexNotify.bash b/readarr/PlexNotify.bash index dab24235..a57d475d 100644 --- a/readarr/PlexNotify.bash +++ b/readarr/PlexNotify.bash @@ -42,17 +42,17 @@ if curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq &>/dev/null; then log "Plex Connection Established, version: $plexVersion" fi else - # Error out if error in curl | xq . command output + # Error out if error in curl | xq command output plexConnectionError fi plexLibraries="$(curl -s "$plexUrl/library/sections?X-Plex-Token=$plexToken")" -if echo "$plexLibraries" | xq ".MediaContainer.Directory | select(.\"@type\"==\"artist\")" &>/dev/null; then - plexKeys=($(echo "$plexLibraries" | xq ".MediaContainer.Directory | select(.\"@type\"==\"artist\")" | jq -r '."@key"')) - plexLibraryData=$(echo "$plexLibraries" | xq ".MediaContainer.Directory | select(.\"@type\"==\"artist\")") -elif echo "$plexLibraries" | xq ".MediaContainer.Directory[] | select(.\"@type\"==\"artist\")" &>/dev/null; then - plexKeys=($(echo "$plexLibraries" | xq ".MediaContainer.Directory[] | select(.\"@type\"==\"artist\")" | jq -r '."@key"')) - plexLibraryData=$(echo "$plexLibraries" | xq ".MediaContainer.Directory[] | select(.\"@type\"==\"artist\")") +if echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory | select(.\"@type\"==\"artist\")" &>/dev/null; then + plexKeys=($(echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory | select(.\"@type\"==\"artist\")" | jq -r '."@key"')) + plexLibraryData=$(echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory | select(.\"@type\"==\"artist\")") +elif echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory[] | select(.\"@type\"==\"artist\")" &>/dev/null; then + plexKeys=($(echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory[] | select(.\"@type\"==\"artist\")" | jq -r '."@key"')) + plexLibraryData=$(echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory[] | select(.\"@type\"==\"artist\")") else log "ERROR: No Plex Music Type libraries found" log "ERROR: Exiting..." diff --git a/sonarr/PlexNotify.bash b/sonarr/PlexNotify.bash index 7a5feea6..a585c34d 100644 --- a/sonarr/PlexNotify.bash +++ b/sonarr/PlexNotify.bash @@ -66,17 +66,17 @@ if curl -s "$plexUrl/?X-Plex-Token=$plexToken" | xq &>/dev/null; then log "Plex Connection Established, version: $plexVersion" fi else - # Error out if error in curl | xq . command output + # Error out if error in curl | xq command output plexConnectionError fi plexLibraries="$(curl -s "$plexUrl/library/sections?X-Plex-Token=$plexToken")" -plexLibraryData=$(echo "$plexLibraries" | xq ".MediaContainer.Directory") +plexLibraryData=$(echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory") if echo "$plexLibraryData" | grep "^\[" | read; then - plexLibraryData=$(echo "$plexLibraries" | xq ".MediaContainer.Directory[]") - plexKeys=($(echo "$plexLibraries" | xq ".MediaContainer.Directory[]" | jq -r '."@key"')) + plexLibraryData=$(echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory[]") + plexKeys=($(echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory[]" | jq -r '."@key"')) else - plexKeys=($(echo "$plexLibraries" | xq ".MediaContainer.Directory" | jq -r '."@key"')) + plexKeys=($(echo "$plexLibraries" | xq -j | jq ".MediaContainer.Directory" | jq -r '."@key"')) fi if echo "$plexLibraryData" | grep "path" | grep "$arrRootFolderPath" | read; then From 699a955232ff619b17a9ce4de9d48c270fadc12e Mon Sep 17 00:00:00 2001 From: Chris Rosenhain Date: Tue, 24 Feb 2026 10:56:31 +1030 Subject: [PATCH 3/4] Some more fixes to the universal functions that help with lidarr support --- universal/functions.bash | 45 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/universal/functions.bash b/universal/functions.bash index 20dbdec7..32db3ddb 100644 --- a/universal/functions.bash +++ b/universal/functions.bash @@ -18,42 +18,43 @@ logfileSetup () { fi } + getArrAppInfo () { - # Get Arr App information if [ -z "$arrUrl" ] || [ -z "$arrApiKey" ]; then - arrUrlBase="$(cat /config/config.xml | xq -x //Config/UrlBase)" - if [ "$arrUrlBase" == "null" ]; then + arrUrlBase="$(xq -x //Config/UrlBase < /config/config.xml)" + arrName="$(xq -x //Config/InstanceName < /config/config.xml)" + arrApiKey="$(xq -x //Config/ApiKey < /config/config.xml)" + arrPort="$(xq -x //Config/Port < /config/config.xml)" + if [ "$arrUrlBase" == "null" ] || [ -z "$arrUrlBase" ] || [ "$arrUrlBase" == "/" ]; then arrUrlBase="" else - arrUrlBase="/$(echo "$arrUrlBase" | sed "s/\///")" + arrUrlBase=$(echo "$arrUrlBase" | sed -e 's/^\/*//' -e 's/\/*$//') + arrUrlBase="/$arrUrlBase" fi - arrName="$(cat /config/config.xml | xq -x //Config/InstanceName)" - arrApiKey="$(cat /config/config.xml | xq -x //Config/ApiKey)" - arrPort="$(cat /config/config.xml | xq -x //Config/Port)" arrUrl="http://127.0.0.1:${arrPort}${arrUrlBase}" fi + arrUrl="${arrUrl%/}" } verifyApiAccess () { + if ! command -v curl >/dev/null 2>&1 || ! command -v jq >/dev/null 2>&1; then + log "Fatal: 'curl' or 'jq' is not installed." + return 1 + fi until false do arrApiTest="" - arrApiVersion="" - if [ -z "$arrApiTest" ]; then - arrApiVersion="v3" - arrApiTest="$(curl -s "$arrUrl/api/$arrApiVersion/system/status?apikey=$arrApiKey" | jq -r .instanceName)" - fi - if [ -z "$arrApiTest" ]; then - arrApiVersion="v1" - arrApiTest="$(curl -s "$arrUrl/api/$arrApiVersion/system/status?apikey=$arrApiKey" | jq -r .instanceName)" - fi - if [ ! -z "$arrApiTest" ]; then - break - else - log "$arrName is not ready, sleeping until valid response..." - sleep 1 - fi + for arrApiVersion in "v3" "v1"; do + echo "$arrUrl/api/$arrApiVersion/system/status?apikey=$arrApiKey" + arrApiTest="$(curl -s "$arrUrl/api/$arrApiVersion/system/status?apikey=$arrApiKey" | jq -r '.instanceName // empty' 2>/dev/null)" + if [ -n "$arrApiTest" ]; then + break 2 + fi + done + log "$arrName is not ready, sleeping until valid response..." + sleep 1 done + log "$arrName ($arrApiTest) is ready!" } ConfValidationCheck () { From 235ae9625709ef8fa045a56420637f381202ba69 Mon Sep 17 00:00:00 2001 From: Chris Rosenhain Date: Tue, 24 Feb 2026 10:57:22 +1030 Subject: [PATCH 4/4] fixing extra spacing --- universal/functions.bash | 1 - 1 file changed, 1 deletion(-) diff --git a/universal/functions.bash b/universal/functions.bash index 32db3ddb..d9c9e773 100644 --- a/universal/functions.bash +++ b/universal/functions.bash @@ -18,7 +18,6 @@ logfileSetup () { fi } - getArrAppInfo () { if [ -z "$arrUrl" ] || [ -z "$arrApiKey" ]; then arrUrlBase="$(xq -x //Config/UrlBase < /config/config.xml)"