Add Deezer ARL favorite artists support

Add get_user_favorite_artists(limit=200) to DeezerDownloadClient to fetch a user's favorite artists via the public API using an ARL-authenticated session (paginated, error-handled, returns deezer_id, name, image_url).

Update web_server to treat Deezer as connected if either OAuth or ARL is authenticated, and to fetch favorite artists from OAuth client when available or from soulseek_client.deezer_dl (ARL) otherwise. Fetched artists are upserted into the database and appropriate log/console messages and counters are updated.
This commit is contained in:
Broque Thomas 2026-04-13 19:46:39 -07:00
parent 8fc4484846
commit 453eb90f19
2 changed files with 61 additions and 11 deletions

View file

@ -282,6 +282,47 @@ class DeezerDownloadClient:
logger.info(f"Fetched {len(playlists)} user playlists from Deezer")
return playlists
def get_user_favorite_artists(self, limit: int = 200) -> list:
"""Fetch the authenticated user's favorite artists via public API with ARL cookies."""
if not self._authenticated or not self._user_data:
return []
user_id = self._user_data.get('USER_ID')
if not user_id:
return []
artists = []
index = 0
while len(artists) < limit:
try:
resp = self._session.get(
f'https://api.deezer.com/user/{user_id}/artists',
params={'index': index, 'limit': min(100, limit - len(artists))},
timeout=15
)
resp.raise_for_status()
data = resp.json()
if 'error' in data:
logger.warning(f"Deezer artists error: {data['error']}")
break
items = data.get('data', [])
if not items:
break
for a in items:
artists.append({
'deezer_id': str(a.get('id', '')),
'name': a.get('name', ''),
'image_url': a.get('picture_xl') or a.get('picture_big') or a.get('picture_medium', ''),
})
if not data.get('next'):
break
index += len(items)
except Exception as e:
logger.error(f"Error fetching favorite artists at index {index}: {e}")
break
logger.info(f"Fetched {len(artists)} favorite artists from Deezer (ARL)")
return artists
def get_playlist_tracks(self, playlist_id: str) -> Optional[dict]:
"""Fetch full playlist details with tracks via public API (ARL cookies grant private access)."""
try:

View file

@ -42405,10 +42405,13 @@ def get_your_artists_sources():
# Last.fm
if config_manager.get('lastfm.api_key', '') and config_manager.get('lastfm.session_key', ''):
connected.append('lastfm')
# Deezer
# Deezer — OAuth token OR ARL token both count as connected
try:
deezer_cl = _get_deezer_client()
if deezer_cl and hasattr(deezer_cl, 'is_user_authenticated') and deezer_cl.is_user_authenticated():
deezer_oauth = deezer_cl and hasattr(deezer_cl, 'is_user_authenticated') and deezer_cl.is_user_authenticated()
deezer_arl = (hasattr(soulseek_client, 'deezer_dl') and soulseek_client.deezer_dl
and soulseek_client.deezer_dl.is_authenticated())
if deezer_oauth or deezer_arl:
connected.append('deezer')
except Exception:
pass
@ -42518,22 +42521,28 @@ def _fetch_and_match_liked_artists(profile_id: int):
except Exception as e:
logger.error(f"[Your Artists] Last.fm fetch error: {e}")
# 4. Fetch from Deezer (favorite artists — requires OAuth)
# 4. Fetch from Deezer (favorite artists — OAuth or ARL)
try:
if 'deezer' not in enabled_sources:
print("[Your Artists] Deezer skipped (disabled in sources config)")
else:
deezer_cl = _get_deezer_client()
artists = []
if deezer_cl and hasattr(deezer_cl, 'is_user_authenticated') and deezer_cl.is_user_authenticated():
print("[Your Artists] Fetching favorite artists from Deezer...")
print("[Your Artists] Fetching favorite artists from Deezer (OAuth)...")
artists = deezer_cl.get_user_favorite_artists(limit=200)
for a in artists:
database.upsert_liked_artist(
artist_name=a['name'], source_service='deezer',
source_id=a.get('deezer_id'), source_id_type='deezer',
image_url=a.get('image_url'), profile_id=profile_id
)
fetched += len(artists)
elif (hasattr(soulseek_client, 'deezer_dl') and soulseek_client.deezer_dl
and soulseek_client.deezer_dl.is_authenticated()):
print("[Your Artists] Fetching favorite artists from Deezer (ARL)...")
artists = soulseek_client.deezer_dl.get_user_favorite_artists(limit=200)
for a in artists:
database.upsert_liked_artist(
artist_name=a['name'], source_service='deezer',
source_id=a.get('deezer_id'), source_id_type='deezer',
image_url=a.get('image_url'), profile_id=profile_id
)
fetched += len(artists)
if artists:
print(f"[Your Artists] Fetched {len(artists)} from Deezer")
except Exception as e:
logger.error(f"[Your Artists] Deezer fetch error: {e}")