Add Radarr discovery + tighten arr sync filters
- playback_aware_radarr_discovery.sh: new two-stage movie discovery using recently watched Emby movies as seeds and TMDB recommendations as the similarity engine; scores on recency + rating + vote count; adds HOST*_TMDB_API_KEY alias to detect_hosts() in common.sh - emby_to_sonarr_sync.sh: restrict to SONARR_EMBY_LIBRARIES allowlist (Anime, Kids Shows, Stand-Up Comedy, TV shows) — excludes Youtube and Recorded Sports libraries; add garbage title filter for multi- season folder names (S01-S03) and bare bracket tags ([Prof]) - emby_to_radarr_sync.sh: add _is_episode_title filter to block anime episode files stored in Movies library (underscore/dot patterns, fansub bracket format, episode markers, codec metadata strings) - emby_to_lidarr_sync.sh: add U+FFFD Unicode replacement character filter alongside the existing ASCII ? filter for encoding corruption - master.conf: RADARR_DISCOVERY_* settings, SONARR/RADARR_EMBY_LIBRARIES allowlists, Radarr discovery added to WEEKLY_MAINTENANCE_SCRIPTS
This commit is contained in:
@@ -100,6 +100,15 @@ _sonarr_post() {
|
||||
"${SONARR_URL}/api/v3/series" 2>/dev/null
|
||||
}
|
||||
|
||||
# Garbage title filter — catches multi-season folder names and bare fansub tags.
|
||||
_is_garbage_title() {
|
||||
local t="$1"
|
||||
[[ "$t" =~ S[0-9]{2}-S[0-9]{2} ]] && return 0 # Fruits Basket S01-S03
|
||||
[[ "$t" =~ ^\[.*\]$ ]] && return 0 # [Prof] bare bracket tag
|
||||
[[ "$t" == *$'\xef\xbf\xbd'* || "$t" == *"?"* ]] && return 0 # encoding corruption
|
||||
return 1
|
||||
}
|
||||
|
||||
# ==============================================================================================
|
||||
# ━━━ Fetch Emby Series Library ━━━
|
||||
# ==============================================================================================
|
||||
@@ -111,17 +120,33 @@ echo "$ICON_HOST $MY_ID ($LOCAL_SERVER_NAME)"
|
||||
echo ""
|
||||
echo "━━━ $ICON_SYNC Emby Series Library ━━━"
|
||||
|
||||
EMBY_SERIES_JSON=$(_emby_api "Items?IncludeItemTypes=Series&Recursive=true&Fields=ProviderIds&Limit=5000") || {
|
||||
error "Could not fetch Emby series"
|
||||
if [[ "${#SONARR_EMBY_LIBRARIES[@]}" -eq 0 ]]; then
|
||||
error "SONARR_EMBY_LIBRARIES not configured — check master.conf"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
|
||||
# Fetch library list and resolve names → ItemIds
|
||||
LIBRARIES_JSON=$(_emby_api "Library/VirtualFolders") || { error "Could not fetch Emby libraries"; exit 1; }
|
||||
|
||||
declare -A EMBY_SERIES # name → tvdb_id (empty string if none)
|
||||
|
||||
while IFS='|' read -r name tvdb_id; do
|
||||
[[ -z "$name" || "$name" == "null" ]] && continue
|
||||
EMBY_SERIES["$name"]="$tvdb_id"
|
||||
done < <(echo "$EMBY_SERIES_JSON" | jq -r '.Items[] | [.Name, (.ProviderIds.Tvdb // "")] | join("|")' 2>/dev/null)
|
||||
for lib_name in "${SONARR_EMBY_LIBRARIES[@]}"; do
|
||||
lib_id=$(echo "$LIBRARIES_JSON" | jq -r --arg n "$lib_name" '.[] | select(.Name == $n) | .ItemId' 2>/dev/null)
|
||||
if [[ -z "$lib_id" ]]; then
|
||||
warn "Emby library not found: $lib_name"
|
||||
continue
|
||||
fi
|
||||
log "Scanning library: $lib_name (ItemId: $lib_id)"
|
||||
LIB_JSON=$(_emby_api "Items?ParentId=${lib_id}&IncludeItemTypes=Series&Recursive=true&Fields=ProviderIds&Limit=5000") || {
|
||||
warn "Could not fetch series from library: $lib_name"
|
||||
continue
|
||||
}
|
||||
while IFS='|' read -r name tvdb_id; do
|
||||
[[ -z "$name" || "$name" == "null" ]] && continue
|
||||
_is_garbage_title "$name" && { log " $ICON_SKIP Skipping garbage title: $name"; continue; }
|
||||
EMBY_SERIES["$name"]="$tvdb_id"
|
||||
done < <(echo "$LIB_JSON" | jq -r '.Items[] | [.Name, (.ProviderIds.Tvdb // "")] | join("|")' 2>/dev/null)
|
||||
done
|
||||
|
||||
EMBY_COUNT=${#EMBY_SERIES[@]}
|
||||
log "$EMBY_COUNT series in Emby library"
|
||||
|
||||
Reference in New Issue
Block a user