From 0542d7eacf5ed6b9eca6b30d8990872632871229 Mon Sep 17 00:00:00 2001 From: RemixDev Date: Tue, 15 Dec 2020 13:27:02 +0100 Subject: [PATCH] Generalized cover URL generation function --- deemix/app/downloadjob.py | 152 ++++++++++++++++---------------------- deemix/app/track.py | 75 +++++++++++++------ deemix/utils/taggers.py | 12 +-- 3 files changed, 125 insertions(+), 114 deletions(-) diff --git a/deemix/app/downloadjob.py b/deemix/app/downloadjob.py index 9b3e380..95a8e57 100644 --- a/deemix/app/downloadjob.py +++ b/deemix/app/downloadjob.py @@ -93,6 +93,28 @@ def downloadImage(url, path, overwrite=OverwriteOption.DONT_OVERWRITE): else: return path +def generatePictureURL(pic, size, format): + if pic['url']: return pic['url'] + if format.startswith("jpg"): + if '-' in format: + quality = format[4:] + else: + quality = 80 + format = 'jpg' + return "https://e-cdns-images.dzcdn.net/images/{}/{}/{}x{}-{}".format( + pic['type'], + pic['md5'], + size, size, + f'000000-{quality}-0-0.jpg' + ) + if format == 'png': + return "https://e-cdns-images.dzcdn.net/images/{}/{}/{}x{}-{}".format( + pic['type'], + pic['md5'], + size, size, + 'none-100-0-0.png' + ) + def formatDate(date, template): elements = { 'year': ['YYYY', 'YY', 'Y'], @@ -269,6 +291,7 @@ class DownloadJob: else: raise DownloadFailed("notEncoded") + # Choose the target bitrate try: selectedFormat = self.getPreferredBitrate(track) except PreferredBitrateNotFound: @@ -302,41 +325,28 @@ class DownloadJob: except TrackNot360: raise DownloadFailed("no360RA") track.selectedFormat = selectedFormat + track.album['bitrate'] = selectedFormat - imageQualityJPEG = f'000000-{self.settings["jpegImageQuality"]}-0-0.jpg' - imageQualityPNG = 'none-100-0-0.png' - imageQuality = imageQualityJPEG - if self.settings['embeddedArtworkPNG']: imageQuality = imageQualityPNG + # Generate covers URLs + embeddedImageFormat = f'jpg-{self.settings["jpegImageQuality"]}' + if self.settings['embeddedArtworkPNG']: imageFormat = 'png' if self.settings['tags']['savePlaylistAsCompilation'] and track.playlist: track.trackNumber = track.position track.discNumber = "1" track.album = {**track.album, **track.playlist} - if 'picType' in track.playlist: - track.playlist['picUrl'] = "https://e-cdns-images.dzcdn.net/images/{}/{}/{}x{}-{}".format( - track.playlist['picType'], - track.playlist['pic'], - self.settings['embeddedArtworkSize'], self.settings['embeddedArtworkSize'], - imageQuality - ) - else: - track.playlist['picUrl'] = track.playlist['pic'] + track.album['embeddedCoverURL'] = generatePictureURL(track.playlist['pic'], self.settings['embeddedArtworkSize'], embeddedImageFormat) - ext = track.playlist['picUrl'][-4:] - if ext[0] != ".": ext = ".jpg" + ext = track.album['embeddedCoverURL'][-4:] + if ext[0] != ".": ext = ".jpg" # Check for Spotify images - track.album['picPath'] = TEMPDIR / f"pl{trackAPI_gw['_EXTRA_PLAYLIST']['id']}_{self.settings['embeddedArtworkSize']}{ext}" + track.album['embeddedCoverPath'] = TEMPDIR / f"pl{trackAPI_gw['_EXTRA_PLAYLIST']['id']}_{self.settings['embeddedArtworkSize']}{ext}" else: if track.album['date']: track.date = track.album['date'] - track.album['picUrl'] = "https://e-cdns-images.dzcdn.net/images/cover/{}/{}x{}-{}".format( - track.album['pic'], - self.settings['embeddedArtworkSize'], self.settings['embeddedArtworkSize'], - imageQuality - ) + track.album['embeddedCoverURL'] = generatePictureURL(track.album['pic'], self.settings['embeddedArtworkSize'], embeddedImageFormat) - track.album['picPath'] = TEMPDIR / f"alb{track.album['id']}_{self.settings['embeddedArtworkSize']}{track.album['picUrl'][-4:]}" - - track.album['bitrate'] = selectedFormat + ext = track.album['embeddedCoverURL'][-4:] + track.album['embeddedCoverPath'] = TEMPDIR / f"alb{track.album['id']}_{self.settings['embeddedArtworkSize']}{ext}" track.dateString = formatDate(track.date, self.settings['dateFormat']) track.album['dateString'] = formatDate(track.album['date'], self.settings['dateFormat']) @@ -385,8 +395,6 @@ class DownloadJob: else: track.artistsString = separator.join(track.artists) - - # Generate filename and filepath from metadata filename = generateFilename(track, self.settings, trackAPI_gw['FILENAME_TEMPLATE']) (filepath, artistPath, coverPath, extrasPath) = generateFilepath(track, self.settings) @@ -395,34 +403,21 @@ class DownloadJob: # Download and cache coverart logger.info(f"[{track.mainArtist['name']} - {track.title}] Getting the album cover") - track.album['picPath'] = downloadImage(track.album['picUrl'], track.album['picPath']) + track.album['embeddedCoverPath'] = downloadImage(track.album['embeddedCoverURL'], track.album['embeddedCoverPath']) # Save local album art if coverPath: result['albumURLs'] = [] for format in self.settings['localArtworkFormat'].split(","): if format in ["png","jpg"]: - if self.settings['tags']['savePlaylistAsCompilation'] and track.playlist: - if track.playlist['picType']: - localImageQuality = imageQualityJPEG - if format == "png": localImageQuality = imageQualityPNG - url = "https://e-cdns-images.dzcdn.net/images/{}/{}/{}x{}-{}".format( - track.album['picType'], - track.album['pic'], - self.settings['localArtworkSize'], self.settings['localArtworkSize'], - localImageQuality - ) - else: - url = track.album['pic'] - if format != "jpg": continue - else: - localImageQuality = imageQualityJPEG - if format == "png": localImageQuality = imageQualityPNG - url = "https://e-cdns-images.dzcdn.net/images/cover/{}/{}x{}-{}".format( - track.album['pic'], - self.settings['localArtworkSize'], self.settings['localArtworkSize'], - localImageQuality - ) + extendedFormat = format + if extendedFormat == "jpg": extendedFormat += f"-{self.settings['jpegImageQuality']}" + url = generatePictureURL(track.album['pic'], self.settings['localArtworkSize'], extendedFormat) + if self.settings['tags']['savePlaylistAsCompilation'] \ + and track.playlist \ + and track.playlist['pic']['url'] \ + and not format.startswith("jpg"): + continue result['albumURLs'].append({'url': url, 'ext': format}) result['albumPath'] = coverPath result['albumFilename'] = f"{settingsRegexAlbum(self.settings['coverImageTemplate'], track.album, self.settings, track.playlist)}" @@ -432,24 +427,31 @@ class DownloadJob: result['artistURLs'] = [] for format in self.settings['localArtworkFormat'].split(","): if format in ["png","jpg"]: - url = "" - if track.album['mainArtist']['pic'] != "": - localImageQuality = imageQualityJPEG - if format == "png": localImageQuality = imageQualityPNG - url = "https://e-cdns-images.dzcdn.net/images/artist/{}/{}x{}-{}".format( - track.album['mainArtist']['pic'], - self.settings['localArtworkSize'], self.settings['localArtworkSize'], - localImageQuality - ) - elif format == "jpg": # Blank artist image is not available in PNG - url = "https://e-cdns-images.dzcdn.net/images/artist//{}x{}-{}".format( - self.settings['localArtworkSize'], self.settings['localArtworkSize'], - imageQualityJPEG - ) - if url: result['artistURLs'].append({'url': url, 'ext': format}) + extendedFormat = format + if extendedFormat == "jpg": extendedFormat += f"-{self.settings['jpegImageQuality']}" + url = generatePictureURL(track.album['mainArtist']['pic'], self.settings['localArtworkSize'], extendedFormat) + if track.album['mainArtist']['pic']['md5'] == "" and not format.startswith("jpg"): continue + result['artistURLs'].append({'url': url, 'ext': format}) result['artistPath'] = artistPath result['artistFilename'] = f"{settingsRegexArtist(self.settings['artistImageTemplate'], track.album['mainArtist'], self.settings, rootArtist=track.album['rootArtist'])}" + # Save playlist cover + if track.playlist: + if not len(self.playlistURLs): + for format in self.settings['localArtworkFormat'].split(","): + if format in ["png","jpg"]: + extendedFormat = format + if extendedFormat == "jpg": extendedFormat += f"-{self.settings['jpegImageQuality']}" + url = generatePictureURL(track.playlist['pic'], self.settings['localArtworkSize'], extendedFormat) + if track.playlist['pic']['url'] and not format.startswith("jpg"): continue + self.playlistURLs.append({'url': url, 'ext': format}) + if not self.playlistCoverName: + track.playlist['id'] = "pl_" + str(trackAPI_gw['_EXTRA_PLAYLIST']['id']) + track.playlist['genre'] = ["Compilation", ] + track.playlist['bitrate'] = selectedFormat + track.playlist['dateString'] = formatDate(track.playlist['date'], self.settings['dateFormat']) + self.playlistCoverName = f"{settingsRegexAlbum(self.settings['coverImageTemplate'], track.playlist, self.settings, track.playlist)}" + # Remove subfolders from filename and add it to filepath if pathSep in filename: tempPath = filename[:filename.rfind(pathSep)] @@ -491,30 +493,6 @@ class DownloadJob: if not self.extrasPath: self.extrasPath = extrasPath result['filename'] = str(writepath)[len(str(extrasPath))+ len(pathSep):] - # Save playlist cover - if track.playlist: - if not len(self.playlistURLs): - if track.playlist['picType']: - for format in self.settings['localArtworkFormat'].split(","): - if format in ["png","jpg"]: - localImageQuality = imageQualityJPEG - if format == "png": localImageQuality = imageQualityPNG - url = "https://e-cdns-images.dzcdn.net/images/{}/{}/{}x{}-{}".format( - track.playlist['picType'], - track.playlist['pic'], - self.settings['localArtworkSize'], self.settings['localArtworkSize'], - localImageQuality - ) - self.playlistURLs.append({'url': url, 'ext': format}) - else: - self.playlistURLs.append({'url': track.playlist['pic'], 'ext': 'jpg'}) - if not self.playlistCoverName: - track.playlist['id'] = "pl_" + str(trackAPI_gw['_EXTRA_PLAYLIST']['id']) - track.playlist['genre'] = ["Compilation", ] - track.playlist['bitrate'] = selectedFormat - track.playlist['dateString'] = formatDate(track.playlist['date'], self.settings['dateFormat']) - self.playlistCoverName = f"{settingsRegexAlbum(self.settings['coverImageTemplate'], track.playlist, self.settings, track.playlist)}" - if not trackAlreadyDownloaded or self.settings['overwriteFile'] == OverwriteOption.OVERWRITE: logger.info(f"[{track.mainArtist['name']} - {track.title}] Downloading the track") track.downloadUrl = generateStreamURL(track.id, track.MD5, track.mediaVersion, track.selectedFormat) diff --git a/deemix/app/track.py b/deemix/app/track.py index 8cbf853..f24961c 100644 --- a/deemix/app/track.py +++ b/deemix/app/track.py @@ -55,8 +55,8 @@ class Track: self.searched = False self.selectedFormat = 0 self.dateString = None - self.album['picUrl'] = None - self.album['picPath'] = None + self.album['embeddedCoverURL'] = None + self.album['embeddedCoverPath'] = None self.album['bitrate'] = 0 self.album['dateString'] = None self.artistsString = "" @@ -78,12 +78,20 @@ class Track: self.album = { 'id': "0", 'title': trackAPI_gw['ALB_TITLE'], - 'pic': trackAPI_gw.get('ALB_PICTURE', "") + 'pic': { + 'md5': trackAPI_gw.get('ALB_PICTURE', ""), + 'type': "cover", + 'url': None + } } self.mainArtist = { 'id': "0", 'name': trackAPI_gw['ART_NAME'], - 'pic': "" + 'pic': { + 'md5': "", + 'type': "artist", + 'url': None + } } self.artists = [trackAPI_gw['ART_NAME']] self.artist = { @@ -162,7 +170,11 @@ class Track: self.mainArtist = { 'id': trackAPI_gw['ART_ID'], 'name': trackAPI_gw['ART_NAME'], - 'pic': trackAPI_gw.get('ART_PICTURE') + 'pic': { + 'md5': trackAPI_gw.get('ART_PICTURE'), + 'type': "artist", + 'url': None + } } self.date = None @@ -176,7 +188,11 @@ class Track: self.album = { 'id': trackAPI_gw['ALB_ID'], 'title': trackAPI_gw['ALB_TITLE'], - 'pic': trackAPI_gw.get('ALB_PICTURE'), + 'pic': { + 'md5': trackAPI_gw.get('ALB_PICTURE'), + 'type': "cover", + 'url': None + }, 'barcode': "Unknown", 'label': "Unknown", 'explicit': False, @@ -202,7 +218,11 @@ class Track: self.album['mainArtist'] = { 'id': albumAPI['artist']['id'], 'name': albumAPI['artist']['name'], - 'pic': artistPicture + 'pic': { + 'md5': artistPicture, + 'type': "artist", + 'url': None + } } self.album['rootArtist'] = albumAPI.get('root_artist', None) @@ -241,10 +261,10 @@ class Track: self.album['discTotal'] = albumAPI.get('nb_disk', "1") self.copyright = albumAPI.get('copyright') - if not self.album['pic']: - # Getting album cover ID + if not self.album['pic']['md5']: + # Getting album cover MD5 # ex: https://e-cdns-images.dzcdn.net/images/cover/2e018122cb56986277102d2041a592c8/56x56-000000-80-0-0.jpg - self.album['pic'] = albumAPI['cover_small'][albumAPI['cover_small'].find('cover/') + 6:-24] + self.album['pic']['md5'] = albumAPI['cover_small'][albumAPI['cover_small'].find('cover/') + 6:-24] if albumAPI.get('genres') and len(albumAPI['genres'].get('data', [])) > 0: for genre in albumAPI['genres']['data']: @@ -262,7 +282,11 @@ class Track: self.album['mainArtist'] = { 'id': albumAPI_gw['ART_ID'], 'name': albumAPI_gw['ART_NAME'], - 'pic': None + 'pic': { + 'md5': "", + 'type': "artist", + 'url': None + } } self.album['rootArtist'] = None @@ -271,7 +295,7 @@ class Track: # ex: https://e-cdns-images.dzcdn.net/images/artist/f2bc007e9133c946ac3c3907ddc5d2ea/56x56-000000-80-0-0.jpg logger.info(f"[{self.mainArtist['name']} - {self.title}] Getting artist picture fallback") artistAPI = dz.api.get_artist(self.album['mainArtist']['id']) - self.album['mainArtist']['pic'] = artistAPI['picture_small'][artistAPI['picture_small'].find('artist/') + 7:-24] + self.album['mainArtist']['pic']['md5'] = artistAPI['picture_small'][artistAPI['picture_small'].find('artist/') + 7:-24] self.album['artists'] = [albumAPI_gw['ART_NAME']] self.album['trackTotal'] = albumAPI_gw['NUMBER_TRACK'] @@ -282,15 +306,14 @@ class Track: explicitLyricsStatus = albumAPI_gw.get('EXPLICIT_ALBUM_CONTENT', {}).get('EXPLICIT_LYRICS_STATUS', LyricsStatus.UNKNOWN) self.album['explicit'] = explicitLyricsStatus in [LyricsStatus.EXPLICIT, LyricsStatus.PARTIALLY_EXPLICIT] - if not self.album['pic']: - self.album['pic'] = albumAPI_gw['ALB_PICTURE'] + if not self.album['pic']['md5']: + self.album['pic']['md5'] = albumAPI_gw['ALB_PICTURE'] if 'PHYSICAL_RELEASE_DATE' in albumAPI_gw: self.album['date'] = { 'day': albumAPI_gw["PHYSICAL_RELEASE_DATE"][8:10], 'month': albumAPI_gw["PHYSICAL_RELEASE_DATE"][5:7], 'year': albumAPI_gw["PHYSICAL_RELEASE_DATE"][0:4] } - self.album['picType'] = 'cover' isAlbumArtistVariousArtists = self.album['mainArtist']['id'] == VARIOUS_ARTISTS self.album['mainArtist']['save'] = not isAlbumArtistVariousArtists or settings['albumVariousArtists'] and isAlbumArtistVariousArtists @@ -348,17 +371,27 @@ class Track: url = playlist['picture_small'] picType = url[url.find('images/')+7:] picType = picType[:picType.find('/')] - self.playlist['pic'] = url[url.find(picType+'/') + len(picType)+1:-24] - self.playlist['picType'] = picType + self.playlist['pic'] = { + 'md5': url[url.find(picType+'/') + len(picType)+1:-24], + 'type': picType, + 'url': None + } else: - self.playlist['pic'] = playlist['picture_xl'] - self.playlist['picType'] = None + self.playlist['pic'] = { + 'md5': None, + 'type': None, + 'url': playlist['picture_xl'] + } self.playlist['title'] = playlist['title'] self.playlist['mainArtist'] = { 'id': playlist['various_artist']['id'], 'name': playlist['various_artist']['name'], - 'pic': playlist['various_artist']['picture_small'][ - playlist['various_artist']['picture_small'].find('artist/') + 7:-24] + 'pic': { + 'md5': playlist['various_artist']['picture_small'][ + playlist['various_artist']['picture_small'].find('artist/') + 7:-24], + 'type': "artist", + 'url': None + } } self.playlist['rootArtist'] = None if settings['albumVariousArtists']: diff --git a/deemix/utils/taggers.py b/deemix/utils/taggers.py index e764b37..1632136 100644 --- a/deemix/utils/taggers.py +++ b/deemix/utils/taggers.py @@ -98,17 +98,17 @@ def tagID3(stream, track, save): tag.add(TXXX(desc="SOURCE", text='Deezer')) tag.add(TXXX(desc="SOURCEID", text=str(track.id))) - if save['cover'] and track.album['picPath']: + if save['cover'] and track.album['embeddedCoverPath']: descEncoding = Encoding.LATIN1 if save['coverDescriptionUTF8']: descEncoding = Encoding.UTF8 mimeType = 'image/jpeg' - if str(track.album['picPath']).endswith('png'): + if str(track.album['embeddedCoverPath']).endswith('png'): mimeType = 'image/png' - with open(track.album['picPath'], 'rb') as f: + with open(track.album['embeddedCoverPath'], 'rb') as f: tag.add(APIC(descEncoding, mimeType, PictureType.COVER_FRONT, desc='cover', data=f.read())) tag.save( stream, @@ -199,13 +199,13 @@ def tagFLAC(stream, track, save): tag["SOURCE"] = 'Deezer' tag["SOURCEID"] = str(track.id) - if save['cover'] and track.album['picPath']: + if save['cover'] and track.album['embeddedCoverPath']: image = Picture() image.type = PictureType.COVER_FRONT image.mime = 'image/jpeg' - if str(track.album['picPath']).endswith('png'): + if str(track.album['embeddedCoverPath']).endswith('png'): image.mime = 'image/png' - with open(track.album['picPath'], 'rb') as f: + with open(track.album['embeddedCoverPath'], 'rb') as f: image.data = f.read() tag.add_picture(image)