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:
parent
8fc4484846
commit
453eb90f19
2 changed files with 61 additions and 11 deletions
|
|
@ -282,6 +282,47 @@ class DeezerDownloadClient:
|
||||||
logger.info(f"Fetched {len(playlists)} user playlists from Deezer")
|
logger.info(f"Fetched {len(playlists)} user playlists from Deezer")
|
||||||
return playlists
|
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]:
|
def get_playlist_tracks(self, playlist_id: str) -> Optional[dict]:
|
||||||
"""Fetch full playlist details with tracks via public API (ARL cookies grant private access)."""
|
"""Fetch full playlist details with tracks via public API (ARL cookies grant private access)."""
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -42405,10 +42405,13 @@ def get_your_artists_sources():
|
||||||
# Last.fm
|
# Last.fm
|
||||||
if config_manager.get('lastfm.api_key', '') and config_manager.get('lastfm.session_key', ''):
|
if config_manager.get('lastfm.api_key', '') and config_manager.get('lastfm.session_key', ''):
|
||||||
connected.append('lastfm')
|
connected.append('lastfm')
|
||||||
# Deezer
|
# Deezer — OAuth token OR ARL token both count as connected
|
||||||
try:
|
try:
|
||||||
deezer_cl = _get_deezer_client()
|
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')
|
connected.append('deezer')
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
@ -42518,22 +42521,28 @@ def _fetch_and_match_liked_artists(profile_id: int):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"[Your Artists] Last.fm fetch error: {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:
|
try:
|
||||||
if 'deezer' not in enabled_sources:
|
if 'deezer' not in enabled_sources:
|
||||||
print("[Your Artists] Deezer skipped (disabled in sources config)")
|
print("[Your Artists] Deezer skipped (disabled in sources config)")
|
||||||
else:
|
else:
|
||||||
deezer_cl = _get_deezer_client()
|
deezer_cl = _get_deezer_client()
|
||||||
|
artists = []
|
||||||
if deezer_cl and hasattr(deezer_cl, 'is_user_authenticated') and deezer_cl.is_user_authenticated():
|
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)
|
artists = deezer_cl.get_user_favorite_artists(limit=200)
|
||||||
for a in artists:
|
elif (hasattr(soulseek_client, 'deezer_dl') and soulseek_client.deezer_dl
|
||||||
database.upsert_liked_artist(
|
and soulseek_client.deezer_dl.is_authenticated()):
|
||||||
artist_name=a['name'], source_service='deezer',
|
print("[Your Artists] Fetching favorite artists from Deezer (ARL)...")
|
||||||
source_id=a.get('deezer_id'), source_id_type='deezer',
|
artists = soulseek_client.deezer_dl.get_user_favorite_artists(limit=200)
|
||||||
image_url=a.get('image_url'), profile_id=profile_id
|
for a in artists:
|
||||||
)
|
database.upsert_liked_artist(
|
||||||
fetched += len(artists)
|
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")
|
print(f"[Your Artists] Fetched {len(artists)} from Deezer")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"[Your Artists] Deezer fetch error: {e}")
|
logger.error(f"[Your Artists] Deezer fetch error: {e}")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue