gw.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. import eventlet
  2. requests = eventlet.import_patched('requests')
  3. import json
  4. from deezer.utils import map_artist_album, map_user_track, map_user_artist, map_user_album, map_user_playlist
  5. class LyricsStatus():
  6. """Explicit Content Lyrics"""
  7. NOT_EXPLICIT = 0
  8. """Not Explicit"""
  9. EXPLICIT = 1
  10. """Explicit"""
  11. UNKNOWN = 2
  12. """Unknown"""
  13. EDITED = 3
  14. """Edited"""
  15. PARTIALLY_EXPLICIT = 4
  16. """Partially Explicit (Album "lyrics" only)"""
  17. PARTIALLY_UNKNOWN = 5
  18. """Partially Unknown (Album "lyrics" only)"""
  19. NO_ADVICE = 6
  20. """No Advice Available"""
  21. PARTIALLY_NO_ADVICE = 7
  22. """Partially No Advice Available (Album "lyrics" only)"""
  23. EMPTY_TRACK_DICT = {
  24. 'SNG_ID': 0,
  25. 'SNG_TITLE': '',
  26. 'DURATION': 0,
  27. 'MD5_ORIGIN': 0,
  28. 'MEDIA_VERSION': 0,
  29. 'FILESIZE': 0,
  30. 'ALB_TITLE': "",
  31. 'ALB_PICTURE': "",
  32. 'ART_ID': 0,
  33. 'ART_NAME': ""
  34. }
  35. class GW:
  36. def __init__(self, session, headers):
  37. self.http_headers = headers
  38. self.session = session
  39. def api_call(self, method, args=None, params=None):
  40. if args is None: args = {}
  41. if params is None: params = {}
  42. p = {'api_version': "1.0",
  43. 'api_token': 'null' if method == 'deezer.getUserData' else self._get_token(),
  44. 'input': '3',
  45. 'method': method}
  46. p.update(params)
  47. try:
  48. result = self.session.post(
  49. "http://www.deezer.com/ajax/gw-light.php",
  50. params=p,
  51. timeout=30,
  52. json=args,
  53. headers=self.http_headers
  54. )
  55. result_json = result.json()
  56. except:
  57. eventlet.sleep(2)
  58. return self.api_call(method, args, params)
  59. if len(result_json['error']):
  60. raise APIError(json.dumps(result_json['error']))
  61. return result.json()['results']
  62. def _get_token(self):
  63. token_data = self.get_user_data()
  64. return token_data['checkForm']
  65. def get_user_data(self):
  66. return self.api_call('deezer.getUserData')
  67. def get_user_profile_page(self, user_id, tab, limit=10):
  68. return self.api_call('deezer.pageProfile', {'user_id': user_id, 'tab': tab, 'nb': limit})
  69. def get_child_accounts(self):
  70. return self.api_call('deezer.getChildAccounts')
  71. def get_track(self, sng_id):
  72. return self.api_call('song.getData', {'sng_id': sng_id})
  73. def get_track_page(self, sng_id):
  74. return self.api_call('deezer.pageTrack', {'sng_id': sng_id})
  75. def get_track_lyrics(self, sng_id):
  76. return self.api_call('song.getLyrics', {'sng_id': sng_id})
  77. def get_tracks_gw(self, sng_ids):
  78. tracks_array = []
  79. body = self.api_call('song.getListData', {'sng_ids': sng_ids})
  80. errors = 0
  81. for i in range(len(sng_ids)):
  82. if sng_ids[i] != 0:
  83. tracks_array.append(body['data'][i - errors])
  84. else:
  85. errors += 1
  86. tracks_array.append(EMPTY_TRACK_DICT)
  87. return tracks_array
  88. def get_album(self, alb_id):
  89. return self.api_call('album.getData', {'alb_id': alb_id})
  90. def get_album_page(self, alb_id):
  91. return self.api_call('deezer.pageAlbum', {
  92. 'alb_id': alb_id,
  93. 'lang': 'en',
  94. 'header': True,
  95. 'tab': 0
  96. })
  97. def get_album_tracks(self, alb_id):
  98. tracks_array = []
  99. body = self.api_call('song.getListByAlbum', {'alb_id': alb_id, 'nb': -1})
  100. for track in body['data']:
  101. _track = track
  102. _track['POSITION'] = body['data'].index(track)
  103. tracks_array.append(_track)
  104. return tracks_array
  105. def get_artist(self, art_id):
  106. return self.api_call('artist.getData', {'art_id': art_id})
  107. def get_artist_page(self, art_id):
  108. return self.api_call('deezer.pageArtist', {
  109. 'alb_id': art_id,
  110. 'lang': 'en',
  111. 'header': True,
  112. 'tab': 0
  113. })
  114. def get_artist_top_tracks(self, art_id, limit=100):
  115. tracks_array = []
  116. body = self.api_call('artist.getTopTrack', {'art_id': art_id, 'nb': limit})
  117. for track in body['data']:
  118. track['POSITION'] = body['data'].index(track)
  119. tracks_array.append(track)
  120. return tracks_array
  121. def get_artist_discography(self, art_id, index=0, limit=25):
  122. return self.api_call('album.getDiscography', {
  123. 'art_id': art_id,
  124. "discography_mode":"all",
  125. 'nb': limit,
  126. 'nb_songs': 0,
  127. 'start': index
  128. })
  129. def get_playlist(self, playlist_id):
  130. return self.api_call('playlist.getData', {'playlist_id': playlist_id})
  131. def get_playlist_page(self, playlist_id):
  132. return self.api_call('deezer.pagePlaylist', {
  133. 'playlist_id': playlist_id,
  134. 'lang': 'en',
  135. 'header': True,
  136. 'tab': 0
  137. })
  138. def get_playlist_tracks(self, playlist_id):
  139. tracks_array = []
  140. body = self.api_call('playlist.getSongs', {'playlist_id': playlist_id, 'nb': -1})
  141. for track in body['data']:
  142. track['POSITION'] = body['data'].index(track)
  143. tracks_array.append(track)
  144. return tracks_array
  145. def add_song_to_favorites(self, sng_id):
  146. return self.gw_api_call('favorite_song.add', {'SNG_ID': sng_id})
  147. def remove_song_from_favorites(self, sng_id):
  148. return self.gw_api_call('favorite_song.remove', {'SNG_ID': sng_id})
  149. def add_album_to_favorites(self, alb_id):
  150. return self.gw_api_call('album.addFavorite', {'ALB_ID': alb_id})
  151. def remove_album_from_favorites(self, alb_id):
  152. return self.gw_api_call('album.deleteFavorite', {'ALB_ID': alb_id})
  153. def add_artist_to_favorites(self, art_id):
  154. return self.gw_api_call('artist.addFavorite', {'ART_ID': art_id})
  155. def remove_artist_from_favorites(self, art_id):
  156. return self.gw_api_call('artist.deleteFavorite', {'ART_ID': art_id})
  157. def add_playlist_to_favorites(self, playlist_id):
  158. return self.gw_api_call('playlist.addFavorite', {'PARENT_PLAYLIST_ID': playlist_id})
  159. def remove_playlist_from_favorites(self, playlist_id):
  160. return self.gw_api_call('playlist.deleteFavorite', {'PLAYLIST_ID': playlist_id})
  161. def get_page(self, page):
  162. params = {
  163. 'gateway_input': json.dumps({
  164. 'PAGE': page,
  165. 'VERSION': '2.3',
  166. 'SUPPORT': {
  167. 'grid': [
  168. 'channel',
  169. 'album'
  170. ],
  171. 'horizontal-grid': [
  172. 'album'
  173. ],
  174. },
  175. 'LANG': 'en'
  176. })
  177. }
  178. return self.api_call('page.get', params=params)
  179. def search(self, query, index=0, limit=10, suggest=True, artist_suggest=True, top_tracks=True):
  180. return self.api_call('deezer.pageSearch', {
  181. "query": query,
  182. "start": index,
  183. "nb": limit,
  184. "suggest": suggest,
  185. "artist_suggest": artist_suggest,
  186. "top_tracks": top_tracks
  187. })
  188. # Extra calls
  189. def get_artist_discography_tabs(self, art_id, limit=100):
  190. index = 0
  191. releases = []
  192. result = {'all': []}
  193. ids = []
  194. # Get all releases
  195. while True:
  196. response = self.get_artist_discography(art_id, index=index, limit=limit)
  197. releases += response['data']
  198. index += limit
  199. if index > response['total']:
  200. break
  201. for release in releases:
  202. if release['ALB_ID'] not in ids:
  203. ids.append(release['ALB_ID'])
  204. obj = map_artist_album(release)
  205. if (release['ART_ID'] == art_id or release['ART_ID'] != art_id and release['ROLE_ID'] == 0) and release['ARTISTS_ALBUMS_IS_OFFICIAL']:
  206. # Handle all base record types
  207. if not obj['record_type'] in result:
  208. result[obj['record_type']] = []
  209. result[obj['record_type']].append(obj)
  210. result['all'].append(obj)
  211. else:
  212. # Handle albums where the artist is featured
  213. if release['ROLE_ID'] == 5:
  214. if not 'featured' in result:
  215. result['featured'] = []
  216. result['featured'].append(obj)
  217. # Handle "more" albums
  218. elif release['ROLE_ID'] == 0:
  219. if not 'more' in result:
  220. result['more'] = []
  221. result['more'].append(obj)
  222. result['all'].append(obj)
  223. return result
  224. def get_track_with_fallback(self, sng_id):
  225. body = None
  226. if int(sng_id) > 0:
  227. try:
  228. body = self.get_track_page(sng_id)
  229. except:
  230. pass
  231. if body:
  232. if 'LYRICS' in body:
  233. body['DATA']['LYRICS'] = body['LYRICS']
  234. body = body['DATA']
  235. else:
  236. body = self.get_track(sng_id)
  237. return body
  238. def get_user_playlists(self, user_id, limit=25):
  239. user_profile_page = self.get_user_profile_page(user_id, 'playlists', limit=limit)
  240. blog_name = user_profile_page['DATA']['USER'].get('BLOG_NAME', "Unkown")
  241. data = user_profile_page['TAB']['playlists']['data']
  242. result = []
  243. for playlist in data:
  244. result.append(map_user_playlist(playlist, blog_name))
  245. return result
  246. def get_user_albums(self, user_id, limit=25):
  247. data = self.get_user_profile_page(user_id, 'albums', limit=limit)['TAB']['albums']['data']
  248. result = []
  249. for album in data:
  250. result.append(map_user_album(album))
  251. return result
  252. def get_user_artists(self, user_id, limit=25):
  253. data = self.get_user_profile_page(user_id, 'artists', limit=limit)['TAB']['artists']['data']
  254. result = []
  255. for artist in data:
  256. result.append(map_user_artist(artist))
  257. return result
  258. def get_user_tracks(self, user_id, limit=25):
  259. data = self.get_user_profile_page(user_id, 'loved', limit=limit)['TAB']['loved']['data']
  260. result = []
  261. for track in data:
  262. result.append(map_user_track(track))
  263. return result
  264. class APIError(Exception):
  265. """Base class for Deezer exceptions"""
  266. pass