from __future__ import unicode_literals import json import re from .common import InfoExtractor from ..utils import ( ExtractorError, int_or_none, orderedSet, ) from hashlib import md5 from Crypto.Cipher import AES from binascii import b2a_hex from ..compat import compat_ord, compat_chr def md5hex(data): """ return hex string of md5 of the given string """ return md5(data).hexdigest().encode('utf-8') def hexaescrypt(data, key): """ returns hex string of aes encrypted data """ c = AES.new(key, AES.MODE_ECB) return b2a_hex(c.encrypt(data)) def calcurlkey(songid, md5origin, mediaver=4, fmt=1): """ Calculate the deezer download url given the songid, origin and media+format """ data = b'\xa4'.join(_.encode("utf-8") for _ in [md5origin, str(fmt), str(songid), str(mediaver)]) data = b'\xa4'.join([md5hex(data), data]) + b'\xa4' if len(data) % 16: data += b'\x00' * (16 - len(data) % 16) return hexaescrypt(data, "jo6aey6haid2Teih").decode('utf-8') def calcblowfishkey(songid): """ Calculate the Blowfish decrypt key for a given songid """ h = md5hex(b"%d" % songid) key = b"g4el58wc0zvf9na1" return "".join(compat_chr(compat_ord(h[i]) ^ compat_ord(h[i + 16]) ^ compat_ord(key[i])) for i in range(16)) def getformat(song): """ return format id for a song """ if song["FILESIZE_MP3_320"]: return 3 if song["FILESIZE_MP3_256"]: return 5 return 1 class DeezerPlaylistIE(InfoExtractor): _VALID_URL = r'https?://(?:www\.)?deezer\.com/\w+/(?P[0-9]+)' _TEST = { 'url': 'http://www.deezer.com/playlist/176747451', 'info_dict': { 'id': '176747451', 'title': 'Best!', 'uploader': 'Anonymous', 'thumbnail': r're:^https?://cdn-images.deezer.com/images/cover/.*\.jpg$', }, 'playlist_count': 30, 'skip': 'Only available in .de', } def _real_extract(self, url): if 'test' not in self._downloader.params: self._downloader.report_warning('For now, this extractor only supports the 30 second previews. Patches welcome!') mobj = re.match(self._VALID_URL, url) playlist_id = mobj.group('id') webpage = self._download_webpage(url, playlist_id) geoblocking_msg = self._html_search_regex( r'

(.*?)

', webpage, 'geoblocking message', default=None) if geoblocking_msg is not None: raise ExtractorError( 'Deezer said: %s' % geoblocking_msg, expected=True) host_stream_cdn = self._search_regex( r'var HOST_STREAM_CDN = \'(.*?)\'', webpage, 'host stream cdn') data_json = self._search_regex( (r'__DZR_APP_STATE__\s*=\s*({.+?})\s*', r'naboo\.display\(\'[^\']+\',\s*(.*?)\);\n'), webpage, 'data JSON') data = json.loads(data_json) playlist_title = data.get('DATA', {}).get('TITLE') playlist_uploader = data.get('DATA', {}).get('PARENT_USERNAME') # playlist_thumbnail = self._search_regex( r'