From f788361b0802eed23568203946a040f1117d0cf3 Mon Sep 17 00:00:00 2001 From: Broque Thomas <26755000+Nezreka@users.noreply.github.com> Date: Mon, 30 Mar 2026 17:50:30 -0700 Subject: [PATCH] Fix pipeline stopping when metadata discovery fails (#224) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Playlist auto-sync was dropping tracks that failed iTunes/Apple Music discovery — they never reached the wishlist or download pipeline. Now undiscovered tracks continue through using available metadata: first from the spotify_hint (embed scraper data with real Spotify track ID, name, artists), then from raw playlist fields if a source track ID exists. Album cover art from the mirrored playlist is included. Only tracks with no usable ID or name are skipped. --- web_server.py | 52 ++++++++++++++++++++++++++++++++++++++++-- webui/static/helper.js | 1 + 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/web_server.py b/web_server.py index 8e697c5d..b868498a 100644 --- a/web_server.py +++ b/web_server.py @@ -834,8 +834,47 @@ def _register_automation_handlers(): 'id': md.get('id', ''), }) else: - # NOT discovered — skip to prevent garbage in wishlist - skipped_count += 1 + # NOT discovered — try to include using available metadata so the + # track can still be searched on Soulseek and added to wishlist. + # Without this, failed discovery blocks the entire download pipeline. + # + # Priority: spotify_hint (has real Spotify ID from embed scraper) + # > raw playlist fields (only if source_track_id is valid) + hint = extra.get('spotify_hint', {}) + # Build album object with cover art from the mirrored playlist track + track_image = (t.get('image_url') or '').strip() + album_obj = { + 'name': (t.get('album_name') or '').strip(), + 'images': [{'url': track_image, 'height': 300, 'width': 300}] if track_image else [], + } + + if hint.get('id') and hint.get('name'): + # spotify_hint has proper Spotify track ID + metadata from embed scraper + hint_artists = hint.get('artists', []) + if hint_artists and isinstance(hint_artists[0], str): + hint_artists = [{'name': a} for a in hint_artists] + elif hint_artists and isinstance(hint_artists[0], dict): + pass # Already in correct format + else: + hint_artists = [{'name': t.get('artist_name', '')}] + tracks_json.append({ + 'name': hint['name'], + 'artists': hint_artists, + 'album': album_obj, + 'duration_ms': t.get('duration_ms', 0), + 'id': hint['id'], + }) + elif t.get('source_track_id') and (t.get('track_name') or '').strip(): + # Has a valid source ID and track name — usable for wishlist + tracks_json.append({ + 'name': t['track_name'].strip(), + 'artists': [{'name': (t.get('artist_name') or '').strip() or 'Unknown Artist'}], + 'album': album_obj, + 'duration_ms': t.get('duration_ms', 0), + 'id': t['source_track_id'], + }) + else: + skipped_count += 1 # No usable ID or name — truly can't process if not tracks_json: _update_automation_progress(auto_id, @@ -19207,6 +19246,15 @@ def get_version_info(): "title": "What's New in SoulSync", "subtitle": f"Version {SOULSYNC_VERSION} — Latest Changes", "sections": [ + { + "title": "🔧 Fix Pipeline Stops When Metadata Match Fails (#224)", + "description": "Playlist sync no longer drops tracks that failed iTunes/Apple Music discovery", + "features": [ + "• Tracks that fail metadata discovery now continue through the pipeline using original playlist data", + "• Track name and artist from the source playlist are used for Soulseek search when discovery fails", + "• Only tracks with completely missing name/artist are skipped (not tracks that simply failed matching)" + ] + }, { "title": "🌳 Playlist Explorer — Visual Discovery Tree", "description": "Use playlists as seeds to discover full albums and discographies", diff --git a/webui/static/helper.js b/webui/static/helper.js index 1e379635..b29148af 100644 --- a/webui/static/helper.js +++ b/webui/static/helper.js @@ -3403,6 +3403,7 @@ function closeHelperSearch() { const WHATS_NEW = { '2.1': [ // Newest features first + { title: 'Fix Pipeline Blocking on Discovery Fail', desc: 'Playlist sync no longer drops tracks that failed metadata discovery — continues with original name/artist for download' }, { title: 'Playlist Explorer', desc: 'New page: expand playlists into visual discovery trees of albums and discographies — select and add to wishlist', page: 'playlist-explorer' }, { title: 'Fix Invalid .LRC Lyrics Files', desc: 'Plain lyrics now saved as .txt — only synced (timestamped) lyrics get the .lrc extension' }, { title: 'Fix Collab Artist on Singles', desc: 'Single/playlist path templates now respect First Listed Artist setting — $albumartist available for all template types' },