diff --git a/Media/play_state_sync.sh b/Media/play_state_sync.sh index dd31a19..71e811b 100755 --- a/Media/play_state_sync.sh +++ b/Media/play_state_sync.sh @@ -276,24 +276,42 @@ done # per-item API call and is faster overall. declare -A PROV_LOOKUP # "si|tvdb.{id}" | "si|imdb.{id}" | "si|mb.{id}" → item_id +# Jellyfin's mixed-type query (Movie,Episode,Audio) changes sort order unpredictably, +# pushing items to positions far beyond the first pages. Query each type separately so +# each list sorts within its own type and items appear where expected. +_PROV_PAGE=2000 +IFS=',' read -ra _prov_types <<< "$SYNC_TYPES" + for _psi in $(seq 0 $(( _srv_count - 1 ))); do [[ -z "${SRV_URL[$_psi]}" ]] && continue log "Building provider ID map for ${SRV_NAME[$_psi]}..." - _raw_prov=$(_api_get "${SRV_URL[$_psi]}" "${SRV_KEY[$_psi]}" \ - "Items?Recursive=true&IncludeItemTypes=${SYNC_TYPES}&Fields=ProviderIds&ExcludeLocationTypes=Virtual" 2>/dev/null) - [[ -z "$_raw_prov" ]] && continue - while IFS=$'\t' read -r _pid _ptvdb _pimdb _ptmdb _pmbtrack; do - [[ "$_ptvdb" != "null" && -n "$_ptvdb" ]] && PROV_LOOKUP["${_psi}|tvdb.${_ptvdb}"]="$_pid" - [[ "$_pimdb" != "null" && -n "$_pimdb" ]] && PROV_LOOKUP["${_psi}|imdb.${_pimdb}"]="$_pid" - [[ "$_ptmdb" != "null" && -n "$_ptmdb" ]] && PROV_LOOKUP["${_psi}|tmdb.${_ptmdb}"]="$_pid" - [[ "$_pmbtrack" != "null" && -n "$_pmbtrack" ]] && PROV_LOOKUP["${_psi}|mb.${_pmbtrack}"]="$_pid" - done < <(echo "$_raw_prov" | jq -r '.Items[] | [ - .Id, - (.ProviderIds.Tvdb // "null"), - (.ProviderIds.Imdb // "null"), - (.ProviderIds.Tmdb // "null"), - (.ProviderIds.MusicBrainzTrackId // "null") - ] | @tsv' 2>/dev/null) + for _prov_type in "${_prov_types[@]}"; do + _prov_start=0 + _prov_total=-1 + while true; do + _page=$(curl -sf --max-time 60 \ + -H "X-Emby-Token: ${SRV_KEY[$_psi]}" \ + "${SRV_URL[$_psi]%/}/Items?Recursive=true&IncludeItemTypes=${_prov_type}&Fields=ProviderIds&Limit=${_PROV_PAGE}&StartIndex=${_prov_start}" 2>/dev/null) + [[ -z "$_page" ]] && break + [[ "$_prov_total" -lt 0 ]] && _prov_total=$(echo "$_page" | jq '.TotalRecordCount // 0' 2>/dev/null || echo 0) + _prov_count=$(echo "$_page" | jq '.Items | length' 2>/dev/null || echo 0) + [[ "$_prov_count" -eq 0 ]] && break + while IFS=$'\t' read -r _pid _ptvdb _pimdb _ptmdb _pmbtrack; do + [[ "$_ptvdb" != "null" && -n "$_ptvdb" ]] && PROV_LOOKUP["${_psi}|tvdb.${_ptvdb}"]="$_pid" + [[ "$_pimdb" != "null" && -n "$_pimdb" ]] && PROV_LOOKUP["${_psi}|imdb.${_pimdb}"]="$_pid" + [[ "$_ptmdb" != "null" && -n "$_ptmdb" ]] && PROV_LOOKUP["${_psi}|tmdb.${_ptmdb}"]="$_pid" + [[ "$_pmbtrack" != "null" && -n "$_pmbtrack" ]] && PROV_LOOKUP["${_psi}|mb.${_pmbtrack}"]="$_pid" + done < <(echo "$_page" | jq -r '.Items[] | [ + .Id, + (.ProviderIds.Tvdb // "null"), + (.ProviderIds.Imdb // "null"), + (.ProviderIds.Tmdb // "null"), + (.ProviderIds.MusicBrainzTrackId // "null") + ] | @tsv' 2>/dev/null) + _prov_start=$(( _prov_start + _prov_count )) + [[ "$_prov_total" -gt 0 && "$_prov_start" -ge "$_prov_total" ]] && break + done + done done # ── Step 3: Sync per matched user ────────────────────────────────────────────