Add play_state_sync.sh — sync watched state across Emby + Jellyfin

Syncs played/resume state bidirectionally across all configured Emby
and Jellyfin servers. Newest LastPlayedDate wins; users matched by
name (case-insensitive); unmatched users skipped cleanly.

Matching: IMDb/TMDB for movies, TVDB+s/e for episodes, MusicBrainz
track ID for audio. Also syncs resume positions for partial plays.

Config: PLAY_SYNC_ENABLED, PLAY_SYNC_DAYS (default 90), PLAY_SYNC_TYPES.
Modes: --dry-run, --status, --full (ignore day window), --log.
Wired into DAILY_MAINTENANCE_SCRIPTS after arr cleanup.
This commit is contained in:
Gmer4Lfe
2026-05-30 00:02:18 -04:00
parent ce9748096c
commit 26693fd11f
2 changed files with 488 additions and 0 deletions
+9
View File
@@ -353,6 +353,7 @@
"Media/lidarr_missing_art.sh" # fetch missing album/artist artwork (HOST1 only — self-guards)
"Media/radarr_tmdb_removed.sh" # remove movies dropped from TMDb
"Media/sonarr_tvdb_removed.sh" # remove series dropped from TVDB
"Media/play_state_sync.sh" # sync watched/resume state across Emby + Jellyfin
"Docker_Essentials/docker_update.sh" # pull container image updates before restart
"Docker_Essentials/docker_daily_restart.sh" # daily container restarts — runs last
)
@@ -1244,6 +1245,14 @@
EMBY_REPORT_DAYS=7 # days to include in the report period
EMBY_REPORT_TOP_N=10 # number of top content items to show
# ━━━ Play State Sync ━━━
# Syncs watched state and resume positions across all configured Emby and Jellyfin servers.
# Newest LastPlayedDate wins — no data is ever lost. Users matched by name (case-insensitive).
# Called via DAILY_MAINTENANCE_SCRIPTS. Run manually: Media/play_state_sync.sh
PLAY_SYNC_ENABLED=true
PLAY_SYNC_DAYS=90 # how many days back to look (0 = all time, slow on large libraries)
PLAY_SYNC_TYPES="Movie,Episode,Audio" # item types to sync
# ==============================================================================================
# ── RESOURCE MANAGER ──────────────────────────────────────────────────────────────────────────
# ==============================================================================================