Bug fixes, arr cleanup API-driven scan, shared JS formatters

Bug fixes:
- fallback.sh: escape sed metacharacters (\ & |) in state_set values
- common.sh: parse PID from lock file content correctly (handles pid:metadata format)
- unraid_api_key_renew.sh: fix path depth (../../../) and sync registry key to conf when stale
- stop.php: only clear pid/status if process is actually dead — D-state survives SIGKILL
- array_started.sh: check ARRAY_START_SCRIPTS empty before printing launch header

Arr cleanup:
- radarr_cleanup.sh / sonarr_cleanup.sh: fetch root folders from arr API instead of
  reverse-looking up the path map — handles multi-root-folder setups correctly

UI:
- varaverk.js: extract shared formatters (_relTime, _fmtBytes, _sz, _uptime, _gb, _tb, _n)
- arrs.php / partnership.php: use shared formatters, remove duplicates
- arrs.php / fallback.php: show error message on fetch failure instead of silent empty
- docker.php: disable rename input during request, restore original value on failure
- setup.php: abort controller timeout on detect fetch
- partnership.php: remove Re-run Phase 2 button opacity dimming
This commit is contained in:
Gmer4Lfe
2026-06-12 21:41:11 -04:00
parent 3937d5e33b
commit f10f09eeb1
13 changed files with 137 additions and 94 deletions
+19 -18
View File
@@ -305,24 +305,25 @@ format_bytes() {
echo ""
echo "━━━ $ICON_SYNC Pre-flight: Radarr Import Scan ━━━"
# Reverse-lookup container path from path map so Radarr gets its own path, not the host path
RADARR_CONTAINER_ROOT=""
for _cp in "${!ARR_PATH_MAP[@]}"; do
if [[ "${ARR_PATH_MAP[$_cp]}" == "$RADARR_MOVIES_ROOT" ]]; then
RADARR_CONTAINER_ROOT="$_cp"
break
fi
done
unset _cp
# Fetch root folders from Radarr API and translate container paths to host paths
mapfile -t SCAN_ROOTS < <(
radarr_api "rootfolder" | \
jq -r '.[].path' 2>/dev/null | \
while IFS= read -r cp; do translate_path "$cp"; done
)
if [[ -n "$RADARR_CONTAINER_ROOT" ]]; then
info "Triggering DownloadedMoviesScan on: $RADARR_CONTAINER_ROOT"
SCAN_PAYLOAD="{\"name\": \"DownloadedMoviesScan\", \"path\": \"$RADARR_CONTAINER_ROOT\"}"
else
info "No path map match — triggering DownloadedMoviesScan (all root folders)"
SCAN_PAYLOAD='{"name": "DownloadedMoviesScan"}'
if [[ "${#SCAN_ROOTS[@]}" -eq 0 ]]; then
error "No root folders returned from Radarr API — aborting"
notify "Radarr cleanup aborted on $(hostname) — no root folders from API" \
"Radarr Cleanup" "warning"
exit 1
fi
info "Scan targets (${#SCAN_ROOTS[@]}): ${SCAN_ROOTS[*]}"
info "Triggering DownloadedMoviesScan (all root folders)"
SCAN_PAYLOAD='{"name": "DownloadedMoviesScan"}'
SCAN_RESPONSE=$(curl -sf --max-time 30 -X POST \
-H "X-Api-Key: $RADARR_API_KEY" \
-H "Content-Type: application/json" \
@@ -487,7 +488,7 @@ while IFS= read -r filepath; do
fi
done < <(
for host_path in "${ARR_PATH_MAP[@]}" "$RADARR_MOVIES_ROOT"; do
for host_path in "${SCAN_ROOTS[@]}"; do
[[ -d "$host_path" ]] && find "$host_path" -type f 2>/dev/null
done | sort -u
)
@@ -532,13 +533,13 @@ if [[ "$DRY_RUN" == false ]]; then
rm -f "$filepath" 2>/dev/null || error "Failed to delete: $filepath"
done < <(
for host_path in "${ARR_PATH_MAP[@]}" "$RADARR_MOVIES_ROOT"; do
for host_path in "${SCAN_ROOTS[@]}"; do
[[ -d "$host_path" ]] && find "$host_path" -type f 2>/dev/null
done | sort -u
)
info "Cleaning up empty folders..."
for host_path in "${ARR_PATH_MAP[@]}" "$RADARR_MOVIES_ROOT"; do
for host_path in "${SCAN_ROOTS[@]}"; do
[[ -d "$host_path" ]] && \
find "$host_path" -mindepth 1 -type d -empty -delete 2>/dev/null
done
+19 -18
View File
@@ -305,24 +305,25 @@ format_bytes() {
echo ""
echo "━━━ $ICON_SYNC Pre-flight: Sonarr Import Scan ━━━"
# Reverse-lookup container path from path map so Sonarr gets its own path, not the host path
SONARR_CONTAINER_ROOT=""
for _cp in "${!ARR_PATH_MAP[@]}"; do
if [[ "${ARR_PATH_MAP[$_cp]}" == "$SONARR_TV_ROOT" ]]; then
SONARR_CONTAINER_ROOT="$_cp"
break
fi
done
unset _cp
# Fetch root folders from Sonarr API and translate container paths to host paths
mapfile -t SCAN_ROOTS < <(
sonarr_api "rootfolder" | \
jq -r '.[].path' 2>/dev/null | \
while IFS= read -r cp; do translate_path "$cp"; done
)
if [[ -n "$SONARR_CONTAINER_ROOT" ]]; then
info "Triggering DownloadedEpisodesScan on: $SONARR_CONTAINER_ROOT"
SCAN_PAYLOAD="{\"name\": \"DownloadedEpisodesScan\", \"path\": \"$SONARR_CONTAINER_ROOT\"}"
else
info "No path map match — triggering DownloadedEpisodesScan (all root folders)"
SCAN_PAYLOAD='{"name": "DownloadedEpisodesScan"}'
if [[ "${#SCAN_ROOTS[@]}" -eq 0 ]]; then
error "No root folders returned from Sonarr API — aborting"
notify "Sonarr cleanup aborted on $(hostname) — no root folders from API" \
"Sonarr Cleanup" "warning"
exit 1
fi
info "Scan targets (${#SCAN_ROOTS[@]}): ${SCAN_ROOTS[*]}"
info "Triggering DownloadedEpisodesScan (all root folders)"
SCAN_PAYLOAD='{"name": "DownloadedEpisodesScan"}'
SCAN_RESPONSE=$(curl -sf --max-time 30 -X POST \
-H "X-Api-Key: $SONARR_API_KEY" \
-H "Content-Type: application/json" \
@@ -486,7 +487,7 @@ while IFS= read -r filepath; do
fi
done < <(
for host_path in "${ARR_PATH_MAP[@]}" "$SONARR_TV_ROOT"; do
for host_path in "${SCAN_ROOTS[@]}"; do
[[ -d "$host_path" ]] && find "$host_path" -type f 2>/dev/null
done | sort -u
)
@@ -531,13 +532,13 @@ if [[ "$DRY_RUN" == false ]]; then
rm -f "$filepath" 2>/dev/null || error "Failed to delete: $filepath"
done < <(
for host_path in "${ARR_PATH_MAP[@]}" "$SONARR_TV_ROOT"; do
for host_path in "${SCAN_ROOTS[@]}"; do
[[ -d "$host_path" ]] && find "$host_path" -type f 2>/dev/null
done | sort -u
)
info "Cleaning up empty folders..."
for host_path in "${ARR_PATH_MAP[@]}" "$SONARR_TV_ROOT"; do
for host_path in "${SCAN_ROOTS[@]}"; do
[[ -d "$host_path" ]] && \
find "$host_path" -mindepth 1 -type d -empty -delete 2>/dev/null
done