Improve Genius artist search for manual matching (#233)
The manual match modal for Genius only returned 0 or 1 artist result because search_artist() searched songs (per_page=5), extracted the primary artist, and returned the first match or None. Added search_artists() that returns multiple unique artists extracted from song results with broader search (per_page=20). The manual match endpoint now shows up to 8 artist candidates and multiple track results instead of one-or-nothing. Also shows the Genius URL as extra info.
This commit is contained in:
parent
982ca77501
commit
778e68a844
2 changed files with 47 additions and 17 deletions
|
|
@ -212,24 +212,47 @@ class GeniusClient:
|
|||
Returns:
|
||||
Artist dict with: id, name, url, image_url
|
||||
"""
|
||||
hits = self.search(artist_name, per_page=5)
|
||||
if not hits:
|
||||
artists = self.search_artists(artist_name, limit=10)
|
||||
if not artists:
|
||||
return None
|
||||
|
||||
artist_lower = artist_name.lower().strip()
|
||||
|
||||
for hit in hits:
|
||||
result = hit.get('result', {})
|
||||
primary = result.get('primary_artist', {})
|
||||
primary_name = (primary.get('name') or '').lower()
|
||||
if primary and (artist_lower in primary_name or primary_name in artist_lower):
|
||||
logger.debug(f"Found artist: {primary.get('name')}")
|
||||
return primary
|
||||
for a in artists:
|
||||
a_name = (a.get('name') or '').lower()
|
||||
if artist_lower in a_name or a_name in artist_lower:
|
||||
logger.debug(f"Found artist: {a.get('name')}")
|
||||
return a
|
||||
|
||||
# No confident match — let the worker mark as not_found and retry later
|
||||
logger.debug(f"No artist match found in search results for: {artist_name}")
|
||||
return None
|
||||
|
||||
@rate_limited
|
||||
def search_artists(self, query: str, limit: int = 10) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Search for artists by name. Extracts unique artists from song results.
|
||||
|
||||
Returns:
|
||||
List of artist dicts with: id, name, url, image_url
|
||||
"""
|
||||
hits = self.search(query, per_page=min(limit * 2, 20))
|
||||
if not hits:
|
||||
return []
|
||||
|
||||
seen_ids = set()
|
||||
artists = []
|
||||
for hit in hits:
|
||||
result = hit.get('result', {})
|
||||
primary = result.get('primary_artist', {})
|
||||
if primary and primary.get('id') and primary['id'] not in seen_ids:
|
||||
seen_ids.add(primary['id'])
|
||||
artists.append(primary)
|
||||
if len(artists) >= limit:
|
||||
break
|
||||
|
||||
return artists
|
||||
|
||||
@rate_limited
|
||||
def get_artist(self, artist_id: int) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -12614,15 +12614,22 @@ def _search_service(service, entity_type, query):
|
|||
raise ValueError("Genius worker not initialized")
|
||||
client = genius_worker.client
|
||||
if entity_type == 'artist':
|
||||
result = client.search_artist(query)
|
||||
if result:
|
||||
return [{'id': str(result.get('id', '')), 'name': result.get('name', ''),
|
||||
'image': result.get('image_url'), 'extra': ''}]
|
||||
artists = client.search_artists(query, limit=8)
|
||||
return [{'id': str(a.get('id', '')), 'name': a.get('name', ''),
|
||||
'image': a.get('image_url'), 'extra': a.get('url', '')} for a in artists]
|
||||
elif entity_type == 'track':
|
||||
result = client.search_song(query, '')
|
||||
if result:
|
||||
return [{'id': str(result.get('id', '')), 'name': result.get('title', ''),
|
||||
'image': result.get('song_art_image_url'), 'extra': result.get('artist_names', '')}]
|
||||
# Search with broader results for manual matching
|
||||
hits = client.search(f"{query}", per_page=10)
|
||||
results = []
|
||||
seen_ids = set()
|
||||
for hit in hits:
|
||||
r = hit.get('result', {})
|
||||
rid = r.get('id')
|
||||
if rid and rid not in seen_ids:
|
||||
seen_ids.add(rid)
|
||||
results.append({'id': str(rid), 'name': r.get('title', ''),
|
||||
'image': r.get('song_art_image_url'), 'extra': r.get('artist_names', '')})
|
||||
return results
|
||||
return []
|
||||
|
||||
elif service == 'tidal':
|
||||
|
|
|
|||
Loading…
Reference in a new issue