Made the refactoring work
This commit is contained in:
parent
4cfdc4872d
commit
34263c150f
|
@ -1,36 +1,25 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import click
|
import click
|
||||||
|
|
||||||
import deemix.app.cli as app
|
from deemix.app.cli import cli
|
||||||
from deemix.app.settings import initSettings
|
|
||||||
from os.path import isfile
|
from os.path import isfile
|
||||||
import random
|
|
||||||
import string
|
|
||||||
|
|
||||||
def randomString(stringLength=8):
|
|
||||||
letters = string.ascii_lowercase
|
|
||||||
return ''.join(random.choice(letters) for i in range(stringLength))
|
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@click.option('-b', '--bitrate', default=None, help='Overwrites the default bitrate selected')
|
@click.option('-b', '--bitrate', default=None, help='Overwrites the default bitrate selected')
|
||||||
@click.option('-l', '--local', is_flag=True, help='Downloads in a local folder insted of using the default')
|
@click.option('-l', '--local', is_flag=True, help='Downloads in a local folder insted of using the default')
|
||||||
@click.argument('url', nargs=-1, required=True)
|
@click.argument('url', nargs=-1, required=True)
|
||||||
def download(bitrate, local, url):
|
def download(bitrate, local, url):
|
||||||
settings = initSettings()
|
app = cli(local)
|
||||||
if local:
|
|
||||||
settings['downloadLocation'] = randomString(12)
|
|
||||||
click.echo("Using a local download folder: "+settings['downloadLocation'])
|
|
||||||
app.login()
|
app.login()
|
||||||
url = list(url)
|
url = list(url)
|
||||||
if isfile(url[0]):
|
if isfile(url[0]):
|
||||||
filename = url[0]
|
filename = url[0]
|
||||||
with open(filename) as f:
|
with open(filename) as f:
|
||||||
url = f.readlines()
|
url = f.readlines()
|
||||||
app.downloadLink(url, settings, bitrate)
|
app.downloadLink(url, bitrate)
|
||||||
click.echo("All done!")
|
click.echo("All done!")
|
||||||
if local:
|
if local:
|
||||||
click.echo(settings['downloadLocation']) #folder name output
|
click.echo(app.set.settings['downloadLocation']) #folder name output
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
download()
|
download()
|
||||||
|
|
|
@ -477,37 +477,37 @@ class Deezer:
|
||||||
for track in data:
|
for track in data:
|
||||||
item = {
|
item = {
|
||||||
'id': track['SNG_ID'],
|
'id': track['SNG_ID'],
|
||||||
'title': track['SNG_TITLE'],
|
'title': track['SNG_TITLE'],
|
||||||
'link': 'https://www.deezer.com/track/'+str(track['SNG_ID']),
|
'link': 'https://www.deezer.com/track/'+str(track['SNG_ID']),
|
||||||
'duration': track['DURATION'],
|
'duration': track['DURATION'],
|
||||||
'rank': track['RANK_SNG'],
|
'rank': track['RANK_SNG'],
|
||||||
'explicit_lyrics': int(track['EXPLICIT_LYRICS']) > 0,
|
'explicit_lyrics': int(track['EXPLICIT_LYRICS']) > 0,
|
||||||
'explicit_content_lyrics': track['EXPLICIT_TRACK_CONTENT']['EXPLICIT_COVER_STATUS'],
|
'explicit_content_lyrics': track['EXPLICIT_TRACK_CONTENT']['EXPLICIT_COVER_STATUS'],
|
||||||
'explicit_content_cover': track['EXPLICIT_TRACK_CONTENT']['EXPLICIT_LYRICS_STATUS'],
|
'explicit_content_cover': track['EXPLICIT_TRACK_CONTENT']['EXPLICIT_LYRICS_STATUS'],
|
||||||
'time_add': track['DATE_ADD'],
|
'time_add': track['DATE_ADD'],
|
||||||
'album': {
|
'album': {
|
||||||
'id': track['ALB_ID'],
|
'id': track['ALB_ID'],
|
||||||
'title': track['ALB_TITLE'],
|
'title': track['ALB_TITLE'],
|
||||||
'cover': 'https://api.deezer.com/album/'+str(track['ALB_ID'])+'/image',
|
'cover': 'https://api.deezer.com/album/'+str(track['ALB_ID'])+'/image',
|
||||||
'cover_small': 'https://e-cdns-images.dzcdn.net/images/cover/'+str(track['ALB_PICTURE'])+'/56x56-000000-80-0-0.jpg',
|
'cover_small': 'https://e-cdns-images.dzcdn.net/images/cover/'+str(track['ALB_PICTURE'])+'/56x56-000000-80-0-0.jpg',
|
||||||
'cover_medium': 'https://e-cdns-images.dzcdn.net/images/cover/'+str(track['ALB_PICTURE'])+'/250x250-000000-80-0-0.jpg',
|
'cover_medium': 'https://e-cdns-images.dzcdn.net/images/cover/'+str(track['ALB_PICTURE'])+'/250x250-000000-80-0-0.jpg',
|
||||||
'cover_big': 'https://e-cdns-images.dzcdn.net/images/cover/'+str(track['ALB_PICTURE'])+'/500x500-000000-80-0-0.jpg',
|
'cover_big': 'https://e-cdns-images.dzcdn.net/images/cover/'+str(track['ALB_PICTURE'])+'/500x500-000000-80-0-0.jpg',
|
||||||
'cover_xl': 'https://e-cdns-images.dzcdn.net/images/cover/'+str(track['ALB_PICTURE'])+'/1000x1000-000000-80-0-0.jpg',
|
'cover_xl': 'https://e-cdns-images.dzcdn.net/images/cover/'+str(track['ALB_PICTURE'])+'/1000x1000-000000-80-0-0.jpg',
|
||||||
'tracklist': 'https://api.deezer.com/album/'+str(track['ALB_ID'])+'/tracks',
|
'tracklist': 'https://api.deezer.com/album/'+str(track['ALB_ID'])+'/tracks',
|
||||||
'type': 'album'
|
'type': 'album'
|
||||||
},
|
},
|
||||||
'artist': {
|
'artist': {
|
||||||
'id': track['ART_ID'],
|
'id': track['ART_ID'],
|
||||||
'name': track['ART_NAME'],
|
'name': track['ART_NAME'],
|
||||||
'picture': 'https://api.deezer.com/artist/'+str(track['ART_ID'])+'/image',
|
'picture': 'https://api.deezer.com/artist/'+str(track['ART_ID'])+'/image',
|
||||||
'picture_small': 'https://e-cdns-images.dzcdn.net/images/artist/'+str(track['ART_PICTURE'])+'/56x56-000000-80-0-0.jpg',
|
'picture_small': 'https://e-cdns-images.dzcdn.net/images/artist/'+str(track['ART_PICTURE'])+'/56x56-000000-80-0-0.jpg',
|
||||||
'picture_medium': 'https://e-cdns-images.dzcdn.net/images/artist/'+str(track['ART_PICTURE'])+'/250x250-000000-80-0-0.jpg',
|
'picture_medium': 'https://e-cdns-images.dzcdn.net/images/artist/'+str(track['ART_PICTURE'])+'/250x250-000000-80-0-0.jpg',
|
||||||
'picture_big': 'https://e-cdns-images.dzcdn.net/images/artist/'+str(track['ART_PICTURE'])+'/500x500-000000-80-0-0.jpg',
|
'picture_big': 'https://e-cdns-images.dzcdn.net/images/artist/'+str(track['ART_PICTURE'])+'/500x500-000000-80-0-0.jpg',
|
||||||
'picture_xl': 'https://e-cdns-images.dzcdn.net/images/artist/'+str(track['ART_PICTURE'])+'/1000x1000-000000-80-0-0.jpg',
|
'picture_xl': 'https://e-cdns-images.dzcdn.net/images/artist/'+str(track['ART_PICTURE'])+'/1000x1000-000000-80-0-0.jpg',
|
||||||
'tracklist': 'https://api.deezer.com/artist/'+str(track['ART_ID'])+'/top?limit=50',
|
'tracklist': 'https://api.deezer.com/artist/'+str(track['ART_ID'])+'/top?limit=50',
|
||||||
'type': 'artist'
|
'type': 'artist'
|
||||||
},
|
},
|
||||||
'type': 'track'
|
'type': 'track'
|
||||||
}
|
}
|
||||||
result.append(item)
|
result.append(item)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
from deemix.api.deezer import Deezer
|
from deemix.api.deezer import Deezer
|
||||||
from deemix.app.settings import Settings
|
from deemix.app.settings import Settings
|
||||||
from deemix.app.queuemanager import QueueManager
|
from deemix.app.queuemanager import QueueManager
|
||||||
from deemix.app.spotify import SpotifyHelper
|
from deemix.app.spotifyhelper import SpotifyHelper
|
||||||
|
|
||||||
class deemix:
|
class deemix:
|
||||||
def __init__(self):
|
def __init__(self, configFolder=None):
|
||||||
self.set = Settings()
|
self.set = Settings(configFolder)
|
||||||
self.dz = Deezer()
|
self.dz = Deezer()
|
||||||
self.sp = SpotifyHelper()
|
self.sp = SpotifyHelper(configFolder)
|
||||||
self.qm = QueueManager()
|
self.qm = QueueManager()
|
||||||
|
|
|
@ -1,43 +1,47 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import os.path as path
|
import os.path as path
|
||||||
|
import string
|
||||||
|
import random
|
||||||
from os import mkdir
|
from os import mkdir
|
||||||
|
|
||||||
from deemix.utils import localpaths
|
from deemix.app import deemix
|
||||||
from deemix.api.deezer import Deezer
|
|
||||||
from deemix.app.queuemanager import addToQueue
|
|
||||||
from deemix.app.spotify import SpotifyHelper
|
|
||||||
|
|
||||||
dz = Deezer()
|
def randomString(stringLength=8):
|
||||||
sp = SpotifyHelper()
|
letters = string.ascii_lowercase
|
||||||
|
return ''.join(random.choice(letters) for i in range(stringLength))
|
||||||
|
|
||||||
|
class cli(deemix):
|
||||||
|
def __init__(self, local, configFolder=None):
|
||||||
|
super().__init__(configFolder)
|
||||||
|
if local:
|
||||||
|
self.set.settings['downloadLocation'] = randomString(12)
|
||||||
|
print("Using a local download folder: "+settings['downloadLocation'])
|
||||||
|
|
||||||
def requestValidArl():
|
def downloadLink(self, url, bitrate=None):
|
||||||
while True:
|
for link in url:
|
||||||
arl = input("Paste here your arl:")
|
if ';' in link:
|
||||||
if dz.login_via_arl(arl):
|
for l in link.split(";"):
|
||||||
break
|
self.qm.addToQueue(self.dz, self.sp, l, self.set.settings, bitrate)
|
||||||
return arl
|
else:
|
||||||
|
self.qm.addToQueue(self.dz, self.sp, link, self.set.settings, bitrate)
|
||||||
|
|
||||||
|
def requestValidArl(self):
|
||||||
|
while True:
|
||||||
|
arl = input("Paste here your arl:")
|
||||||
|
if self.dz.login_via_arl(arl):
|
||||||
|
break
|
||||||
|
return arl
|
||||||
|
|
||||||
def login():
|
def login(self):
|
||||||
configFolder = localpaths.getConfigFolder()
|
configFolder = self.set.configFolder
|
||||||
if not path.isdir(configFolder):
|
if not path.isdir(configFolder):
|
||||||
mkdir(configFolder)
|
mkdir(configFolder)
|
||||||
if path.isfile(path.join(configFolder, '.arl')):
|
if path.isfile(path.join(configFolder, '.arl')):
|
||||||
with open(path.join(configFolder, '.arl'), 'r') as f:
|
with open(path.join(configFolder, '.arl'), 'r') as f:
|
||||||
arl = f.readline().rstrip("\n")
|
arl = f.readline().rstrip("\n")
|
||||||
if not dz.login_via_arl(arl):
|
if not self.dz.login_via_arl(arl):
|
||||||
arl = requestValidArl()
|
arl = self.requestValidArl()
|
||||||
else:
|
|
||||||
arl = requestValidArl()
|
|
||||||
with open(path.join(configFolder, '.arl'), 'w') as f:
|
|
||||||
f.write(arl)
|
|
||||||
|
|
||||||
|
|
||||||
def downloadLink(url, settings, bitrate=None):
|
|
||||||
for link in url:
|
|
||||||
if ';' in link:
|
|
||||||
for l in link.split(";"):
|
|
||||||
addToQueue(dz, sp, l, settings, bitrate)
|
|
||||||
else:
|
else:
|
||||||
addToQueue(dz, sp, link, settings, bitrate)
|
arl = self.requestValidArl()
|
||||||
|
with open(path.join(configFolder, '.arl'), 'w') as f:
|
||||||
|
f.write(arl)
|
||||||
|
|
|
@ -11,7 +11,7 @@ from tempfile import gettempdir
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from deemix.app.queueitem import QIConvertable, QISingle, QICollection
|
from deemix.app.queueitem import QIConvertable, QISingle, QICollection
|
||||||
from deemix.app.Track import Track
|
from deemix.app.track import Track
|
||||||
from deemix.utils.misc import changeCase
|
from deemix.utils.misc import changeCase
|
||||||
from deemix.utils.pathtemplates import generateFilename, generateFilepath, settingsRegexAlbum, settingsRegexArtist, settingsRegexPlaylistFile
|
from deemix.utils.pathtemplates import generateFilename, generateFilepath, settingsRegexAlbum, settingsRegexArtist, settingsRegexPlaylistFile
|
||||||
from deemix.api.deezer import USER_AGENT_HEADER
|
from deemix.api.deezer import USER_AGENT_HEADER
|
||||||
|
@ -46,8 +46,8 @@ errorMessages = {
|
||||||
'wrongBitrate': "Track not found at desired bitrate.",
|
'wrongBitrate': "Track not found at desired bitrate.",
|
||||||
'wrongBitrateNoAlternative': "Track not found at desired bitrate and no alternative found!",
|
'wrongBitrateNoAlternative': "Track not found at desired bitrate and no alternative found!",
|
||||||
'no360RA': "Track is not available in Reality Audio 360.",
|
'no360RA': "Track is not available in Reality Audio 360.",
|
||||||
'notAvailable': "Track not available on deezer's servers!"
|
'notAvailable': "Track not available on deezer's servers!",
|
||||||
'notAvailableNoAlternative': "Track not available on deezer's servers and no alternative found!",
|
'notAvailableNoAlternative': "Track not available on deezer's servers and no alternative found!"
|
||||||
}
|
}
|
||||||
|
|
||||||
def after_download(tracks, settings, queueItem):
|
def after_download(tracks, settings, queueItem):
|
||||||
|
@ -168,8 +168,10 @@ class DownloadJob:
|
||||||
def __init__(self, dz, sp, queueItem, interface=None):
|
def __init__(self, dz, sp, queueItem, interface=None):
|
||||||
self.dz = dz
|
self.dz = dz
|
||||||
self.sp = sp
|
self.sp = sp
|
||||||
self.queueItem = queueItem
|
|
||||||
self.interface = interface
|
self.interface = interface
|
||||||
|
if isinstance(queueItem, QIConvertable):
|
||||||
|
self.sp.convert_spotify_playlist(self.dz, queueItem, interface=self.interface)
|
||||||
|
self.queueItem = queueItem
|
||||||
self.settings = queueItem.settings
|
self.settings = queueItem.settings
|
||||||
self.bitrate = queueItem.bitrate
|
self.bitrate = queueItem.bitrate
|
||||||
self.downloadPercentage = 0
|
self.downloadPercentage = 0
|
||||||
|
@ -177,8 +179,6 @@ class DownloadJob:
|
||||||
self.extrasPath = self.settings['downloadLocation']
|
self.extrasPath = self.settings['downloadLocation']
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
if isinstance(self.queueItem, QIConvertable):
|
|
||||||
self.sp.convert_spotify_playlist(self.dz, self.queueItem, self.settings, interface=self.interface)
|
|
||||||
if isinstance(self.queueItem, QISingle):
|
if isinstance(self.queueItem, QISingle):
|
||||||
result = self.downloadWrapper(self.queueItem.single)
|
result = self.downloadWrapper(self.queueItem.single)
|
||||||
if result:
|
if result:
|
||||||
|
@ -215,15 +215,15 @@ class DownloadJob:
|
||||||
)
|
)
|
||||||
if self.queueItem.cancel: raise DownloadCancelled
|
if self.queueItem.cancel: raise DownloadCancelled
|
||||||
|
|
||||||
if self.MD5 == '':
|
if track.MD5 == '':
|
||||||
if track.fallbackId != "0":
|
if track.fallbackId != "0":
|
||||||
logger.warn(f"[{track.mainArtist['name']} - {track.title}] Track not yet encoded, using fallback id")
|
logger.warn(f"[{track.mainArtist['name']} - {track.title}] Track not yet encoded, using fallback id")
|
||||||
newTrack = self.dz.get_track_gw(track.fallbackId)
|
newTrack = self.dz.get_track_gw(track.fallbackId)
|
||||||
track.parseEssentialData(self.dz, newTrack)
|
track.parseEssentialData(self.dz, newTrack)
|
||||||
return self.download(trackAPI_gw, track)
|
return self.download(trackAPI_gw, track)
|
||||||
elif not track.searched and self.settings['fallbackSearch']:
|
elif not track.searched and self.settings['fallbackSearch']:
|
||||||
logger.warn(f"[{self.mainArtist['name']} - {self.title}] Track not yet encoded, searching for alternative")
|
logger.warn(f"[{track.mainArtist['name']} - {track.title}] Track not yet encoded, searching for alternative")
|
||||||
searchedId = self.dz.get_track_from_metadata(self.mainArtist['name'], self.title, self.album['title'])
|
searchedId = self.dz.get_track_from_metadata(track.mainArtist['name'], track.title, track.album['title'])
|
||||||
if searchedId != 0:
|
if searchedId != 0:
|
||||||
newTrack = self.dz.get_track_gw(searchedId)
|
newTrack = self.dz.get_track_gw(searchedId)
|
||||||
track.parseEssentialData(self.dz, newTrack)
|
track.parseEssentialData(self.dz, newTrack)
|
||||||
|
@ -242,8 +242,8 @@ class DownloadJob:
|
||||||
track.parseEssentialData(self.dz, newTrack)
|
track.parseEssentialData(self.dz, newTrack)
|
||||||
return self.download(trackAPI_gw, track)
|
return self.download(trackAPI_gw, track)
|
||||||
elif not track.searched and self.settings['fallbackSearch']:
|
elif not track.searched and self.settings['fallbackSearch']:
|
||||||
logger.warn(f"[{self.mainArtist['name']} - {self.title}] Track not found at desired bitrate, searching for alternative")
|
logger.warn(f"[{track.mainArtist['name']} - {track.title}] Track not found at desired bitrate, searching for alternative")
|
||||||
searchedId = self.dz.get_track_from_metadata(self.mainArtist['name'], self.title, self.album['title'])
|
searchedId = self.dz.get_track_from_metadata(track.mainArtist['name'], track.title, track.album['title'])
|
||||||
if searchedId != 0:
|
if searchedId != 0:
|
||||||
newTrack = self.dz.get_track_gw(searchedId)
|
newTrack = self.dz.get_track_gw(searchedId)
|
||||||
track.parseEssentialData(self.dz, newTrack)
|
track.parseEssentialData(self.dz, newTrack)
|
||||||
|
@ -261,8 +261,7 @@ class DownloadJob:
|
||||||
track.trackNumber = track.position
|
track.trackNumber = track.position
|
||||||
track.discNumber = "1"
|
track.discNumber = "1"
|
||||||
track.album = {**track.album, **track.playlist}
|
track.album = {**track.album, **track.playlist}
|
||||||
track.album['picPath'] = os.path.join(TEMPDIR,
|
track.album['picPath'] = os.path.join(TEMPDIR, f"pl{trackAPI_gw['_EXTRA_PLAYLIST']['id']}_{self.settings['embeddedArtworkSize']}.jpg")
|
||||||
f"pl{trackAPI_gw['_EXTRA_PLAYLIST']['id']}_{settings['embeddedArtworkSize']}.jpg")
|
|
||||||
else:
|
else:
|
||||||
if track.album['date']:
|
if track.album['date']:
|
||||||
track.date = track.album['date']
|
track.date = track.album['date']
|
||||||
|
@ -271,10 +270,11 @@ class DownloadJob:
|
||||||
self.settings['embeddedArtworkSize'], self.settings['embeddedArtworkSize'],
|
self.settings['embeddedArtworkSize'], self.settings['embeddedArtworkSize'],
|
||||||
f'000000-{self.settings["jpegImageQuality"]}-0-0.jpg'
|
f'000000-{self.settings["jpegImageQuality"]}-0-0.jpg'
|
||||||
)
|
)
|
||||||
|
track.album['picPath'] = os.path.join(TEMPDIR, f"alb{track.album['id']}_{self.settings['embeddedArtworkSize']}.jpg")
|
||||||
track.album['bitrate'] = selectedFormat
|
track.album['bitrate'] = selectedFormat
|
||||||
|
|
||||||
track.dateString = formatDate(track.date, settings['dateFormat'])
|
track.dateString = formatDate(track.date, self.settings['dateFormat'])
|
||||||
track.album['dateString'] = formatDate(track.album['date'], settings['dateFormat'])
|
track.album['dateString'] = formatDate(track.album['date'], self.settings['dateFormat'])
|
||||||
|
|
||||||
# Check if user wants the feat in the title
|
# Check if user wants the feat in the title
|
||||||
# 0 => do not change
|
# 0 => do not change
|
||||||
|
@ -320,11 +320,6 @@ class DownloadJob:
|
||||||
if self.queueItem.cancel: raise DownloadCancelled
|
if self.queueItem.cancel: raise DownloadCancelled
|
||||||
|
|
||||||
# Download and cache coverart
|
# Download and cache coverart
|
||||||
if self.settings['tags']['savePlaylistAsCompilation'] and track.playlist:
|
|
||||||
|
|
||||||
else:
|
|
||||||
track.album['picPath'] = os.path.join(TEMPDIR,
|
|
||||||
f"alb{track.album['id']}_{settings['embeddedArtworkSize']}.jpg")
|
|
||||||
logger.info(f"[{track.mainArtist['name']} - {track.title}] Getting the album cover")
|
logger.info(f"[{track.mainArtist['name']} - {track.title}] Getting the album cover")
|
||||||
track.album['picPath'] = downloadImage(track.album['picUrl'], track.album['picPath'])
|
track.album['picPath'] = downloadImage(track.album['picUrl'], track.album['picPath'])
|
||||||
|
|
||||||
|
@ -418,7 +413,7 @@ class DownloadJob:
|
||||||
|
|
||||||
if not trackAlreadyDownloaded or self.settings['overwriteFile'] == 'y':
|
if not trackAlreadyDownloaded or self.settings['overwriteFile'] == 'y':
|
||||||
logger.info(f"[{track.mainArtist['name']} - {track.title}] Downloading the track")
|
logger.info(f"[{track.mainArtist['name']} - {track.title}] Downloading the track")
|
||||||
track.downloadUrl = dz.get_track_stream_url(track.id, track.MD5, track.mediaVersion, track.selectedFormat)
|
track.downloadUrl = self.dz.get_track_stream_url(track.id, track.MD5, track.mediaVersion, track.selectedFormat)
|
||||||
|
|
||||||
def downloadMusic(track, trackAPI_gw):
|
def downloadMusic(track, trackAPI_gw):
|
||||||
try:
|
try:
|
||||||
|
@ -435,8 +430,8 @@ class DownloadJob:
|
||||||
track.parseEssentialData(self.dz, newTrack)
|
track.parseEssentialData(self.dz, newTrack)
|
||||||
return False
|
return False
|
||||||
elif not track.searched and self.settings['fallbackSearch']:
|
elif not track.searched and self.settings['fallbackSearch']:
|
||||||
logger.warn(f"[{self.mainArtist['name']} - {self.title}] Track not available, searching for alternative")
|
logger.warn(f"[{track.mainArtist['name']} - {track.title}] Track not available, searching for alternative")
|
||||||
searchedId = self.dz.get_track_from_metadata(self.mainArtist['name'], self.title, self.album['title'])
|
searchedId = self.dz.get_track_from_metadata(track.mainArtist['name'], track.title, track.album['title'])
|
||||||
if searchedId != 0:
|
if searchedId != 0:
|
||||||
newTrack = self.dz.get_track_gw(searchedId)
|
newTrack = self.dz.get_track_gw(searchedId)
|
||||||
track.parseEssentialData(self.dz, newTrack)
|
track.parseEssentialData(self.dz, newTrack)
|
||||||
|
@ -460,7 +455,7 @@ class DownloadJob:
|
||||||
try:
|
try:
|
||||||
trackDownloaded = downloadMusic(track, trackAPI_gw)
|
trackDownloaded = downloadMusic(track, trackAPI_gw)
|
||||||
except DownloadFailed as e:
|
except DownloadFailed as e:
|
||||||
raise DownloadFailed
|
raise e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
@ -468,7 +463,7 @@ class DownloadJob:
|
||||||
return self.download(trackAPI_gw, track)
|
return self.download(trackAPI_gw, 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")
|
||||||
trackCompletePercentage(trackAPI, queueItem, interface)
|
self.completeTrackPercentage()
|
||||||
|
|
||||||
# Adding tags
|
# Adding tags
|
||||||
if (not trackAlreadyDownloaded or self.settings['overwriteFile'] in ['t', 'y']) and not track.localTrack:
|
if (not trackAlreadyDownloaded or self.settings['overwriteFile'] in ['t', 'y']) and not track.localTrack:
|
||||||
|
@ -482,10 +477,10 @@ class DownloadJob:
|
||||||
remove(writepath)
|
remove(writepath)
|
||||||
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(trackAPI, queueItem, interface)
|
self.removeTrackPercentage(trackAPI, queueItem, interface)
|
||||||
track.formats['FILESIZE_FLAC'] = "0"
|
track.filesizes['FILESIZE_FLAC'] = "0"
|
||||||
return self.download(trackAPI_gw, track)
|
return self.download(trackAPI_gw, track)
|
||||||
if track.searched:
|
if track.searched:
|
||||||
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")
|
||||||
self.queueItem.downloaded += 1
|
self.queueItem.downloaded += 1
|
||||||
|
@ -533,16 +528,16 @@ class DownloadJob:
|
||||||
|
|
||||||
return error_num # fallback is enabled and loop went through all formats
|
return error_num # fallback is enabled and loop went through all formats
|
||||||
|
|
||||||
def stream_track(self, stream, track, trackAPI):
|
def streamTrack(self, stream, track, trackAPI):
|
||||||
if self.queueItem.cancel: raise DownloadCancelled
|
if self.queueItem.cancel: raise DownloadCancelled
|
||||||
|
|
||||||
try:
|
try:
|
||||||
request = get(track.downloadUrl, headers=dz.http_headers, stream=True, timeout=30)
|
request = get(track.downloadUrl, headers=self.dz.http_headers, stream=True, timeout=30)
|
||||||
except ConnectionError:
|
except ConnectionError:
|
||||||
sleep(2)
|
sleep(2)
|
||||||
return stream_track(dz, track, stream, trackAPI, queueItem, interface)
|
return self.streamTrack(stream, track, trackAPI)
|
||||||
request.raise_for_status()
|
request.raise_for_status()
|
||||||
blowfish_key = str.encode(dz._get_blowfish_key(str(track.id)))
|
blowfish_key = str.encode(self.dz._get_blowfish_key(str(track.id)))
|
||||||
complete = int(request.headers["Content-Length"])
|
complete = int(request.headers["Content-Length"])
|
||||||
chunkLength = 0
|
chunkLength = 0
|
||||||
percentage = 0
|
percentage = 0
|
||||||
|
@ -585,9 +580,9 @@ class DownloadJob:
|
||||||
|
|
||||||
def downloadWrapper(self, trackAPI_gw):
|
def downloadWrapper(self, trackAPI_gw):
|
||||||
track = {
|
track = {
|
||||||
'id': queueItem.single['SNG_ID'],
|
'id': trackAPI_gw['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': trackAPI_gw['SNG_TITLE'] + (trackAPI_gw['VERSION'] if 'VERSION' in trackAPI_gw and trackAPI_gw['VERSION'] and not trackAPI_gw['VERSION'] in trackAPI_gw['SNG_TITLE'] else ""),
|
||||||
'mainArtist': {'name': queueItem.single['ART_NAME']}
|
'artist': trackAPI_gw['ART_NAME']
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -595,14 +590,14 @@ class DownloadJob:
|
||||||
except DownloadCancelled:
|
except DownloadCancelled:
|
||||||
return None
|
return None
|
||||||
except DownloadFailed as error:
|
except DownloadFailed as error:
|
||||||
logger.error(f"[{track['mainArtist']['name']} - {track['title']}] {error.message}")
|
logger.error(f"[{track['artist']} - {track['title']}] {error.message}")
|
||||||
result = {'error': {
|
result = {'error': {
|
||||||
'message': error.message,
|
'message': error.message,
|
||||||
'errid': error.errid,
|
'errid': error.errid,
|
||||||
'data': track
|
'data': track
|
||||||
}}
|
}}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(str(e))
|
logger.exception(f"[{track['artist']} - {track['title']}] {str(e)}")
|
||||||
result = {'error': {
|
result = {'error': {
|
||||||
'message': str(e),
|
'message': str(e),
|
||||||
'data': track
|
'data': track
|
||||||
|
@ -611,10 +606,10 @@ class DownloadJob:
|
||||||
if 'error' in result:
|
if 'error' in result:
|
||||||
self.completeTrackPercentage()
|
self.completeTrackPercentage()
|
||||||
self.queueItem.failed += 1
|
self.queueItem.failed += 1
|
||||||
self.queueItem.errors.append(error.message)
|
self.queueItem.errors.append(result['error']['message'])
|
||||||
if interface:
|
if self.interface:
|
||||||
error = result['error']
|
error = result['error']
|
||||||
interface.send("updateQueue", {
|
self.interface.send("updateQueue", {
|
||||||
'uuid': self.queueItem.uuid,
|
'uuid': self.queueItem.uuid,
|
||||||
'failed': True,
|
'failed': True,
|
||||||
'data': error['data'],
|
'data': error['data'],
|
|
@ -4,43 +4,43 @@ class QueueItem:
|
||||||
def __init__(self, id=None, bitrate=None, title=None, artist=None, cover=None, size=None, type=None, settings=None, queueItemList=None):
|
def __init__(self, id=None, bitrate=None, title=None, artist=None, cover=None, size=None, type=None, settings=None, queueItemList=None):
|
||||||
if queueItemList:
|
if queueItemList:
|
||||||
self.title = queueItemList['title']
|
self.title = queueItemList['title']
|
||||||
self.artist = queueItemList['artist']
|
self.artist = queueItemList['artist']
|
||||||
self.cover = queueItemList['cover']
|
self.cover = queueItemList['cover']
|
||||||
self.size = queueItemList['size']
|
self.size = queueItemList['size']
|
||||||
self.type = queueItemList['type']
|
self.type = queueItemList['type']
|
||||||
self.id = queueItemList['id']
|
self.id = queueItemList['id']
|
||||||
self.bitrate = queueItemList['bitrate']
|
self.bitrate = queueItemList['bitrate']
|
||||||
self.settings = queueItemList['settings']
|
self.settings = queueItemList['settings']
|
||||||
else:
|
else:
|
||||||
self.title = title
|
self.title = title
|
||||||
self.artist = artist
|
self.artist = artist
|
||||||
self.cover = cover
|
self.cover = cover
|
||||||
self.size = size
|
self.size = size
|
||||||
self.type = type
|
self.type = type
|
||||||
self.id = id
|
self.id = id
|
||||||
self.bitrate = bitrate
|
self.bitrate = bitrate
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
self.downloaded = 0
|
self.downloaded = 0
|
||||||
self.failed = 0
|
self.failed = 0
|
||||||
self.errors = []
|
self.errors = []
|
||||||
self.progress = 0
|
self.progress = 0
|
||||||
self.uuid = f"{self.type}_{self.id}_{self.bitrate}"
|
self.uuid = f"{self.type}_{self.id}_{self.bitrate}"
|
||||||
self.cancel = False
|
self.cancel = False
|
||||||
|
|
||||||
def toDict(self):
|
def toDict(self):
|
||||||
return {
|
return {
|
||||||
'title': self.title,
|
'title': self.title,
|
||||||
'artist': self.artist,
|
'artist': self.artist,
|
||||||
'cover': self.cover,
|
'cover': self.cover,
|
||||||
'size': self.size,
|
'size': self.size,
|
||||||
'downloaded': self.downloaded,
|
'downloaded': self.downloaded,
|
||||||
'failed': self.failed,
|
'failed': self.failed,
|
||||||
'errors': self.errors,
|
'errors': self.errors,
|
||||||
'progress': self.progress,
|
'progress': self.progress,
|
||||||
'type': self.type,
|
'type': self.type,
|
||||||
'id': self.id,
|
'id': self.id,
|
||||||
'bitrate': self.bitrate,
|
'bitrate': self.bitrate,
|
||||||
'uuid': self.uuid
|
'uuid': self.uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
def getResettedItem(self):
|
def getResettedItem(self):
|
||||||
|
@ -87,13 +87,13 @@ class QICollection(QueueItem):
|
||||||
queueItem['collection'] = self.collection
|
queueItem['collection'] = self.collection
|
||||||
return queueItem
|
return queueItem
|
||||||
|
|
||||||
class QIConvertable(QueueItem):
|
class QIConvertable(QICollection):
|
||||||
def __init__(self, id=None, bitrate=None, title=None, artist=None, cover=None, size=None, type=None, settings=None, extra=None, queueItemList=None):
|
def __init__(self, id=None, bitrate=None, title=None, artist=None, cover=None, size=None, type=None, settings=None, extra=None, queueItemList=None):
|
||||||
if queueItemList:
|
if queueItemList:
|
||||||
super().__init__(queueItemList=queueItemList)
|
super().__init__(queueItemList=queueItemList)
|
||||||
self.extra = queueItemList['_EXTRA']
|
self.extra = queueItemList['_EXTRA']
|
||||||
else:
|
else:
|
||||||
super().__init__(id, bitrate, title, artist, cover, size, type, settings)
|
super().__init__(id, bitrate, title, artist, cover, size, type, settings, [])
|
||||||
self.extra = extra
|
self.extra = extra
|
||||||
|
|
||||||
def toDict(self):
|
def toDict(self):
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from deemix.app.downloader import download
|
from deemix.app.downloadjob import DownloadJob
|
||||||
from deemix.utils.misc import getIDFromLink, getTypeFromLink, getBitrateInt
|
from deemix.utils.misc import getIDFromLink, getTypeFromLink, getBitrateInt
|
||||||
from deemix.api.deezer import APIError
|
from deemix.api.deezer import APIError
|
||||||
from spotipy.exceptions import SpotifyException
|
from spotipy.exceptions import SpotifyException
|
||||||
|
@ -35,7 +35,7 @@ class QueueManager:
|
||||||
if 'id' in trackAPI and 'title' in trackAPI:
|
if 'id' in trackAPI and 'title' in trackAPI:
|
||||||
id = trackAPI['id']
|
id = trackAPI['id']
|
||||||
else:
|
else:
|
||||||
|
return QueueError(url, "Track ISRC is not available on deezer", "ISRCnotOnDeezer")
|
||||||
except APIError as e:
|
except APIError as e:
|
||||||
e = json.loads(str(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(url, f"Wrong URL: {e['type']+': ' if 'type' in e else ''}{e['message'] if 'message' in e else ''}")
|
||||||
|
@ -303,7 +303,7 @@ class QueueManager:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
playlist = sp.generate_playlist_queueitem(dz, id, settings)
|
playlist = sp.generate_playlist_queueitem(dz, id, settings)
|
||||||
playlist['bitrate'] = bitrate
|
playlist.bitrate = 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:])
|
||||||
|
@ -317,12 +317,14 @@ class QueueManager:
|
||||||
if interface:
|
if interface:
|
||||||
interface.send("loginNeededToDownload")
|
interface.send("loginNeededToDownload")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def parseLink(link):
|
def parseLink(link):
|
||||||
link = link.strip()
|
link = link.strip()
|
||||||
if link == "":
|
if link == "":
|
||||||
return False
|
return False
|
||||||
logger.info("Generating queue item for: "+link)
|
logger.info("Generating queue item for: "+link)
|
||||||
return self.generateQueueItem(dz, sp, link, settings, bitrate, interface=interface)
|
return self.generateQueueItem(dz, sp, link, settings, bitrate, interface=interface)
|
||||||
|
|
||||||
if type(url) is list:
|
if type(url) is list:
|
||||||
queueItem = []
|
queueItem = []
|
||||||
for link in url:
|
for link in url:
|
||||||
|
@ -339,6 +341,7 @@ class QueueManager:
|
||||||
queueItem = parseLink(url)
|
queueItem = parseLink(url)
|
||||||
if not queueItem:
|
if not queueItem:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if type(queueItem) is list:
|
if type(queueItem) is list:
|
||||||
ogLen = len(self.queue)
|
ogLen = len(self.queue)
|
||||||
for x in queueItem:
|
for x in queueItem:
|
||||||
|
@ -369,6 +372,7 @@ class QueueManager:
|
||||||
logger.info(f"[{queueItem.uuid}] Added to queue.")
|
logger.info(f"[{queueItem.uuid}] Added to queue.")
|
||||||
self.queue.append(queueItem.uuid)
|
self.queue.append(queueItem.uuid)
|
||||||
self.queueList[queueItem.uuid] = queueItem
|
self.queueList[queueItem.uuid] = queueItem
|
||||||
|
|
||||||
self.nextItem(dz, sp, interface)
|
self.nextItem(dz, sp, interface)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -383,7 +387,7 @@ class QueueManager:
|
||||||
if interface:
|
if interface:
|
||||||
interface.send("startDownload", self.currentItem)
|
interface.send("startDownload", self.currentItem)
|
||||||
logger.info(f"[{self.currentItem}] Started downloading.")
|
logger.info(f"[{self.currentItem}] Started downloading.")
|
||||||
download(dz, sp, self.queueList[self.currentItem], interface)
|
DownloadJob(dz, sp, self.queueList[self.currentItem]).start()
|
||||||
self.afterDownload(dz, sp, interface)
|
self.afterDownload(dz, sp, interface)
|
||||||
|
|
||||||
def afterDownload(self, dz, sp, interface):
|
def afterDownload(self, dz, sp, interface):
|
|
@ -213,7 +213,7 @@ class SpotifyHelper:
|
||||||
if not 'explicit' in playlistAPI:
|
if not 'explicit' in playlistAPI:
|
||||||
playlistAPI['explicit'] = False
|
playlistAPI['explicit'] = False
|
||||||
extra['playlistAPI'] = playlistAPI
|
extra['playlistAPI'] = playlistAPI
|
||||||
return QICollection(
|
return QIConvertable(
|
||||||
playlist_id,
|
playlist_id,
|
||||||
0,
|
0,
|
||||||
spotify_playlist['name'],
|
spotify_playlist['name'],
|
||||||
|
@ -225,7 +225,7 @@ class SpotifyHelper:
|
||||||
extra,
|
extra,
|
||||||
)
|
)
|
||||||
|
|
||||||
def convert_spotify_playlist(self, dz, item, settings, interface=None):
|
def convert_spotify_playlist(self, dz, queueItem, interface=None):
|
||||||
convertPercentage = 0
|
convertPercentage = 0
|
||||||
lastPercentage = 0
|
lastPercentage = 0
|
||||||
if path.isfile(path.join(self.configFolder, 'spotifyCache.json')):
|
if path.isfile(path.join(self.configFolder, 'spotifyCache.json')):
|
||||||
|
@ -234,13 +234,13 @@ class SpotifyHelper:
|
||||||
else:
|
else:
|
||||||
cache = {'tracks': {}, 'albums': {}}
|
cache = {'tracks': {}, 'albums': {}}
|
||||||
if interface:
|
if interface:
|
||||||
interface.send("startConversion", item.uuid)
|
interface.send("startConversion", queueItem.uuid)
|
||||||
collection = []
|
collection = []
|
||||||
for pos, track in enumerate(item.extra['unconverted'], start=1):
|
for pos, track in enumerate(queueItem.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:
|
||||||
trackID = self.get_trackid_spotify(dz, 0, settings['fallbackSearch'], track)
|
trackID = self.get_trackid_spotify(dz, 0, queueItem.settings['fallbackSearch'], track)
|
||||||
cache['tracks'][str(track['id'])] = trackID
|
cache['tracks'][str(track['id'])] = trackID
|
||||||
if trackID == 0:
|
if trackID == 0:
|
||||||
deezerTrack = {
|
deezerTrack = {
|
||||||
|
@ -257,35 +257,25 @@ 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'] = queueItem.extra['playlistAPI']
|
||||||
deezerTrack['POSITION'] = pos
|
deezerTrack['POSITION'] = pos
|
||||||
deezerTrack['SIZE'] = item.size
|
deezerTrack['SIZE'] = queueItem.size
|
||||||
deezerTrack['FILENAME_TEMPLATE'] = settings['playlistTracknameTemplate']
|
deezerTrack['FILENAME_TEMPLATE'] = queueItem.settings['playlistTracknameTemplate']
|
||||||
collection.append(deezerTrack)
|
collection.append(deezerTrack)
|
||||||
|
|
||||||
convertPercentage = (pos / item.size) * 100
|
convertPercentage = (pos / queueItem.size) * 100
|
||||||
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': queueItem.uuid, 'conversion': lastPercentage})
|
||||||
|
|
||||||
|
queueItem.extra = None
|
||||||
|
queueItem.collection = collection
|
||||||
|
|
||||||
item = QICollection(
|
|
||||||
item.id,
|
|
||||||
item.bitrate,
|
|
||||||
item.title,
|
|
||||||
item.artist,
|
|
||||||
item.cover,
|
|
||||||
item.size,
|
|
||||||
item.type,
|
|
||||||
item.settings,
|
|
||||||
collection,
|
|
||||||
)
|
|
||||||
|
|
||||||
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:
|
||||||
interface.send("startDownload", item['uuid'])
|
interface.send("startDownload", queueItem.uuid)
|
||||||
|
|
||||||
def get_user_playlists(self, user):
|
def get_user_playlists(self, user):
|
||||||
if not self.spotifyEnabled:
|
if not self.spotifyEnabled:
|
|
@ -13,7 +13,7 @@ class Track:
|
||||||
|
|
||||||
self.title = trackAPI_gw['SNG_TITLE'].strip()
|
self.title = trackAPI_gw['SNG_TITLE'].strip()
|
||||||
if 'VERSION' in trackAPI_gw and trackAPI_gw['VERSION'] and not trackAPI_gw['VERSION'] in trackAPI_gw['SNG_TITLE']:
|
if 'VERSION' in trackAPI_gw and trackAPI_gw['VERSION'] and not trackAPI_gw['VERSION'] in trackAPI_gw['SNG_TITLE']:
|
||||||
track.title += " " + trackAPI_gw['VERSION'].strip()
|
self.title += " " + trackAPI_gw['VERSION'].strip()
|
||||||
|
|
||||||
self.position = None
|
self.position = None
|
||||||
if 'POSITION' in trackAPI_gw:
|
if 'POSITION' in trackAPI_gw:
|
||||||
|
@ -87,7 +87,7 @@ class Track:
|
||||||
self.album['bitrate'] = 0
|
self.album['bitrate'] = 0
|
||||||
self.album['dateString'] = None
|
self.album['dateString'] = None
|
||||||
|
|
||||||
self.artistsString
|
self.artistsString = ""
|
||||||
|
|
||||||
def parseEssentialData(self, dz, trackAPI_gw):
|
def parseEssentialData(self, dz, trackAPI_gw):
|
||||||
self.id = trackAPI_gw['SNG_ID']
|
self.id = trackAPI_gw['SNG_ID']
|
||||||
|
@ -97,7 +97,7 @@ class Track:
|
||||||
self.fallbackId = "0"
|
self.fallbackId = "0"
|
||||||
if 'FALLBACK' in trackAPI_gw:
|
if 'FALLBACK' in trackAPI_gw:
|
||||||
self.fallbackId = trackAPI_gw['FALLBACK']['SNG_ID']
|
self.fallbackId = trackAPI_gw['FALLBACK']['SNG_ID']
|
||||||
self.formats = dz.get_track_filesizes(track["id"])
|
self.filesizes = dz.get_track_filesizes(self.id)
|
||||||
|
|
||||||
def parseLocalTrackData(self, trackAPI_gw):
|
def parseLocalTrackData(self, trackAPI_gw):
|
||||||
self.album = {
|
self.album = {
|
||||||
|
@ -160,7 +160,7 @@ class Track:
|
||||||
self.trackNumber = trackAPI_gw['TRACK_NUMBER']
|
self.trackNumber = trackAPI_gw['TRACK_NUMBER']
|
||||||
self.contributors = trackAPI_gw['SNG_CONTRIBUTORS']
|
self.contributors = trackAPI_gw['SNG_CONTRIBUTORS']
|
||||||
|
|
||||||
track.lyrics = {
|
self.lyrics = {
|
||||||
'id': None,
|
'id': None,
|
||||||
'unsync': None,
|
'unsync': None,
|
||||||
'sync': None
|
'sync': None
|
||||||
|
@ -184,13 +184,13 @@ class Track:
|
||||||
self.lyrics['sync'] += lastTimestamp
|
self.lyrics['sync'] += lastTimestamp
|
||||||
self.lyrics['sync'] += trackAPI_gw["LYRICS"]["LYRICS_SYNC_JSON"][i]["line"] + "\r\n"
|
self.lyrics['sync'] += trackAPI_gw["LYRICS"]["LYRICS_SYNC_JSON"][i]["line"] + "\r\n"
|
||||||
|
|
||||||
track.mainArtist = {
|
self.mainArtist = {
|
||||||
'id': trackAPI_gw['ART_ID'],
|
'id': trackAPI_gw['ART_ID'],
|
||||||
'name': trackAPI_gw['ART_NAME'],
|
'name': trackAPI_gw['ART_NAME'],
|
||||||
'pic': None
|
'pic': None
|
||||||
}
|
}
|
||||||
if 'ART_PICTURE' in trackAPI_gw:
|
if 'ART_PICTURE' in trackAPI_gw:
|
||||||
track.mainArtist['pic'] = trackAPI_gw['ART_PICTURE']
|
self.mainArtist['pic'] = trackAPI_gw['ART_PICTURE']
|
||||||
|
|
||||||
self.date = None
|
self.date = None
|
||||||
if 'PHYSICAL_RELEASE_DATE' in trackAPI_gw:
|
if 'PHYSICAL_RELEASE_DATE' in trackAPI_gw:
|
||||||
|
@ -261,7 +261,7 @@ class Track:
|
||||||
if 'copyright' in albumAPI:
|
if 'copyright' in albumAPI:
|
||||||
self.copyright = albumAPI['copyright']
|
self.copyright = albumAPI['copyright']
|
||||||
|
|
||||||
if not track.album['pic']:
|
if not self.album['pic']:
|
||||||
self.album['pic'] = albumAPI['cover_small'][albumAPI['cover_small'].find('cover/') + 6:-24]
|
self.album['pic'] = albumAPI['cover_small'][albumAPI['cover_small'].find('cover/') + 6:-24]
|
||||||
|
|
||||||
if 'genres' in albumAPI and 'data' in albumAPI['genres'] and len(albumAPI['genres']['data']) > 0:
|
if 'genres' in albumAPI and 'data' in albumAPI['genres'] and len(albumAPI['genres']['data']) > 0:
|
|
@ -50,7 +50,6 @@ def andCommaConcat(lst):
|
||||||
result = ""
|
result = ""
|
||||||
for i, art in enumerate(lst):
|
for i, art in enumerate(lst):
|
||||||
result += art
|
result += art
|
||||||
track['commaArtistsString'] += art
|
|
||||||
if tot != i + 1:
|
if tot != i + 1:
|
||||||
if tot - 1 == i + 1:
|
if tot - 1 == i + 1:
|
||||||
result += " & "
|
result += " & "
|
||||||
|
|
|
@ -130,10 +130,10 @@ 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.commaArtistsString, settings['illegalCharacterReplacer']))
|
filename = filename.replace("%artists%", fixName(", ".join(track.artists), settings['illegalCharacterReplacer']))
|
||||||
filename = filename.replace("%allartists%", fixName(track.artistsString, settings['illegalCharacterReplacer']))
|
filename = filename.replace("%allartists%", fixName(track.artistsString, settings['illegalCharacterReplacer']))
|
||||||
filename = filename.replace("%mainartists%", fixName(track.mainArtistsString, settings['illegalCharacterReplacer']))
|
filename = filename.replace("%mainartists%", fixName(track.mainArtistsString, settings['illegalCharacterReplacer']))
|
||||||
filename = filename.replace("%featartists%", fixName('('+track.featArtistsString+')', settings['illegalCharacterReplacer']) if 'featArtistsString' in track else "")
|
filename = filename.replace("%featartists%", fixName('('+track.featArtistsString+')', settings['illegalCharacterReplacer']) if track.featArtistsString else "")
|
||||||
filename = filename.replace("%album%", fixName(track.album['title'], settings['illegalCharacterReplacer']))
|
filename = filename.replace("%album%", fixName(track.album['title'], settings['illegalCharacterReplacer']))
|
||||||
filename = filename.replace("%albumartist%",
|
filename = filename.replace("%albumartist%",
|
||||||
fixName(track.album['mainArtist']['name'], settings['illegalCharacterReplacer']))
|
fixName(track.album['mainArtist']['name'], settings['illegalCharacterReplacer']))
|
||||||
|
|
|
@ -75,7 +75,7 @@ def tagID3(stream, track, save):
|
||||||
|
|
||||||
if save['copyright']:
|
if save['copyright']:
|
||||||
tag.add(TCOP(text=track.copyright))
|
tag.add(TCOP(text=track.copyright))
|
||||||
if save['savePlaylistAsCompilation'] and "playlist" in track:
|
if save['savePlaylistAsCompilation'] and track.playlist:
|
||||||
tag.add(TCMP(text="1"))
|
tag.add(TCMP(text="1"))
|
||||||
|
|
||||||
if save['cover'] and track.album['picPath']:
|
if save['cover'] and track.album['picPath']:
|
||||||
|
@ -155,7 +155,7 @@ def tagFLAC(stream, track, save):
|
||||||
|
|
||||||
if save['copyright']:
|
if save['copyright']:
|
||||||
tag["COPYRIGHT"] = track.copyright
|
tag["COPYRIGHT"] = track.copyright
|
||||||
if save['savePlaylistAsCompilation'] and "playlist" in track:
|
if save['savePlaylistAsCompilation'] and track.playlist:
|
||||||
tag["COMPILATION"] = "1"
|
tag["COMPILATION"] = "1"
|
||||||
|
|
||||||
if save['cover'] and track.album['picPath']:
|
if save['cover'] and track.album['picPath']:
|
||||||
|
|
Loading…
Reference in New Issue