More work on the library (WIP)

This commit is contained in:
RemixDev 2021-03-19 15:44:21 +01:00
parent 5ee81ced44
commit dc6adc7887
No known key found for this signature in database
GPG Key ID: B33962B465BDB51C
8 changed files with 187 additions and 100 deletions

View File

@ -26,19 +26,19 @@ def parseLink(link):
id = link[link.rfind("/") + 1:] id = link[link.rfind("/") + 1:]
elif '/playlist' in link: elif '/playlist' in link:
type = 'playlist' type = 'playlist'
id = re.search("\/playlist\/(\d+)", link)[0] id = re.search("\/playlist\/(\d+)", link).group(1)
elif '/album' in link: elif '/album' in link:
type = 'album' type = 'album'
id = link[link.rfind("/") + 1:] id = link[link.rfind("/") + 1:]
elif re.search("\/artist\/(\d+)\/top_track", link): elif re.search("\/artist\/(\d+)\/top_track", link):
type = 'artist_top' type = 'artist_top'
id = re.search("\/artist\/(\d+)\/top_track", link)[0] id = re.search("\/artist\/(\d+)\/top_track", link).group(1)
elif re.search("\/artist\/(\d+)\/discography", link): elif re.search("\/artist\/(\d+)\/discography", link):
type = 'artist_discography' type = 'artist_discography'
id = re.search("\/artist\/(\d+)\/discography", link)[0] id = re.search("\/artist\/(\d+)\/discography", link).group(1)
elif '/artist' in link: elif '/artist' in link:
type = 'artist' type = 'artist'
id = re.search("\/artist\/(\d+)", link)[0] id = re.search("\/artist\/(\d+)", link).group(1)
return (link, type, id) return (link, type, id)

View File

@ -2,6 +2,18 @@ import binascii
from Cryptodome.Cipher import Blowfish, AES from Cryptodome.Cipher import Blowfish, AES
from Cryptodome.Hash import MD5 from Cryptodome.Hash import MD5
from deemix import USER_AGENT_HEADER
from deemix.types.DownloadObjects import Single, Collection
from requests import get
from requests.exceptions import ConnectionError, ReadTimeout
from ssl import SSLError
from urllib3.exceptions import SSLError as u3SSLError
import logging
logger = logging.getLogger('deemix')
def _md5(data): def _md5(data):
h = MD5.new() h = MD5.new()
h.update(str.encode(data) if isinstance(data, str) else data) h.update(str.encode(data) if isinstance(data, str) else data)
@ -40,3 +52,127 @@ def generateUnencryptedStreamURL(sng_id, md5, media_version, format):
def reverseStreamURL(url): def reverseStreamURL(url):
urlPart = url[url.find("/1/")+3:] urlPart = url[url.find("/1/")+3:]
return generateStreamPath(urlPart) return generateStreamPath(urlPart)
def streamUnencryptedTrack(outputStream, track, start=0, downloadObject=None, interface=None):
headers= {'User-Agent': USER_AGENT_HEADER}
chunkLength = start
percentage = 0
itemName = f"[{track.mainArtist.name} - {track.title}]"
try:
with get(track.downloadUrl, headers=headers, stream=True, timeout=10) as request:
request.raise_for_status()
complete = int(request.headers["Content-Length"])
if complete == 0: raise DownloadEmpty
if start != 0:
responseRange = request.headers["Content-Range"]
logger.info(f'{itemName} downloading range {responseRange}')
else:
logger.info(f'{itemName} downloading {complete} bytes')
for chunk in request.iter_content(2048 * 3):
outputStream.write(chunk)
chunkLength += len(chunk)
if downloadObject:
if isinstance(downloadObject, Single):
percentage = (chunkLength / (complete + start)) * 100
downloadObject.progressNext = percentage
else:
chunkProgres = (len(chunk) / (complete + start)) / downloadObject.size * 100
downloadObject.progressNext += chunkProgres
downloadObject.updateProgress(interface)
except (SSLError, u3SSLError) as e:
logger.info(f'{itemName} retrying from byte {chunkLength}')
return streamUnencryptedTrack(outputStream, track, chunkLength, downloadObject, interface)
except (ConnectionError, ReadTimeout):
sleep(2)
return streamUnencryptedTrack(outputStream, track, start, downloadObject, interface)
def streamUnencryptedTrack(outputStream, track, start=0, downloadObject=None, interface=None):
headers= {'User-Agent': USER_AGENT_HEADER}
chunkLength = start
percentage = 0
itemName = f"[{track.mainArtist.name} - {track.title}]"
try:
with get(track.downloadUrl, headers=headers, stream=True, timeout=10) as request:
request.raise_for_status()
complete = int(request.headers["Content-Length"])
if complete == 0: raise DownloadEmpty
if start != 0:
responseRange = request.headers["Content-Range"]
logger.info(f'{itemName} downloading range {responseRange}')
else:
logger.info(f'{itemName} downloading {complete} bytes')
for chunk in request.iter_content(2048 * 3):
outputStream.write(chunk)
chunkLength += len(chunk)
if downloadObject:
if isinstance(downloadObject, Single):
percentage = (chunkLength / (complete + start)) * 100
downloadObject.progressNext = percentage
else:
chunkProgres = (len(chunk) / (complete + start)) / downloadObject.size * 100
downloadObject.progressNext += chunkProgres
downloadObject.updateProgress(interface)
except (SSLError, u3SSLError) as e:
logger.info(f'{itemName} retrying from byte {chunkLength}')
return streamUnencryptedTrack(outputStream, track, chunkLength, downloadObject, interface)
except (ConnectionError, ReadTimeout):
sleep(2)
return streamUnencryptedTrack(outputStream, track, start, downloadObject, interface)
def streamTrack(outputStream, track, start=0, downloadObject=None, interface=None):
headers= {'User-Agent': USER_AGENT_HEADER}
chunkLength = start
percentage = 0
itemName = f"[{track.mainArtist.name} - {track.title}]"
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"]
logger.info(f'{itemName} downloading range {responseRange}')
else:
logger.info(f'{itemName} downloading {complete} bytes')
for chunk in request.iter_content(2048 * 3):
if len(chunk) >= 2048:
chunk = Blowfish.new(blowfish_key, Blowfish.MODE_CBC, b"\x00\x01\x02\x03\x04\x05\x06\x07").decrypt(chunk[0:2048]) + chunk[2048:]
outputStream.write(chunk)
chunkLength += len(chunk)
if downloadObject:
if isinstance(downloadObject, Single):
percentage = (chunkLength / (complete + start)) * 100
downloadObject.progressNext = percentage
else:
chunkProgres = (len(chunk) / (complete + start)) / downloadObject.size * 100
downloadObject.progressNext += chunkProgres
downloadObject.updateProgress(interface)
except (SSLError, u3SSLError) as e:
logger.info(f'{itemName} retrying from byte {chunkLength}')
return streamTrack(outputStream, track, chunkLength, downloadObject, interface)
except (ConnectionError, ReadTimeout):
sleep(2)
return streamTrack(outputStream, track, start, downloadObject, interface)
class DownloadEmpty(Exception):
pass

View File

@ -11,24 +11,21 @@ import re
import errno import errno
from ssl import SSLError from ssl import SSLError
from os import makedirs
from urllib3.exceptions import SSLError as u3SSLError from urllib3.exceptions import SSLError as u3SSLError
from os import makedirs
from deemix.types.DownloadObjects import Single, Collection from deemix.types.DownloadObjects import Single, Collection
from deemix.types.Track import Track, AlbumDoesntExists from deemix.types.Track import Track, AlbumDoesntExists
from deemix.utils import changeCase
from deemix.utils.pathtemplates import generateFilename, generateFilepath, settingsRegexAlbum, settingsRegexArtist, settingsRegexPlaylistFile from deemix.utils.pathtemplates import generateFilename, generateFilepath, settingsRegexAlbum, settingsRegexArtist, settingsRegexPlaylistFile
from deezer import TrackFormats from deezer import TrackFormats
from deemix import USER_AGENT_HEADER from deemix import USER_AGENT_HEADER
from deemix.taggers import tagID3, tagFLAC from deemix.taggers import tagID3, tagFLAC
from deemix.decryption import generateStreamURL, generateBlowfishKey from deemix.decryption import generateUnencryptedStreamURL, streamUnencryptedTrack
from deemix.settings import OverwriteOption from deemix.settings import OverwriteOption
from Cryptodome.Cipher import Blowfish
from mutagen.flac import FLACNoHeaderError, error as FLACError from mutagen.flac import FLACNoHeaderError, error as FLACError
import logging
logging.basicConfig(level=logging.INFO) import logging
logger = logging.getLogger('deemix') logger = logging.getLogger('deemix')
from tempfile import gettempdir from tempfile import gettempdir
@ -124,7 +121,7 @@ def getPreferredBitrate(track, preferredBitrate, shouldFallback, downloadObjectU
if int(track.filesizes[f"FILESIZE_{formatName}"]) != 0: return formatNumber if int(track.filesizes[f"FILESIZE_{formatName}"]) != 0: return formatNumber
if not track.filesizes[f"FILESIZE_{formatName}_TESTED"]: if not track.filesizes[f"FILESIZE_{formatName}_TESTED"]:
request = requests.head( request = requests.head(
generateStreamURL(track.id, track.MD5, track.mediaVersion, formatNumber), generateUnencryptedStreamURL(track.id, track.MD5, track.mediaVersion, formatNumber),
headers={'User-Agent': USER_AGENT_HEADER}, headers={'User-Agent': USER_AGENT_HEADER},
timeout=30 timeout=30
) )
@ -159,8 +156,6 @@ class Downloader:
self.settings = settings self.settings = settings
self.bitrate = downloadObject.bitrate self.bitrate = downloadObject.bitrate
self.interface = interface self.interface = interface
self.downloadPercentage = 0
self.lastPercentage = 0
self.extrasPath = None self.extrasPath = None
self.playlistCoverName = None self.playlistCoverName = None
self.playlistURLs = [] self.playlistURLs = []
@ -184,7 +179,6 @@ class Downloader:
if trackAPI_gw['SNG_ID'] == "0": raise DownloadFailed("notOnDeezer") if trackAPI_gw['SNG_ID'] == "0": raise DownloadFailed("notOnDeezer")
# Create Track object # Create Track object
print(track)
if not track: if not track:
logger.info(f"[{trackAPI_gw['ART_NAME']} - {trackAPI_gw['SNG_TITLE']}] Getting the tags") logger.info(f"[{trackAPI_gw['ART_NAME']} - {trackAPI_gw['SNG_TITLE']}] Getting the tags")
try: try:
@ -252,7 +246,7 @@ class Downloader:
url = track.album.pic.generatePictureURL(self.settings['localArtworkSize'], extendedFormat) url = track.album.pic.generatePictureURL(self.settings['localArtworkSize'], extendedFormat)
if self.settings['tags']['savePlaylistAsCompilation'] \ if self.settings['tags']['savePlaylistAsCompilation'] \
and track.playlist \ and track.playlist \
and track.playlist.pic.url \ and track.playlist.pic.staticUrl \
and not format.startswith("jpg"): and not format.startswith("jpg"):
continue continue
result['albumURLs'].append({'url': url, 'ext': format}) result['albumURLs'].append({'url': url, 'ext': format})
@ -280,7 +274,7 @@ class Downloader:
extendedFormat = format extendedFormat = format
if extendedFormat == "jpg": extendedFormat += f"-{self.settings['jpegImageQuality']}" if extendedFormat == "jpg": extendedFormat += f"-{self.settings['jpegImageQuality']}"
url = track.playlist.pic.generatePictureURL(self.settings['localArtworkSize'], extendedFormat) url = track.playlist.pic.generatePictureURL(self.settings['localArtworkSize'], extendedFormat)
if track.playlist.pic.url and not format.startswith("jpg"): continue if track.playlist.pic.staticUrl and not format.startswith("jpg"): continue
self.playlistURLs.append({'url': url, 'ext': format}) self.playlistURLs.append({'url': url, 'ext': format})
if not self.playlistCoverName: if not self.playlistCoverName:
track.playlist.bitrate = selectedFormat track.playlist.bitrate = selectedFormat
@ -316,12 +310,12 @@ class Downloader:
if not trackAlreadyDownloaded or self.settings['overwriteFile'] == OverwriteOption.OVERWRITE: if not trackAlreadyDownloaded or self.settings['overwriteFile'] == OverwriteOption.OVERWRITE:
logger.info(f"[{track.mainArtist.name} - {track.title}] Downloading the track") logger.info(f"[{track.mainArtist.name} - {track.title}] Downloading the track")
track.downloadUrl = generateStreamURL(track.id, track.MD5, track.mediaVersion, track.selectedFormat) track.downloadUrl = generateUnencryptedStreamURL(track.id, track.MD5, track.mediaVersion, track.selectedFormat)
def downloadMusic(track, trackAPI_gw): def downloadMusic(track, trackAPI_gw):
try: try:
with open(writepath, 'wb') as stream: with open(writepath, 'wb') as stream:
self.streamTrack(stream, track) streamUnencryptedTrack(stream, track, downloadObject=self.downloadObject, interface=self.interface)
except DownloadCancelled: except DownloadCancelled:
if writepath.is_file(): writepath.unlink() if writepath.is_file(): writepath.unlink()
raise DownloadCancelled raise DownloadCancelled
@ -382,7 +376,7 @@ class Downloader:
if not trackDownloaded: return self.download(trackAPI_gw, track=track) if not trackDownloaded: return self.download(trackAPI_gw, track=track)
else: else:
logger.info(f"[{track.mainArtist.name} - {track.title}] Skipping track as it's already downloaded") logger.info(f"[{track.mainArtist.name} - {track.title}] Skipping track as it's already downloaded")
self.completeTrackPercentage() self.downloadObject.completeTrackProgress(self.interface)
# Adding tags # Adding tags
if (not trackAlreadyDownloaded or self.settings['overwriteFile'] in [OverwriteOption.ONLY_TAGS, OverwriteOption.OVERWRITE]) and not track.localTrack: if (not trackAlreadyDownloaded or self.settings['overwriteFile'] in [OverwriteOption.ONLY_TAGS, OverwriteOption.OVERWRITE]) and not track.localTrack:
@ -395,7 +389,7 @@ class Downloader:
except (FLACNoHeaderError, FLACError): except (FLACNoHeaderError, FLACError):
if writepath.is_file(): writepath.unlink() if writepath.is_file(): writepath.unlink()
logger.warn(f"[{track.mainArtist.name} - {track.title}] Track not available in FLAC, falling back if necessary") logger.warn(f"[{track.mainArtist.name} - {track.title}] Track not available in FLAC, falling back if necessary")
self.removeTrackPercentage() self.downloadObject.removeTrackProgress(self.interface)
track.filesizes['FILESIZE_FLAC'] = "0" track.filesizes['FILESIZE_FLAC'] = "0"
track.filesizes['FILESIZE_FLAC_TESTED'] = True track.filesizes['FILESIZE_FLAC_TESTED'] = True
return self.download(trackAPI_gw, track=track) return self.download(trackAPI_gw, track=track)
@ -409,71 +403,6 @@ class Downloader:
self.interface.send("updateQueue", {'uuid': self.downloadObject.uuid, 'downloaded': True, 'downloadPath': str(writepath), 'extrasPath': str(self.extrasPath)}) self.interface.send("updateQueue", {'uuid': self.downloadObject.uuid, 'downloaded': True, 'downloadPath': str(writepath), 'extrasPath': str(self.extrasPath)})
return result return result
def streamTrack(self, stream, track, start=0):
headers=dict(self.dz.http_headers)
if range != 0: headers['Range'] = f'bytes={start}-'
chunkLength = start
percentage = 0
itemName = f"[{track.mainArtist.name} - {track.title}]"
try:
with self.dz.session.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"]
logger.info(f'{itemName} downloading range {responseRange}')
else:
logger.info(f'{itemName} downloading {complete} bytes')
for chunk in request.iter_content(2048 * 3):
if len(chunk) >= 2048:
chunk = Blowfish.new(blowfish_key, Blowfish.MODE_CBC, b"\x00\x01\x02\x03\x04\x05\x06\x07").decrypt(chunk[0:2048]) + chunk[2048:]
stream.write(chunk)
chunkLength += len(chunk)
if isinstance(self.downloadObject, Single):
percentage = (chunkLength / (complete + start)) * 100
self.downloadPercentage = percentage
else:
chunkProgres = (len(chunk) / (complete + start)) / self.downloadObject.size * 100
self.downloadPercentage += chunkProgres
self.updatePercentage()
except (SSLError, u3SSLError) as e:
logger.info(f'{itemName} retrying from byte {chunkLength}')
return self.streamTrack(stream, track, chunkLength)
except (requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout):
sleep(2)
return self.streamTrack(stream, track, start)
def updatePercentage(self):
if round(self.downloadPercentage) != self.lastPercentage and round(self.downloadPercentage) % 2 == 0:
self.lastPercentage = round(self.downloadPercentage)
self.downloadObject.progress = self.lastPercentage
if self.interface: self.interface.send("updateQueue", {'uuid': self.downloadObject.uuid, 'progress': self.lastPercentage})
def completeTrackPercentage(self):
if isinstance(self.downloadObject, Single):
self.downloadPercentage = 100
else:
self.downloadPercentage += (1 / self.downloadObject.size) * 100
self.updatePercentage()
def removeTrackPercentage(self):
if isinstance(self.downloadObject, Single):
self.downloadPercentage = 0
else:
self.downloadPercentage -= (1 / self.downloadObject.size) * 100
self.updatePercentage()
def downloadWrapper(self, trackAPI_gw, trackAPI=None, albumAPI=None, playlistAPI=None, track=None): def downloadWrapper(self, trackAPI_gw, trackAPI=None, albumAPI=None, playlistAPI=None, track=None):
# Temp metadata to generate logs # Temp metadata to generate logs
tempTrack = { tempTrack = {
@ -531,7 +460,7 @@ class Downloader:
}} }}
if 'error' in result: if 'error' in result:
self.completeTrackPercentage() self.downloadObject.completeTrackProgress(self.interface)
self.downloadObject.failed += 1 self.downloadObject.failed += 1
self.downloadObject.errors.append(result['error']) self.downloadObject.errors.append(result['error'])
if self.interface: if self.interface:
@ -640,9 +569,6 @@ class DownloadFailed(DownloadError):
class DownloadCancelled(DownloadError): class DownloadCancelled(DownloadError):
pass pass
class DownloadEmpty(DownloadError):
pass
class PreferredBitrateNotFound(DownloadError): class PreferredBitrateNotFound(DownloadError):
pass pass

View File

@ -1,4 +1,6 @@
from deemix.types.DownloadObjects import Single, Collection from deemix.types.DownloadObjects import Single, Collection
from deezer.api import APIError
from deezer.gw import GWAPIError, LyricsStatus
class GenerationError(Exception): class GenerationError(Exception):
def __init__(self, link, message, errid=None): def __init__(self, link, message, errid=None):
@ -29,7 +31,7 @@ def generateTrackItem(dz, id, bitrate, trackAPI=None, albumAPI=None):
# Get essential track info # Get essential track info
try: try:
trackAPI_gw = dz.gw.get_track_with_fallback(id) trackAPI_gw = dz.gw.get_track_with_fallback(id)
except gwAPIError as e: except GWAPIError as e:
e = str(e) e = str(e)
message = "Wrong URL" message = "Wrong URL"
if "DATA_ERROR" in e: message += f": {e['DATA_ERROR']}" if "DATA_ERROR" in e: message += f": {e['DATA_ERROR']}"
@ -116,7 +118,7 @@ def generatePlaylistItem(dz, id, bitrate, playlistAPI=None, playlistTracksAPI=No
try: try:
userPlaylist = dz.gw.get_playlist_page(id) userPlaylist = dz.gw.get_playlist_page(id)
playlistAPI = map_user_playlist(userPlaylist['DATA']) playlistAPI = map_user_playlist(userPlaylist['DATA'])
except gwAPIError as e: except GWAPIError as e:
e = str(e) e = str(e)
message = "Wrong URL" message = "Wrong URL"
if "DATA_ERROR" in e: if "DATA_ERROR" in e:

View File

@ -28,6 +28,7 @@ class IDownloadObject:
self.progress = 0 self.progress = 0
self.errors = [] self.errors = []
self.files = [] self.files = []
self.progressNext = 0
self.uuid = f"{self.type}_{self.id}_{self.bitrate}" self.uuid = f"{self.type}_{self.id}_{self.bitrate}"
self.ack = None self.ack = None
self.__type__ = None self.__type__ = None
@ -69,6 +70,11 @@ class IDownloadObject:
del light[property] del light[property]
return light return light
def updateProgress(self, interface=None):
if round(self.progressNext) != self.progress and round(self.progressNext) % 2 == 0:
self.progress = round(self.progressNext)
if interface: interface.send("updateQueue", {'uuid': self.uuid, 'progress': self.progress})
class Single(IDownloadObject): class Single(IDownloadObject):
def __init__(self, type=None, id=None, bitrate=None, title=None, artist=None, cover=None, explicit=False, trackAPI_gw=None, trackAPI=None, albumAPI=None, dictItem=None): def __init__(self, type=None, id=None, bitrate=None, title=None, artist=None, cover=None, explicit=False, trackAPI_gw=None, trackAPI=None, albumAPI=None, dictItem=None):
if dictItem: if dictItem:
@ -88,6 +94,14 @@ class Single(IDownloadObject):
item['single'] = self.single item['single'] = self.single
return item return item
def completeTrackProgress(self, interface=None):
self.progressNext = 100
self.updateProgress(interface)
def removeTrackProgress(self, interface=None):
self.progressNext = 0
self.updateProgress(interface)
class Collection(IDownloadObject): class Collection(IDownloadObject):
def __init__(self, type=None, id=None, bitrate=None, title=None, artist=None, cover=None, explicit=False, size=None, tracks_gw=None, albumAPI=None, playlistAPI=None, dictItem=None): def __init__(self, type=None, id=None, bitrate=None, title=None, artist=None, cover=None, explicit=False, size=None, tracks_gw=None, albumAPI=None, playlistAPI=None, dictItem=None):
if dictItem: if dictItem:
@ -107,6 +121,14 @@ class Collection(IDownloadObject):
item['collection'] = self.collection item['collection'] = self.collection
return item return item
def completeTrackProgress(self, interface=None):
self.progressNext += (1 / self.size) * 100
self.updateProgress(interface)
def removeTrackProgress(self, interface=None):
self.progressNext -= (1 / self.size) * 100
self.updateProgress(interface)
class Convertable(Collection): class Convertable(Collection):
def __init__(self, type=None, id=None, bitrate=None, title=None, artist=None, cover=None, explicit=False, size=None, plugin=None, conversion_data=None, dictItem=None): def __init__(self, type=None, id=None, bitrate=None, title=None, artist=None, cover=None, explicit=False, size=None, plugin=None, conversion_data=None, dictItem=None):
if dictItem: if dictItem:

View File

@ -39,7 +39,7 @@ class Playlist:
if 'various_artist' in playlistAPI: if 'various_artist' in playlistAPI:
pic_md5 = playlistAPI['various_artist']['picture_small'] pic_md5 = playlistAPI['various_artist']['picture_small']
pic_md5 = pic_md5[pic_md5.indexOf('artist/') + 7:-24] pic_md5 = pic_md5[pic_md5.find('artist/') + 7:-24]
self.variousArtists = Artist( self.variousArtists = Artist(
id = playlistAPI['various_artist']['id'], id = playlistAPI['various_artist']['id'],
name = playlistAPI['various_artist']['name'], name = playlistAPI['various_artist']['name'],

View File

@ -5,9 +5,10 @@ import logging
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('deemix') logger = logging.getLogger('deemix')
from deezer.gw import APIError as gwAPIError from deezer.gw import GWAPIError
from deezer.api import APIError from deezer.api import APIError
from deemix.utils import removeFeatures, andCommaConcat, removeDuplicateArtists, generateReplayGainString from deemix.utils import removeFeatures, andCommaConcat, removeDuplicateArtists, generateReplayGainString, changeCase
from deemix.types.Album import Album from deemix.types.Album import Album
from deemix.types.Artist import Artist from deemix.types.Artist import Artist
from deemix.types.Date import Date from deemix.types.Date import Date
@ -114,7 +115,7 @@ class Track:
# Get Lyrics data # Get Lyrics data
if not "LYRICS" in trackAPI_gw and self.lyrics.id != "0": if not "LYRICS" in trackAPI_gw and self.lyrics.id != "0":
try: trackAPI_gw["LYRICS"] = dz.gw.get_track_lyrics(self.id) try: trackAPI_gw["LYRICS"] = dz.gw.get_track_lyrics(self.id)
except gwAPIError: self.lyrics.id = "0" except GWAPIError: self.lyrics.id = "0"
if self.lyrics.id != "0": self.lyrics.parseLyrics(trackAPI_gw["LYRICS"]) if self.lyrics.id != "0": self.lyrics.parseLyrics(trackAPI_gw["LYRICS"])
# Parse Album data # Parse Album data
@ -132,7 +133,7 @@ class Track:
# Get album_gw Data # Get album_gw Data
if not albumAPI_gw: if not albumAPI_gw:
try: albumAPI_gw = dz.gw.get_album(self.album.id) try: albumAPI_gw = dz.gw.get_album(self.album.id)
except gwAPIError: albumAPI_gw = None except GWAPIError: albumAPI_gw = None
if albumAPI: if albumAPI:
self.album.parseAlbum(albumAPI) self.album.parseAlbum(albumAPI)

View File

@ -148,7 +148,7 @@ def settingsRegex(filename, track, settings):
filename = filename.replace("%album_id%", str(track.album.id)) filename = filename.replace("%album_id%", str(track.album.id))
filename = filename.replace("%artist_id%", str(track.mainArtist.id)) filename = filename.replace("%artist_id%", str(track.mainArtist.id))
if track.playlist: if track.playlist:
filename = filename.replace("%playlist_id%", str(track.playlist.playlistId)) filename = filename.replace("%playlist_id%", str(track.playlist.playlistID))
filename = filename.replace("%position%", pad(track.position, track.playlist.trackTotal, settings)) filename = filename.replace("%position%", pad(track.position, track.playlist.trackTotal, settings))
else: else:
filename = filename.replace("%playlist_id%", '') filename = filename.replace("%playlist_id%", '')
@ -159,7 +159,7 @@ def settingsRegex(filename, track, settings):
def settingsRegexAlbum(foldername, album, settings, playlist=None): def settingsRegexAlbum(foldername, album, settings, playlist=None):
if playlist and settings['tags']['savePlaylistAsCompilation']: if playlist and settings['tags']['savePlaylistAsCompilation']:
foldername = foldername.replace("%album_id%", "pl_" + str(playlist.playlistId)) foldername = foldername.replace("%album_id%", "pl_" + str(playlist.playlistID))
foldername = foldername.replace("%genre%", "Compile") foldername = foldername.replace("%genre%", "Compile")
else: else:
foldername = foldername.replace("%album_id%", str(album.id)) foldername = foldername.replace("%album_id%", str(album.id))
@ -205,7 +205,7 @@ def settingsRegexArtist(foldername, artist, settings, rootArtist=None):
def settingsRegexPlaylist(foldername, playlist, settings): def settingsRegexPlaylist(foldername, playlist, settings):
foldername = foldername.replace("%playlist%", fixName(playlist.title, settings['illegalCharacterReplacer'])) foldername = foldername.replace("%playlist%", fixName(playlist.title, settings['illegalCharacterReplacer']))
foldername = foldername.replace("%playlist_id%", fixName(playlist.playlistId, settings['illegalCharacterReplacer'])) foldername = foldername.replace("%playlist_id%", fixName(playlist.playlistID, settings['illegalCharacterReplacer']))
foldername = foldername.replace("%owner%", fixName(playlist.owner['name'], settings['illegalCharacterReplacer'])) foldername = foldername.replace("%owner%", fixName(playlist.owner['name'], settings['illegalCharacterReplacer']))
foldername = foldername.replace("%owner_id%", str(playlist.owner['id'])) foldername = foldername.replace("%owner_id%", str(playlist.owner['id']))
foldername = foldername.replace("%year%", str(playlist.date.year)) foldername = foldername.replace("%year%", str(playlist.date.year))