Fix hero slider + recommended modal returning 0 artists
get_top_similar_artists now accepts require_source parameter to filter by source ID in SQL. Previously fetched 200 artists then post-filtered, but cycling logic (last_featured ASC) rotated artists without IDs to the front, causing all 200 to be filtered out. Both /api/discover/hero and /api/discover/similar-artists now pass require_source=active_source so only artists with valid IDs are returned.
This commit is contained in:
parent
36e83e64ee
commit
c336604b71
2 changed files with 20 additions and 22 deletions
|
|
@ -7260,13 +7260,23 @@ class MusicDatabase:
|
||||||
logger.error(f"Error checking similar artists freshness: {e}")
|
logger.error(f"Error checking similar artists freshness: {e}")
|
||||||
return False # Default to re-fetching on error
|
return False # Default to re-fetching on error
|
||||||
|
|
||||||
def get_top_similar_artists(self, limit: int = 50, profile_id: int = 1) -> List[SimilarArtist]:
|
def get_top_similar_artists(self, limit: int = 50, profile_id: int = 1, require_source: str = None) -> List[SimilarArtist]:
|
||||||
"""Get top similar artists excluding watchlist artists, with cycling support"""
|
"""Get top similar artists excluding watchlist artists, with cycling support.
|
||||||
|
require_source: if set ('spotify','itunes','deezer'), only returns artists with that source ID."""
|
||||||
try:
|
try:
|
||||||
with self._get_connection() as conn:
|
with self._get_connection() as conn:
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
||||||
cursor.execute("""
|
# Build source filter
|
||||||
|
source_filter = ''
|
||||||
|
if require_source == 'spotify':
|
||||||
|
source_filter = "AND sa.similar_artist_spotify_id IS NOT NULL AND sa.similar_artist_spotify_id != ''"
|
||||||
|
elif require_source == 'itunes':
|
||||||
|
source_filter = "AND sa.similar_artist_itunes_id IS NOT NULL AND sa.similar_artist_itunes_id != ''"
|
||||||
|
elif require_source == 'deezer':
|
||||||
|
source_filter = "AND sa.similar_artist_deezer_id IS NOT NULL AND sa.similar_artist_deezer_id != ''"
|
||||||
|
|
||||||
|
cursor.execute(f"""
|
||||||
SELECT
|
SELECT
|
||||||
MAX(sa.id) as id,
|
MAX(sa.id) as id,
|
||||||
MAX(sa.source_artist_id) as source_artist_id,
|
MAX(sa.source_artist_id) as source_artist_id,
|
||||||
|
|
@ -7287,7 +7297,7 @@ class MusicDatabase:
|
||||||
OR (sa.similar_artist_deezer_id IS NOT NULL AND sa.similar_artist_deezer_id = wa.deezer_artist_id)
|
OR (sa.similar_artist_deezer_id IS NOT NULL AND sa.similar_artist_deezer_id = wa.deezer_artist_id)
|
||||||
OR LOWER(sa.similar_artist_name) = LOWER(wa.artist_name)
|
OR LOWER(sa.similar_artist_name) = LOWER(wa.artist_name)
|
||||||
) AND wa.profile_id = ?
|
) AND wa.profile_id = ?
|
||||||
WHERE wa.id IS NULL AND sa.profile_id = ?
|
WHERE wa.id IS NULL AND sa.profile_id = ? {source_filter}
|
||||||
GROUP BY sa.similar_artist_name
|
GROUP BY sa.similar_artist_name
|
||||||
ORDER BY
|
ORDER BY
|
||||||
CASE WHEN MAX(sa.last_featured) IS NULL THEN 0 ELSE 1 END,
|
CASE WHEN MAX(sa.last_featured) IS NULL THEN 0 ELSE 1 END,
|
||||||
|
|
|
||||||
|
|
@ -39021,7 +39021,8 @@ def get_discover_hero():
|
||||||
# Get top similar artists (excluding watchlist, cycled by last_featured)
|
# Get top similar artists (excluding watchlist, cycled by last_featured)
|
||||||
# Fetch more than needed since strict source filtering may drop many
|
# Fetch more than needed since strict source filtering may drop many
|
||||||
pid = get_current_profile_id()
|
pid = get_current_profile_id()
|
||||||
similar_artists = database.get_top_similar_artists(limit=200, profile_id=pid)
|
print(f"[Discover Hero] Profile ID: {pid}, Active source: {active_source}")
|
||||||
|
similar_artists = database.get_top_similar_artists(limit=200, profile_id=pid, require_source=active_source)
|
||||||
|
|
||||||
# FALLBACK: If no similar artists exist, use watchlist artists for Hero section
|
# FALLBACK: If no similar artists exist, use watchlist artists for Hero section
|
||||||
if not similar_artists:
|
if not similar_artists:
|
||||||
|
|
@ -39067,15 +39068,8 @@ def get_discover_hero():
|
||||||
print(f"[Discover Hero] Returning {len(hero_artists)} watchlist artists as fallback")
|
print(f"[Discover Hero] Returning {len(hero_artists)} watchlist artists as fallback")
|
||||||
return jsonify({"success": True, "artists": hero_artists, "source": active_source, "fallback": "watchlist"})
|
return jsonify({"success": True, "artists": hero_artists, "source": active_source, "fallback": "watchlist"})
|
||||||
|
|
||||||
# Filter to artists that have the appropriate ID for the active source
|
# Artists are already filtered by source in SQL — no post-filter needed
|
||||||
valid_artists = []
|
valid_artists = list(similar_artists)
|
||||||
for artist in similar_artists:
|
|
||||||
if active_source == 'spotify' and artist.similar_artist_spotify_id:
|
|
||||||
valid_artists.append(artist)
|
|
||||||
elif active_source == 'deezer' and getattr(artist, 'similar_artist_deezer_id', None):
|
|
||||||
valid_artists.append(artist)
|
|
||||||
elif active_source == 'itunes' and artist.similar_artist_itunes_id:
|
|
||||||
valid_artists.append(artist)
|
|
||||||
|
|
||||||
# FALLBACK: If no valid artists for fallback source, try to resolve IDs on-the-fly
|
# FALLBACK: If no valid artists for fallback source, try to resolve IDs on-the-fly
|
||||||
if active_source in ('itunes', 'deezer') and not valid_artists:
|
if active_source in ('itunes', 'deezer') and not valid_artists:
|
||||||
|
|
@ -39198,20 +39192,14 @@ def get_discover_similar_artists():
|
||||||
database = get_database()
|
database = get_database()
|
||||||
active_source = _get_active_discovery_source()
|
active_source = _get_active_discovery_source()
|
||||||
|
|
||||||
similar_artists = database.get_top_similar_artists(limit=200, profile_id=get_current_profile_id())
|
similar_artists = database.get_top_similar_artists(limit=200, profile_id=get_current_profile_id(), require_source=active_source)
|
||||||
|
|
||||||
if not similar_artists:
|
if not similar_artists:
|
||||||
return jsonify({"success": True, "artists": [], "source": active_source, "count": 0})
|
return jsonify({"success": True, "artists": [], "source": active_source, "count": 0})
|
||||||
|
|
||||||
# Filter to artists with valid ID for active source (strict — no cross-source)
|
# Artists already filtered by source in SQL
|
||||||
result_artists = []
|
result_artists = []
|
||||||
for artist in similar_artists:
|
for artist in similar_artists:
|
||||||
if active_source == 'spotify' and not artist.similar_artist_spotify_id:
|
|
||||||
continue
|
|
||||||
if active_source == 'deezer' and not getattr(artist, 'similar_artist_deezer_id', None) and not artist.similar_artist_itunes_id:
|
|
||||||
continue
|
|
||||||
if active_source == 'itunes' and not artist.similar_artist_itunes_id:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if active_source == 'spotify':
|
if active_source == 'spotify':
|
||||||
artist_id = artist.similar_artist_spotify_id
|
artist_id = artist.similar_artist_spotify_id
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue