diff --git a/ui/pages/__pycache__/artists.cpython-312.pyc b/ui/pages/__pycache__/artists.cpython-312.pyc index a150c96c..6cd77227 100644 Binary files a/ui/pages/__pycache__/artists.cpython-312.pyc and b/ui/pages/__pycache__/artists.cpython-312.pyc differ diff --git a/ui/pages/__pycache__/downloads.cpython-310.pyc b/ui/pages/__pycache__/downloads.cpython-310.pyc index e79b52f0..cfb035e0 100644 Binary files a/ui/pages/__pycache__/downloads.cpython-310.pyc and b/ui/pages/__pycache__/downloads.cpython-310.pyc differ diff --git a/ui/pages/__pycache__/downloads.cpython-312.pyc b/ui/pages/__pycache__/downloads.cpython-312.pyc index b3d8760b..645a368e 100644 Binary files a/ui/pages/__pycache__/downloads.cpython-312.pyc and b/ui/pages/__pycache__/downloads.cpython-312.pyc differ diff --git a/ui/pages/downloads.py b/ui/pages/downloads.py index cc320e42..6176e3f8 100644 --- a/ui/pages/downloads.py +++ b/ui/pages/downloads.py @@ -7965,8 +7965,18 @@ class DownloadsPage(QWidget): 'album_image_url': album_image_url } - # PRIORITY 1: Always try Spotify API first for clean metadata - print(f"🔍 Searching Spotify for track info (PRIORITY 1)...") + # PRIORITY 1: Try album-aware search if we have album context + if hasattr(download_item, 'album') and download_item.album and download_item.album.strip() and download_item.album != "Unknown Album": + print(f"🎯 ALBUM-AWARE SEARCH: Looking for '{download_item.title}' in album '{download_item.album}'") + album_result = self._search_track_in_album_context(download_item, artist) + if album_result: + print(f"✅ Found track in album context - using album classification") + return album_result + else: + print(f"⚠️ Track not found in album context, falling back to individual search") + + # PRIORITY 2: Fallback to individual track search for clean metadata + print(f"🔍 Searching Spotify for individual track info (PRIORITY 2)...") # Clean the track title before searching - remove artist prefix clean_title = self._clean_track_title(download_item.title, artist.name) @@ -8101,7 +8111,7 @@ class DownloadsPage(QWidget): 'album_image_url': album_image_url } - # PRIORITY 2: Fallback to Soulseek album context if Spotify search failed + # PRIORITY 3: Fallback to Soulseek album context if Spotify search failed print(f"🔍 No good Spotify match found (confidence: {best_confidence:.2f}), checking Soulseek album context...") if hasattr(download_item, 'album') and download_item.album and download_item.album != "Unknown Album": @@ -8129,7 +8139,7 @@ class DownloadsPage(QWidget): 'album_image_url': album_image_url } - # PRIORITY 3: Complete fallback - single track with cleaned title + # PRIORITY 4: Complete fallback - single track with cleaned title print(f"🎯 No album context found, defaulting to single track structure with cleaned title") clean_title = self._clean_track_title(download_item.title, artist.name) @@ -8168,6 +8178,72 @@ class DownloadsPage(QWidget): 'album_image_url': album_image_url } + def _search_track_in_album_context(self, download_item, artist: Artist) -> Optional[dict]: + """Search for a track within its album context to avoid promotional single confusion""" + try: + album_name = download_item.album + track_title = download_item.title + + print(f"🎯 Album-aware search: '{track_title}' in album '{album_name}' by '{artist.name}'") + + # Clean the album name for better search results + clean_album = self._clean_album_title(album_name, artist.name) + clean_track = self._clean_track_title(track_title, artist.name) + + # Search for the specific album first + album_query = f"album:{clean_album} artist:{artist.name}" + print(f"🔍 Searching albums: {album_query}") + albums = self.spotify_client.search_albums(album_query, limit=5) + + if not albums: + print(f"❌ No albums found for query: {album_query}") + return None + + # Check each album to see if our track is in it + for album in albums: + print(f"🎵 Checking album: '{album.name}' ({album.total_tracks} tracks)") + + # Get tracks from this album + album_tracks_data = self.spotify_client.get_album_tracks(album.id) + if not album_tracks_data or 'items' not in album_tracks_data: + print(f"❌ Could not get tracks for album: {album.name}") + continue + + # Check if our track is in this album + for track_data in album_tracks_data['items']: + track_name = track_data['name'] + track_number = track_data['track_number'] + + # Calculate similarity between our track and this album track + similarity = self.matching_engine.similarity_score( + self.matching_engine.normalize_string(clean_track), + self.matching_engine.normalize_string(track_name) + ) + + if similarity > 0.7: # Good match threshold + print(f"✅ FOUND: '{track_name}' (track #{track_number}) matches '{clean_track}' (similarity: {similarity:.2f})") + print(f"🎯 Forcing album classification for track in '{album.name}'") + + # Return album info - force album classification! + return { + 'is_album': True, # Always true - we found it in an album! + 'album_name': album.name, + 'track_number': track_number, + 'clean_track_name': track_name, # Use Spotify's clean name + 'album_image_url': album.image_url, + 'confidence': similarity, + 'source': 'album_context_search' + } + + print(f"❌ Track '{clean_track}' not found in album '{album.name}'") + + print(f"❌ Track '{clean_track}' not found in any matching albums") + return None + + except Exception as e: + print(f"❌ Error in album-aware search: {e}") + return None + def _download_cover_art(self, artist: Artist, album_info: dict, target_dir: str): """Download cover art for the album, prioritizing album artwork from Spotify""" try: