Implemented custom casing and refactored some code
This commit is contained in:
parent
157fbcc169
commit
d14be6ad46
|
@ -11,5 +11,3 @@ Finish porting all features:
|
||||||
|
|
||||||
Settings not yet implemented:
|
Settings not yet implemented:
|
||||||
- savePlaylistAsCompilation
|
- savePlaylistAsCompilation
|
||||||
- titleCasing
|
|
||||||
- artistCasing
|
|
||||||
|
|
|
@ -310,6 +310,29 @@ class Deezer:
|
||||||
urlPart = self._ecb_crypt(b'jo6aey6haid2Teih', step2)
|
urlPart = self._ecb_crypt(b'jo6aey6haid2Teih', step2)
|
||||||
return "https://e-cdns-proxy-" + md5[0] + ".dzcdn.net/mobile/1/" + urlPart.decode("utf-8")
|
return "https://e-cdns-proxy-" + md5[0] + ".dzcdn.net/mobile/1/" + urlPart.decode("utf-8")
|
||||||
|
|
||||||
|
def get_track_from_metadata(self, artist, track, album):
|
||||||
|
artist = artist.replace("–","-").replace("’", "'")
|
||||||
|
track = track.replace("–","-").replace("’", "'")
|
||||||
|
album = album.replace("–","-").replace("’", "'")
|
||||||
|
|
||||||
|
resp = self.search(f'artist:"{artist}" track:"{track}" album:"{album}"', "track", 1)
|
||||||
|
if len(resp['data'])>0:
|
||||||
|
return resp['data'][0]['id']
|
||||||
|
resp = self.search(f'artist:"{artist}" track:"{track}"', "track", 1)
|
||||||
|
if len(resp['data'])>0:
|
||||||
|
return resp['data'][0]['id']
|
||||||
|
if "(" in track and ")" in track and track.find("(") < track.find(")"):
|
||||||
|
resp = self.search(f'artist:"{artist}" track:"{track[:track.find("(")]}"', "track", 1)
|
||||||
|
if len(resp['data'])>0:
|
||||||
|
return resp['data'][0]['id']
|
||||||
|
elif " - " in track:
|
||||||
|
resp = self.search(f'artist:"{artist}" track:"{track[:track.find(" - ")]}"', "track", 1)
|
||||||
|
if len(resp['data'])>0:
|
||||||
|
return resp['data'][0]['id']
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
class APIError(Exception):
|
class APIError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -30,13 +30,10 @@
|
||||||
"saveArtworkArtist": false,
|
"saveArtworkArtist": false,
|
||||||
"artistImageTemplate": "folder",
|
"artistImageTemplate": "folder",
|
||||||
"PNGcovers": false,
|
"PNGcovers": false,
|
||||||
"multitagSeparator": "default",
|
|
||||||
"dateFormat": "Y-M-D",
|
"dateFormat": "Y-M-D",
|
||||||
"savePlaylistAsCompilation": false,
|
"savePlaylistAsCompilation": false,
|
||||||
"removeAlbumVersion": false,
|
"removeAlbumVersion": false,
|
||||||
"featuredToTitle": "0",
|
"featuredToTitle": "0",
|
||||||
"useNullSeparator": false,
|
|
||||||
"saveID3v1": true,
|
|
||||||
"titleCasing": "nothing",
|
"titleCasing": "nothing",
|
||||||
"artistCasing": "nothing",
|
"artistCasing": "nothing",
|
||||||
"executeCommand": "",
|
"executeCommand": "",
|
||||||
|
@ -63,6 +60,9 @@
|
||||||
"lyrics": false,
|
"lyrics": false,
|
||||||
"copyright": false,
|
"copyright": false,
|
||||||
"composer": false,
|
"composer": false,
|
||||||
"involvedPeople": false
|
"involvedPeople": false,
|
||||||
|
"useNullSeparator": false,
|
||||||
|
"saveID3v1": true,
|
||||||
|
"multitagSeparator": "default"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,29 +82,6 @@ def getPreferredBitrate(filesize, bitrate, fallback=True):
|
||||||
break
|
break
|
||||||
return (selectedFormat, selectedFilesize)
|
return (selectedFormat, selectedFilesize)
|
||||||
|
|
||||||
def convertMetadata2Deezer(dz, artist, track, album):
|
|
||||||
artist = artist.replace("–","-").replace("’", "'")
|
|
||||||
track = track.replace("–","-").replace("’", "'")
|
|
||||||
album = album.replace("–","-").replace("’", "'")
|
|
||||||
|
|
||||||
resp = dz.search(f'artist:"{artist}" track:"{track}" album:"{album}"', "track", 1)
|
|
||||||
if len(resp['data'])>0:
|
|
||||||
return resp['data'][0]['id']
|
|
||||||
resp = dz.search(f'artist:"{artist}" track:"{track}"', "track", 1)
|
|
||||||
if len(resp['data'])>0:
|
|
||||||
return resp['data'][0]['id']
|
|
||||||
if "(" in track and ")" in track and track.find("(") < track.find(")"):
|
|
||||||
resp = dz.search(f'artist:"{artist}" track:"{track[:track.find("(")]}"', "track", 1)
|
|
||||||
if len(resp['data'])>0:
|
|
||||||
return resp['data'][0]['id']
|
|
||||||
elif " - " in track:
|
|
||||||
resp = dz.search(f'artist:"{artist}" track:"{track[:track.find(" - ")]}"', "track", 1)
|
|
||||||
if len(resp['data'])>0:
|
|
||||||
return resp['data'][0]['id']
|
|
||||||
else:
|
|
||||||
return 0
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def parseEssentialTrackData(track, trackAPI):
|
def parseEssentialTrackData(track, trackAPI):
|
||||||
track['id'] = trackAPI['SNG_ID']
|
track['id'] = trackAPI['SNG_ID']
|
||||||
track['duration'] = trackAPI['DURATION']
|
track['duration'] = trackAPI['DURATION']
|
||||||
|
@ -372,7 +349,7 @@ def downloadTrackObj(dz, trackAPI, settings, overwriteBitrate=False, extraTrack=
|
||||||
return downloadTrackObj(dz, trackAPI, settings, extraTrack=track)
|
return downloadTrackObj(dz, trackAPI, settings, extraTrack=track)
|
||||||
elif not 'searched' in track and settings['fallbackSearch']:
|
elif not 'searched' in track and settings['fallbackSearch']:
|
||||||
print("Track not yet encoded, searching for alternative")
|
print("Track not yet encoded, searching for alternative")
|
||||||
searchedId = convertMetadata2Deezer(dz, track['mainArtist']['name'], track['title'], track['album']['title'])
|
searchedId = dz.get_track_from_metadata(track['mainArtist']['name'], track['title'], track['album']['title'])
|
||||||
if searchedId != 0:
|
if searchedId != 0:
|
||||||
trackNew = dz.get_track_gw(searchedId)
|
trackNew = dz.get_track_gw(searchedId)
|
||||||
if not 'MD5_ORIGIN' in trackNew:
|
if not 'MD5_ORIGIN' in trackNew:
|
||||||
|
@ -433,6 +410,25 @@ def downloadTrackObj(dz, trackAPI, settings, overwriteBitrate=False, extraTrack=
|
||||||
if "Album Version" in track['title']:
|
if "Album Version" in track['title']:
|
||||||
track['title'] = re.sub(r' ?\(Album Version\)', "", track['title']).strip()
|
track['title'] = re.sub(r' ?\(Album Version\)', "", track['title']).strip()
|
||||||
|
|
||||||
|
# Generate artist tag if needed
|
||||||
|
if settings['tags']['multitagSeparator'] != "default":
|
||||||
|
if settings['tags']['multitagSeparator'] == "andFeat":
|
||||||
|
track['artistsString'] = track['mainArtistsString']
|
||||||
|
if 'featArtistsString' in track and settings['featuredToTitle'] != "2":
|
||||||
|
track['artistsString'] += " "+track['featArtistsString']
|
||||||
|
else:
|
||||||
|
track['artistsString'] = settings['tags']['multitagSeparator'].join(track['artists'])
|
||||||
|
else:
|
||||||
|
track['artistsString'] = ", ".join(track['artists'])
|
||||||
|
|
||||||
|
# Change Title and Artists casing if needed
|
||||||
|
if settings['titleCasing'] != "nothing":
|
||||||
|
tags['title'] = changeCase(tags['title'], settings['titleCasing'])
|
||||||
|
if settings['artistCasing'] != "nothing":
|
||||||
|
track['artistsString'] = changeCase(track['artistsString'], settings['artistCasing'])
|
||||||
|
for i, artist in enumerate(track['artists']):
|
||||||
|
track['artists'][i] = changeCase(artist, settings['artistCasing'])
|
||||||
|
|
||||||
# Generate filename and filepath from metadata
|
# Generate filename and filepath from metadata
|
||||||
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)
|
||||||
|
@ -464,15 +460,6 @@ def downloadTrackObj(dz, trackAPI, settings, overwriteBitrate=False, extraTrack=
|
||||||
result['extrasPath'] = extrasPath
|
result['extrasPath'] = extrasPath
|
||||||
result['playlistPosition'] = writepath[len(extrasPath):]
|
result['playlistPosition'] = writepath[len(extrasPath):]
|
||||||
|
|
||||||
# Generate artist tag if needed
|
|
||||||
if settings['multitagSeparator'] != "default":
|
|
||||||
if settings['multitagSeparator'] == "andFeat":
|
|
||||||
track['artistsString'] = track['mainArtistsString']
|
|
||||||
if 'featArtistsString' in track and settings['featuredToTitle'] != "2":
|
|
||||||
track['artistsString'] += " "+track['featArtistsString']
|
|
||||||
else:
|
|
||||||
track['artistsString'] = settings['multitagSeparator'].join(track['artists'])
|
|
||||||
|
|
||||||
track['downloadUrl'] = dz.get_track_stream_url(track['id'], track['MD5'], track['mediaVersion'], track['selectedFormat'])
|
track['downloadUrl'] = dz.get_track_stream_url(track['id'], track['MD5'], track['mediaVersion'], track['selectedFormat'])
|
||||||
try:
|
try:
|
||||||
with open(writepath, 'wb') as stream:
|
with open(writepath, 'wb') as stream:
|
||||||
|
@ -492,7 +479,7 @@ def downloadTrackObj(dz, trackAPI, settings, overwriteBitrate=False, extraTrack=
|
||||||
return downloadTrackObj(dz, trackAPI, settings, extraTrack=track)
|
return downloadTrackObj(dz, trackAPI, settings, extraTrack=track)
|
||||||
elif not 'searched' in track and settings['fallbackSearch']:
|
elif not 'searched' in track and settings['fallbackSearch']:
|
||||||
print("Track not available, searching for alternative")
|
print("Track not available, searching for alternative")
|
||||||
searchedId = convertMetadata2Deezer(dz, track['mainArtist']['name'], track['title'], track['album']['title'])
|
searchedId = dz.get_track_from_metadata(track['mainArtist']['name'], track['title'], track['album']['title'])
|
||||||
if searchedId != 0:
|
if searchedId != 0:
|
||||||
trackNew = dz.get_track_gw(searchedId)
|
trackNew = dz.get_track_gw(searchedId)
|
||||||
if not 'MD5_ORIGIN' in trackNew:
|
if not 'MD5_ORIGIN' in trackNew:
|
||||||
|
@ -515,7 +502,7 @@ def downloadTrackObj(dz, trackAPI, settings, overwriteBitrate=False, extraTrack=
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
if track['selectedFormat'] in [3, 1, 8]:
|
if track['selectedFormat'] in [3, 1, 8]:
|
||||||
tagID3(writepath, track, settings['tags'], settings['saveID3v1'], settings['useNullSeparator'])
|
tagID3(writepath, track, settings['tags'])
|
||||||
elif track['selectedFormat'] == 9:
|
elif track['selectedFormat'] == 9:
|
||||||
tagFLAC(writepath, track, settings['tags'])
|
tagFLAC(writepath, track, settings['tags'])
|
||||||
if 'searched' in track:
|
if 'searched' in track:
|
||||||
|
|
|
@ -18,6 +18,25 @@ def getBitrateInt(txt):
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def changeCase(string, type):
|
||||||
|
if type == "lower":
|
||||||
|
return string.lower()
|
||||||
|
elif type == "upper":
|
||||||
|
return string.upper()
|
||||||
|
elif type == "start":
|
||||||
|
string = string.split(" ")
|
||||||
|
res = []
|
||||||
|
for index, value in enumerate(string):
|
||||||
|
res.append(value[0].upper() + value[0:].lower())
|
||||||
|
})
|
||||||
|
res = " ".join(res)
|
||||||
|
return res
|
||||||
|
elif type == "sentence":
|
||||||
|
res = string[0].upper() + string[0:].lower()
|
||||||
|
return res
|
||||||
|
else:
|
||||||
|
return string
|
||||||
|
|
||||||
def getIDFromLink(link, type):
|
def getIDFromLink(link, type):
|
||||||
if '?' in link:
|
if '?' in link:
|
||||||
link = link[:link.find('?')]
|
link = link[:link.find('?')]
|
||||||
|
|
|
@ -29,12 +29,12 @@ def fixLongName(name):
|
||||||
name = name[:200]
|
name = name[:200]
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def antiDot(str):
|
def antiDot(string):
|
||||||
while str[-1:] == "." or str[-1:] == " " or str[-1:] == "\n":
|
while string[-1:] == "." or string[-1:] == " " or string[-1:] == "\n":
|
||||||
str = str[:-1]
|
string = string[:-1]
|
||||||
if len(str) < 1:
|
if len(string) < 1:
|
||||||
str = "dot"
|
string = "dot"
|
||||||
return str
|
return string
|
||||||
|
|
||||||
def pad(num, max, dopad=True):
|
def pad(num, max, dopad=True):
|
||||||
paddingsize = len(str(max))
|
paddingsize = len(str(max))
|
||||||
|
@ -97,6 +97,7 @@ def generateFilepath(track, trackAPI, settings):
|
||||||
def settingsRegex(filename, track, settings, playlist=None):
|
def settingsRegex(filename, track, settings, playlist=None):
|
||||||
filename = filename.replace("%title%", fixName(track['title'], settings['illegalCharacterReplacer']))
|
filename = filename.replace("%title%", fixName(track['title'], settings['illegalCharacterReplacer']))
|
||||||
filename = filename.replace("%artist%", fixName(track['mainArtist']['name'], settings['illegalCharacterReplacer']))
|
filename = filename.replace("%artist%", fixName(track['mainArtist']['name'], settings['illegalCharacterReplacer']))
|
||||||
|
filename = filename.replace("%artists%", fixName(track['artistString'], settings['illegalCharacterReplacer']))
|
||||||
filename = filename.replace("%album%", fixName(track['album']['title'], settings['illegalCharacterReplacer']))
|
filename = filename.replace("%album%", fixName(track['album']['title'], settings['illegalCharacterReplacer']))
|
||||||
filename = filename.replace("%albumartist%", fixName(track['album']['mainArtist']['name'], settings['illegalCharacterReplacer']))
|
filename = filename.replace("%albumartist%", fixName(track['album']['mainArtist']['name'], settings['illegalCharacterReplacer']))
|
||||||
filename = filename.replace("%tracknumber%", pad(track['trackNumber'], track['album']['trackTotal'] if int(settings['paddingSize']) == 0 else 10 ** (int(settings['paddingSize'])-1), settings['padTracks']))
|
filename = filename.replace("%tracknumber%", pad(track['trackNumber'], track['album']['trackTotal'] if int(settings['paddingSize']) == 0 else 10 ** (int(settings['paddingSize'])-1), settings['padTracks']))
|
||||||
|
|
|
@ -4,7 +4,7 @@ from mutagen.id3 import ID3, ID3NoHeaderError, TXXX, TIT2, TPE1, TALB, TPE2, TRC
|
||||||
TPUB, TSRC, USLT, APIC, IPLS, TCOM, TCOP
|
TPUB, TSRC, USLT, APIC, IPLS, TCOM, TCOP
|
||||||
|
|
||||||
|
|
||||||
def tagID3(stream, track, save, id3v1=False, nullSeparator=True):
|
def tagID3(stream, track, save):
|
||||||
try:
|
try:
|
||||||
tag = ID3(stream)
|
tag = ID3(stream)
|
||||||
except ID3NoHeaderError:
|
except ID3NoHeaderError:
|
||||||
|
@ -13,7 +13,7 @@ def tagID3(stream, track, save, id3v1=False, nullSeparator=True):
|
||||||
if save['title']:
|
if save['title']:
|
||||||
tag.add(TIT2(text=track['title']))
|
tag.add(TIT2(text=track['title']))
|
||||||
if save['artist']:
|
if save['artist']:
|
||||||
if 'artistsString' in track:
|
if save['multitagSeparator'] != "default":
|
||||||
tag.add(TPE1(text=track['artistsString']))
|
tag.add(TPE1(text=track['artistsString']))
|
||||||
tag.add(TXXX(desc="ARTISTS", text=track['artists']))
|
tag.add(TXXX(desc="ARTISTS", text=track['artists']))
|
||||||
else:
|
else:
|
||||||
|
@ -62,7 +62,7 @@ def tagID3(stream, track, save, id3v1=False, nullSeparator=True):
|
||||||
with open(track['album']['picPath'], 'rb') as f:
|
with open(track['album']['picPath'], 'rb') as f:
|
||||||
tag.add(APIC(3, 'image/jpeg' if track['album']['picPath'].endswith('jpg') else 'image/png', 3, data=f.read()))
|
tag.add(APIC(3, 'image/jpeg' if track['album']['picPath'].endswith('jpg') else 'image/png', 3, data=f.read()))
|
||||||
|
|
||||||
tag.save(stream, v1=2 if id3v1 else 0, v2_version=3, v23_sep=None if nullSeparator else '/')
|
tag.save(stream, v1=2 if save['saveID3v1'] else 0, v2_version=3, v23_sep=None if save['useNullSeparator'] else ' / ')
|
||||||
|
|
||||||
|
|
||||||
def tagFLAC(stream, track, save):
|
def tagFLAC(stream, track, save):
|
||||||
|
@ -71,7 +71,7 @@ def tagFLAC(stream, track, save):
|
||||||
if save['title']:
|
if save['title']:
|
||||||
tag["TITLE"] = track['title']
|
tag["TITLE"] = track['title']
|
||||||
if save['artist']:
|
if save['artist']:
|
||||||
if 'artistsString' in track:
|
if save['multitagSeparator'] != "default":
|
||||||
tag["ARTIST"] = track['artistsString']
|
tag["ARTIST"] = track['artistsString']
|
||||||
tag["ARTISTS"] = track['artists']
|
tag["ARTISTS"] = track['artists']
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in New Issue