rewrote getPreferredBitrate function using mobile API workaround

should be more stable than constantly requesting the CDN
This commit is contained in:
uh_wot 2020-07-24 16:21:24 +02:00
parent ec38923701
commit a85396600a
2 changed files with 62 additions and 25 deletions

View File

@ -29,12 +29,37 @@ class Deezer:
self.selectedAccount = 0 self.selectedAccount = 0
self.session = requests.Session() self.session = requests.Session()
self.logged_in = False self.logged_in = False
self.session.post("http://www.deezer.com/", headers=self.http_headers) self.session.post("https://www.deezer.com/", headers=self.http_headers)
self.sid = self.session.cookies.get('sid') self.guest_sid = self.session.cookies.get('sid')
def get_token(self): def get_token(self):
token_data = self.gw_api_call('deezer.getUserData') token_data = self.gw_api_call('deezer.getUserData')
return token_data["results"]["checkForm"] return token_data["results"]["checkForm"]
def get_track_filesizes(self, sng_id):
try:
site = requests.post(
"https://api.deezer.com/1.0/gateway.php",
params={
'api_key': "4VCYIJUCDLOUELGD1V8WBVYBNVDYOXEWSLLZDONGBBDFVXTZJRXPR29JRLQFO6ZE",
'sid': self.guest_sid,
'input': '3',
'output': '3',
'method': 'song_getData'
},
timeout=30,
json={'sng_id': sng_id},
headers=self.http_headers
)
except:
time.sleep(2)
return self.get_track_filesizes(sng_id)
response = site.json()["results"]
filesizes = {}
for key, value in response.items():
if key.startswith("FILESIZE_"):
filesizes[key] = value
return filesizes
def gw_api_call(self, method, args=None): def gw_api_call(self, method, args=None):
if args is None: if args is None:
@ -129,13 +154,14 @@ class Deezer:
def login_via_arl(self, arl, child=0): def login_via_arl(self, arl, child=0):
cookie_obj = requests.cookies.create_cookie( cookie_obj = requests.cookies.create_cookie(
domain='deezer.com', domain='.deezer.com',
name='arl', name='arl',
value=arl, value=arl,
path="/", path="/",
rest={'HttpOnly': True} rest={'HttpOnly': True}
) )
self.session.cookies.set_cookie(cookie_obj) self.session.cookies.set_cookie(cookie_obj)
self.session.cookies.clear(".deezer.com", "/", "sid")
user_data = self.gw_api_call("deezer.getUserData") user_data = self.gw_api_call("deezer.getUserData")
if user_data["results"]["USER"]["USER_ID"] == 0: if user_data["results"]["USER"]["USER_ID"] == 0:
self.logged_in = False self.logged_in = False

View File

@ -56,7 +56,7 @@ def stream_track(dz, track, stream, trackAPI, queueItem, interface=None):
for chunk in request.iter_content(2048): for chunk in request.iter_content(2048):
if 'cancel' in queueItem: if 'cancel' in queueItem:
raise downloadCancelled raise downloadCancelled
if (i % 3) == 0 and len(chunk) == 2048: if i % 3 == 0 and len(chunk) == 2048:
chunk = Blowfish.new(blowfish_key, Blowfish.MODE_CBC, b"\x00\x01\x02\x03\x04\x05\x06\x07").decrypt(chunk) chunk = Blowfish.new(blowfish_key, Blowfish.MODE_CBC, b"\x00\x01\x02\x03\x04\x05\x06\x07").decrypt(chunk)
stream.write(chunk) stream.write(chunk)
chunkLength += len(chunk) chunkLength += len(chunk)
@ -130,31 +130,42 @@ def formatDate(date, template):
def getPreferredBitrate(dz, track, bitrate, fallback=True): def getPreferredBitrate(dz, track, bitrate, fallback=True):
if 'localTrack' in track: if 'localTrack' in track:
return 0 return 0
formatsnon360 = [9, 3, 1] # flac, mp3_320, mp3_128
formats360 = [15, 14, 13] # 360_hq, 360_mq, 360_lq formats_non_360 = {
if not fallback: 9: "FLAC",
errorNum = -100 3: "MP3_320",
formats = formats360 1: "MP3_128",
formats.extend(formatsnon360) }
elif int(bitrate) in formats360: formats_360 = {
errorNum = -200 15: "MP4_RA3",
formats = formats360 14: "MP4_RA2",
else: 13: "MP4_RA1",
errorNum = 8 }
formats = formatsnon360
for formatNum in formats: if not fallback:
if formatNum <= int(bitrate): error_num = -100
request = get(dz.get_track_stream_url(track['id'], track['MD5'], track['mediaVersion'], formatNum), stream=True) formats = formats360
try: formats.extend(formats_non_360)
request.raise_for_status() elif int(bitrate) in formats_360:
except HTTPError: # if the format is not available, Deezer returns a 403 error error_num = -200
formats = formats_360
else:
error_num = 8
formats = formats_non_360
filesizes = dz.get_track_filesizes(track["id"])
for format_num, format in formats.items():
if format_num <= int(bitrate):
if f"FILESIZE_{format}" in filesizes and int(filesizes[f"FILESIZE_{format}"]) != 0:
return format_num
else:
if fallback: if fallback:
continue continue
else: else:
return errorNum return error_num
return formatNum
return errorNum # fallback is enabled and loop went through all formats return error_num # fallback is enabled and loop went through all formats
def parseEssentialTrackData(track, trackAPI): def parseEssentialTrackData(track, trackAPI):