More code reworking

This commit is contained in:
RemixDev 2020-08-15 15:49:45 +02:00
parent 243cf3dfa6
commit 7a536caf1c
6 changed files with 199 additions and 178 deletions

View File

@ -258,7 +258,6 @@ class Deezer:
def get_playlist_gw(self, playlist_id): def get_playlist_gw(self, playlist_id):
playlistAPI = self.gw_api_call('deezer.pagePlaylist', {'playlist_id': playlist_id, 'lang': 'en'})['results']['DATA'] playlistAPI = self.gw_api_call('deezer.pagePlaylist', {'playlist_id': playlist_id, 'lang': 'en'})['results']['DATA']
print(json.dumps(playlistAPI))
return { return {
'id': playlistAPI['PLAYLIST_ID'], 'id': playlistAPI['PLAYLIST_ID'],
'title': playlistAPI['TITLE'], 'title': playlistAPI['TITLE'],

View File

@ -1,6 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# Empty File from deemix.api.deezer import Deezer
from deemix.app.settings import Settings
from deemix.app.queuemanager import QueueManager
from deemix.app.spotify import SpotifyHelper
class deemix: class deemix:
def __init__(self): def __init__(self):
self.set = Settings()
self.dz = Deezer()
self.sp = SpotifyHelper()
self.qm = QueueManager()

View File

@ -15,6 +15,7 @@ from deemix.api.deezer import APIError, USER_AGENT_HEADER
from deemix.utils.misc import changeCase, uniqueArray from deemix.utils.misc import changeCase, uniqueArray
from deemix.utils.pathtemplates import generateFilename, generateFilepath, settingsRegexAlbum, settingsRegexArtist, settingsRegexPlaylistFile from deemix.utils.pathtemplates import generateFilename, generateFilepath, settingsRegexAlbum, settingsRegexArtist, settingsRegexPlaylistFile
from deemix.utils.taggers import tagID3, tagFLAC from deemix.utils.taggers import tagID3, tagFLAC
from deemix.app.queueitem import QISingle, QICollection, QIConvertable
from mutagen.flac import FLACNoHeaderError from mutagen.flac import FLACNoHeaderError
import logging import logging
@ -41,7 +42,7 @@ lastPercentage = 0
def stream_track(dz, track, stream, trackAPI, queueItem, interface=None): def stream_track(dz, track, stream, trackAPI, queueItem, interface=None):
global downloadPercentage, lastPercentage global downloadPercentage, lastPercentage
if 'cancel' in queueItem: if queueItem.cancel:
raise downloadCancelled raise downloadCancelled
try: try:
request = get(track['downloadUrl'], headers=dz.http_headers, stream=True, timeout=30) request = get(track['downloadUrl'], headers=dz.http_headers, stream=True, timeout=30)
@ -55,7 +56,7 @@ def stream_track(dz, track, stream, trackAPI, queueItem, interface=None):
percentage = 0 percentage = 0
i = 0 i = 0
for chunk in request.iter_content(2048): for chunk in request.iter_content(2048):
if 'cancel' in queueItem: if queueItem.cancel:
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)
@ -69,9 +70,9 @@ def stream_track(dz, track, stream, trackAPI, queueItem, interface=None):
downloadPercentage += chunkProgres downloadPercentage += chunkProgres
if round(downloadPercentage) != lastPercentage and round(downloadPercentage) % 2 == 0: if round(downloadPercentage) != lastPercentage and round(downloadPercentage) % 2 == 0:
lastPercentage = round(downloadPercentage) lastPercentage = round(downloadPercentage)
queueItem['progress'] = lastPercentage queueItem.progress = lastPercentage
if interface: if interface:
interface.send("updateQueue", {'uuid': queueItem['uuid'], 'progress': lastPercentage}) interface.send("updateQueue", {'uuid': queueItem.uuid, 'progress': lastPercentage})
i += 1 i += 1
@ -83,9 +84,9 @@ def trackCompletePercentage(trackAPI, queueItem, interface):
downloadPercentage += 1 / trackAPI['SIZE'] * 100 downloadPercentage += 1 / trackAPI['SIZE'] * 100
if round(downloadPercentage) != lastPercentage and round(downloadPercentage) % 2 == 0: if round(downloadPercentage) != lastPercentage and round(downloadPercentage) % 2 == 0:
lastPercentage = round(downloadPercentage) lastPercentage = round(downloadPercentage)
queueItem['progress'] = lastPercentage queueItem.progress = lastPercentage
if interface: if interface:
interface.send("updateQueue", {'uuid': queueItem['uuid'], 'progress': lastPercentage}) interface.send("updateQueue", {'uuid': queueItem.uuid, 'progress': lastPercentage})
def trackRemovePercentage(trackAPI, queueItem, interface): def trackRemovePercentage(trackAPI, queueItem, interface):
global downloadPercentage, lastPercentage global downloadPercentage, lastPercentage
@ -95,9 +96,9 @@ def trackRemovePercentage(trackAPI, queueItem, interface):
downloadPercentage -= 1 / trackAPI['SIZE'] * 100 downloadPercentage -= 1 / trackAPI['SIZE'] * 100
if round(downloadPercentage) != lastPercentage and round(downloadPercentage) % 2 == 0: if round(downloadPercentage) != lastPercentage and round(downloadPercentage) % 2 == 0:
lastPercentage = round(downloadPercentage) lastPercentage = round(downloadPercentage)
queueItem['progress'] = lastPercentage queueItem.progress = lastPercentage
if interface: if interface:
interface.send("updateQueue", {'uuid': queueItem['uuid'], 'progress': lastPercentage}) interface.send("updateQueue", {'uuid': queueItem.uuid, 'progress': lastPercentage})
def downloadImage(url, path, overwrite="n"): def downloadImage(url, path, overwrite="n"):
@ -474,12 +475,45 @@ def getTrackData(dz, trackAPI_gw, settings, trackAPI=None, albumAPI_gw=None, alb
else: else:
track['title_feat'] = track['title'] track['title_feat'] = track['title']
if "_EXTRA_PLAYLIST" in trackAPI:
track['playlist'] = {}
if 'dzcdn.net' in trackAPI["_EXTRA_PLAYLIST"]['picture_small']:
track['playlist']['picUrl'] = trackAPI["_EXTRA_PLAYLIST"]['picture_small'][:-24] + "/{}x{}-{}".format(
settings['embeddedArtworkSize'], settings['embeddedArtworkSize'],
f'000000-{settings["jpegImageQuality"]}-0-0.jpg')
else:
track['playlist']['picUrl'] = trackAPI["_EXTRA_PLAYLIST"]['picture_xl']
track['playlist']['title'] = trackAPI["_EXTRA_PLAYLIST"]['title']
track['playlist']['mainArtist'] = {
'id': trackAPI["_EXTRA_PLAYLIST"]['various_artist']['id'],
'name': trackAPI["_EXTRA_PLAYLIST"]['various_artist']['name'],
'pic': trackAPI["_EXTRA_PLAYLIST"]['various_artist']['picture_small'][
trackAPI["_EXTRA_PLAYLIST"]['various_artist']['picture_small'].find('artist/') + 7:-24]
}
if settings['albumVariousArtists']:
track['playlist']['artist'] = {"Main": [trackAPI["_EXTRA_PLAYLIST"]['various_artist']['name'], ]}
track['playlist']['artists'] = [trackAPI["_EXTRA_PLAYLIST"]['various_artist']['name'], ]
else:
track['playlist']['artist'] = {"Main": []}
track['playlist']['artists'] = []
track['playlist']['trackTotal'] = trackAPI["_EXTRA_PLAYLIST"]['nb_tracks']
track['playlist']['recordType'] = "Compilation"
track['playlist']['barcode'] = ""
track['playlist']['label'] = ""
track['playlist']['explicit'] = trackAPI['_EXTRA_PLAYLIST']['explicit']
track['playlist']['date'] = {
'day': trackAPI["_EXTRA_PLAYLIST"]["creation_date"][8:10],
'month': trackAPI["_EXTRA_PLAYLIST"]["creation_date"][5:7],
'year': trackAPI["_EXTRA_PLAYLIST"]["creation_date"][0:4]
}
track['playlist']['discTotal'] = "1"
return track return track
def downloadTrackObj(dz, trackAPI, settings, bitrate, queueItem, extraTrack=None, interface=None): def downloadTrackObj(dz, trackAPI, settings, bitrate, queueItem, extraTrack=None, interface=None):
result = {} result = {}
if 'cancel' in queueItem: if queueItem.cancel:
result['cancel'] = True result['cancel'] = True
return result return result
@ -495,10 +529,10 @@ def downloadTrackObj(dz, trackAPI, settings, bitrate, queueItem, extraTrack=None
'artist': trackAPI['ART_NAME'] 'artist': trackAPI['ART_NAME']
} }
logger.error(f"[{result['error']['data']['artist']} - {result['error']['data']['title']}] This track is not available on Deezer!") logger.error(f"[{result['error']['data']['artist']} - {result['error']['data']['title']}] This track is not available on Deezer!")
queueItem['failed'] += 1 queueItem.failed += 1
queueItem['errors'].append(result['error']) queueItem.errors.append(result['error'])
if interface: if interface:
interface.send("updateQueue", {'uuid': queueItem['uuid'], 'failed': True, 'data': result['error']['data'], interface.send("updateQueue", {'uuid': queueItem.uuid, 'failed': True, 'data': result['error']['data'],
'error': result['error']['message'], 'errid': result['error']['errid']}) 'error': result['error']['message'], 'errid': result['error']['errid']})
return result return result
# Get the metadata # Get the metadata
@ -512,7 +546,7 @@ def downloadTrackObj(dz, trackAPI, settings, bitrate, queueItem, extraTrack=None
trackAPI=trackAPI['_EXTRA_TRACK'] if '_EXTRA_TRACK' in trackAPI else None, trackAPI=trackAPI['_EXTRA_TRACK'] if '_EXTRA_TRACK' in trackAPI else None,
albumAPI=trackAPI['_EXTRA_ALBUM'] if '_EXTRA_ALBUM' in trackAPI else None albumAPI=trackAPI['_EXTRA_ALBUM'] if '_EXTRA_ALBUM' in trackAPI else None
) )
if 'cancel' in queueItem: if queueItem.cancel:
result['cancel'] = True result['cancel'] = True
return result return result
if track['MD5'] == '': if track['MD5'] == '':
@ -545,10 +579,10 @@ def downloadTrackObj(dz, trackAPI, settings, bitrate, queueItem, extraTrack=None
'artist': track['mainArtist']['name'] 'artist': track['mainArtist']['name']
} }
} }
queueItem['failed'] += 1 queueItem.failed += 1
queueItem['errors'].append(result['error']) queueItem.errors.append(result['error'])
if interface: if interface:
interface.send("updateQueue", {'uuid': queueItem['uuid'], 'failed': True, 'data': result['error']['data'], interface.send("updateQueue", {'uuid': queueItem.uuid, 'failed': True, 'data': result['error']['data'],
'error': result['error']['message'], 'errid': result['error']['errid']}) 'error': result['error']['message'], 'errid': result['error']['errid']})
return result return result
else: else:
@ -563,10 +597,10 @@ def downloadTrackObj(dz, trackAPI, settings, bitrate, queueItem, extraTrack=None
'artist': track['mainArtist']['name'] 'artist': track['mainArtist']['name']
} }
} }
queueItem['failed'] += 1 queueItem.failed += 1
queueItem['errors'].append(result['error']) queueItem.errors.append(result['error'])
if interface: if interface:
interface.send("updateQueue", {'uuid': queueItem['uuid'], 'failed': True, 'data': result['error']['data'], interface.send("updateQueue", {'uuid': queueItem.uuid, 'failed': True, 'data': result['error']['data'],
'error': result['error']['message'], 'errid': result['error']['errid']}) 'error': result['error']['message'], 'errid': result['error']['errid']})
return result return result
@ -602,10 +636,10 @@ def downloadTrackObj(dz, trackAPI, settings, bitrate, queueItem, extraTrack=None
'artist': track['mainArtist']['name'] 'artist': track['mainArtist']['name']
} }
} }
queueItem['failed'] += 1 queueItem.failed += 1
queueItem['errors'].append(result['error']) queueItem.errors.append(result['error'])
if interface: if interface:
interface.send("updateQueue", {'uuid': queueItem['uuid'], 'failed': True, 'data': result['error']['data'], interface.send("updateQueue", {'uuid': queueItem.uuid, 'failed': True, 'data': result['error']['data'],
'error': result['error']['message'], 'errid': result['error']['errid']}) 'error': result['error']['message'], 'errid': result['error']['errid']})
return result return result
else: else:
@ -620,10 +654,10 @@ def downloadTrackObj(dz, trackAPI, settings, bitrate, queueItem, extraTrack=None
'artist': track['mainArtist']['name'] 'artist': track['mainArtist']['name']
} }
} }
queueItem['failed'] += 1 queueItem.failed += 1
queueItem['errors'].append(result['error']) queueItem.errors.append(result['error'])
if interface: if interface:
interface.send("updateQueue", {'uuid': queueItem['uuid'], 'failed': True, 'data': result['error']['data'], interface.send("updateQueue", {'uuid': queueItem.uuid, 'failed': True, 'data': result['error']['data'],
'error': result['error']['message'], 'errid': result['error']['errid']}) 'error': result['error']['message'], 'errid': result['error']['errid']})
return result return result
elif selectedBitrate == -200: elif selectedBitrate == -200:
@ -638,45 +672,13 @@ def downloadTrackObj(dz, trackAPI, settings, bitrate, queueItem, extraTrack=None
'artist': track['mainArtist']['name'] 'artist': track['mainArtist']['name']
} }
} }
queueItem['failed'] += 1 queueItem.failed += 1
queueItem['errors'].append(result['error']) queueItem.errors.append(result['error'])
if interface: if interface:
interface.send("updateQueue", {'uuid': queueItem['uuid'], 'failed': True, 'data': result['error']['data'], interface.send("updateQueue", {'uuid': queueItem.uuid, 'failed': True, 'data': result['error']['data'],
'error': result['error']['message'], 'errid': result['error']['errid']}) 'error': result['error']['message'], 'errid': result['error']['errid']})
return result return result
track['selectedFormat'] = selectedBitrate track['selectedFormat'] = selectedBitrate
if "_EXTRA_PLAYLIST" in trackAPI:
track['playlist'] = {}
if 'dzcdn.net' in trackAPI["_EXTRA_PLAYLIST"]['picture_small']:
track['playlist']['picUrl'] = trackAPI["_EXTRA_PLAYLIST"]['picture_small'][:-24] + "/{}x{}-{}".format(
settings['embeddedArtworkSize'], settings['embeddedArtworkSize'],
f'000000-{settings["jpegImageQuality"]}-0-0.jpg')
else:
track['playlist']['picUrl'] = trackAPI["_EXTRA_PLAYLIST"]['picture_xl']
track['playlist']['title'] = trackAPI["_EXTRA_PLAYLIST"]['title']
track['playlist']['mainArtist'] = {
'id': trackAPI["_EXTRA_PLAYLIST"]['various_artist']['id'],
'name': trackAPI["_EXTRA_PLAYLIST"]['various_artist']['name'],
'pic': trackAPI["_EXTRA_PLAYLIST"]['various_artist']['picture_small'][
trackAPI["_EXTRA_PLAYLIST"]['various_artist']['picture_small'].find('artist/') + 7:-24]
}
if settings['albumVariousArtists']:
track['playlist']['artist'] = {"Main": [trackAPI["_EXTRA_PLAYLIST"]['various_artist']['name'], ]}
track['playlist']['artists'] = [trackAPI["_EXTRA_PLAYLIST"]['various_artist']['name'], ]
else:
track['playlist']['artist'] = {"Main": []}
track['playlist']['artists'] = []
track['playlist']['trackTotal'] = trackAPI["_EXTRA_PLAYLIST"]['nb_tracks']
track['playlist']['recordType'] = "Compilation"
track['playlist']['barcode'] = ""
track['playlist']['label'] = ""
track['playlist']['explicit'] = trackAPI['_EXTRA_PLAYLIST']['explicit']
track['playlist']['date'] = {
'day': trackAPI["_EXTRA_PLAYLIST"]["creation_date"][8:10],
'month': trackAPI["_EXTRA_PLAYLIST"]["creation_date"][5:7],
'year': trackAPI["_EXTRA_PLAYLIST"]["creation_date"][0:4]
}
track['playlist']['discTotal'] = "1"
if settings['tags']['savePlaylistAsCompilation'] and "playlist" in track: if settings['tags']['savePlaylistAsCompilation'] and "playlist" in track:
track['trackNumber'] = trackAPI["POSITION"] track['trackNumber'] = trackAPI["POSITION"]
track['discNumber'] = "1" track['discNumber'] = "1"
@ -732,7 +734,7 @@ def downloadTrackObj(dz, trackAPI, settings, bitrate, queueItem, extraTrack=None
filename = generateFilename(track, trackAPI, settings) filename = generateFilename(track, trackAPI, settings)
(filepath, artistPath, coverPath, extrasPath) = generateFilepath(track, trackAPI, settings) (filepath, artistPath, coverPath, extrasPath) = generateFilepath(track, trackAPI, settings)
if 'cancel' in queueItem: if queueItem.cancel:
result['cancel'] = True result['cancel'] = True
return result return result
# Download and cache coverart # Download and cache coverart
@ -865,10 +867,10 @@ def downloadTrackObj(dz, trackAPI, settings, bitrate, queueItem, extraTrack=None
'artist': track['mainArtist']['name'] 'artist': track['mainArtist']['name']
} }
} }
queueItem['failed'] += 1 queueItem.failed += 1
queueItem['errors'].append(result['error']) queueItem.errors.append(result['error'])
if interface: if interface:
interface.send("updateQueue", {'uuid': queueItem['uuid'], 'failed': True, 'data': result['error']['data'], interface.send("updateQueue", {'uuid': queueItem.uuid, 'failed': True, 'data': result['error']['data'],
'error': result['error']['message'], 'errid': result['error']['errid']}) 'error': result['error']['message'], 'errid': result['error']['errid']})
return 1 return 1
else: else:
@ -883,10 +885,10 @@ def downloadTrackObj(dz, trackAPI, settings, bitrate, queueItem, extraTrack=None
'artist': track['mainArtist']['name'] 'artist': track['mainArtist']['name']
} }
} }
queueItem['failed'] += 1 queueItem.failed += 1
queueItem['errors'].append(result['error']) queueItem.errors.append(result['error'])
if interface: if interface:
interface.send("updateQueue", {'uuid': queueItem['uuid'], 'failed': True, 'data': result['error']['data'], interface.send("updateQueue", {'uuid': queueItem.uuid, 'failed': True, 'data': result['error']['data'],
'error': result['error']['message'], 'errid': result['error']['errid']}) 'error': result['error']['message'], 'errid': result['error']['errid']})
return 1 return 1
except Exception as e: except Exception as e:
@ -919,9 +921,9 @@ def downloadTrackObj(dz, trackAPI, settings, bitrate, queueItem, extraTrack=None
if 'searched' in track: if 'searched' in track:
result['searched'] = f'{track["mainArtist"]["name"]} - {track["title"]}' result['searched'] = f'{track["mainArtist"]["name"]} - {track["title"]}'
logger.info(f"[{track['mainArtist']['name']} - {track['title']}] Track download completed") logger.info(f"[{track['mainArtist']['name']} - {track['title']}] Track download completed")
queueItem['downloaded'] += 1 queueItem.downloaded += 1
if interface: if interface:
interface.send("updateQueue", {'uuid': queueItem['uuid'], 'downloaded': True, 'downloadPath': writepath}) interface.send("updateQueue", {'uuid': queueItem.uuid, 'downloaded': True, 'downloadPath': writepath})
return result return result
@ -939,61 +941,56 @@ def downloadTrackObj_wrap(dz, track, settings, bitrate, queueItem, interface):
} }
} }
} }
queueItem['failed'] += 1 queueItem.failed += 1
queueItem['errors'].append(result['error']) queueItem.errors.append(result['error'])
if interface: if interface:
interface.send("updateQueue", {'uuid': queueItem['uuid'], 'failed': True, 'data': result['error']['data'], interface.send("updateQueue", {'uuid': queueItem.uuid, 'failed': True, 'data': result['error']['data'],
'error': result['error']['message']}) 'error': result['error']['message']})
return result return result
def download(dz, sp, queueItem, interface=None): def download(dz, sp, queueItem, interface=None):
global downloadPercentage, lastPercentage global downloadPercentage, lastPercentage
settings = queueItem['settings'] settings = queueItem.settings
bitrate = queueItem['bitrate'] bitrate = queueItem.bitrate
downloadPercentage = 0 downloadPercentage = 0
lastPercentage = 0 lastPercentage = 0
if '_EXTRA' in queueItem: if isinstance(queueItem, QIConvertable):
sp.convert_spotify_playlist(dz, queueItem, settings, interface=interface) sp.convert_spotify_playlist(dz, queueItem, settings, interface=interface)
if 'single' in queueItem: if isinstance(queueItem, QISingle):
try: try:
result = downloadTrackObj(dz, queueItem['single'], settings, bitrate, queueItem, interface=interface) result = downloadTrackObj(dz, queueItem.single, settings, bitrate, queueItem, interface=interface)
except Exception as e: except Exception as e:
logger.exception(str(e)) logger.exception(str(e))
result = {'error': { result = {'error': {
'message': str(e), 'message': str(e),
'data': { 'data': {
'id': queueItem['single']['SNG_ID'], 'id': queueItem.single['SNG_ID'],
'title': queueItem['single']['SNG_TITLE'] + (queueItem['single']['VERSION'] if 'VERSION' in queueItem['single'] and queueItem['single']['VERSION'] and not queueItem['single']['VERSION'] in queueItem['single']['SNG_TITLE'] else ""), 'title': queueItem.single['SNG_TITLE'] + (queueItem.single['VERSION'] if 'VERSION' in queueItem.single and queueItem.single['VERSION'] and not queueItem.single['VERSION'] in queueItem.single['SNG_TITLE'] else ""),
'mainArtist': {'name': queueItem['single']['ART_NAME']} 'mainArtist': {'name': queueItem.single['ART_NAME']}
} }
} }
} }
queueItem['failed'] += 1 queueItem.failed += 1
queueItem['errors'].append(result['error']) queueItem.errors.append(result['error'])
if interface: if interface:
interface.send("updateQueue", {'uuid': queueItem['uuid'], 'failed': True, 'data': result['error']['data'], interface.send("updateQueue", {'uuid': queueItem.uuid, 'failed': True, 'data': result['error']['data'],
'error': result['error']['message']}) 'error': result['error']['message']})
download_path = after_download_single(result, settings, queueItem) download_path = after_download_single(result, settings)
elif 'collection' in queueItem: elif isinstance(queueItem, QICollection):
playlist = [None] * len(queueItem['collection']) playlist = [None] * len(queueItem.collection)
with ThreadPoolExecutor(settings['queueConcurrency']) as executor: with ThreadPoolExecutor(settings['queueConcurrency']) as executor:
for pos, track in enumerate(queueItem['collection'], start=0): for pos, track in enumerate(queueItem.collection, start=0):
playlist[pos] = executor.submit(downloadTrackObj_wrap, dz, track, settings, bitrate, queueItem, playlist[pos] = executor.submit(downloadTrackObj_wrap, dz, track, settings, bitrate, queueItem,
interface=interface) interface=interface)
download_path = after_download(playlist, settings, queueItem) download_path = after_download(playlist, settings, queueItem)
if interface: if interface:
if 'cancel' in queueItem: if queueItem.cancel:
interface.send('currentItemCancelled', queueItem['uuid']) interface.send('currentItemCancelled', queueItem.uuid)
interface.send("removedFromQueue", queueItem['uuid']) interface.send("removedFromQueue", queueItem.uuid)
else: else:
interface.send("finishDownload", queueItem['uuid']) interface.send("finishDownload", queueItem.uuid)
return { return download_path
'dz': dz,
'sp': sp,
'interface': interface,
'download_path': download_path
}
def after_download(tracks, settings, queueItem): def after_download(tracks, settings, queueItem):
@ -1049,7 +1046,7 @@ def after_download(tracks, settings, queueItem):
return extrasPath return extrasPath
def after_download_single(track, settings, queueItem): def after_download_single(track, settings):
if 'cancel' in track: if 'cancel' in track:
return None return None
if 'extrasPath' not in track: if 'extrasPath' not in track:

View File

@ -101,7 +101,7 @@ class QueueManager:
trackAPI['FILENAME_TEMPLATE'] = settings['albumTracknameTemplate'] trackAPI['FILENAME_TEMPLATE'] = settings['albumTracknameTemplate']
collection.append(trackAPI) collection.append(trackAPI)
return return QICollection( return QICollection(
id, id,
bitrate, bitrate,
albumAPI['title'], albumAPI['title'],
@ -128,7 +128,7 @@ class QueueManager:
return QueueError(url, message) return QueueError(url, message)
if not playlistAPI['public'] and playlistAPI['creator']['id'] != str(dz.user['id']): if not playlistAPI['public'] and playlistAPI['creator']['id'] != str(dz.user['id']):
logger.warn("You can't download others private playlists.") logger.warn("You can't download others private playlists.")
return return QueueError(url, "You can't download others private playlists.", "notYourPrivatePlaylist") return QueueError(url, "You can't download others private playlists.", "notYourPrivatePlaylist")
playlistTracksAPI = dz.get_playlist_tracks_gw(id) playlistTracksAPI = dz.get_playlist_tracks_gw(id)
playlistAPI['various_artist'] = dz.get_artist(5080) playlistAPI['various_artist'] = dz.get_artist(5080)
@ -146,7 +146,7 @@ class QueueManager:
if not 'explicit' in playlistAPI: if not 'explicit' in playlistAPI:
playlistAPI['explicit'] = False playlistAPI['explicit'] = False
return return QICollection( return QICollection(
id, id,
bitrate, bitrate,
playlistAPI['title'], playlistAPI['title'],
@ -163,7 +163,7 @@ class QueueManager:
artistAPI = dz.get_artist(id) artistAPI = dz.get_artist(id)
except APIError as e: except APIError as e:
e = json.loads(str(e)) e = json.loads(str(e))
return return QueueError(url, f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}") return QueueError(url, f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}")
if interface: if interface:
interface.send("startAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']}) interface.send("startAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']})
@ -183,7 +183,7 @@ class QueueManager:
artistAPI = dz.get_artist(id) artistAPI = dz.get_artist(id)
except APIError as e: except APIError as e:
e = json.loads(str(e)) e = json.loads(str(e))
return return QueueError(url, f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}") return QueueError(url, f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}")
if interface: if interface:
interface.send("startAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']}) interface.send("startAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']})
@ -205,7 +205,7 @@ class QueueManager:
artistAPI = dz.get_artist(id) artistAPI = dz.get_artist(id)
except APIError as e: except APIError as e:
e = json.loads(str(e)) e = json.loads(str(e))
return return QueueError(url, f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}") return QueueError(url, f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}")
playlistAPI = { playlistAPI = {
'id': str(artistAPI['id'])+"_top_track", 'id': str(artistAPI['id'])+"_top_track",
@ -252,7 +252,7 @@ class QueueManager:
if not 'explicit' in playlistAPI: if not 'explicit' in playlistAPI:
playlistAPI['explicit'] = False playlistAPI['explicit'] = False
return return QICollection( return QICollection(
id, id,
bitrate, bitrate,
playlistAPI['title'], playlistAPI['title'],
@ -302,9 +302,8 @@ class QueueManager:
return QueueError(url, "Spotify Features is not setted up correctly.", "spotifyDisabled") return QueueError(url, "Spotify Features is not setted up correctly.", "spotifyDisabled")
try: try:
playlist = sp.adapt_spotify_playlist(dz, id, settings) playlist = sp.generate_playlist_queueitem(dz, id, settings)
playlist['bitrate'] = bitrate playlist['bitrate'] = bitrate
playlist['uuid'] = f"{playlist['type']}_{id}_{bitrate}"
return playlist return playlist
except SpotifyException as e: except SpotifyException as e:
return QueueError(url, "Wrong URL: "+e.msg[e.msg.find('\n')+2:]) return QueueError(url, "Wrong URL: "+e.msg[e.msg.find('\n')+2:])

View File

@ -6,19 +6,9 @@ from os import mkdir
import spotipy import spotipy
from spotipy.oauth2 import SpotifyClientCredentials from spotipy.oauth2 import SpotifyClientCredentials
from deemix.utils.localpaths import getConfigFolder from deemix.utils.localpaths import getConfigFolder
from deemix.app.queueitem import QIConvertable from deemix.app.queueitem import QIConvertable, QICollection
emptyPlaylist = {
class SpotifyHelper:
def __init__(self, configFolder=None):
self.credentials = {}
self.spotifyEnabled = False
self.sp = None
if not configFolder:
self.configFolder = getConfigFolder()
else:
self.configFolder = configFolder
self.emptyPlaylist = {
'collaborative': False, 'collaborative': False,
'description': "", 'description': "",
'external_urls': {'spotify': None}, 'external_urls': {'spotify': None},
@ -34,15 +24,27 @@ class SpotifyHelper:
'tracks' : [], 'tracks' : [],
'type': 'playlist', 'type': 'playlist',
'uri': None 'uri': None
} }
self.initCredentials()
def initCredentials(self): class SpotifyHelper:
def __init__(self, configFolder=None):
self.credentials = {}
self.spotifyEnabled = False
self.sp = None
self.configFolder = configFolder
# Make sure config folder exsists
if not self.configFolder:
self.configFolder = getConfigFolder()
if not path.isdir(self.configFolder): if not path.isdir(self.configFolder):
mkdir(self.configFolder) mkdir(self.configFolder)
# Make sure authCredentials exsits
if not path.isfile(path.join(self.configFolder, 'authCredentials.json')): if not path.isfile(path.join(self.configFolder, 'authCredentials.json')):
with open(path.join(self.configFolder, 'authCredentials.json'), 'w') as f: with open(path.join(self.configFolder, 'authCredentials.json'), 'w') as f:
json.dump({'clientId': "", 'clientSecret': ""}, f, indent=2) json.dump({'clientId': "", 'clientSecret': ""}, f, indent=2)
# Load spotify id and secret and check if they are usable
with open(path.join(self.configFolder, 'authCredentials.json'), 'r') as credentialsFile: with open(path.join(self.configFolder, 'authCredentials.json'), 'r') as credentialsFile:
self.credentials = json.load(credentialsFile) self.credentials = json.load(credentialsFile)
self.checkCredentials() self.checkCredentials()
@ -52,7 +54,9 @@ class SpotifyHelper:
spotifyEnabled = False spotifyEnabled = False
else: else:
try: try:
self.createSpotifyConnection() client_credentials_manager = SpotifyClientCredentials(client_id=self.credentials['clientId'],
client_secret=self.credentials['clientSecret'])
self.sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
self.sp.user_playlists('spotify') self.sp.user_playlists('spotify')
self.spotifyEnabled = True self.spotifyEnabled = True
except Exception as e: except Exception as e:
@ -63,18 +67,19 @@ class SpotifyHelper:
return self.credentials return self.credentials
def setCredentials(self, spotifyCredentials): def setCredentials(self, spotifyCredentials):
# Remove extra spaces, just to be sure
spotifyCredentials['clientId'] = spotifyCredentials['clientId'].strip() spotifyCredentials['clientId'] = spotifyCredentials['clientId'].strip()
spotifyCredentials['clientSecret'] = spotifyCredentials['clientSecret'].strip() spotifyCredentials['clientSecret'] = spotifyCredentials['clientSecret'].strip()
# Save them to disk
with open(path.join(self.configFolder, 'authCredentials.json'), 'w') as f: with open(path.join(self.configFolder, 'authCredentials.json'), 'w') as f:
json.dump(spotifyCredentials, f, indent=2) json.dump(spotifyCredentials, f, indent=2)
# Check if they are usable
self.credentials = spotifyCredentials self.credentials = spotifyCredentials
self.checkCredentials() self.checkCredentials()
def createSpotifyConnection(self): # Converts spotify API playlist structure to deezer's playlist structure
client_credentials_manager = SpotifyClientCredentials(client_id=self.credentials['clientId'],
client_secret=self.credentials['clientSecret'])
self.sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
def _convert_playlist_structure(self, spotify_obj): def _convert_playlist_structure(self, spotify_obj):
if len(spotify_obj['images']): if len(spotify_obj['images']):
url = spotify_obj['images'][0]['url'] url = spotify_obj['images'][0]['url']
@ -115,6 +120,7 @@ class SpotifyHelper:
deezer_obj['picture_xl'] = "https://e-cdns-images.dzcdn.net/images/cover/d41d8cd98f00b204e9800998ecf8427e/1000x1000-000000-80-0-0.jpg" deezer_obj['picture_xl'] = "https://e-cdns-images.dzcdn.net/images/cover/d41d8cd98f00b204e9800998ecf8427e/1000x1000-000000-80-0-0.jpg"
return deezer_obj return deezer_obj
# Returns deezer song_id from spotify track_id or track dict
def get_trackid_spotify(self, dz, track_id, fallbackSearch, spotifyTrack=None): def get_trackid_spotify(self, dz, track_id, fallbackSearch, spotifyTrack=None):
if not self.spotifyEnabled: if not self.spotifyEnabled:
raise spotifyFeaturesNotEnabled raise spotifyFeaturesNotEnabled
@ -148,6 +154,7 @@ class SpotifyHelper:
json.dump(cache, spotifyCache) json.dump(cache, spotifyCache)
return dz_track return dz_track
# Returns deezer album_id from spotify album_id
def get_albumid_spotify(self, dz, album_id): def get_albumid_spotify(self, dz, album_id):
if not self.spotifyEnabled: if not self.spotifyEnabled:
raise spotifyFeaturesNotEnabled raise spotifyFeaturesNotEnabled
@ -175,33 +182,24 @@ class SpotifyHelper:
json.dump(cache, spotifyCache) json.dump(cache, spotifyCache)
return dz_album return dz_album
def adapt_spotify_playlist(self, dz, playlist_id, settings):
def generate_playlist_queueitem(self, dz, playlist_id, settings):
if not self.spotifyEnabled: if not self.spotifyEnabled:
raise spotifyFeaturesNotEnabled raise spotifyFeaturesNotEnabled
spotify_playlist = self.sp.playlist(playlist_id) spotify_playlist = self.sp.playlist(playlist_id)
result = {
'title': spotify_playlist['name'],
'artist': spotify_playlist['owner']['display_name'],
'size': spotify_playlist['tracks']['total'],
'downloaded': 0,
'failed': 0,
'progress': 0,
'errors': [],
'type': 'spotify_playlist',
'settings': settings or {},
'id': playlist_id
}
if len(spotify_playlist['images']): if len(spotify_playlist['images']):
result['cover'] = spotify_playlist['images'][0]['url'] cover = spotify_playlist['images'][0]['url']
else: else:
result[ cover = "https://e-cdns-images.dzcdn.net/images/cover/d41d8cd98f00b204e9800998ecf8427e/75x75-000000-80-0-0.jpg"
'cover'] = "https://e-cdns-images.dzcdn.net/images/cover/d41d8cd98f00b204e9800998ecf8427e/75x75-000000-80-0-0.jpg"
playlistAPI = self._convert_playlist_structure(spotify_playlist) playlistAPI = self._convert_playlist_structure(spotify_playlist)
playlistAPI['various_artist'] = dz.get_artist(5080) playlistAPI['various_artist'] = dz.get_artist(5080)
extra = {}
extra['unconverted'] = []
tracklistTmp = spotify_playlist['tracks']['items'] tracklistTmp = spotify_playlist['tracks']['items']
result['collection'] = []
result['_EXTRA'] = {}
result['_EXTRA']['unconverted'] = []
while spotify_playlist['tracks']['next']: while spotify_playlist['tracks']['next']:
spotify_playlist['tracks'] = self.sp.next(spotify_playlist['tracks']) spotify_playlist['tracks'] = self.sp.next(spotify_playlist['tracks'])
tracklistTmp += spotify_playlist['tracks']['items'] tracklistTmp += spotify_playlist['tracks']['items']
@ -209,13 +207,23 @@ class SpotifyHelper:
if item['track']: if item['track']:
if item['track']['explicit']: if item['track']['explicit']:
playlistAPI['explicit'] = True playlistAPI['explicit'] = True
result['_EXTRA']['unconverted'].append(item['track']) extra['unconverted'].append(item['track'])
totalSize = len(result['_EXTRA']['unconverted'])
result['size'] = totalSize totalSize = len(extra['unconverted'])
if not 'explicit' in playlistAPI: if not 'explicit' in playlistAPI:
playlistAPI['explicit'] = False playlistAPI['explicit'] = False
result['_EXTRA']['playlistAPI'] = playlistAPI extra['playlistAPI'] = playlistAPI
return result return QICollection(
playlist_id,
0,
spotify_playlist['name'],
spotify_playlist['owner']['display_name'],
cover,
totalSize,
'spotify_playlist',
settings,
extra,
)
def convert_spotify_playlist(self, dz, item, settings, interface=None): def convert_spotify_playlist(self, dz, item, settings, interface=None):
convertPercentage = 0 convertPercentage = 0
@ -226,8 +234,9 @@ class SpotifyHelper:
else: else:
cache = {'tracks': {}, 'albums': {}} cache = {'tracks': {}, 'albums': {}}
if interface: if interface:
interface.send("startConversion", item['uuid']) interface.send("startConversion", item.uuid)
for pos, track in enumerate(item['_EXTRA']['unconverted'], start=1): collection = []
for pos, track in enumerate(item.extra['unconverted'], start=1):
if str(track['id']) in cache['tracks']: if str(track['id']) in cache['tracks']:
trackID = cache['tracks'][str(track['id'])] trackID = cache['tracks'][str(track['id'])]
else: else:
@ -248,20 +257,31 @@ class SpotifyHelper:
} }
else: else:
deezerTrack = dz.get_track_gw(trackID) deezerTrack = dz.get_track_gw(trackID)
deezerTrack['_EXTRA_PLAYLIST'] = item['_EXTRA']['playlistAPI'] deezerTrack['_EXTRA_PLAYLIST'] = item.extra['playlistAPI']
deezerTrack['POSITION'] = pos deezerTrack['POSITION'] = pos
deezerTrack['SIZE'] = item['size'] deezerTrack['SIZE'] = item.size
deezerTrack['FILENAME_TEMPLATE'] = settings['playlistTracknameTemplate'] deezerTrack['FILENAME_TEMPLATE'] = settings['playlistTracknameTemplate']
item['collection'].append(deezerTrack) collection.append(deezerTrack)
convertPercentage = (pos / item['size']) * 100 convertPercentage = (pos / item.size) * 100
print(convertPercentage) print(convertPercentage)
if round(convertPercentage) != lastPercentage and round(convertPercentage) % 2 == 0: if round(convertPercentage) != lastPercentage and round(convertPercentage) % 2 == 0:
lastPercentage = round(convertPercentage) lastPercentage = round(convertPercentage)
if interface: if interface:
interface.send("updateQueue", {'uuid': item['uuid'], 'conversion': lastPercentage}) interface.send("updateQueue", {'uuid': item.uuid, 'conversion': lastPercentage})
item = QICollection(
item.id,
item.bitrate,
item.title,
item.artist,
item.cover,
item.size,
item.type,
item.settings,
collection,
)
del item['_EXTRA']
with open(path.join(self.configFolder, 'spotifyCache.json'), 'w') as spotifyCache: with open(path.join(self.configFolder, 'spotifyCache.json'), 'w') as spotifyCache:
json.dump(cache, spotifyCache) json.dump(cache, spotifyCache)
if interface: if interface:

View File

@ -218,11 +218,11 @@ def settingsRegexPlaylist(foldername, playlist, settings):
return antiDot(fixLongName(foldername)) return antiDot(fixLongName(foldername))
def settingsRegexPlaylistFile(foldername, queueItem, settings): def settingsRegexPlaylistFile(foldername, queueItem, settings):
foldername = foldername.replace("%title%", fixName(queueItem['title'], settings['illegalCharacterReplacer'])) foldername = foldername.replace("%title%", fixName(queueItem.title, settings['illegalCharacterReplacer']))
foldername = foldername.replace("%artist%", fixName(queueItem['artist'], settings['illegalCharacterReplacer'])) foldername = foldername.replace("%artist%", fixName(queueItem.artist, settings['illegalCharacterReplacer']))
foldername = foldername.replace("%size%", str(queueItem['size'])) foldername = foldername.replace("%size%", str(queueItem.size))
foldername = foldername.replace("%type%", fixName(queueItem['type'], settings['illegalCharacterReplacer'])) foldername = foldername.replace("%type%", fixName(queueItem.type, settings['illegalCharacterReplacer']))
foldername = foldername.replace("%id%", fixName(queueItem['id'], settings['illegalCharacterReplacer'])) foldername = foldername.replace("%id%", fixName(queueItem.id, settings['illegalCharacterReplacer']))
foldername = foldername.replace("%bitrate%", bitrateLabels[int(queueItem['bitrate'])]) foldername = foldername.replace("%bitrate%", bitrateLabels[int(queueItem.bitrate)])
foldername = foldername.replace('\\', pathSep).replace('/', pathSep).replace(pathSep, settings['illegalCharacterReplacer']) foldername = foldername.replace('\\', pathSep).replace('/', pathSep).replace(pathSep, settings['illegalCharacterReplacer'])
return antiDot(fixLongName(foldername)) return antiDot(fixLongName(foldername))