Bash common.sh: consolidate docker_cmd/retry_docker/verify_running/emby_api, fix tailscale dups
common.sh gains: - docker_cmd() + verify_running() + retry_docker() — removed from all 3 Docker_Essentials scripts where they were byte-for-byte duplicates - emby_api(endpoint, [timeout=30]) — removed from 6 Media/Tools scripts that each defined their own _emby_api() with the same curl/parse/error pattern; call sites renamed emby_api - format_duration() extended with days/hours branch (was capped at minutes+seconds) - notify() comment: scripts do not need to preflight the notify script via validate_unraid_cmd Tailscale deduplication: - arr_sync.sh: _resolve_node_ip() and inline block in _delete_remote_item() both replaced with resolve_tailscale_ip() from common.sh - git_pull_execute.sh: inline tailscale ip -4 replaced with resolve_tailscale_ip() (adds the tailscale status fallback that was missing)
This commit is contained in:
+2
-13
@@ -315,12 +315,8 @@ _delete_remote_item() {
|
||||
local node_id="$1" port="$2" api_ver="$3" endpoint="$4" config_xml="$5"
|
||||
local id_field="$6" id_type="$7" stable_id="$8"
|
||||
local node_name="${!node_id}"
|
||||
local ts_name="${node_name,,}"
|
||||
local node_ip
|
||||
node_ip=$(tailscale ip -4 "$ts_name" 2>/dev/null)
|
||||
[[ -z "$node_ip" ]] && node_ip=$(tailscale status 2>/dev/null | \
|
||||
awk -v n="$ts_name" '$2 ~ "^" n { print $1; exit }')
|
||||
[[ -z "$node_ip" ]] && return 1
|
||||
node_ip=$(resolve_tailscale_ip "$node_name") || return 1
|
||||
|
||||
local select_expr
|
||||
if [[ "$id_type" == "string" ]]; then
|
||||
@@ -478,14 +474,7 @@ fi
|
||||
|
||||
_resolve_node_ip() {
|
||||
local node_id="$1"
|
||||
local node_name="${!node_id}"
|
||||
local ts_name="${node_name,,}"
|
||||
local ip
|
||||
ip=$(tailscale ip -4 "$ts_name" 2>/dev/null)
|
||||
[[ -z "$ip" ]] && ip=$(tailscale status 2>/dev/null | \
|
||||
awk -v n="$ts_name" '$2 ~ "^" n { print $1; exit }')
|
||||
[[ -z "$ip" ]] && return 1
|
||||
echo "$ip"
|
||||
resolve_tailscale_ip "${!node_id}"
|
||||
}
|
||||
|
||||
# Check if arr is reachable on remote node
|
||||
|
||||
@@ -186,18 +186,6 @@ fi
|
||||
# ── API HELPERS ───────────────────────────────────────────────────────────────────────────────
|
||||
# ==============================================================================================
|
||||
|
||||
_emby_api() {
|
||||
local endpoint="$1"
|
||||
local response http_code body
|
||||
response=$(curl -sf --max-time 15 \
|
||||
-H "X-Emby-Token: $EMBY_API_KEY" \
|
||||
-w "\n%{http_code}" \
|
||||
"${EMBY_URL}/${endpoint}" 2>/dev/null)
|
||||
http_code=$(echo "$response" | tail -1)
|
||||
body=$(echo "$response" | head -n -1)
|
||||
[[ "$http_code" != "200" ]] && { error "Emby API HTTP $http_code: $endpoint"; return 1; }
|
||||
echo "$body"
|
||||
}
|
||||
|
||||
_lidarr_get() {
|
||||
curl -sf --max-time 20 \
|
||||
@@ -329,7 +317,7 @@ CUTOFF_ISO=$(date -d "${LOOKBACK_DAYS} days ago" '+%Y-%m-%dT%H:%M:%SZ')
|
||||
TODAY_EPOCH=$(date +%s)
|
||||
TODAY=$(date +%Y-%m-%d)
|
||||
|
||||
ACTIVITY_JSON=$(_emby_api "System/ActivityLog/Entries?MinDate=${CUTOFF_ISO}&Limit=5000") || {
|
||||
ACTIVITY_JSON=$(emby_api "System/ActivityLog/Entries?MinDate=${CUTOFF_ISO}&Limit=5000") || {
|
||||
error "Could not fetch Emby activity log"
|
||||
exit 1
|
||||
}
|
||||
@@ -512,7 +500,7 @@ LIDARR_NAMES=$(echo "$LIDARR_ARTISTS_JSON" | jq -r '.[].artistName' 2>/dev/null)
|
||||
LIDARR_COUNT=$(echo "$LIDARR_NAMES" | grep -c . 2>/dev/null || echo 0)
|
||||
log "$LIDARR_COUNT artists in Lidarr"
|
||||
|
||||
EMBY_LIBRARY_JSON=$(_emby_api "Items?IncludeItemTypes=MusicAlbum&Recursive=true&Fields=AlbumArtists&Limit=10000") || {
|
||||
EMBY_LIBRARY_JSON=$(emby_api "Items?IncludeItemTypes=MusicAlbum&Recursive=true&Fields=AlbumArtists&Limit=10000") || {
|
||||
warn "Could not fetch Emby artist library — skipping Emby filter"
|
||||
EMBY_ARTIST_NAMES=""
|
||||
}
|
||||
|
||||
@@ -194,17 +194,6 @@ fi
|
||||
# ── API HELPERS ───────────────────────────────────────────────────────────────────────────────
|
||||
# ==============================================================================================
|
||||
|
||||
_emby_api() {
|
||||
local response http_code body
|
||||
response=$(curl -sf --max-time 20 \
|
||||
-H "X-Emby-Token: $EMBY_API_KEY" \
|
||||
-w "\n%{http_code}" \
|
||||
"${EMBY_URL}/${1}" 2>/dev/null)
|
||||
http_code=$(echo "$response" | tail -1)
|
||||
body=$(echo "$response" | head -n -1)
|
||||
[[ "$http_code" != "200" ]] && { error "Emby API HTTP $http_code: $1"; return 1; }
|
||||
echo "$body"
|
||||
}
|
||||
|
||||
_radarr_get() {
|
||||
curl -sf --max-time 20 \
|
||||
@@ -306,7 +295,7 @@ echo "$ICON_HOST $MY_ID ($LOCAL_SERVER_NAME) | lookback: ${LOOKBACK_DAYS}d | thr
|
||||
echo ""
|
||||
echo "━━━ $ICON_SYNC Emby Watch History ━━━"
|
||||
|
||||
LIBRARIES_JSON=$(_emby_api "Library/VirtualFolders") || { error "Could not fetch Emby libraries"; exit 1; }
|
||||
LIBRARIES_JSON=$(emby_api "Library/VirtualFolders") || { error "Could not fetch Emby libraries"; exit 1; }
|
||||
CUTOFF_ISO=$(date -d "${LOOKBACK_DAYS} days ago" '+%Y-%m-%dT%H:%M:%SZ')
|
||||
TODAY_EPOCH=$(date +%s)
|
||||
TODAY=$(date +%Y-%m-%d)
|
||||
@@ -321,7 +310,7 @@ for lib_name in "${SEED_LIBRARIES[@]}"; do
|
||||
continue
|
||||
fi
|
||||
log "Indexing library: $lib_name (ItemId: $lib_id)"
|
||||
LIB_JSON=$(_emby_api "Items?ParentId=${lib_id}&IncludeItemTypes=Movie&Recursive=true&Fields=ProviderIds&Limit=10000") || {
|
||||
LIB_JSON=$(emby_api "Items?ParentId=${lib_id}&IncludeItemTypes=Movie&Recursive=true&Fields=ProviderIds&Limit=10000") || {
|
||||
warn "Could not index library: $lib_name"
|
||||
continue
|
||||
}
|
||||
@@ -335,7 +324,7 @@ log "${#EMBY_TMDB_IDS[@]} movies in Emby TMDB index"
|
||||
# Each entry includes an ItemId — batch-fetch those items to determine type (Movie vs. Music/TV).
|
||||
# SortBy=DatePlayed on Items requires UserId context and errors without one; the activity log
|
||||
# is server-scoped and doesn't have that limitation.
|
||||
ACTIVITY_JSON=$(_emby_api "System/ActivityLog/Entries?MinDate=${CUTOFF_ISO}&Limit=5000") || {
|
||||
ACTIVITY_JSON=$(emby_api "System/ActivityLog/Entries?MinDate=${CUTOFF_ISO}&Limit=5000") || {
|
||||
error "Could not fetch Emby activity log"
|
||||
exit 1
|
||||
}
|
||||
@@ -366,7 +355,7 @@ if [[ "${#ITEM_PLAYS[@]}" -gt 0 ]]; then
|
||||
for (( _b=0; _b<${#ALL_ITEM_IDS[@]}; _b+=BATCH_SIZE )); do
|
||||
BATCH=("${ALL_ITEM_IDS[@]:_b:BATCH_SIZE}")
|
||||
IDS_CSV=$(printf '%s,' "${BATCH[@]}"); IDS_CSV="${IDS_CSV%,}"
|
||||
ITEMS_DETAIL=$(_emby_api "Items?Ids=${IDS_CSV}&Fields=ProviderIds,Type&Limit=200") || {
|
||||
ITEMS_DETAIL=$(emby_api "Items?Ids=${IDS_CSV}&Fields=ProviderIds,Type&Limit=200") || {
|
||||
warn "Could not fetch item batch starting at $_b"
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -216,17 +216,6 @@ fi
|
||||
# ── API HELPERS ───────────────────────────────────────────────────────────────────────────────
|
||||
# ==============================================================================================
|
||||
|
||||
_emby_api() {
|
||||
local response http_code body
|
||||
response=$(curl -sf --max-time 30 \
|
||||
-H "X-Emby-Token: $EMBY_API_KEY" \
|
||||
-w "\n%{http_code}" \
|
||||
"${EMBY_URL}/${1}" 2>/dev/null)
|
||||
http_code=$(echo "$response" | tail -1)
|
||||
body=$(echo "$response" | head -n -1)
|
||||
[[ "$http_code" != "200" ]] && { error "Emby API HTTP $http_code: $1"; return 1; }
|
||||
echo "$body"
|
||||
}
|
||||
|
||||
_sonarr_get() {
|
||||
curl -sf --max-time 30 \
|
||||
@@ -348,7 +337,7 @@ echo "$ICON_HOST $MY_ID ($LOCAL_SERVER_NAME) | lookback: ${LOOKBACK_DAYS}d | thr
|
||||
echo ""
|
||||
echo "━━━ $ICON_SYNC Emby Series Library ━━━"
|
||||
|
||||
LIBRARIES_JSON=$(_emby_api "Library/VirtualFolders") || { error "Could not fetch Emby libraries"; exit 1; }
|
||||
LIBRARIES_JSON=$(emby_api "Library/VirtualFolders") || { error "Could not fetch Emby libraries"; exit 1; }
|
||||
CUTOFF_ISO=$(date -d "${LOOKBACK_DAYS} days ago" '+%Y-%m-%dT%H:%M:%SZ')
|
||||
TODAY_EPOCH=$(date +%s)
|
||||
TODAY=$(date +%Y-%m-%d)
|
||||
@@ -369,7 +358,7 @@ for lib_name in "${SONARR_EMBY_LIBRARIES[@]}"; do
|
||||
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") || {
|
||||
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
|
||||
}
|
||||
@@ -404,7 +393,7 @@ echo "━━━ $ICON_SYNC Emby Watch History ━━━"
|
||||
declare -A ITEM_USER_PLAYS # "episode_item_id|user_id" → play count
|
||||
declare -A ITEM_LAST_PLAY # episode_item_id → ISO date of most recent play
|
||||
|
||||
ACTIVITY_JSON=$(_emby_api "System/ActivityLog/Entries?MinDate=${CUTOFF_ISO}&Limit=5000") || {
|
||||
ACTIVITY_JSON=$(emby_api "System/ActivityLog/Entries?MinDate=${CUTOFF_ISO}&Limit=5000") || {
|
||||
error "Could not fetch Emby activity log"
|
||||
exit 1
|
||||
}
|
||||
@@ -448,7 +437,7 @@ if [[ "${#ALL_EPISODE_IDS[@]}" -gt 0 ]]; then
|
||||
for (( _b=0; _b<${#ALL_EPISODE_IDS[@]}; _b+=BATCH_SIZE )); do
|
||||
BATCH=("${ALL_EPISODE_IDS[@]:_b:BATCH_SIZE}")
|
||||
IDS_CSV=$(printf '%s,' "${BATCH[@]}"); IDS_CSV="${IDS_CSV%,}"
|
||||
ITEMS_DETAIL=$(_emby_api "Items?Ids=${IDS_CSV}&Fields=SeriesId,Type&Limit=200") || {
|
||||
ITEMS_DETAIL=$(emby_api "Items?Ids=${IDS_CSV}&Fields=SeriesId,Type&Limit=200") || {
|
||||
warn "Could not fetch episode batch starting at $_b"
|
||||
continue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user