From 8cbd0fdad4dfe21eb0c4d5af824796555f7d2e8d Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Fri, 10 Apr 2026 11:07:47 +0000 Subject: [PATCH] Fix file path construction using placeholder artist names When Spotify API is rate-limited or returns incomplete metadata, the album-level artist resolution logic in _build_final_path_for_track would incorrectly override valid track artist names with placeholder values like 'Unknown Artist' or empty strings from fallback sources. This fix adds validation to prevent placeholder names from overriding valid artist names: - Define placeholder set: 'Unknown Artist', 'Unknown', '', 'Various Artists', 'No artist', 'MISSING' - Add _is_valid_artist_name() helper to validate names before using them - Only override default artist name if fallback provides a valid non-placeholder - Preserve spotify_artist['name'] when fallbacks are invalid Fixes paths like '/app/Transfer/Unknown Artist/Unknown Artist - Album/' when correct artist metadata is available but spotify_album.artists contains empty or placeholder values. --- web_server.py | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/web_server.py b/web_server.py index 747b3f47..3bbb6be2 100644 --- a/web_server.py +++ b/web_server.py @@ -16766,28 +16766,51 @@ def _build_final_path_for_track(context, spotify_artist, album_info, file_ext): # Per-track spotify_artist may vary on collab albums or after artist name changes. # Prefer stable album-level sources so all tracks land in the same folder. _artist_name = spotify_artist["name"] if isinstance(spotify_artist, dict) else spotify_artist.name - _album_artist_name = _artist_name # default: same as track artist + _album_artist_name = _artist_name # default: same as track artist (always valid) + + # Placeholder names that should NEVER override a valid artist name + _placeholder_names = {'Unknown Artist', 'Unknown', '', 'Various Artists', 'No artist', 'MISSING'} # Build album-level artists list for collab mode resolution. # Using album-level artists (instead of per-track _artists) ensures collab mode # produces the SAME result for every track, preventing folder/tag splits. _album_artists_for_collab = None # None = fall back to per-track _artists _explicit_artist_ctx = track_info.get('_explicit_artist_context') if isinstance(track_info, dict) else None + + # Helper to check if a name is valid (non-empty and not a placeholder) + def _is_valid_artist_name(name): + if not name or not isinstance(name, str): + return False + return name.strip() and name.strip() not in _placeholder_names + + # Try to get album artist from explicit context first if isinstance(_explicit_artist_ctx, dict) and _explicit_artist_ctx.get('name'): - _album_artist_name = _explicit_artist_ctx['name'] - _album_artists_for_collab = [_explicit_artist_ctx] + candidate_name = _explicit_artist_ctx['name'] + if _is_valid_artist_name(candidate_name): + _album_artist_name = candidate_name + _album_artists_for_collab = [_explicit_artist_ctx] elif isinstance(_explicit_artist_ctx, str) and _explicit_artist_ctx: - _album_artist_name = _explicit_artist_ctx - _album_artists_for_collab = [{'name': _explicit_artist_ctx}] - else: + if _is_valid_artist_name(_explicit_artist_ctx): + _album_artist_name = _explicit_artist_ctx + _album_artists_for_collab = [{'name': _explicit_artist_ctx}] + + # Fallback to spotify_album.artists - BUT only use if name is valid and not a placeholder + # This prevents "Unknown Artist" or empty names from overriding the correct track artist + if _album_artists_for_collab is None: _sa_artists = _spotify_album.get('artists', []) if _spotify_album else [] if _sa_artists: _first_sa = _sa_artists[0] + candidate_name = None if isinstance(_first_sa, dict) and _first_sa.get('name'): - _album_artist_name = _first_sa['name'] + candidate_name = _first_sa['name'] elif isinstance(_first_sa, str) and _first_sa: - _album_artist_name = _first_sa - _album_artists_for_collab = _sa_artists + candidate_name = _first_sa + + # Only override if we have a valid name that's not a placeholder + if _is_valid_artist_name(candidate_name): + _album_artist_name = candidate_name + _album_artists_for_collab = _sa_artists + # Otherwise, keep _album_artist_name = _artist_name (the track artist) template_context = { 'artist': _artist_name,