Sync: append mode preserves the playlist image like reconcile (#811)
#811 (reopen of #792, carlosjfcasero, Emby/Jellyfin): "append" mode clobbered the playlist's custom image. The post-sync image push only excluded 'reconcile' — so append (which edits the playlist in place via append_to_playlist) still re-pushed the source image over the user's poster every sync. Now both in-place modes (reconcile + append) skip the image push; only the destructive 'replace' (recreate-from-scratch) pushes it. append_to_playlist + set_playlist_image were verified to NOT touch tracks or description (image push only POSTs /Images/Primary), so this is the identity- clobber fix for append. Tests: append + reconcile preserve the image, replace still pushes it.
This commit is contained in:
parent
1fba950284
commit
40e3dac881
2 changed files with 49 additions and 6 deletions
|
|
@ -524,12 +524,12 @@ def run_sync_task(
|
|||
# don't want persisted to app.log.
|
||||
_synced = getattr(result, 'synced_tracks', 0)
|
||||
logger.info(f"[PLAYLIST IMAGE] has_image={bool(playlist_image_url)}, synced_tracks={_synced}")
|
||||
# In reconcile mode the whole point (#792) is to NOT touch the playlist's
|
||||
# existing image — pushing the source image here would re-clobber a
|
||||
# user's custom poster every sync, the exact bug reconcile fixes. So skip
|
||||
# the auto image push for reconcile (the playlist keeps its own art).
|
||||
if sync_mode == 'reconcile':
|
||||
logger.info("[PLAYLIST IMAGE] reconcile mode — preserving existing playlist image")
|
||||
# Modes that edit a playlist in place (reconcile #792, append #811) must
|
||||
# NOT push the source image — doing so re-clobbers a user's custom poster
|
||||
# every sync, the exact bug these modes exist to avoid. Only the
|
||||
# destructive 'replace' (recreate-from-scratch) pushes the image.
|
||||
if sync_mode in ('reconcile', 'append'):
|
||||
logger.info(f"[PLAYLIST IMAGE] {sync_mode} mode — preserving existing playlist image")
|
||||
elif playlist_image_url and _synced > 0:
|
||||
try:
|
||||
active_server = deps.config_manager.get_active_media_server()
|
||||
|
|
|
|||
|
|
@ -364,6 +364,49 @@ def test_playlist_image_uploaded_to_jellyfin(patched_db):
|
|||
assert jf.image_calls == [('PJF', 'https://img/y.png')]
|
||||
|
||||
|
||||
def test_append_mode_preserves_playlist_image(patched_db):
|
||||
"""Append edits in place — it must NOT re-push the source image over the
|
||||
user's custom poster (#811)."""
|
||||
jf = _FakeJellyfin()
|
||||
cfg = _FakeConfig(server='jellyfin')
|
||||
result = _FakeSyncResult(synced_tracks=3)
|
||||
svc = _FakeSyncService(media_client=_FakeMediaClient(), sync_result=result)
|
||||
deps = _build_deps(sync_service=svc, jellyfin=jf, config=cfg)
|
||||
|
||||
ds.run_sync_task('pA', 'PA', [_track()],
|
||||
playlist_image_url='https://img/a.png', deps=deps, sync_mode='append')
|
||||
|
||||
assert jf.image_calls == [] # preserved, not clobbered
|
||||
|
||||
|
||||
def test_reconcile_mode_preserves_playlist_image(patched_db):
|
||||
"""Reconcile likewise preserves the image (#792)."""
|
||||
jf = _FakeJellyfin()
|
||||
cfg = _FakeConfig(server='jellyfin')
|
||||
result = _FakeSyncResult(synced_tracks=3)
|
||||
svc = _FakeSyncService(media_client=_FakeMediaClient(), sync_result=result)
|
||||
deps = _build_deps(sync_service=svc, jellyfin=jf, config=cfg)
|
||||
|
||||
ds.run_sync_task('pR', 'PR', [_track()],
|
||||
playlist_image_url='https://img/r.png', deps=deps, sync_mode='reconcile')
|
||||
|
||||
assert jf.image_calls == []
|
||||
|
||||
|
||||
def test_replace_mode_still_pushes_playlist_image(patched_db):
|
||||
"""Replace recreates from scratch, so it does push the source image."""
|
||||
jf = _FakeJellyfin()
|
||||
cfg = _FakeConfig(server='jellyfin')
|
||||
result = _FakeSyncResult(synced_tracks=3)
|
||||
svc = _FakeSyncService(media_client=_FakeMediaClient(), sync_result=result)
|
||||
deps = _build_deps(sync_service=svc, jellyfin=jf, config=cfg)
|
||||
|
||||
ds.run_sync_task('pRep', 'PRep', [_track()],
|
||||
playlist_image_url='https://img/rep.png', deps=deps, sync_mode='replace')
|
||||
|
||||
assert jf.image_calls == [('PRep', 'https://img/rep.png')]
|
||||
|
||||
|
||||
def test_no_image_upload_when_zero_synced(patched_db):
|
||||
"""synced_tracks == 0 → no playlist image upload."""
|
||||
plex = _FakePlex()
|
||||
|
|
|
|||
Loading…
Reference in a new issue