diff --git a/core/deezer_download_client.py b/core/deezer_download_client.py index 82d7dce4..d0f290e2 100644 --- a/core/deezer_download_client.py +++ b/core/deezer_download_client.py @@ -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: diff --git a/web_server.py b/web_server.py index 2d23ade7..58b980b0 100644 --- a/web_server.py +++ b/web_server.py @@ -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}")