deezer-py/deezer/api.py

320 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import eventlet
requests = eventlet.import_patched('requests')
class SearchOrder():
"""Possible values for order parameter in search"""
RANKING = "RANKING"
TRACK_ASC = "TRACK_ASC"
TRACK_DESC = "TRACK_DESC"
ARTIST_ASC = "ARTIST_ASC"
ARTIST_DESC = "ARTIST_DESC"
ALBUM_ASC = "ALBUM_ASC"
ALBUM_DESC = "ALBUM_DESC"
RATING_ASC = "RATING_ASC"
RATING_DESC = "RATING_DESC"
DURATION_ASC = "DURATION_ASC"
DURATION_DESC = "DURATION_DESC"
class API:
def __init__(self, session, headers):
self.http_headers = headers
self.session = session
def api_call(self, method, args=None):
if args is None:
args = {}
try:
result = self.session.get(
"https://api.deezer.com/" + method,
params=args,
headers=self.http_headers,
timeout=30
)
result_json = result.json()
except:
eventlet.sleep(2)
return self.api_call(method, args)
if 'error' in result_json.keys():
if 'code' in result_json['error']:
if result_json['error']['code'] in [4, 700]:
eventlet.sleep(5)
return self.api_call(method, args)
if result_json['error']['code'] == 100: raise ItemsLimitExceededException
if result_json['error']['code'] == 200: raise PermissionException
if result_json['error']['code'] == 300: raise InvalidTokenException
if result_json['error']['code'] == 500: raise WrongParameterException
if result_json['error']['code'] == 501: raise MissingParameterException
if result_json['error']['code'] == 600: raise InvalidQueryException
if result_json['error']['code'] == 800: raise DataException
if result_json['error']['code'] == 901: raise IndividualAccountChangedNotAllowedException
raise APIError(json.dumps(result_json['error']))
return result_json
def get_album(self, album_id):
return self.api_call(f'album/{str(album_id)}')
def get_album_by_UPC(self, upc):
return self.get_album(f'upc:{upc}')
def get_album_comments(self, album_id, index=0, limit=10):
return self.api_call(f'album/{str(album_id)}/comments', {'index': index, 'limit': limit})
def get_album_fans(self, album_id, index=0, limit=100):
return self.api_call(f'album/{str(album_id)}/fans', {'index': index, 'limit': limit})
def get_album_tracks(self, album_id, index=0, limit=-1):
return self.api_call(f'album/{str(album_id)}/tracks', {'index': index, 'limit': limit})
def get_artist(self, artist_id):
return self.api_call(f'artist/{str(artist_id)}')
def get_artist_top(self, artist_id, index=0, limit=10):
return self.api_call(f'artist/{str(artist_id)}/top', {'index': index, 'limit': limit})
def get_artist_albums(self, artist_id, index=0, limit=-1):
return self.api_call(f'artist/{str(artist_id)}/albums', {'index': index, 'limit': limit})
def get_artist_comments(self, artist_id, index=0, limit=10):
return self.api_call(f'artist/{str(artist_id)}/comments', {'index': index, 'limit': limit})
def get_artist_fans(self, artist_id, index=0, limit=100):
return self.api_call(f'artist/{str(artist_id)}/fans', {'index': index, 'limit': limit})
def get_artist_related(self, artist_id, index=0, limit=20):
return self.api_call(f'artist/{str(artist_id)}/related', {'index': index, 'limit': limit})
def get_artist_radio(self, artist_id, index=0, limit=25):
return self.api_call(f'artist/{str(artist_id)}/radio', {'index': index, 'limit': limit})
def get_artist_playlists(self, artist_id, index=0, limit=-1):
return self.api_call(f'artist/{str(artist_id)}/playlists', {'index': index, 'limit': limit})
def get_chart(self, genre_id=0, index=0, limit=10):
return self.api_call(f'chart/{str(genre_id)}', {'index': index, 'limit': limit})
def get_chart_tracks(self, genre_id=0, index=0, limit=10):
return self.api_call(f'chart/{str(genre_id)}/tracks', {'index': index, 'limit': limit})
def get_chart_albums(self, genre_id=0, index=0, limit=10):
return self.api_call(f'chart/{str(genre_id)}/albums', {'index': index, 'limit': limit})
def get_chart_artists(self, genre_id=0, index=0, limit=10):
return self.api_call(f'chart/{str(genre_id)}/artists', {'index': index, 'limit': limit})
def get_chart_playlists(self, genre_id=0, index=0, limit=10):
return self.api_call(f'chart/{str(genre_id)}/playlists', {'index': index, 'limit': limit})
def get_chart_podcasts(self, genre_id=0, index=0, limit=10):
return self.api_call(f'chart/{str(genre_id)}/podcasts', {'index': index, 'limit': limit})
def get_comment(self, comment_id):
return self.api_call(f'comment/{str(comment_id)}')
def get_editorials(self, index=0, limit=10):
return self.api_call('editorial', {'index': index, 'limit': limit})
def get_editorial(self, genre_id=0):
return self.api_call(f'editorial/{str(genre_id)}')
def get_editorial_selection(self, genre_id=0, index=0, limit=10):
return self.api_call(f'editorial/{str(genre_id)}/selection', {'index': index, 'limit': limit})
def get_editorial_charts(self, genre_id=0, index=0, limit=10):
return self.api_call(f'editorial/{str(genre_id)}/charts', {'index': index, 'limit': limit})
def get_editorial_releases(self, genre_id=0, index=0, limit=10):
return self.api_call(f'editorial/{str(genre_id)}/releases', {'index': index, 'limit': limit})
def get_genres(self, index=0, limit=10):
return self.api_call('genre', {'index': index, 'limit': limit})
def get_genre(self, genre_id=0):
return self.api_call(f'genre/{str(genre_id)}')
def get_genre_artists(self, genre_id=0, index=0, limit=10):
return self.api_call(f'genre/{str(genre_id)}/artists', {'index': index, 'limit': limit})
def get_genre_radios(self, genre_id=0, index=0, limit=10):
return self.api_call(f'genre/{str(genre_id)}/radios', {'index': index, 'limit': limit})
def get_infos(self):
return self.api_call('infos')
def get_options(self):
return self.api_call('options')
def get_playlist(self, playlist_id):
return self.api_call(f'playlist/{str(playlist_id)}')
def get_playlist_comments(self, album_id, index=0, limit=10):
return self.api_call(f'playlist/{str(album_id)}/comments', {'index': index, 'limit': limit})
def get_playlist_fans(self, album_id, index=0, limit=100):
return self.api_call(f'playlist/{str(album_id)}/fans', {'index': index, 'limit': limit})
def get_playlist_tracks(self, album_id, index=0, limit=-1):
return self.api_call(f'playlist/{str(album_id)}/tracks', {'index': index, 'limit': limit})
def get_playlist_radio(self, album_id, index=0, limit=100):
return self.api_call(f'playlist/{str(album_id)}/radio', {'index': index, 'limit': limit})
def get_radios(self, index=0, limit=10):
return self.api_call('radio', {'index': index, 'limit': limit})
def get_radios_genres(self, index=0, limit=25):
return self.api_call('radio/genres', {'index': index, 'limit': limit})
def get_radios_top(self, index=0, limit=50):
return self.api_call('radio/top', {'index': index, 'limit': limit})
def get_radios_lists(self, index=0, limit=25):
return self.api_call('radio/lists', {'index': index, 'limit': limit})
def get_radio(self, radio_id):
return self.api_call(f'radio/{str(radio_id)}')
def get_radio_tracks(self, radio_id, index=0, limit=40):
return self.api_call(f'radio/{str(radio_id)}/tracks', {'index': index, 'limit': limit})
def _generate_search_advanced_query(self, artist="", album="", track="", label="", dur_min=0, dur_max=0, bpm_min=0, bpm_max=0):
query = ""
if artist: query += f'artist:"{artist}" '
if album: query += f'album:"{album}" '
if track: query += f'track:"{track}" '
if label: query += f'label:"{label}" '
if dur_min: query += f'dur_min:"{str(dur_min)}" '
if dur_max: query += f'dur_max:"{str(dur_max)}" '
if bpm_min: query += f'bpm_min:"{str(bpm_min)}" '
if bpm_max: query += f'bpm_max:"{str(bpm_max)}" '
return query.strip()
def _generate_search_args(self, query, strict=False, order=None, index=0, limit=25):
args = {'q': query, 'index': index, 'limit': limit}
if strict: args['strict'] = 'on'
if order: args['order'] = order
return args
def search(self, query, strict=False, order=None, index=0, limit=25):
args = self._generate_search_args(query, strict, order, index, limit)
return self.api_call('search', args)
def advanced_search(self, artist="", album="", track="", label="", dur_min=0, dur_max=0, bpm_min=0, bpm_max=0, strict=False, order=None, index=0, limit=25):
query = self._generate_search_advanced_query(artist, album, track, label, dur_min, dur_max, bpm_min, bpm_max)
return self.search(query, strict, order, index, limit)
def search_album(self, query, strict=False, order=None, index=0, limit=25):
args = self._generate_search_args(query, strict, order, index, limit)
return self.api_call('search/album', args)
def search_artist(self, query, strict=False, order=None, index=0, limit=25):
args = self._generate_search_args(query, strict, order, index, limit)
return self.api_call('search/artist', args)
def search_playlist(self, query, strict=False, order=None, index=0, limit=25):
args = self._generate_search_args(query, strict, order, index, limit)
return self.api_call('search/playlist', args)
def search_radio(self, query, strict=False, order=None, index=0, limit=25):
args = self._generate_search_args(query, strict, order, index, limit)
return self.api_call('search/playlist', radio)
def search_track(self, query, strict=False, order=None, index=0, limit=25):
args = self._generate_search_args(query, strict, order, index, limit)
return self.api_call('search/track', radio)
def search_user(self, query, strict=False, order=None, index=0, limit=25):
args = self._generate_search_args(query, strict, order, index, limit)
return self.api_call('search/user', radio)
def get_track(self, song_id):
return self.api_call(f'track/{str(song_id)}')
def get_track_by_ISRC(self, isrc):
return self.get_track(f'isrc:{isrc}')
def get_user(self, user_id):
return self.api_call(f'user/{str(user_id)}')
def get_user_albums(self, user_id, index=0, limit=25):
return self.api_call(f'user/{str(user_id)}/albums', {'index': index, 'limit': limit})
def get_user_artists(self, user_id, index=0, limit=25):
return self.api_call(f'user/{str(user_id)}/artists', {'index': index, 'limit': limit})
def get_user_artists(self, user_id, index=0, limit=25):
return self.api_call(f'user/{str(user_id)}/artists', {'index': index, 'limit': limit})
def get_user_flow(self, user_id, index=0, limit=25):
return self.api_call(f'user/{str(user_id)}/flow', {'index': index, 'limit': limit})
def get_user_following(self, user_id, index=0, limit=25):
return self.api_call(f'user/{str(user_id)}/followings', {'index': index, 'limit': limit})
def get_user_followers(self, user_id, index=0, limit=25):
return self.api_call(f'user/{str(user_id)}/followers', {'index': index, 'limit': limit})
def get_user_playlists(self, user_id, index=0, limit=25):
return self.api_call(f'user/{str(user_id)}/playlists', {'index': index, 'limit': limit})
def get_user_radios(self, user_id, index=0, limit=25):
return self.api_call(f'user/{str(user_id)}/radios', {'index': index, 'limit': limit})
def get_user_tracks(self, user_id, index=0, limit=25):
return self.api_call(f'user/{str(user_id)}/tracks', {'index': index, 'limit': limit})
# Extra calls
def get_countries_charts(self):
temp = self.get_user_playlists('637006841', limit=-1)['data']
result = sorted(temp, key=lambda k: k['title']) # Sort all playlists
if not result[0]['title'].startswith('Top'): result = result[1:] # Remove loved tracks playlist
return result
def get_track_id_from_metadata(self, artist, track, album):
artist = artist.replace("", "-").replace("", "'")
track = track.replace("", "-").replace("", "'")
album = album.replace("", "-").replace("", "'")
resp = self.advanced_search(artist=artist, track=track, album=album, limit=1)
if len(resp['data']) > 0: return resp['data'][0]['id']
resp = self.advanced_search(artist=artist, track=track, limit=1)
if len(resp['data']) > 0: return resp['data'][0]['id']
# Try removing version
if "(" in track and ")" in track and track.find("(") < track.find(")"):
resp = self.advanced_search(artist=artist, track=track[:track.find("(")], limit=1)
if len(resp['data']) > 0: return resp['data'][0]['id']
elif " - " in track:
resp = self.advanced_search(artist=artist, track=track[:track.find(" - ")], limit=1)
if len(resp['data']) > 0: return resp['data'][0]['id']
return 0
class APIError(Exception):
"""Base class for Deezer exceptions"""
pass
class ItemsLimitExceededException(APIError):
pass
class PermissionException(APIError):
pass
class InvalidTokenException(APIError):
pass
class WrongParameterException(APIError):
pass
class MissingParameterException(APIError):
pass
class InvalidQueryException(APIError):
pass
class DataException(APIError):
pass
class IndividualAccountChangedNotAllowedException(APIError):
pass