From fedacde6a1c6645666a4b851bd7c561e53779c41 Mon Sep 17 00:00:00 2001 From: RemixDev Date: Sat, 11 Apr 2020 00:21:30 +0200 Subject: [PATCH] Implemented fluent download bars --- deemix/app/downloader.py | 39 ++++++++++++++++++++++++++++++++++++-- deemix/app/queuemanager.py | 4 ++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/deemix/app/downloader.py b/deemix/app/downloader.py index e4843ae..c5de77f 100644 --- a/deemix/app/downloader.py +++ b/deemix/app/downloader.py @@ -10,6 +10,7 @@ from requests import get from requests.exceptions import HTTPError, ConnectionError from tempfile import gettempdir from concurrent.futures import ThreadPoolExecutor +from Cryptodome.Cipher import Blowfish from time import sleep import re @@ -26,6 +27,38 @@ extensions = { 14: '.mp4', 13: '.mp4' } +downloadPercentage = 0 +lastPercentage = 0 + +def stream_track(dz, track, stream, trackAPI, uuid, socket=None): + global downloadPercentage, lastPercentage + try: + request = get(track['downloadUrl'], headers=dz.http_headers, stream=True, timeout=30) + except Exception as e: + sleep(2) + return stream_track(dz, track, stream, trackAPI, uuid, socket) + request.raise_for_status() + blowfish_key = str.encode(dz._get_blowfish_key(str(track['id']))) + complete = track['selectedFilesize'] + chunkLength = 0 + percentage = 0 + i = 0 + for chunk in request.iter_content(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) + stream.write(chunk) + chunkLength += len(chunk) + if 'SINGLE_TRACK' in trackAPI: + percentage = (chunkLength / complete) * 100 + downloadPercentage = percentage + else: + chunkProgres = (len(chunk) / complete) / trackAPI['SIZE'] * 100 + downloadPercentage += chunkProgres + if round(downloadPercentage) != lastPercentage and round(percentage) % 5 == 0: + lastPercentage = round(downloadPercentage) + if socket: + socket.emit("updateQueue", {'uuid': uuid, 'progress': lastPercentage}) + i += 1 def downloadImage(url, path): if not os.path.isfile(path): @@ -60,7 +93,6 @@ def formatDate(date, template): template = template.replace('D', str(date['day'])) return template - def getPreferredBitrate(filesize, bitrate, fallback=True): if not fallback: formats = {9: 'flac', 3: 'mp3_320', 1: 'mp3_128', 15: '360_hq', 14: '360_mq', 13: '360_lq'} @@ -468,7 +500,7 @@ def downloadTrackObj(dz, trackAPI, settings, bitrate, uuid, extraTrack=None, soc track['downloadUrl'] = dz.get_track_stream_url(track['id'], track['MD5'], track['mediaVersion'], track['selectedFormat']) try: with open(writepath, 'wb') as stream: - dz.stream_track(track['id'], track['downloadUrl'], stream) + stream_track(dz, track, stream, trackAPI, uuid, socket) except HTTPError: remove(writepath) if track['selectedFormat'] == 9 and settings['fallbackBitrate']: @@ -518,8 +550,11 @@ def downloadTrackObj(dz, trackAPI, settings, bitrate, uuid, extraTrack=None, soc return result def download(dz, queueItem, socket=None): + global downloadPercentage, lastPercentage settings = queueItem['settings'] bitrate = queueItem['bitrate'] + downloadPercentage = 0 + lastPercentage = 0 if 'single' in queueItem: result = downloadTrackObj(dz, queueItem['single'], settings, bitrate, queueItem['uuid'], socket=socket) download_path = after_download_single(result, settings) diff --git a/deemix/app/queuemanager.py b/deemix/app/queuemanager.py index 606a564..9df0d33 100644 --- a/deemix/app/queuemanager.py +++ b/deemix/app/queuemanager.py @@ -80,10 +80,12 @@ def generateQueueItem(dz, url, settings, bitrate=None, albumAPI=None): result['bitrate'] = bitrate result['uuid'] = f"{result['type']}_{id}_{bitrate}" result['settings'] = settings or {} + totalSize = len(tracksArray) result['collection'] = [] for pos, trackAPI in enumerate(tracksArray, start=1): trackAPI['_EXTRA_ALBUM'] = albumAPI trackAPI['POSITION'] = pos + trackAPI['SIZE'] = totalSize trackAPI['FILENAME_TEMPLATE'] = settings['albumTracknameTemplate'] result['collection'].append(trackAPI) @@ -103,10 +105,12 @@ def generateQueueItem(dz, url, settings, bitrate=None, albumAPI=None): result['bitrate'] = bitrate result['uuid'] = f"{result['type']}_{id}_{bitrate}" result['settings'] = settings or {} + totalSize = len(playlistTracksAPI) result['collection'] = [] for pos, trackAPI in enumerate(playlistTracksAPI, start=1): trackAPI['_EXTRA_PLAYLIST'] = playlistAPI trackAPI['POSITION'] = pos + trackAPI['SIZE'] = totalSize trackAPI['FILENAME_TEMPLATE'] = settings['playlistTracknameTemplate'] result['collection'].append(trackAPI)