Reverted back to crypted streams
This commit is contained in:
parent
d80702e949
commit
c007d39e15
|
@ -43,6 +43,7 @@ def streamTrack(outputStream, track, start=0, downloadObject=None, listener=None
|
||||||
if downloadObject.isCanceled: raise DownloadCanceled
|
if downloadObject.isCanceled: raise DownloadCanceled
|
||||||
headers= {'User-Agent': USER_AGENT_HEADER}
|
headers= {'User-Agent': USER_AGENT_HEADER}
|
||||||
chunkLength = start
|
chunkLength = start
|
||||||
|
isCryptedStream = "/mobile/" in track.downloadUrl
|
||||||
|
|
||||||
itemData = {
|
itemData = {
|
||||||
'id': track.id,
|
'id': track.id,
|
||||||
|
@ -53,6 +54,8 @@ def streamTrack(outputStream, track, start=0, downloadObject=None, listener=None
|
||||||
try:
|
try:
|
||||||
with get(track.downloadUrl, headers=headers, stream=True, timeout=10) as request:
|
with get(track.downloadUrl, headers=headers, stream=True, timeout=10) as request:
|
||||||
request.raise_for_status()
|
request.raise_for_status()
|
||||||
|
if isCryptedStream:
|
||||||
|
blowfish_key = generateBlowfishKey(str(track.id))
|
||||||
|
|
||||||
complete = int(request.headers["Content-Length"])
|
complete = int(request.headers["Content-Length"])
|
||||||
if complete == 0: raise DownloadEmpty
|
if complete == 0: raise DownloadEmpty
|
||||||
|
@ -77,6 +80,10 @@ def streamTrack(outputStream, track, start=0, downloadObject=None, listener=None
|
||||||
})
|
})
|
||||||
|
|
||||||
for chunk in request.iter_content(2048 * 3):
|
for chunk in request.iter_content(2048 * 3):
|
||||||
|
if isCryptedStream:
|
||||||
|
if len(chunk) >= 2048:
|
||||||
|
chunk = decryptChunk(blowfish_key, chunk[0:2048]) + chunk[2048:]
|
||||||
|
|
||||||
outputStream.write(chunk)
|
outputStream.write(chunk)
|
||||||
chunkLength += len(chunk)
|
chunkLength += len(chunk)
|
||||||
|
|
||||||
|
@ -95,66 +102,6 @@ def streamTrack(outputStream, track, start=0, downloadObject=None, listener=None
|
||||||
sleep(2)
|
sleep(2)
|
||||||
streamTrack(outputStream, track, start, downloadObject, listener)
|
streamTrack(outputStream, track, start, downloadObject, listener)
|
||||||
|
|
||||||
def streamCryptedTrack(outputStream, track, start=0, downloadObject=None, listener=None):
|
|
||||||
if downloadObject.isCanceled: raise DownloadCanceled
|
|
||||||
headers= {'User-Agent': USER_AGENT_HEADER}
|
|
||||||
chunkLength = start
|
|
||||||
|
|
||||||
itemData = {
|
|
||||||
'id': track.id,
|
|
||||||
'title': track.title,
|
|
||||||
'artist': track.mainArtist.name
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
|
||||||
with get(track.downloadUrl, headers=headers, stream=True, timeout=10) as request:
|
|
||||||
request.raise_for_status()
|
|
||||||
blowfish_key = str.encode(generateBlowfishKey(str(track.id)))
|
|
||||||
|
|
||||||
complete = int(request.headers["Content-Length"])
|
|
||||||
if complete == 0: raise DownloadEmpty
|
|
||||||
if start != 0:
|
|
||||||
responseRange = request.headers["Content-Range"]
|
|
||||||
if listener:
|
|
||||||
listener.send('downloadInfo', {
|
|
||||||
'uuid': downloadObject.uuid,
|
|
||||||
'data': itemData,
|
|
||||||
'state': "downloading",
|
|
||||||
'alreadyStarted': True,
|
|
||||||
'value': responseRange
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
if listener:
|
|
||||||
listener.send('downloadInfo', {
|
|
||||||
'uuid': downloadObject.uuid,
|
|
||||||
'data': itemData,
|
|
||||||
'state': "downloading",
|
|
||||||
'alreadyStarted': False,
|
|
||||||
'value': complete
|
|
||||||
})
|
|
||||||
|
|
||||||
for chunk in request.iter_content(2048 * 3):
|
|
||||||
if len(chunk) >= 2048:
|
|
||||||
chunk = decryptChunk(blowfish_key, chunk[0:2048]) + chunk[2048:]
|
|
||||||
|
|
||||||
outputStream.write(chunk)
|
|
||||||
chunkLength += len(chunk)
|
|
||||||
|
|
||||||
if downloadObject:
|
|
||||||
if isinstance(downloadObject, Single):
|
|
||||||
chunkProgres = (chunkLength / (complete + start)) * 100
|
|
||||||
downloadObject.progressNext = chunkProgres
|
|
||||||
else:
|
|
||||||
chunkProgres = (len(chunk) / (complete + start)) / downloadObject.size * 100
|
|
||||||
downloadObject.progressNext += chunkProgres
|
|
||||||
downloadObject.updateProgress(listener)
|
|
||||||
|
|
||||||
except (SSLError, u3SSLError):
|
|
||||||
streamCryptedTrack(outputStream, track, chunkLength, downloadObject, listener)
|
|
||||||
except (RequestsConnectionError, ReadTimeout, ChunkedEncodingError):
|
|
||||||
sleep(2)
|
|
||||||
streamCryptedTrack(outputStream, track, start, downloadObject, listener)
|
|
||||||
|
|
||||||
class DownloadCanceled(Exception):
|
class DownloadCanceled(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ from deemix.types.Picture import StaticPicture
|
||||||
from deemix.utils import USER_AGENT_HEADER
|
from deemix.utils import USER_AGENT_HEADER
|
||||||
from deemix.utils.pathtemplates import generatePath, generateAlbumName, generateArtistName, generateDownloadObjectName
|
from deemix.utils.pathtemplates import generatePath, generateAlbumName, generateArtistName, generateDownloadObjectName
|
||||||
from deemix.tagger import tagID3, tagFLAC
|
from deemix.tagger import tagID3, tagFLAC
|
||||||
from deemix.decryption import generateStreamURL, streamTrack, DownloadCanceled
|
from deemix.decryption import generateCryptedStreamURL, streamTrack, DownloadCanceled
|
||||||
from deemix.settings import OverwriteOption
|
from deemix.settings import OverwriteOption
|
||||||
|
|
||||||
logger = logging.getLogger('deemix')
|
logger = logging.getLogger('deemix')
|
||||||
|
@ -99,7 +99,7 @@ def getPreferredBitrate(track, bitrate, shouldFallback, uuid=None, listener=None
|
||||||
|
|
||||||
def testBitrate(track, formatNumber, formatName):
|
def testBitrate(track, formatNumber, formatName):
|
||||||
request = requests.head(
|
request = requests.head(
|
||||||
generateStreamURL(track.id, track.MD5, track.mediaVersion, formatNumber),
|
generateCryptedStreamURL(track.id, track.MD5, track.mediaVersion, formatNumber),
|
||||||
headers={'User-Agent': USER_AGENT_HEADER},
|
headers={'User-Agent': USER_AGENT_HEADER},
|
||||||
timeout=30
|
timeout=30
|
||||||
)
|
)
|
||||||
|
@ -342,7 +342,7 @@ class Downloader:
|
||||||
writepath = Path(currentFilename)
|
writepath = Path(currentFilename)
|
||||||
|
|
||||||
if not trackAlreadyDownloaded or self.settings['overwriteFile'] == OverwriteOption.OVERWRITE:
|
if not trackAlreadyDownloaded or self.settings['overwriteFile'] == OverwriteOption.OVERWRITE:
|
||||||
track.downloadUrl = generateStreamURL(track.id, track.MD5, track.mediaVersion, track.bitrate)
|
track.downloadUrl = generateCryptedStreamURL(track.id, track.MD5, track.mediaVersion, track.bitrate)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(writepath, 'wb') as stream:
|
with open(writepath, 'wb') as stream:
|
||||||
|
|
|
@ -20,7 +20,7 @@ def generateBlowfishKey(trackId):
|
||||||
bfKey = ""
|
bfKey = ""
|
||||||
for i in range(16):
|
for i in range(16):
|
||||||
bfKey += chr(ord(idMd5[i]) ^ ord(idMd5[i + 16]) ^ ord(SECRET[i]))
|
bfKey += chr(ord(idMd5[i]) ^ ord(idMd5[i + 16]) ^ ord(SECRET[i]))
|
||||||
return bfKey
|
return str.encode(bfKey)
|
||||||
|
|
||||||
def decryptChunk(key, data):
|
def decryptChunk(key, data):
|
||||||
return Blowfish.new(key, Blowfish.MODE_CBC, b"\x00\x01\x02\x03\x04\x05\x06\x07").decrypt(data)
|
return Blowfish.new(key, Blowfish.MODE_CBC, b"\x00\x01\x02\x03\x04\x05\x06\x07").decrypt(data)
|
||||||
|
|
Loading…
Reference in New Issue