Cleaned up queuemanager.py

This commit is contained in:
RemixDev 2020-09-30 15:34:30 +02:00
parent 860d57c437
commit f209df1fe1

View file

@ -1,6 +1,6 @@
from deemix.app.downloadjob import DownloadJob
from deemix.utils import getIDFromLink, getTypeFromLink, getBitrateInt
from deemix.api.deezer import APIError
from deemix.api.deezer import APIError, LyricsStatus
from spotipy.exceptions import SpotifyException
from deemix.app.queueitem import QueueItem, QISingle, QICollection, QIConvertable
import logging
@ -21,30 +21,17 @@ class QueueManager:
self.currentItem = ""
self.sp = spotifyHelper
def generateQueueItem(self, dz, url, settings, bitrate=None, albumAPI=None, trackAPI=None, interface=None):
forcedBitrate = getBitrateInt(bitrate)
bitrate = forcedBitrate if forcedBitrate else settings['maxBitrate']
if 'deezer.page.link' in url:
url = urlopen(url).url
type = getTypeFromLink(url)
id = getIDFromLink(url, type)
if type == None or id == None:
logger.warn("URL not recognized")
return QueueError(url, "URL not recognized", "invalidURL")
elif type == "track":
def generateTrackQueueItem(self, dz, id, settings, bitrate, trackAPI=None, albumAPI=None):
if id.startswith("isrc"):
try:
trackAPI = dz.get_track(id)
except APIError as e:
e = json.loads(str(e))
return QueueError("https://deezer.com/track/"+str(id), f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}")
if 'id' in trackAPI and 'title' in trackAPI:
id = trackAPI['id']
else:
return QueueError(url, "Track ISRC is not available on deezer", "ISRCnotOnDeezer")
except APIError as e:
e = json.loads(str(e))
return QueueError(url, f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}")
return QueueError("https://deezer.com/track/"+str(id), "Track ISRC is not available on deezer", "ISRCnotOnDeezer")
try:
trackAPI_gw = dz.get_track_gw(id)
except APIError as e:
@ -52,55 +39,62 @@ class QueueManager:
message = "Wrong URL"
if "DATA_ERROR" in e:
message += f": {e['DATA_ERROR']}"
return QueueError(url, message)
return QueueError("https://deezer.com/track/"+str(id), message)
if albumAPI:
trackAPI_gw['_EXTRA_ALBUM'] = albumAPI
if trackAPI:
trackAPI_gw['_EXTRA_TRACK'] = trackAPI
if settings['createSingleFolder']:
trackAPI_gw['FILENAME_TEMPLATE'] = settings['albumTracknameTemplate']
else:
trackAPI_gw['FILENAME_TEMPLATE'] = settings['tracknameTemplate']
trackAPI_gw['SINGLE_TRACK'] = True
title = trackAPI_gw['SNG_TITLE']
if 'VERSION' in trackAPI_gw and trackAPI_gw['VERSION']:
title += " " + trackAPI_gw['VERSION']
explicit = int(trackAPI_gw['EXPLICIT_LYRICS']) > 0
return QISingle(
id,
bitrate,
title,
trackAPI_gw['ART_NAME'],
f"https://e-cdns-images.dzcdn.net/images/cover/{trackAPI_gw['ALB_PICTURE']}/75x75-000000-80-0-0.jpg",
int(trackAPI_gw['EXPLICIT_LYRICS']) > 0,
'track',
settings,
trackAPI_gw,
id=id,
bitrate=bitrate,
title=title,
artist=trackAPI_gw['ART_NAME'],
cover=f"https://e-cdns-images.dzcdn.net/images/cover/{trackAPI_gw['ALB_PICTURE']}/75x75-000000-80-0-0.jpg",
explicit=explicit,
type='track',
settings=settings,
single=trackAPI_gw,
)
elif type == "album":
def generateAlbumQueueItem(self, dz, id, settings, bitrate):
try:
albumAPI = dz.get_album(id)
except APIError as e:
e = json.loads(str(e))
return QueueError(url, f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}")
return QueueError("https://deezer.com/album/"+str(id), f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}")
if id.startswith('upc'):
id = albumAPI['id']
albumAPI_gw = dz.get_album_gw(id)
albumAPI['nb_disk'] = albumAPI_gw['NUMBER_DISK']
albumAPI['copyright'] = albumAPI_gw['COPYRIGHT']
if albumAPI['nb_tracks'] == 1:
return self.generateQueueItem(dz, f"https://www.deezer.com/track/{albumAPI['tracks']['data'][0]['id']}",
settings, bitrate, albumAPI=albumAPI, interface=interface)
return self.generateTrackQueueItem(dz, albumAPI['tracks']['data'][0]['id'], settings, bitrate, albumAPI=albumAPI)
tracksArray = dz.get_album_tracks_gw(id)
if albumAPI['nb_tracks'] == 255:
albumAPI['nb_tracks'] = len(tracksArray)
if albumAPI['cover_small'] != None:
cover = albumAPI['cover_small'][:-24] + '/75x75-000000-80-0-0.jpg'
else:
cover = f"https://e-cdns-images.dzcdn.net/images/cover/{albumAPI_gw['ALB_PICTURE']}/75x75-000000-80-0-0.jpg"
totalSize = len(tracksArray)
collection = []
for pos, trackAPI in enumerate(tracksArray, start=1):
@ -110,24 +104,27 @@ class QueueManager:
trackAPI['FILENAME_TEMPLATE'] = settings['albumTracknameTemplate']
collection.append(trackAPI)
explicit = albumAPI_gw['EXPLICIT_ALBUM_CONTENT']['EXPLICIT_LYRICS_STATUS'] in [LyricsStatus.EXPLICIT, LyricsStatus.PARTIALLY_EXPLICIT]
return QICollection(
id,
bitrate,
albumAPI['title'],
albumAPI['artist']['name'],
cover,
albumAPI_gw['EXPLICIT_ALBUM_CONTENT']['EXPLICIT_LYRICS_STATUS'] > 0,
totalSize,
'album',
settings,
collection,
id=id,
bitrate=bitrate,
title=albumAPI['title'],
artist=albumAPI['artist']['name'],
cover=cover,
explicit=explicit,
size=totalSize,
type='album',
settings=settings,
collection=collection,
)
elif type == "playlist":
def generatePlaylistQueueItem(self, dz, id, settings, bitrate):
try:
playlistAPI = dz.get_playlist(id)
except:
playlistAPI = None
if not playlistAPI:
try:
playlistAPI = dz.get_playlist_gw(id)
except APIError as e:
@ -135,10 +132,11 @@ class QueueManager:
message = "Wrong URL"
if "DATA_ERROR" in e:
message += f": {e['DATA_ERROR']}"
return QueueError(url, message)
return QueueError("https://deezer.com/playlist/"+str(id), message)
if not playlistAPI['public'] and playlistAPI['creator']['id'] != str(dz.user['id']):
logger.warn("You can't download others private playlists.")
return QueueError(url, "You can't download others private playlists.", "notYourPrivatePlaylist")
return QueueError("https://deezer.com/playlist/"+str(id), "You can't download others private playlists.", "notYourPrivatePlaylist")
playlistTracksAPI = dz.get_playlist_tracks_gw(id)
playlistAPI['various_artist'] = dz.get_artist(5080)
@ -146,7 +144,7 @@ class QueueManager:
totalSize = len(playlistTracksAPI)
collection = []
for pos, trackAPI in enumerate(playlistTracksAPI, start=1):
if 'EXPLICIT_TRACK_CONTENT' in trackAPI and trackAPI['EXPLICIT_TRACK_CONTENT'].get('EXPLICIT_LYRICS_STATUS') in [1,4]:
if trackAPI['EXPLICIT_TRACK_CONTENT'].get('EXPLICIT_LYRICS_STATUS', LyricsStatus.UNKNOWN) in [LyricsStatus.EXPLICIT, LyricsStatus.PARTIALLY_EXPLICIT]:
playlistAPI['explicit'] = True
trackAPI['_EXTRA_PLAYLIST'] = playlistAPI
trackAPI['POSITION'] = pos
@ -157,66 +155,62 @@ class QueueManager:
playlistAPI['explicit'] = False
return QICollection(
id,
bitrate,
playlistAPI['title'],
playlistAPI['creator']['name'],
playlistAPI['picture_small'][:-24] + '/75x75-000000-80-0-0.jpg',
playlistAPI['explicit'],
totalSize,
'playlist',
settings,
collection,
id=id,
bitrate=bitrate,
title=playlistAPI['title'],
artist=playlistAPI['creator']['name'],
cover=playlistAPI['picture_small'][:-24] + '/75x75-000000-80-0-0.jpg',
explicit=playlistAPI['explicit'],
size=totalSize,
type='playlist',
settings=settings,
collection=collection,
)
elif type == "artist":
def generateArtistQueueItem(self, dz, id, settings, bitrate, interface=None):
try:
artistAPI = dz.get_artist(id)
except APIError as e:
e = json.loads(str(e))
return QueueError(url, f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}")
return QueueError("https://deezer.com/artist/"+str(id), f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}")
if interface:
interface.send("startAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']})
if interface: interface.send("startAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']})
artistAPITracks = dz.get_artist_albums(id)
albumList = []
for album in artistAPITracks['data']:
albumList.append(self.generateQueueItem(dz, album['link'], settings, bitrate, interface=interface))
albumList.append(self.generateAlbumQueueItem(dz, album['id'], settings, bitrate))
if interface:
interface.send("finishAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']})
if interface: interface.send("finishAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']})
return albumList
elif type == "artistdiscography":
def generateArtistDiscographyQueueItem(self, dz, id, settings, bitrate, interface=None):
try:
artistAPI = dz.get_artist(id)
except APIError as e:
e = json.loads(str(e))
return QueueError(url, f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}")
return QueueError("https://deezer.com/artist/"+str(id)+"/discography", f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}")
if interface:
interface.send("startAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']})
if interface: interface.send("startAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']})
artistDiscographyAPI = dz.get_artist_discography_gw(id, 100)
albumList = []
for type in artistDiscographyAPI:
if type != 'all':
for album in artistDiscographyAPI[type]:
albumList.append(self.generateQueueItem(dz, album['link'], settings, bitrate, interface=interface))
albumList.append(self.generateAlbumQueueItem(dz, album['id'], settings, bitrate))
if interface:
interface.send("finishAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']})
if interface: interface.send("finishAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']})
return albumList
elif type == "artisttop":
def generateArtistTopQueueItem(self, dz, id, settings, bitrate, interface=None):
try:
artistAPI = dz.get_artist(id)
except APIError as e:
e = json.loads(str(e))
return QueueError(url, f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}")
return QueueError("https://deezer.com/artist/"+str(id)+"/top_track", f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}")
playlistAPI = {
'id': str(artistAPI['id'])+"_top_track",
@ -253,7 +247,7 @@ class QueueManager:
totalSize = len(artistTopTracksAPI_gw)
collection = []
for pos, trackAPI in enumerate(artistTopTracksAPI_gw, start=1):
if 'EXPLICIT_TRACK_CONTENT' in trackAPI and trackAPI['EXPLICIT_TRACK_CONTENT'].get('EXPLICIT_LYRICS_STATUS') in [1,4]:
if trackAPI['EXPLICIT_TRACK_CONTENT'].get('EXPLICIT_LYRICS_STATUS', LyricsStatus.UNKNOWN) in [LyricsStatus.EXPLICIT, LyricsStatus.PARTIALLY_EXPLICIT]:
playlistAPI['explicit'] = True
trackAPI['_EXTRA_PLAYLIST'] = playlistAPI
trackAPI['POSITION'] = pos
@ -264,23 +258,46 @@ class QueueManager:
playlistAPI['explicit'] = False
return QICollection(
id,
bitrate,
playlistAPI['title'],
playlistAPI['creator']['name'],
playlistAPI['picture_small'][:-24] + '/75x75-000000-80-0-0.jpg',
playlistAPI['explicit'],
totalSize,
'playlist',
settings,
collection,
id=id,
bitrate=bitrate,
title=playlistAPI['title'],
artist=playlistAPI['creator']['name'],
cover=playlistAPI['picture_small'][:-24] + '/75x75-000000-80-0-0.jpg',
explicit=playlistAPI['explicit'],
size=totalSize,
type='playlist',
settings=settings,
collection=collection,
)
elif type == "spotifytrack" and self.sp:
def generateQueueItem(self, dz, url, settings, bitrate=None, interface=None):
bitrate = getBitrateInt(bitrate) or settings['maxBitrate']
if 'deezer.page.link' in url: url = urlopen(url).url
type = getTypeFromLink(url)
id = getIDFromLink(url, type)
if type == None or id == None:
logger.warn("URL not recognized")
return QueueError(url, "URL not recognized", "invalidURL")
if type == "track":
return self.generateTrackQueueItem(dz, id, settings, bitrate)
elif type == "album":
return self.generateAlbumQueueItem(dz, id, settings, bitrate)
elif type == "playlist":
return self.generatePlaylistQueueItem(dz, id, settings, bitrate)
elif type == "artist":
return self.generateArtistQueueItem(dz, id, settings, bitrate, interface=interface)
elif type == "artistdiscography":
return self.generateArtistDiscographyQueueItem(dz, id, settings, bitrate, interface=interface)
elif type == "artisttop":
return self.generateArtistTopQueueItem(dz, id, settings, bitrate, interface=interface)
elif type.startswith("spotify") and self.sp:
if not self.sp.spotifyEnabled:
logger.warn("Spotify Features is not setted up correctly.")
return QueueError(url, "Spotify Features is not setted up correctly.", "spotifyDisabled")
if type == "spotifytrack":
try:
(track_id, trackAPI, _) = self.sp.get_trackid_spotify(dz, id, settings['fallbackSearch'])
except SpotifyException as e:
@ -289,16 +306,12 @@ class QueueManager:
return QueueError(url, "Something went wrong: "+str(e))
if track_id != "0":
return self.generateQueueItem(dz, f'https://www.deezer.com/track/{track_id}', settings, bitrate, trackAPI=trackAPI, interface=interface)
return self.generateTrackQueueItem(dz, track_id, settings, bitrate, trackAPI=trackAPI)
else:
logger.warn("Track not found on deezer!")
return QueueError(url, "Track not found on deezer!", "trackNotOnDeezer")
elif type == "spotifyalbum" and self.sp:
if not self.sp.spotifyEnabled:
logger.warn("Spotify Features is not setted up correctly.")
return QueueError(url, "Spotify Features is not setted up correctly.", "spotifyDisabled")
elif type == "spotifyalbum":
try:
album_id = self.sp.get_albumid_spotify(dz, id)
except SpotifyException as e:
@ -307,31 +320,25 @@ class QueueManager:
return QueueError(url, "Something went wrong: "+str(e))
if album_id != "0":
return self.generateQueueItem(dz, f'https://www.deezer.com/album/{album_id}', settings, bitrate, interface=interface)
return self.generateAlbumQueueItem(dz, album_id, settings, bitrate)
else:
logger.warn("Album not found on deezer!")
return QueueError(url, "Album not found on deezer!", "albumNotOnDeezer")
elif type == "spotifyplaylist" and self.sp:
if not self.sp.spotifyEnabled:
logger.warn("Spotify Features is not setted up correctly.")
return QueueError(url, "Spotify Features is not setted up correctly.", "spotifyDisabled")
elif type == "spotifyplaylist":
try:
return self.sp.generate_playlist_queueitem(dz, id, bitrate, settings)
except SpotifyException as e:
return QueueError(url, "Wrong URL: "+e.msg[e.msg.find('\n')+2:])
except Exception as e:
return QueueError(url, "Something went wrong: "+str(e))
else:
logger.warn("URL not supported yet")
return QueueError(url, "URL not supported yet", "unsupportedURL")
def addToQueue(self, dz, url, settings, bitrate=None, interface=None, ack=None):
if not dz.logged_in:
if interface:
interface.send("loginNeededToDownload")
if interface: interface.send("loginNeededToDownload")
return False
def parseLink(link):
@ -340,6 +347,8 @@ class QueueManager:
return False
logger.info("Generating queue item for: "+link)
item = self.generateQueueItem(dz, link, settings, bitrate, interface=interface)
# Add ack to all items
if type(item) is list:
for i in item:
if isinstance(i, QueueItem):
@ -365,41 +374,35 @@ class QueueManager:
if not queueItem:
return False
if type(queueItem) is list:
ogLen = len(self.queue)
slimmedItems = []
for x in queueItem:
if isinstance(x, QueueError):
logger.error(f"[{x.link}] {x.message}")
continue
if x.uuid in list(self.queueList.keys()):
logger.warn(f"[{x.uuid}] Already in queue, will not be added again.")
continue
self.queue.append(x.uuid)
self.queueList[x.uuid] = x
logger.info(f"[{x.uuid}] Added to queue.")
slimmedItems.append(x.getSlimmedItem())
if len(self.queue) <= ogLen:
def processQueueItem(item, silenced=False):
if isinstance(item, QueueError):
logger.error(f"[{item.link}] {item.message}")
if interface and not silenced: interface.send("queueError", item.toDict())
return False
if interface:
interface.send("addedToQueue", slimmedItems)
else:
if isinstance(queueItem, QueueError):
logger.error(f"[{queueItem.link}] {queueItem.message}")
if interface:
interface.send("queueError", queueItem.toDict())
if item.uuid in list(self.queueList.keys()):
logger.warn(f"[{item.uuid}] Already in queue, will not be added again.")
if interface and not silenced: interface.send("alreadyInQueue", {'uuid': item.uuid, 'title': item.title})
return False
if queueItem.uuid in list(self.queueList.keys()):
logger.warn(f"[{queueItem.uuid}] Already in queue, will not be added again.")
if interface:
interface.send("alreadyInQueue", {'uuid': queueItem.uuid, 'title': queueItem.title})
return False
if interface:
interface.send("addedToQueue", queueItem.getSlimmedItem())
logger.info(f"[{queueItem.uuid}] Added to queue.")
self.queue.append(queueItem.uuid)
self.queueList[queueItem.uuid] = queueItem
self.queue.append(item.uuid)
self.queueList[item.uuid] = item
logger.info(f"[{item.uuid}] Added to queue.")
return True
if type(queueItem) is list:
slimmedItems = []
for item in queueItem:
if processQueueItem(item, silenced=True):
slimmedItems.append(item.getSlimmedItem())
else:
continue
if not len(slimmedItems):
return False
if interface: interface.send("addedToQueue", slimmedItems)
else:
if processQueueItem(queueItem):
if interface: interface.send("addedToQueue", queueItem.getSlimmedItem())
else:
return False
self.nextItem(dz, interface)
return True
@ -411,17 +414,15 @@ class QueueManager:
self.currentItem = self.queue.pop(0)
else:
return None
if isinstance(self.queueList[self.currentItem], QIConvertable) and self.queueList[self.currentItem].extra:
logger.info(f"[{self.currentItem}] Converting tracks to deezer.")
self.sp.convert_spotify_playlist(dz, self.queueList[self.currentItem], interface=interface)
logger.info(f"[{self.currentItem}] Tracks converted.")
if interface:
interface.send("startDownload", self.currentItem)
if interface: interface.send("startDownload", self.currentItem)
logger.info(f"[{self.currentItem}] Started downloading.")
DownloadJob(dz, self.queueList[self.currentItem], interface).start()
self.afterDownload(dz, interface)
def afterDownload(self, dz, interface):
if self.queueList[self.currentItem].cancel:
del self.queueList[self.currentItem]
else:
@ -430,7 +431,6 @@ class QueueManager:
self.currentItem = ""
self.nextItem(dz, interface)
def getQueue(self):
return (self.queue, self.queueComplete, self.slimQueueList(), self.currentItem)