Relocate + trigger search for hasFile=false forward-misplacements
Instead of skipping monitored-but-undownloaded titles entirely, correct their DB pointer (rootFolderPath/path) now so Radarr saves under the right root whenever it grabs a release, and fire an immediate MoviesSearch rather than waiting for the next scheduled one. Junk entries stay excluded — nothing to search for there.
This commit is contained in:
@@ -268,12 +268,14 @@ if [[ "$MOVE_MODE" == true ]]; then
|
||||
|
||||
build_arr_path_map "RADARR"
|
||||
|
||||
# hasFile==false entries have nothing to physically move (some monitored titles simply
|
||||
# were never downloaded — confirmed live: "Biohazard 4: Incubate" had hasFile=false even
|
||||
# in the cache from before this run started, not something this script broke). Moving
|
||||
# Radarr's DB pointer for those is harmless but pointless — skip them here; they still
|
||||
# show up correctly in the report above as a classification finding.
|
||||
MOVE_TARGETS=$(echo "$RESULTS" | jq -c '[.[] | select((.forward_anime_miss or .forward_kids_miss) and (.is_junk | not) and .hasFile)]')
|
||||
# hasFile==false entries (monitored but never downloaded) have nothing to physically
|
||||
# move — confirmed live: "Biohazard 4: Incubate" had hasFile=false even in the cache from
|
||||
# before any of this ran, not something this script broke. There's still real value in
|
||||
# fixing them, though: correct the DB pointer now (so Radarr saves to the right root
|
||||
# whenever it does find a release) and kick off an immediate search rather than waiting
|
||||
# for the next scheduled one. Junk entries are still excluded entirely — nothing to
|
||||
# search for there, they need removal instead.
|
||||
MOVE_TARGETS=$(echo "$RESULTS" | jq -c '[.[] | select((.forward_anime_miss or .forward_kids_miss) and (.is_junk | not))]')
|
||||
MOVE_COUNT=$(echo "$MOVE_TARGETS" | jq 'length')
|
||||
|
||||
if [[ "$MOVE_COUNT" -eq 0 ]]; then
|
||||
@@ -281,15 +283,17 @@ if [[ "$MOVE_MODE" == true ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
warn "About to move $MOVE_COUNT movies — one at a time, verifying after each"
|
||||
warn "About to process $MOVE_COUNT movies — one at a time, verifying after each"
|
||||
|
||||
MOVED=0
|
||||
RELOCATED_SEARCH=0
|
||||
FAILED=0
|
||||
|
||||
while IFS= read -r item; do
|
||||
id=$(echo "$item" | jq -r '.id')
|
||||
title=$(echo "$item" | jq -r '.title')
|
||||
is_anime_flag=$(echo "$item" | jq -r '.is_anime')
|
||||
had_file=$(echo "$item" | jq -r '.hasFile')
|
||||
if [[ "$is_anime_flag" == "true" ]]; then
|
||||
target_root="$RADARR_ANIME_ROOT"
|
||||
else
|
||||
@@ -317,7 +321,14 @@ if [[ "$MOVE_MODE" == true ]]; then
|
||||
fi
|
||||
|
||||
new_path="${target_root}/${folder_name}"
|
||||
info " → $title: $old_path → $new_path"
|
||||
|
||||
if [[ "$had_file" == "true" ]]; then
|
||||
info " → $title: $old_path → $new_path (moving file)"
|
||||
move_qs="?moveFiles=true"
|
||||
else
|
||||
info " → $title: $old_path → $new_path (no file — relocating + search)"
|
||||
move_qs=""
|
||||
fi
|
||||
|
||||
updated_movie=$(echo "$full_movie" | jq --arg root "$target_root" --arg path "$new_path" \
|
||||
'.rootFolderPath = $root | .path = $path')
|
||||
@@ -327,7 +338,7 @@ if [[ "$MOVE_MODE" == true ]]; then
|
||||
-H "X-Api-Key: $RADARR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$updated_movie" \
|
||||
"${RADARR_URL}/api/v3/movie/${id}?moveFiles=true" 2>/dev/null)
|
||||
"${RADARR_URL}/api/v3/movie/${id}${move_qs}" 2>/dev/null)
|
||||
|
||||
if [[ "$http_code" != "200" && "$http_code" != "202" ]]; then
|
||||
error " ✗ $title — API returned HTTP $http_code — stopping (review before re-running)"
|
||||
@@ -342,21 +353,42 @@ if [[ "$MOVE_MODE" == true ]]; then
|
||||
verify_root=$(echo "$verify_movie" | jq -r '.rootFolderPath')
|
||||
verify_hasfile=$(echo "$verify_movie" | jq -r '.hasFile')
|
||||
|
||||
if [[ "$verify_root" == "$target_root" ]] && [[ "$verify_hasfile" == "true" ]]; then
|
||||
echo " $ICON_SUCCESS $title — moved and verified"
|
||||
(( MOVED++ ))
|
||||
else
|
||||
error " ✗ $title — verification failed (root: $verify_root, hasFile: $verify_hasfile) — stopping"
|
||||
if [[ "$verify_root" != "$target_root" ]]; then
|
||||
error " ✗ $title — verification failed (root: $verify_root) — stopping"
|
||||
(( FAILED++ ))
|
||||
break
|
||||
fi
|
||||
|
||||
if [[ "$had_file" == "true" ]]; then
|
||||
if [[ "$verify_hasfile" == "true" ]]; then
|
||||
echo " $ICON_SUCCESS $title — moved and verified"
|
||||
(( MOVED++ ))
|
||||
else
|
||||
error " ✗ $title — verification failed (root updated but hasFile now false) — stopping"
|
||||
(( FAILED++ ))
|
||||
break
|
||||
fi
|
||||
else
|
||||
search_code=$(curl -sf -o /dev/null -w "%{http_code}" -X POST \
|
||||
--max-time 30 \
|
||||
-H "X-Api-Key: $RADARR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"name\":\"MoviesSearch\",\"movieIds\":[${id}]}" \
|
||||
"${RADARR_URL}/api/v3/command" 2>/dev/null)
|
||||
if [[ "$search_code" == "200" || "$search_code" == "201" ]]; then
|
||||
echo " $ICON_SUCCESS $title — relocated, search triggered"
|
||||
else
|
||||
warn " $title — relocated but search trigger returned HTTP $search_code (will pick up on next scheduled search)"
|
||||
fi
|
||||
(( RELOCATED_SEARCH++ ))
|
||||
fi
|
||||
done < <(echo "$MOVE_TARGETS" | jq -c '.[]')
|
||||
|
||||
# arr_get_tracked_data() is cache-first — every write above changed rootFolderPath, so the
|
||||
# shared cache is now stale until the next scheduled arr_cache_prefill run (up to 30min).
|
||||
# Every other script reading this cache (cleanup, discovery, etc.) would see wrong data
|
||||
# until then — refresh it now with one more live fetch rather than leave that window open.
|
||||
if [[ "$MOVED" -gt 0 ]]; then
|
||||
if [[ "$(( MOVED + RELOCATED_SEARCH ))" -gt 0 ]]; then
|
||||
info "Refreshing shared tracked-data cache..."
|
||||
fresh_movies=$(arr_api "$RADARR_URL" "$RADARR_API_KEY" "v3" "movie" "Radarr")
|
||||
[[ -n "$fresh_movies" ]] && arr_cache_write "radarr" "$fresh_movies"
|
||||
@@ -364,8 +396,9 @@ if [[ "$MOVE_MODE" == true ]]; then
|
||||
|
||||
echo ""
|
||||
echo "━━━━━ $ICON_SUMMARY MOVE SUMMARY ━━━━━"
|
||||
echo "$ICON_SUCCESS Moved: $MOVED"
|
||||
echo "$ICON_ERROR Failed: $FAILED"
|
||||
echo "$ICON_SUCCESS Moved (file relocated): $MOVED"
|
||||
echo "$ICON_SUCCESS Relocated + search triggered: $RELOCATED_SEARCH"
|
||||
echo "$ICON_ERROR Failed: $FAILED"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user