More function implementation

This commit is contained in:
RemixDev 2020-11-19 18:56:40 +01:00
parent 67c6ff4ca8
commit 5a03419c53
No known key found for this signature in database
GPG key ID: B33962B465BDB51C
5 changed files with 205 additions and 25 deletions

View file

@ -2,8 +2,9 @@ import eventlet
requests = eventlet.import_patched('requests')
from deezer.gw import GW
from deezer.api import API
import json
__version__ = "0.0.1"
__version__ = "0.0.2"
class TrackFormats():
"""Number associtation for formats"""
@ -27,6 +28,11 @@ class Deezer:
self.session.mount('http://', requests.adapters.HTTPAdapter(pool_maxsize=100))
self.session.mount('https://', requests.adapters.HTTPAdapter(pool_maxsize=100))
self.logged_in = False
self.current_user = {}
self.childs = []
self.selected_account = 0
self.api = API(self.session, self.http_headers)
self.gw = GW(self.session, self.http_headers)
@ -36,28 +42,78 @@ class Deezer:
def get_accept_language(self):
return self.http_headers['Accept-Language']
def get_countries_charts(self):
temp = self.api.get_user_playlists('637006841')['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 login(self, email, password, re_captcha_token, child=0):
# Check if user already logged in
user_data = self.gw.get_user_data()
if user_data['USER']['USER_ID'] == 0:
self.logged_in = False
return False
# Get the checkFormLogin
check_form_login = user_data['checkFormLogin']
login = self.session.post(
"https://www.deezer.com/ajax/action.php",
data={
'type': 'login',
'mail': email,
'password': password,
'checkFormLogin': check_form_login,
'reCaptchaToken': re_captcha_token
},
headers={'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', **self.http_headers}
)
# Check if user logged in
if 'success' not in login.text:
self.logged_in = False
return False
user_data = self.gw.get_user_data()
self._post_login(user_data)
self.change_account(child)
self.logged_in = True
return True
def get_track_id_from_metadata(self, artist, track, album):
artist = artist.replace("", "-").replace("", "'")
track = track.replace("", "-").replace("", "'")
album = album.replace("", "-").replace("", "'")
def login_via_arl(self, arl, child=0):
arl = arl.strip()
cookie_obj = requests.cookies.create_cookie(
domain='.deezer.com',
name='arl',
value=arl,
path="/",
rest={'HttpOnly': True}
)
self.session.cookies.set_cookie(cookie_obj)
user_data = self.gw.get_user_data()
# Check if user logged in
if user_data["USER"]["USER_ID"] == 0:
self.logged_in = False
return False
self._post_login(user_data)
self.change_account(child)
self.logged_in = True
return True
resp = self.api.advanced_search(artist=artist, track=track, album=album, limit=1)
if len(resp['data']) > 0: return resp['data'][0]['id']
def _post_login(self, user_data):
self.childs = []
family = user_data["USER"]["MULTI_ACCOUNT"]["ENABLED"]
if family:
childs = self.gw.get_child_accounts()
for child in childs:
self.childs.append({
'id': child["USER_ID"],
'name': child["BLOG_NAME"],
'picture': child.get("USER_PICTURE", "")
})
else:
self.childs.append({
'id': user_data["USER"]["USER_ID"],
'name': user_data["USER"]["BLOG_NAME"],
'picture': user_data["USER"].get("USER_PICTURE", "")
})
resp = self.api.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.api.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.api.advanced_search(artist=artist, track=track[:track.find(" - ")], limit=1)
if len(resp['data']) > 0: return resp['data'][0]['id']
return "0"
def change_account(self, child_n):
if len(self.childs)-1 >= child_n:
self.current_user =self.childs[child_n]
self.selected_account = child_n
else:
self.current_user = self.childs[0]
self.selected_account = 0
return (self.current_user, self.selected_account)

View file

@ -53,7 +53,7 @@ class API:
def get_album(self, album_id):
return self.api_call(f'album/{str(album_id)}')
def get_track_by_UPC(self, upc):
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):
@ -262,6 +262,34 @@ class API:
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')
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

View file

@ -1,6 +1,8 @@
import eventlet
requests = eventlet.import_patched('requests')
from deezer.utils import map_artist_album
class LyricsStatus():
"""Explicit Content Lyrics"""
@ -211,6 +213,46 @@ class GW:
}
return self.api_call('page.get', params=params)
# Extra calls
def get_artist_discography_tabs(self, art_id, limit=100):
index = 0
releases = []
result = {'all': []}
ids = []
# Get all releases
while True:
response = self.get_artist_discography(art_id, index=index, limit=limit)
releases += response['data']
index += limit
if index > response['total']:
break
for release in releases:
if release['ALB_ID'] not in ids:
ids.append(release['ALB_ID'])
obj = map_artist_album(release)
if (release['ART_ID'] == art_id or release['ART_ID'] != art_id and release['ROLE_ID'] == 0) and release['ARTISTS_ALBUMS_IS_OFFICIAL']:
# Handle all base record types
if not obj['record_type'] in result:
result[obj['record_type']] = []
result[obj['record_type']].append(obj)
result['all'].append(obj)
else:
# Handle albums where the artist is featured
if release['ROLE_ID'] == 5:
if not 'featured' in result:
result['featured'] = []
result['featured'].append(obj)
# Handle "more" albums
elif release['ROLE_ID'] == 0:
if not 'more' in result:
result['more'] = []
result['more'].append(obj)
result['all'].append(obj)
return result
class APIError(Exception):
"""Base class for Deezer exceptions"""
pass

View file

@ -131,3 +131,57 @@ def map_album(album):
# Extras
'nb_disk': album['NUMBER_DISK']
}
# maps gw-light api artist/albums to standard api
def map_artist_album(album):
return {
'id': album['ALB_ID'],
'title': album['ALB_TITLE'],
'link': f"https://www.deezer.com/album/{album['ALB_ID']}",
'cover': f"https://api.deezer.com/album/{album['ALB_ID']}/image",
'cover_small': f"https://cdns-images.dzcdn.net/images/cover/{album['ALB_PICTURE']}/56x56-000000-80-0-0.jpg",
'cover_medium': f"https://cdns-images.dzcdn.net/images/cover/{album['ALB_PICTURE']}/250x250-000000-80-0-0.jpg",
'cover_big': f"https://cdns-images.dzcdn.net/images/cover/{album['ALB_PICTURE']}/500x500-000000-80-0-0.jpg",
'cover_xl': f"https://cdns-images.dzcdn.net/images/cover/{album['ALB_PICTURE']}/1000x1000-000000-80-0-0.jpg",
'genre_id': album['GENRE_ID'],
'fans': album['RANK'],
'release_date': album['PHYSICAL_RELEASE_DATE'],
'record_type': RELEASE_TYPE.get(int(album['TYPE']), "unknown"),
'tracklist': f"https://api.deezer.com/album/{album['ALB_ID']}/tracks",
'explicit_lyrics': int(album['EXPLICIT_LYRICS']) > 0,
'type': album['__TYPE__'],
# Extras
'nb_tracks': album['NUMBER_TRACK'],
'nb_disk': album['NUMBER_DISK']
}
# maps gw-light api playlists to standard api
def map_playlist(playlist):
return {
'id': playlist['PLAYLIST_ID'],
'title': playlist['TITLE'],
'description': playlist['DESCRIPTION'],
'duration': playlist['DURATION'],
'public': playlist['STATUS'] == 1,
'is_loved_track': playlist['TYPE'] == 4,
'collaborative': playlist['STATUS'] == 2,
'nb_tracks': playlist['NB_SONG'],
'fans': playlist['NB_FAN'],
'link': "https://www.deezer.com/playlist/"+playlist['PLAYLIST_ID'],
'share': "https://www.deezer.com/playlist/"+playlist['PLAYLIST_ID'],
'picture': "https://api.deezer.com/playlist/"+playlist['PLAYLIST_ID']+"/image",
'picture_small': "https://cdns-images.dzcdn.net/images/"+playlist['PICTURE_TYPE']+"/"+playlist['PLAYLIST_PICTURE']+"/56x56-000000-80-0-0.jpg",
'picture_medium': "https://cdns-images.dzcdn.net/images/"+playlist['PICTURE_TYPE']+"/"+playlist['PLAYLIST_PICTURE']+"/250x250-000000-80-0-0.jpg",
'picture_big': "https://cdns-images.dzcdn.net/images/"+playlist['PICTURE_TYPE']+"/"+playlist['PLAYLIST_PICTURE']+"/500x500-000000-80-0-0.jpg",
'picture_xl': "https://cdns-images.dzcdn.net/images/"+playlist['PICTURE_TYPE']+"/"+playlist['PLAYLIST_PICTURE']+"/1000x1000-000000-80-0-0.jpg",
'checksum': playlist['CHECKSUM'],
'tracklist': "https://api.deezer.com/playlist/"+playlist['PLAYLIST_ID']+"/tracks",
'creation_date': playlist['DATE_ADD'],
'creator': {
'id': playlist['PARENT_USER_ID'],
'name': playlist['PARENT_USERNAME'],
'tracklist': "https://api.deezer.com/user/"+playlist['PARENT_USER_ID']+"/flow",
'type': "user"
},
'type': "playlist"
}

View file

@ -7,7 +7,7 @@ README = (HERE / "README.md").read_text()
setup(
name="deezer-py",
version="0.0.1",
version="0.0.2",
description="A wrapper for all Deezer's APIs",
long_description=README,
long_description_content_type="text/markdown",