From 6ce90ba10db5319cc5476abf75f0ad8fa91c9cfd Mon Sep 17 00:00:00 2001 From: JohnBaumb <80135794+JohnBaumb@users.noreply.github.com> Date: Mon, 27 Apr 2026 10:11:06 -0700 Subject: [PATCH] fix: seasonal service constructor, source-aware track IDs, deep-link timing - Use get_seasonal_discovery_service(spotify_client, database) instead of broken SeasonalDiscoveryService(database) in both auto-sync and track_count paths - Replace nonexistent get_current_season_playlist() with working get_current_season() + get_curated_seasonal_playlist() pattern - Use generic track_id field for personalized playlist auto-sync instead of hardcoded spotify_track_id (fixes Deezer/iTunes) - Replace fixed 400ms setTimeout in _applySyncTabAction with polling loop that waits for target element (up to 4s) --- web_server.py | 60 +++++++++++++++++++++++++---------- webui/static/sync-services.js | 15 +++++++-- 2 files changed, 57 insertions(+), 18 deletions(-) diff --git a/web_server.py b/web_server.py index 0f458af4..08a65f9c 100644 --- a/web_server.py +++ b/web_server.py @@ -44103,17 +44103,41 @@ def _auto_sync_discover_playlists(profile_id, active_source): 'duration_ms': t.duration_ms or 0 }) elif ptype == 'seasonal_playlist': - from core.seasonal_discovery import SeasonalDiscoveryService - seasonal_svc = SeasonalDiscoveryService(database) - season_data = seasonal_svc.get_current_season_playlist() - if season_data and season_data.get('tracks'): - tracks = [{ - 'id': t.get('spotify_track_id', ''), - 'name': t.get('track_name', ''), - 'artists': [t.get('artist_name', '')], - 'album': t.get('album_name', ''), - 'duration_ms': t.get('duration_ms', 0) - } for t in season_data['tracks']] + from core.seasonal_discovery import get_seasonal_discovery_service, SEASONAL_CONFIG + seasonal_svc = get_seasonal_discovery_service(spotify_client, database) + current_season = seasonal_svc.get_current_season() + if current_season and current_season in SEASONAL_CONFIG: + track_ids = seasonal_svc.get_curated_seasonal_playlist(current_season, source=active_source) + if track_ids: + if active_source == 'itunes': + s_id_col = 'itunes_track_id' + elif active_source == 'deezer': + s_id_col = 'deezer_track_id' + else: + s_id_col = 'spotify_track_id' + with database._get_connection() as conn: + cursor = conn.cursor() + for tid in track_ids: + cursor.execute(f""" + SELECT {s_id_col} as track_id, track_name, artist_name, album_name, duration_ms + FROM seasonal_tracks WHERE {s_id_col} = ? AND source = ? + """, (tid, active_source)) + row = cursor.fetchone() + if not row: + cursor.execute(f""" + SELECT {s_id_col} as track_id, track_name, artist_name, album_name, duration_ms + FROM discovery_pool WHERE {s_id_col} = ? AND source = ? + """, (tid, active_source)) + row = cursor.fetchone() + if row: + r = dict(row) + tracks.append({ + 'id': r.get('track_id', ''), + 'name': r.get('track_name', ''), + 'artists': [r.get('artist_name', '')], + 'album': r.get('album_name', ''), + 'duration_ms': r.get('duration_ms', 0) + }) else: from core.personalized_playlists import PersonalizedPlaylistsService service = PersonalizedPlaylistsService(database) @@ -44126,7 +44150,7 @@ def _auto_sync_discover_playlists(profile_id, active_source): if ptype in method_map: raw_tracks = method_map[ptype](limit=50) tracks = [{ - 'id': t.get('spotify_track_id', ''), + 'id': t.get('track_id') or t.get('spotify_track_id') or t.get('deezer_track_id') or t.get('itunes_track_id') or '', 'name': t.get('track_name', ''), 'artists': [t.get('artist_name', '')], 'album': t.get('album_name', ''), @@ -44192,11 +44216,15 @@ def get_discover_synced_playlists(): curated_ids = database.get_curated_playlist(ptype, profile_id=pid) track_count = len(curated_ids) if curated_ids else 0 elif ptype == 'seasonal_playlist': - from core.seasonal_discovery import SeasonalDiscoveryService + from core.seasonal_discovery import get_seasonal_discovery_service try: - seasonal_svc = SeasonalDiscoveryService(database) - season_data = seasonal_svc.get_current_season_playlist() - track_count = len(season_data.get('tracks', [])) if season_data else 0 + seasonal_svc = get_seasonal_discovery_service(spotify_client, database) + current_season = seasonal_svc.get_current_season() + if current_season: + curated = seasonal_svc.get_curated_seasonal_playlist(current_season, source=active_source) + track_count = len(curated) if curated else 0 + else: + track_count = 0 except Exception: track_count = 0 else: diff --git a/webui/static/sync-services.js b/webui/static/sync-services.js index 26a817f1..a6e8ddf9 100644 --- a/webui/static/sync-services.js +++ b/webui/static/sync-services.js @@ -2780,8 +2780,19 @@ function _applySyncTabAction() { syncDiscoverPlaylistFromTab(action.autoSync, action.autoSyncName || action.autoSync); } }; - // Small delay to let lazy tab content render - setTimeout(apply, 400); + // Wait for lazy-loaded content to appear before applying + let attempts = 0; + const maxAttempts = 20; // 20 * 200ms = 4s max + const waitAndApply = () => { + const ready = !action.highlight || document.getElementById(action.highlight); + if (ready || attempts >= maxAttempts) { + apply(); + } else { + attempts++; + setTimeout(waitAndApply, 200); + } + }; + setTimeout(waitAndApply, 200); } function initializeSyncPage() {