2020-02-20 14:42:12 +00:00
#!/usr/bin/env python3
2020-03-02 12:46:48 +00:00
from deemix . api . deezer import APIError , USER_AGENT_HEADER
2020-02-20 14:42:12 +00:00
from deemix . utils . taggers import tagID3 , tagFLAC
2020-02-29 20:42:21 +00:00
from deemix . utils . pathtemplates import generateFilename , generateFilepath , settingsRegexAlbum , settingsRegexArtist
2020-03-31 12:37:45 +00:00
from deemix . utils . misc import changeCase
2020-04-06 13:57:10 +00:00
from deemix . utils . spotifyHelper import get_trackid_spotify , get_albumid_spotify
2020-02-20 14:42:12 +00:00
import os . path
2020-03-01 12:14:37 +00:00
from os import makedirs , remove
2020-02-29 19:40:03 +00:00
from requests import get
2020-04-10 21:21:09 +00:00
from requests . exceptions import HTTPError , ConnectionError
2020-02-27 17:37:40 +00:00
from tempfile import gettempdir
2020-02-29 21:30:12 +00:00
from concurrent . futures import ThreadPoolExecutor
2020-04-10 22:21:30 +00:00
from Cryptodome . Cipher import Blowfish
2020-04-10 21:21:09 +00:00
from time import sleep
2020-03-22 15:52:17 +00:00
import re
2020-02-20 14:42:12 +00:00
2020-04-14 10:58:31 +00:00
TEMPDIR = os . path . join ( gettempdir ( ) , ' deemix-imgs ' )
2020-02-27 17:37:40 +00:00
if not os . path . isdir ( TEMPDIR ) :
makedirs ( TEMPDIR )
2020-02-20 14:42:12 +00:00
extensions = {
9 : ' .flac ' ,
3 : ' .mp3 ' ,
1 : ' .mp3 ' ,
8 : ' .mp3 ' ,
15 : ' .mp4 ' ,
14 : ' .mp4 ' ,
13 : ' .mp4 '
}
2020-04-10 22:21:30 +00:00
downloadPercentage = 0
lastPercentage = 0
2020-04-15 12:49:40 +00:00
def stream_track ( dz , track , stream , trackAPI , queueItem , interface = None ) :
2020-04-10 22:21:30 +00:00
global downloadPercentage , lastPercentage
2020-04-11 13:43:59 +00:00
if ' cancel ' in queueItem :
raise downloadCancelled
2020-04-10 22:21:30 +00:00
try :
request = get ( track [ ' downloadUrl ' ] , headers = dz . http_headers , stream = True , timeout = 30 )
2020-04-11 13:43:59 +00:00
except ConnectionError :
2020-04-10 22:21:30 +00:00
sleep ( 2 )
2020-04-15 12:49:40 +00:00
return stream_track ( dz , track , stream , trackAPI , queueItem , interface )
2020-04-10 22:21:30 +00:00
request . raise_for_status ( )
blowfish_key = str . encode ( dz . _get_blowfish_key ( str ( track [ ' id ' ] ) ) )
complete = track [ ' selectedFilesize ' ]
chunkLength = 0
percentage = 0
i = 0
for chunk in request . iter_content ( 2048 ) :
2020-04-11 13:43:59 +00:00
if ' cancel ' in queueItem :
raise downloadCancelled
2020-04-10 22:21:30 +00:00
if ( i % 3 ) == 0 and len ( chunk ) == 2048 :
chunk = Blowfish . new ( blowfish_key , Blowfish . MODE_CBC , b " \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 " ) . decrypt ( chunk )
stream . write ( chunk )
chunkLength + = len ( chunk )
if ' SINGLE_TRACK ' in trackAPI :
percentage = ( chunkLength / complete ) * 100
downloadPercentage = percentage
else :
chunkProgres = ( len ( chunk ) / complete ) / trackAPI [ ' SIZE ' ] * 100
downloadPercentage + = chunkProgres
if round ( downloadPercentage ) != lastPercentage and round ( percentage ) % 5 == 0 :
lastPercentage = round ( downloadPercentage )
2020-04-15 12:49:40 +00:00
if interface :
2020-04-14 10:58:31 +00:00
queueItem [ ' progress ' ] = lastPercentage
2020-04-15 12:49:40 +00:00
interface . send ( " updateQueue " , { ' uuid ' : queueItem [ ' uuid ' ] , ' progress ' : lastPercentage } )
2020-04-10 22:21:30 +00:00
i + = 1
2020-02-20 14:42:12 +00:00
2020-03-01 12:14:37 +00:00
def downloadImage ( url , path ) :
if not os . path . isfile ( path ) :
2020-04-14 10:58:31 +00:00
try :
image = get ( url , headers = { ' User-Agent ' : USER_AGENT_HEADER } , timeout = 30 )
with open ( path , ' wb ' ) as f :
f . write ( image . content )
2020-03-01 12:14:37 +00:00
return path
2020-04-14 10:58:31 +00:00
except ConnectionError :
sleep ( 1 )
return downloadImage ( url , path )
except HTTPError :
print ( " Couldn ' t download Image " )
2020-03-01 12:14:37 +00:00
remove ( path )
return None
else :
return path
2020-03-20 15:27:58 +00:00
def formatDate ( date , template ) :
if ' YYYY ' in template :
template = template . replace ( ' YYYY ' , str ( date [ ' year ' ] ) )
if ' YY ' in template :
template = template . replace ( ' YY ' , str ( date [ ' year ' ] ) )
if ' Y ' in template :
template = template . replace ( ' Y ' , str ( date [ ' year ' ] ) )
if ' MM ' in template :
template = template . replace ( ' MM ' , str ( date [ ' month ' ] ) )
if ' M ' in template :
template = template . replace ( ' M ' , str ( date [ ' month ' ] ) )
if ' DD ' in template :
template = template . replace ( ' DD ' , str ( date [ ' day ' ] ) )
if ' D ' in template :
template = template . replace ( ' D ' , str ( date [ ' day ' ] ) )
return template
2020-03-21 20:13:29 +00:00
def getPreferredBitrate ( filesize , bitrate , fallback = True ) :
if not fallback :
formats = { 9 : ' flac ' , 3 : ' mp3_320 ' , 1 : ' mp3_128 ' , 15 : ' 360_hq ' , 14 : ' 360_mq ' , 13 : ' 360_lq ' }
if filesize [ formats [ int ( bitrate ) ] ] > 0 :
return ( int ( bitrate ) , filesize [ formats [ int ( bitrate ) ] ] )
else :
return ( - 100 , 0 )
if int ( bitrate ) in [ 13 , 14 , 15 ] :
formats = { ' 360_hq ' : 15 , ' 360_mq ' : 14 , ' 360_lq ' : 13 }
selectedFormat = - 200
selectedFilesize = 0
for format , formatNum in formats . items ( ) :
if formatNum < = int ( bitrate ) and filesize [ format ] > 0 :
selectedFormat = formatNum
selectedFilesize = filesize [ format ]
break
else :
formats = { ' flac ' : 9 , ' mp3_320 ' : 3 , ' mp3_128 ' : 1 }
selectedFormat = 8
selectedFilesize = filesize [ ' default ' ]
for format , formatNum in formats . items ( ) :
if formatNum < = int ( bitrate ) and filesize [ format ] > 0 :
selectedFormat = formatNum
selectedFilesize = filesize [ format ]
break
2020-02-24 17:36:11 +00:00
return ( selectedFormat , selectedFilesize )
2020-02-22 13:38:01 +00:00
def parseEssentialTrackData ( track , trackAPI ) :
track [ ' id ' ] = trackAPI [ ' SNG_ID ' ]
track [ ' duration ' ] = trackAPI [ ' DURATION ' ]
track [ ' MD5 ' ] = trackAPI [ ' MD5_ORIGIN ' ]
track [ ' mediaVersion ' ] = trackAPI [ ' MEDIA_VERSION ' ]
if ' FALLBACK ' in trackAPI :
track [ ' fallbackId ' ] = trackAPI [ ' FALLBACK ' ] [ ' SNG_ID ' ]
else :
track [ ' fallbackId ' ] = 0
track [ ' filesize ' ] = { }
2020-03-21 20:13:29 +00:00
track [ ' filesize ' ] [ ' default ' ] = int ( trackAPI [ ' FILESIZE ' ] ) if ' FILESIZE ' in trackAPI else 0
track [ ' filesize ' ] [ ' mp3_128 ' ] = int ( trackAPI [ ' FILESIZE_MP3_128 ' ] ) if ' FILESIZE_MP3_128 ' in trackAPI else 0
track [ ' filesize ' ] [ ' mp3_320 ' ] = int ( trackAPI [ ' FILESIZE_MP3_320 ' ] ) if ' FILESIZE_MP3_320 ' in trackAPI else 0
track [ ' filesize ' ] [ ' flac ' ] = int ( trackAPI [ ' FILESIZE_FLAC ' ] ) if ' FILESIZE_FLAC ' in trackAPI else 0
track [ ' filesize ' ] [ ' 360_lq ' ] = int ( trackAPI [ ' FILESIZE_MP4_RA1 ' ] ) if ' FILESIZE_MP4_RA1 ' in trackAPI else 0
track [ ' filesize ' ] [ ' 360_mq ' ] = int ( trackAPI [ ' FILESIZE_MP4_RA2 ' ] ) if ' FILESIZE_MP4_RA2 ' in trackAPI else 0
track [ ' filesize ' ] [ ' 360_hq ' ] = int ( trackAPI [ ' FILESIZE_MP4_RA3 ' ] ) if ' FILESIZE_MP4_RA3 ' in trackAPI else 0
2020-02-22 13:38:01 +00:00
return track
2020-03-02 12:46:48 +00:00
def getTrackData ( dz , trackAPI_gw , trackAPI = None , albumAPI_gw = None , albumAPI = None ) :
2020-02-27 16:34:49 +00:00
if not ' MD5_ORIGIN ' in trackAPI_gw :
trackAPI_gw [ ' MD5_ORIGIN ' ] = dz . get_track_md5 ( trackAPI_gw [ ' SNG_ID ' ] )
2020-02-20 14:42:12 +00:00
track = { }
2020-02-27 16:34:49 +00:00
track [ ' title ' ] = trackAPI_gw [ ' SNG_TITLE ' ]
2020-03-15 18:18:52 +00:00
if ' VERSION ' in trackAPI_gw and trackAPI_gw [ ' VERSION ' ] :
2020-02-27 16:34:49 +00:00
track [ ' title ' ] + = " " + trackAPI_gw [ ' VERSION ' ]
2020-02-22 13:38:01 +00:00
2020-02-27 16:34:49 +00:00
track = parseEssentialTrackData ( track , trackAPI_gw )
2020-02-20 14:42:12 +00:00
if int ( track [ ' id ' ] ) < 0 :
2020-02-27 16:34:49 +00:00
track [ ' filesize ' ] = trackAPI_gw [ ' FILESIZE ' ]
2020-02-20 14:42:12 +00:00
track [ ' album ' ] = { }
track [ ' album ' ] [ ' id ' ] = 0
2020-02-27 16:34:49 +00:00
track [ ' album ' ] [ ' title ' ] = trackAPI_gw [ ' ALB_TITLE ' ]
if ' ALB_PICTURE ' in trackAPI_gw :
track [ ' album ' ] [ ' pic ' ] = trackAPI_gw [ ' ALB_PICTURE ' ]
2020-02-20 14:42:12 +00:00
track [ ' mainArtist ' ] = { }
track [ ' mainArtist ' ] [ ' id ' ] = 0
2020-02-27 16:34:49 +00:00
track [ ' mainArtist ' ] [ ' name ' ] = trackAPI_gw [ ' ART_NAME ' ]
track [ ' artists ' ] = [ trackAPI_gw [ ' ART_NAME ' ] ]
2020-02-24 17:36:11 +00:00
track [ ' aritst ' ] = {
2020-02-27 16:34:49 +00:00
' Main ' : [ trackAPI_gw [ ' ART_NAME ' ] ]
2020-02-24 17:36:11 +00:00
}
2020-02-20 14:42:12 +00:00
track [ ' date ' ] = {
' day ' : 0 ,
' month ' : 0 ,
' year ' : 0
}
track [ ' localTrack ' ] = True
return track
2020-02-27 16:34:49 +00:00
if ' DISK_NUMBER ' in trackAPI_gw :
track [ ' discNumber ' ] = trackAPI_gw [ ' DISK_NUMBER ' ]
if ' EXPLICIT_LYRICS ' in trackAPI_gw :
track [ ' explicit ' ] = trackAPI_gw [ ' EXPLICIT_LYRICS ' ] != " 0 "
if ' COPYRIGHT ' in trackAPI_gw :
track [ ' copyright ' ] = trackAPI_gw [ ' COPYRIGHT ' ]
track [ ' replayGain ' ] = " {0:.2f} dB " . format ( ( float ( trackAPI_gw [ ' GAIN ' ] ) + 18.4 ) * - 1 ) if ' GAIN ' in trackAPI_gw else None
track [ ' ISRC ' ] = trackAPI_gw [ ' ISRC ' ]
track [ ' trackNumber ' ] = trackAPI_gw [ ' TRACK_NUMBER ' ]
track [ ' contributors ' ] = trackAPI_gw [ ' SNG_CONTRIBUTORS ' ]
if ' POSITION ' in trackAPI_gw :
track [ ' position ' ] = trackAPI_gw [ ' POSITION ' ]
2020-02-20 14:42:12 +00:00
track [ ' lyrics ' ] = { }
2020-02-27 16:34:49 +00:00
if ' LYRICS_ID ' in trackAPI_gw :
track [ ' lyrics ' ] [ ' id ' ] = trackAPI_gw [ ' LYRICS_ID ' ]
2020-02-29 20:22:44 +00:00
if not " LYRICS " in trackAPI_gw and int ( track [ ' lyrics ' ] [ ' id ' ] ) != 0 :
trackAPI_gw [ " LYRICS " ] = dz . get_lyrics_gw ( track [ ' id ' ] )
if int ( track [ ' lyrics ' ] [ ' id ' ] ) != 0 :
2020-02-27 16:34:49 +00:00
if " LYRICS_TEXT " in trackAPI_gw [ " LYRICS " ] :
track [ ' lyrics ' ] [ ' unsync ' ] = trackAPI_gw [ " LYRICS " ] [ " LYRICS_TEXT " ]
if " LYRICS_SYNC_JSON " in trackAPI_gw [ " LYRICS " ] :
2020-02-20 14:42:12 +00:00
track [ ' lyrics ' ] [ ' sync ' ] = " "
2020-04-12 12:12:43 +00:00
lastTimestamp = " "
2020-02-27 16:34:49 +00:00
for i in range ( len ( trackAPI_gw [ " LYRICS " ] [ " LYRICS_SYNC_JSON " ] ) ) :
if " lrc_timestamp " in trackAPI_gw [ " LYRICS " ] [ " LYRICS_SYNC_JSON " ] [ i ] :
2020-04-12 12:12:43 +00:00
track [ ' lyrics ' ] [ ' sync ' ] + = trackAPI_gw [ " LYRICS " ] [ " LYRICS_SYNC_JSON " ] [ i ] [ " lrc_timestamp " ]
lastTimestamp = trackAPI_gw [ " LYRICS " ] [ " LYRICS_SYNC_JSON " ] [ i ] [ " lrc_timestamp " ]
else :
track [ ' lyrics ' ] [ ' sync ' ] + = lastTimestamp
track [ ' lyrics ' ] [ ' sync ' ] + = trackAPI_gw [ " LYRICS " ] [ " LYRICS_SYNC_JSON " ] [ i ] [ " line " ] + " \r \n "
2020-02-20 14:42:12 +00:00
track [ ' mainArtist ' ] = { }
2020-02-27 16:34:49 +00:00
track [ ' mainArtist ' ] [ ' id ' ] = trackAPI_gw [ ' ART_ID ' ]
track [ ' mainArtist ' ] [ ' name ' ] = trackAPI_gw [ ' ART_NAME ' ]
if ' ART_PICTURE ' in trackAPI_gw :
track [ ' mainArtist ' ] [ ' pic ' ] = trackAPI_gw [ ' ART_PICTURE ' ]
2020-02-20 14:42:12 +00:00
2020-02-27 16:34:49 +00:00
if ' PHYSICAL_RELEASE_DATE ' in trackAPI_gw :
2020-02-20 14:42:12 +00:00
track [ ' date ' ] = {
2020-02-27 16:34:49 +00:00
' day ' : trackAPI_gw [ " PHYSICAL_RELEASE_DATE " ] [ 8 : 10 ] ,
' month ' : trackAPI_gw [ " PHYSICAL_RELEASE_DATE " ] [ 5 : 7 ] ,
' year ' : trackAPI_gw [ " PHYSICAL_RELEASE_DATE " ] [ 0 : 4 ]
2020-02-20 14:42:12 +00:00
}
track [ ' album ' ] = { }
2020-02-27 16:34:49 +00:00
track [ ' album ' ] [ ' id ' ] = trackAPI_gw [ ' ALB_ID ' ]
track [ ' album ' ] [ ' title ' ] = trackAPI_gw [ ' ALB_TITLE ' ]
if ' ALB_PICTURE ' in trackAPI_gw :
track [ ' album ' ] [ ' pic ' ] = trackAPI_gw [ ' ALB_PICTURE ' ]
2020-02-20 14:42:12 +00:00
try :
2020-02-27 16:34:49 +00:00
if not albumAPI :
2020-02-20 14:42:12 +00:00
albumAPI = dz . get_album ( track [ ' album ' ] [ ' id ' ] )
2020-03-20 14:58:25 +00:00
track [ ' album ' ] [ ' mainArtist ' ] = {
2020-02-20 14:42:12 +00:00
' id ' : albumAPI [ ' artist ' ] [ ' id ' ] ,
' name ' : albumAPI [ ' artist ' ] [ ' name ' ] ,
2020-03-01 12:14:37 +00:00
' pic ' : albumAPI [ ' artist ' ] [ ' picture_small ' ] [ albumAPI [ ' artist ' ] [ ' picture_small ' ] . find ( ' artist/ ' ) + 7 : - 24 ]
2020-02-20 14:42:12 +00:00
}
2020-03-20 14:58:25 +00:00
track [ ' album ' ] [ ' artist ' ] = { }
track [ ' album ' ] [ ' artists ' ] = [ ]
for artist in albumAPI [ ' contributors ' ] :
if artist [ ' id ' ] != 5080 :
track [ ' album ' ] [ ' artists ' ] . append ( artist [ ' name ' ] )
if not artist [ ' role ' ] in track [ ' album ' ] [ ' artist ' ] :
track [ ' album ' ] [ ' artist ' ] [ artist [ ' role ' ] ] = [ ]
track [ ' album ' ] [ ' artist ' ] [ artist [ ' role ' ] ] . append ( artist [ ' name ' ] )
2020-02-20 14:42:12 +00:00
track [ ' album ' ] [ ' trackTotal ' ] = albumAPI [ ' nb_tracks ' ]
track [ ' album ' ] [ ' recordType ' ] = albumAPI [ ' record_type ' ]
2020-02-22 13:38:01 +00:00
track [ ' album ' ] [ ' barcode ' ] = albumAPI [ ' upc ' ] if ' upc ' in albumAPI else " Unknown "
track [ ' album ' ] [ ' label ' ] = albumAPI [ ' label ' ] if ' label ' in albumAPI else " Unknown "
2020-02-20 14:42:12 +00:00
if not ' pic ' in track [ ' album ' ] :
2020-03-01 12:14:37 +00:00
track [ ' album ' ] [ ' pic ' ] = albumAPI [ ' cover_small ' ] [ albumAPI [ ' cover_small ' ] . find ( ' cover/ ' ) + 6 : - 24 ]
2020-02-24 17:36:11 +00:00
if ' release_date ' in albumAPI :
track [ ' album ' ] [ ' date ' ] = {
2020-02-20 14:42:12 +00:00
' day ' : albumAPI [ " release_date " ] [ 8 : 10 ] ,
' month ' : albumAPI [ " release_date " ] [ 5 : 7 ] ,
' year ' : albumAPI [ " release_date " ] [ 0 : 4 ]
}
track [ ' album ' ] [ ' discTotal ' ] = albumAPI [ ' nb_disk ' ] if ' nb_disk ' in albumAPI else None
track [ ' copyright ' ] = albumAPI [ ' copyright ' ] if ' copyright ' in albumAPI else None
track [ ' album ' ] [ ' genre ' ] = [ ]
if ' genres ' in albumAPI and ' data ' in albumAPI [ ' genres ' ] and len ( albumAPI [ ' genres ' ] [ ' data ' ] ) > 0 :
for genre in albumAPI [ ' genres ' ] [ ' data ' ] :
track [ ' album ' ] [ ' genre ' ] . append ( genre [ ' name ' ] )
except APIError :
2020-02-27 16:34:49 +00:00
if not albumAPI_gw :
albumAPI_gw = dz . get_album_gw ( track [ ' album ' ] [ ' id ' ] )
2020-03-21 13:55:16 +00:00
track [ ' album ' ] [ ' mainArtist ' ] = {
2020-02-27 16:34:49 +00:00
' id ' : albumAPI_gw [ ' ART_ID ' ] ,
' name ' : albumAPI_gw [ ' ART_NAME ' ]
2020-02-20 14:42:12 +00:00
}
2020-03-21 13:55:16 +00:00
artistAPI = dz . get_artist ( track [ ' album ' ] [ ' mainArtist ' ] [ ' id ' ] )
track [ ' album ' ] [ ' artists ' ] = albumAPI_gw [ ' ART_NAME ' ]
track [ ' album ' ] [ ' mainArtist ' ] [ ' pic ' ] = artistAPI [ ' picture_small ' ] [ artistAPI [ ' picture_small ' ] . find ( ' artist/ ' ) + 7 : - 24 ]
2020-02-27 16:34:49 +00:00
track [ ' album ' ] [ ' trackTotal ' ] = albumAPI_gw [ ' NUMBER_TRACK ' ]
track [ ' album ' ] [ ' discTotal ' ] = albumAPI_gw [ ' NUMBER_DISK ' ]
2020-02-22 14:57:24 +00:00
track [ ' album ' ] [ ' recordType ' ] = " Album "
2020-02-22 13:38:01 +00:00
track [ ' album ' ] [ ' barcode ' ] = " Unknown "
2020-02-27 16:34:49 +00:00
track [ ' album ' ] [ ' label ' ] = albumAPI_gw [ ' LABEL_NAME ' ] if ' LABEL_NAME ' in albumAPI_gw else " Unknown "
2020-02-20 14:42:12 +00:00
if not ' pic ' in track [ ' album ' ] :
2020-02-27 16:34:49 +00:00
track [ ' album ' ] [ ' pic ' ] = albumAPI_gw [ ' ALB_PICTURE ' ]
if ' PHYSICAL_RELEASE_DATE ' in albumAPI_gw :
2020-02-24 17:36:11 +00:00
track [ ' album ' ] [ ' date ' ] = {
2020-02-27 16:34:49 +00:00
' day ' : albumAPI_gw [ " PHYSICAL_RELEASE_DATE " ] [ 8 : 10 ] ,
' month ' : albumAPI_gw [ " PHYSICAL_RELEASE_DATE " ] [ 5 : 7 ] ,
' year ' : albumAPI_gw [ " PHYSICAL_RELEASE_DATE " ] [ 0 : 4 ]
2020-02-20 14:42:12 +00:00
}
track [ ' album ' ] [ ' genre ' ] = [ ]
2020-02-24 17:36:11 +00:00
if ' date ' in track [ ' album ' ] :
track [ ' date ' ] = track [ ' album ' ] [ ' date ' ]
2020-02-27 16:34:49 +00:00
if not trackAPI :
trackAPI = dz . get_track ( track [ ' id ' ] )
track [ ' bpm ' ] = trackAPI [ ' bpm ' ]
2020-02-20 14:42:12 +00:00
if not ' replayGain ' in track :
2020-02-27 16:34:49 +00:00
track [ ' replayGain ' ] = " {0:.2f} dB " . format ( ( float ( trackAPI [ ' gain ' ] ) + 18.4 ) * - 1 ) if ' gain ' in trackAPI else " "
2020-02-20 14:42:12 +00:00
if not ' explicit ' in track :
2020-02-27 16:34:49 +00:00
track [ ' explicit ' ] = trackAPI [ ' explicit_lyrics ' ]
2020-02-22 13:38:01 +00:00
if not ' discNumber ' in track :
2020-02-27 16:34:49 +00:00
track [ ' discNumber ' ] = trackAPI [ ' disk_number ' ]
2020-02-20 14:42:12 +00:00
track [ ' artist ' ] = { }
track [ ' artists ' ] = [ ]
2020-02-27 16:34:49 +00:00
for artist in trackAPI [ ' contributors ' ] :
2020-02-22 14:57:24 +00:00
if artist [ ' id ' ] != 5080 :
track [ ' artists ' ] . append ( artist [ ' name ' ] )
if not artist [ ' role ' ] in track [ ' artist ' ] :
track [ ' artist ' ] [ artist [ ' role ' ] ] = [ ]
track [ ' artist ' ] [ artist [ ' role ' ] ] . append ( artist [ ' name ' ] )
2020-02-20 14:42:12 +00:00
2020-02-22 13:38:01 +00:00
if not ' discTotal ' in track [ ' album ' ] or not track [ ' album ' ] [ ' discTotal ' ] :
2020-02-27 16:34:49 +00:00
if not albumAPI_gw :
albumAPI_gw = dz . get_album_gw ( track [ ' album ' ] [ ' id ' ] )
track [ ' album ' ] [ ' discTotal ' ] = albumAPI_gw [ ' NUMBER_DISK ' ]
2020-02-22 13:38:01 +00:00
if not ' copyright ' in track or not track [ ' copyright ' ] :
2020-02-27 16:34:49 +00:00
if not albumAPI_gw :
albumAPI_gw = dz . get_album_gw ( track [ ' album ' ] [ ' id ' ] )
track [ ' copyright ' ] = albumAPI_gw [ ' COPYRIGHT ' ]
2020-03-20 15:27:58 +00:00
# Fix incorrect day month when detectable
if int ( track [ ' date ' ] [ ' month ' ] ) > 12 :
monthTemp = track [ ' date ' ] [ ' month ' ]
track [ ' date ' ] [ ' month ' ] = track [ ' date ' ] [ ' day ' ]
track [ ' date ' ] [ ' day ' ] = monthTemp
if int ( track [ ' album ' ] [ ' date ' ] [ ' month ' ] ) > 12 :
monthTemp = track [ ' album ' ] [ ' date ' ] [ ' month ' ]
track [ ' album ' ] [ ' date ' ] [ ' month ' ] = track [ ' album ' ] [ ' date ' ] [ ' day ' ]
track [ ' album ' ] [ ' date ' ] [ ' day ' ] = monthTemp
2020-03-21 12:47:34 +00:00
# Remove featuring from the title
track [ ' title_clean ' ] = track [ ' title ' ]
if " (feat. " in track [ ' title_clean ' ] . lower ( ) :
pos = track [ ' title_clean ' ] . lower ( ) . find ( " (feat. " )
tempTrack = track [ ' title_clean ' ] [ : pos ]
if " ) " in track [ ' title_clean ' ] :
tempTrack + = track [ ' title_clean ' ] [ track [ ' title_clean ' ] . find ( " ) " , pos + 1 ) + 1 : ]
track [ ' title_clean ' ] = tempTrack . strip ( )
# Create artists strings
track [ ' mainArtistsString ' ] = " "
2020-03-21 13:55:16 +00:00
if ' Main ' in track [ ' artist ' ] :
tot = len ( track [ ' artist ' ] [ ' Main ' ] )
2020-03-21 12:47:34 +00:00
for i , art in enumerate ( track [ ' artist ' ] [ ' Main ' ] ) :
track [ ' mainArtistsString ' ] + = art
if tot != i + 1 :
if tot - 1 == i + 1 :
track [ ' mainArtistsString ' ] + = " & "
else :
track [ ' mainArtistsString ' ] + = " , "
else :
track [ ' mainArtistsString ' ] = track [ ' mainArtist ' ] [ ' name ' ]
2020-03-21 13:55:16 +00:00
if ' Featured ' in track [ ' artist ' ] :
tot = len ( track [ ' artist ' ] [ ' Featured ' ] )
2020-03-21 12:47:34 +00:00
track [ ' featArtistsString ' ] = " feat. "
for i , art in enumerate ( track [ ' artist ' ] [ ' Featured ' ] ) :
track [ ' featArtistsString ' ] + = art
if tot != i + 1 :
if tot - 1 == i + 1 :
track [ ' featArtistsString ' ] + = " & "
else :
track [ ' featArtistsString ' ] + = " , "
# Create title with feat
if " (feat. " in track [ ' title ' ] . lower ( ) :
track [ ' title_feat ' ] = track [ ' title ' ]
2020-03-21 13:55:16 +00:00
elif ' Featured ' in track [ ' artist ' ] :
2020-03-21 12:47:34 +00:00
track [ ' title_feat ' ] = track [ ' title ' ] + " ( {} ) " . format ( track [ ' featArtistsString ' ] )
else :
track [ ' title_feat ' ] = track [ ' title ' ]
2020-02-20 14:42:12 +00:00
return track
2020-04-15 12:49:40 +00:00
def downloadTrackObj ( dz , trackAPI , settings , bitrate , queueItem , extraTrack = None , interface = None ) :
2020-03-01 12:14:37 +00:00
result = { }
2020-04-11 13:43:59 +00:00
if ' cancel ' in queueItem :
result [ ' cancel ' ] = True
return result
2020-04-15 09:13:55 +00:00
if trackAPI [ ' SNG_ID ' ] == 0 :
result [ ' error ' ] = {
' message ' : " Track not available on Deezer! " ,
}
if ' SNG_TITLE ' in trackAPI :
result [ ' error ' ] [ ' data ' ] = {
' id ' : trackAPI [ ' SNG_ID ' ] ,
' title ' : trackAPI [ ' SNG_TITLE ' ] ,
' mainArtist ' : { ' name ' : trackAPI [ ' ART_NAME ' ] }
}
2020-04-15 12:49:40 +00:00
if interface :
2020-04-15 09:13:55 +00:00
queueItem [ ' failed ' ] + = 1
2020-04-15 12:49:40 +00:00
interface . send ( " updateQueue " , { ' uuid ' : queueItem [ ' uuid ' ] , ' failed ' : True , ' data ' : result [ ' error ' ] [ ' data ' ] , ' error ' : " Track not available on Deezer! " } )
2020-04-15 09:13:55 +00:00
return result
2020-02-20 14:42:12 +00:00
# Get the metadata
2020-02-22 13:38:01 +00:00
if extraTrack :
track = extraTrack
else :
2020-03-02 12:46:48 +00:00
track = getTrackData ( dz ,
2020-02-27 16:34:49 +00:00
trackAPI_gw = trackAPI ,
trackAPI = trackAPI [ ' _EXTRA_TRACK ' ] if ' _EXTRA_TRACK ' in trackAPI else None ,
albumAPI = trackAPI [ ' _EXTRA_ALBUM ' ] if ' _EXTRA_ALBUM ' in trackAPI else None
)
2020-04-11 13:43:59 +00:00
if ' cancel ' in queueItem :
result [ ' cancel ' ] = True
return result
2020-02-20 14:42:12 +00:00
print ( ' Downloading: {} - {} ' . format ( track [ ' mainArtist ' ] [ ' name ' ] , track [ ' title ' ] ) )
2020-03-15 17:48:04 +00:00
if track [ ' MD5 ' ] == ' ' :
if track [ ' fallbackId ' ] != 0 :
2020-03-22 12:57:31 +00:00
print ( " Track not yet encoded, using fallback id " )
2020-03-15 17:48:04 +00:00
trackNew = dz . get_track_gw ( track [ ' fallbackId ' ] )
if not ' MD5_ORIGIN ' in trackNew :
trackNew [ ' MD5_ORIGIN ' ] = dz . get_track_md5 ( trackNew [ ' SNG_ID ' ] )
track = parseEssentialTrackData ( track , trackNew )
2020-04-15 12:49:40 +00:00
return downloadTrackObj ( dz , trackAPI , settings , bitrate , queueItem , extraTrack = track , interface = interface )
2020-03-22 12:57:31 +00:00
elif not ' searched ' in track and settings [ ' fallbackSearch ' ] :
print ( " Track not yet encoded, searching for alternative " )
2020-03-30 09:59:18 +00:00
searchedId = dz . get_track_from_metadata ( track [ ' mainArtist ' ] [ ' name ' ] , track [ ' title ' ] , track [ ' album ' ] [ ' title ' ] )
2020-03-22 12:57:31 +00:00
if searchedId != 0 :
trackNew = dz . get_track_gw ( searchedId )
if not ' MD5_ORIGIN ' in trackNew :
trackNew [ ' MD5_ORIGIN ' ] = dz . get_track_md5 ( trackNew [ ' SNG_ID ' ] )
track = parseEssentialTrackData ( track , trackNew )
track [ ' searched ' ] = True
2020-04-15 12:49:40 +00:00
return downloadTrackObj ( dz , trackAPI , settings , bitrate , queueItem , extraTrack = track , interface = interface )
2020-03-22 12:57:31 +00:00
else :
print ( " ERROR: Track not yet encoded and no alternative found! " )
result [ ' error ' ] = {
' message ' : " Track not yet encoded and no alternative found! " ,
' data ' : track
}
2020-04-15 12:49:40 +00:00
if interface :
2020-04-14 10:58:31 +00:00
queueItem [ ' failed ' ] + = 1
2020-04-15 12:49:40 +00:00
interface . send ( " updateQueue " , { ' uuid ' : queueItem [ ' uuid ' ] , ' failed ' : True , ' data ' : track , ' error ' : " Track not yet encoded and no alternative found! " } )
2020-03-22 12:57:31 +00:00
return result
2020-03-15 17:48:04 +00:00
else :
print ( " ERROR: Track not yet encoded! " )
2020-03-21 13:55:16 +00:00
result [ ' error ' ] = {
' message ' : " Track not yet encoded! " ,
' data ' : track
}
2020-04-15 12:49:40 +00:00
if interface :
2020-04-14 10:58:31 +00:00
queueItem [ ' failed ' ] + = 1
2020-04-15 12:49:40 +00:00
interface . send ( " updateQueue " , { ' uuid ' : queueItem [ ' uuid ' ] , ' failed ' : True , ' data ' : track , ' error ' : " Track not yet encoded! " } )
2020-03-15 18:18:52 +00:00
return result
2020-02-20 14:42:12 +00:00
# Get the selected bitrate
2020-03-21 20:13:29 +00:00
( format , filesize ) = getPreferredBitrate ( track [ ' filesize ' ] , bitrate , settings [ ' fallbackBitrate ' ] )
if format == - 100 :
print ( " ERROR: Track not found at desired bitrate. Enable fallback to lower bitrates to fix this issue. " )
result [ ' error ' ] = {
' message ' : " Track not found at desired bitrate. " ,
' data ' : track
}
2020-04-15 12:49:40 +00:00
if interface :
2020-04-14 10:58:31 +00:00
queueItem [ ' failed ' ] + = 1
2020-04-15 12:49:40 +00:00
interface . send ( " updateQueue " , { ' uuid ' : queueItem [ ' uuid ' ] , ' failed ' : True , ' data ' : track , ' error ' : " Track not found at desired bitrate. " } )
2020-03-21 20:13:29 +00:00
return result
elif format == - 200 :
print ( " ERROR: This track is not available in 360 Reality Audio format. Please select another format. " )
result [ ' error ' ] = {
' message ' : " Track is not available in Reality Audio 360. " ,
' data ' : track
}
2020-04-15 12:49:40 +00:00
if interface :
2020-04-14 10:58:31 +00:00
queueItem [ ' failed ' ] + = 1
2020-04-15 12:49:40 +00:00
interface . send ( " updateQueue " , { ' uuid ' : queueItem [ ' uuid ' ] , ' failed ' : True , ' data ' : track , ' error ' : " Track is not available in Reality Audio 360. " } )
2020-03-21 20:13:29 +00:00
return result
2020-02-24 17:36:11 +00:00
track [ ' selectedFormat ' ] = format
track [ ' selectedFilesize ' ] = filesize
track [ ' album ' ] [ ' bitrate ' ] = format
2020-02-29 20:57:35 +00:00
track [ ' album ' ] [ ' picUrl ' ] = " https://e-cdns-images.dzcdn.net/images/cover/ {} / {} x {} -000000-80-0-0. {} " . format ( track [ ' album ' ] [ ' pic ' ] , settings [ ' embeddedArtworkSize ' ] , settings [ ' embeddedArtworkSize ' ] , ' png ' if settings [ ' PNGcovers ' ] else ' jpg ' )
2020-03-20 15:27:58 +00:00
track [ ' dateString ' ] = formatDate ( track [ ' date ' ] , settings [ ' dateFormat ' ] )
track [ ' album ' ] [ ' dateString ' ] = formatDate ( track [ ' album ' ] [ ' date ' ] , settings [ ' dateFormat ' ] )
2020-02-27 17:37:40 +00:00
2020-03-22 16:02:33 +00:00
# Check if user wants the feat in the title
# 0 => do not change
# 1 => remove from title
# 2 => add to title
if settings [ ' featuredToTitle ' ] == " 1 " :
track [ ' title ' ] = track [ ' title_clean ' ]
elif settings [ ' featuredToTitle ' ] == " 2 " :
track [ ' title ' ] = track [ ' title_feat ' ]
2020-03-22 15:52:17 +00:00
# Remove (Album Version) from tracks that have that
if settings [ ' removeAlbumVersion ' ] :
if " Album Version " in track [ ' title ' ] :
track [ ' title ' ] = re . sub ( r ' ? \ (Album Version \ ) ' , " " , track [ ' title ' ] ) . strip ( )
2020-03-30 09:59:18 +00:00
# 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 " :
2020-03-31 12:37:45 +00:00
track [ ' title ' ] = changeCase ( track [ ' title ' ] , settings [ ' titleCasing ' ] )
2020-03-30 09:59:18 +00:00
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 ' ] )
2020-02-27 17:37:40 +00:00
# Generate filename and filepath from metadata
2020-02-29 20:22:44 +00:00
filename = generateFilename ( track , trackAPI , settings )
2020-02-24 17:36:11 +00:00
( filepath , artistPath , coverPath , extrasPath ) = generateFilepath ( track , trackAPI , settings )
2020-04-11 13:43:59 +00:00
if ' cancel ' in queueItem :
result [ ' cancel ' ] = True
return result
2020-02-27 17:37:40 +00:00
# Download and cache coverart
2020-02-27 17:46:32 +00:00
track [ ' album ' ] [ ' picPath ' ] = os . path . join ( TEMPDIR , f " alb { track [ ' album ' ] [ ' id ' ] } _ { settings [ ' embeddedArtworkSize ' ] } . { ' png ' if settings [ ' PNGcovers ' ] else ' jpg ' } " )
2020-03-01 12:14:37 +00:00
track [ ' album ' ] [ ' picPath ' ] = downloadImage ( track [ ' album ' ] [ ' picUrl ' ] , track [ ' album ' ] [ ' picPath ' ] )
2020-02-27 17:37:40 +00:00
2020-04-13 17:22:34 +00:00
if os . path . sep in filename :
tempPath = filename [ : filename . rfind ( os . path . sep ) ]
filepath = os . path . join ( filepath , tempPath )
filename = filename [ filename . rfind ( os . path . sep ) + len ( os . path . sep ) : ]
2020-02-24 17:36:11 +00:00
makedirs ( filepath , exist_ok = True )
2020-02-29 20:22:44 +00:00
writepath = os . path . join ( filepath , filename + extensions [ track [ ' selectedFormat ' ] ] )
# Save lyrics in lrc file
if settings [ ' syncedLyrics ' ] and ' sync ' in track [ ' lyrics ' ] :
with open ( os . path . join ( filepath , filename + ' .lrc ' ) , ' w ' ) as f :
f . write ( track [ ' lyrics ' ] [ ' sync ' ] )
2020-02-20 14:42:12 +00:00
2020-02-29 20:42:21 +00:00
# Save local album art
if coverPath :
2020-03-01 12:14:37 +00:00
result [ ' albumURL ' ] = track [ ' album ' ] [ ' picUrl ' ] . replace ( f " { settings [ ' embeddedArtworkSize ' ] } x { settings [ ' embeddedArtworkSize ' ] } " , f " { settings [ ' localArtworkSize ' ] } x { settings [ ' localArtworkSize ' ] } " )
result [ ' albumPath ' ] = os . path . join ( coverPath , f " { settingsRegexAlbum ( settings [ ' coverImageTemplate ' ] , track [ ' album ' ] , settings ) } . { ' png ' if settings [ ' PNGcovers ' ] else ' jpg ' } " )
2020-02-29 20:42:21 +00:00
# Save artist art
if artistPath :
2020-04-13 16:35:29 +00:00
result [ ' artistURL ' ] = " https://e-cdns-images.dzcdn.net/images/artist/ {} / {} x {} -000000-80-0-0. {} " . format ( track [ ' album ' ] [ ' mainArtist ' ] [ ' pic ' ] , settings [ ' localArtworkSize ' ] , settings [ ' localArtworkSize ' ] , ' png ' if settings [ ' PNGcovers ' ] else ' jpg ' )
result [ ' artistPath ' ] = os . path . join ( artistPath , f " { settingsRegexArtist ( settings [ ' artistImageTemplate ' ] , track [ ' album ' ] [ ' mainArtist ' ] , settings ) } . { ' png ' if settings [ ' PNGcovers ' ] else ' jpg ' } " )
2020-02-20 14:42:12 +00:00
2020-03-01 10:48:08 +00:00
# Data for m3u file
if extrasPath :
2020-03-01 12:14:37 +00:00
result [ ' extrasPath ' ] = extrasPath
result [ ' playlistPosition ' ] = writepath [ len ( extrasPath ) : ]
2020-03-01 10:48:08 +00:00
2020-02-24 17:36:11 +00:00
track [ ' downloadUrl ' ] = dz . get_track_stream_url ( track [ ' id ' ] , track [ ' MD5 ' ] , track [ ' mediaVersion ' ] , track [ ' selectedFormat ' ] )
2020-03-01 12:14:37 +00:00
try :
with open ( writepath , ' wb ' ) as stream :
2020-04-15 12:49:40 +00:00
stream_track ( dz , track , stream , trackAPI , queueItem , interface )
2020-04-11 13:43:59 +00:00
except downloadCancelled :
remove ( writepath )
result [ ' cancel ' ] = True
return result
2020-03-01 12:14:37 +00:00
except HTTPError :
2020-03-01 20:48:57 +00:00
remove ( writepath )
2020-03-21 20:13:29 +00:00
if track [ ' selectedFormat ' ] == 9 and settings [ ' fallbackBitrate ' ] :
2020-03-01 12:14:37 +00:00
print ( " Track not available in flac, trying mp3 " )
track [ ' filesize ' ] [ ' flac ' ] = 0
2020-04-15 12:49:40 +00:00
return downloadTrackObj ( dz , trackAPI , settings , bitrate , queueItem , extraTrack = track , interface = interface )
2020-03-01 12:14:37 +00:00
elif track [ ' fallbackId ' ] != 0 :
print ( " Track not available, using fallback id " )
trackNew = dz . get_track_gw ( track [ ' fallbackId ' ] )
if not ' MD5_ORIGIN ' in trackNew :
trackNew [ ' MD5_ORIGIN ' ] = dz . get_track_md5 ( trackNew [ ' SNG_ID ' ] )
track = parseEssentialTrackData ( track , trackNew )
2020-04-15 12:49:40 +00:00
return downloadTrackObj ( dz , trackAPI , settings , bitrate , queueItem , extraTrack = track , interface = interface )
2020-03-22 12:57:31 +00:00
elif not ' searched ' in track and settings [ ' fallbackSearch ' ] :
print ( " Track not available, searching for alternative " )
2020-03-30 09:59:18 +00:00
searchedId = dz . get_track_from_metadata ( track [ ' mainArtist ' ] [ ' name ' ] , track [ ' title ' ] , track [ ' album ' ] [ ' title ' ] )
2020-03-22 12:57:31 +00:00
if searchedId != 0 :
trackNew = dz . get_track_gw ( searchedId )
if not ' MD5_ORIGIN ' in trackNew :
trackNew [ ' MD5_ORIGIN ' ] = dz . get_track_md5 ( trackNew [ ' SNG_ID ' ] )
track = parseEssentialTrackData ( track , trackNew )
track [ ' searched ' ] = True
2020-04-15 12:49:40 +00:00
return downloadTrackObj ( dz , trackAPI , settings , bitrate , queueItem , extraTrack = track , interface = interface )
2020-03-22 12:57:31 +00:00
else :
print ( " ERROR: Track not available on deezer ' s servers and no alternative found! " )
result [ ' error ' ] = {
' message ' : " Track not available on deezer ' s servers and no alternative found! " ,
' data ' : track
}
2020-04-15 12:49:40 +00:00
if interface :
2020-04-14 10:58:31 +00:00
queueItem [ ' failed ' ] + = 1
2020-04-15 12:49:40 +00:00
interface . send ( " updateQueue " , { ' uuid ' : queueItem [ ' uuid ' ] , ' failed ' : True , ' data ' : track , ' error ' : " Track not available on deezer ' s servers and no alternative found! " } )
2020-03-22 12:57:31 +00:00
return result
2020-03-01 12:14:37 +00:00
else :
print ( " ERROR: Track not available on deezer ' s servers! " )
2020-03-21 13:55:16 +00:00
result [ ' error ' ] = {
' message ' : " Track not available on deezer ' s servers! " ,
' data ' : track
}
2020-04-15 12:49:40 +00:00
if interface :
2020-04-14 10:58:31 +00:00
queueItem [ ' failed ' ] + = 1
2020-04-15 12:49:40 +00:00
interface . send ( " updateQueue " , { ' uuid ' : queueItem [ ' uuid ' ] , ' failed ' : True , ' data ' : track , ' error ' : " Track not available on deezer ' s servers! " } )
2020-03-15 18:18:52 +00:00
return result
2020-02-20 14:42:12 +00:00
if track [ ' selectedFormat ' ] in [ 3 , 1 , 8 ] :
2020-03-30 09:59:18 +00:00
tagID3 ( writepath , track , settings [ ' tags ' ] )
2020-02-20 14:42:12 +00:00
elif track [ ' selectedFormat ' ] == 9 :
2020-02-22 11:59:42 +00:00
tagFLAC ( writepath , track , settings [ ' tags ' ] )
2020-03-22 12:57:31 +00:00
if ' searched ' in track :
result [ ' searched ' ] = f ' { track [ " mainArtist " ] [ " name " ] } - { track [ " title " ] } '
2020-02-22 13:38:01 +00:00
print ( " Done! " )
2020-04-15 12:49:40 +00:00
if interface :
2020-04-14 10:58:31 +00:00
queueItem [ ' downloaded ' ] + = 1
2020-04-15 12:49:40 +00:00
interface . send ( " updateQueue " , { ' uuid ' : queueItem [ ' uuid ' ] , ' downloaded ' : True } )
2020-03-01 10:48:08 +00:00
return result
2020-02-20 14:42:12 +00:00
2020-04-15 12:49:40 +00:00
def downloadTrackObj_wrap ( dz , track , settings , bitrate , queueItem , interface ) :
2020-04-12 07:50:49 +00:00
try :
2020-04-15 12:49:40 +00:00
result = downloadTrackObj ( dz , track , settings , bitrate , queueItem , interface = interface )
2020-04-12 07:50:49 +00:00
except Exception as e :
result = { ' error ' : {
2020-04-12 09:54:33 +00:00
' message ' : str ( e ) ,
' data ' : {
' id ' : track [ ' SNG_ID ' ] ,
' title ' : track [ ' SNG_TITLE ' ] + ( " " + track [ ' VERSION ' ] if ' VERSION ' in track and track [ ' VERSION ' ] else " " ) ,
' mainArtist ' : { ' name ' : track [ ' ART_NAME ' ] }
}
2020-04-12 07:50:49 +00:00
}
}
2020-04-15 12:49:40 +00:00
if interface :
2020-04-14 10:58:31 +00:00
queueItem [ ' failed ' ] + = 1
2020-04-15 12:49:40 +00:00
interface . send ( " updateQueue " , { ' uuid ' : queueItem [ ' uuid ' ] , ' failed ' : True } )
2020-04-12 07:50:49 +00:00
return result
2020-04-15 12:49:40 +00:00
def download ( dz , queueItem , interface = None ) :
2020-04-10 22:21:30 +00:00
global downloadPercentage , lastPercentage
2020-04-10 14:12:21 +00:00
settings = queueItem [ ' settings ' ]
bitrate = queueItem [ ' bitrate ' ]
2020-04-10 22:21:30 +00:00
downloadPercentage = 0
lastPercentage = 0
2020-04-10 14:12:21 +00:00
if ' single ' in queueItem :
2020-04-12 07:50:49 +00:00
try :
2020-04-15 12:49:40 +00:00
result = downloadTrackObj ( dz , queueItem [ ' single ' ] , settings , bitrate , queueItem , interface = interface )
2020-04-12 07:50:49 +00:00
except Exception as e :
result = { ' error ' : {
2020-04-12 09:54:33 +00:00
' message ' : str ( e ) ,
' data ' : {
2020-04-13 17:22:34 +00:00
' id ' : queueItem [ ' single ' ] [ ' SNG_ID ' ] ,
' title ' : queueItem [ ' single ' ] [ ' SNG_TITLE ' ] + ( " " + queueItem [ ' single ' ] [ ' VERSION ' ] if ' VERSION ' in queueItem [ ' single ' ] and queueItem [ ' single ' ] [ ' VERSION ' ] else " " ) ,
' mainArtist ' : { ' name ' : queueItem [ ' single ' ] [ ' ART_NAME ' ] }
2020-04-12 09:54:33 +00:00
}
2020-04-12 07:50:49 +00:00
}
}
2020-04-15 12:49:40 +00:00
if interface :
2020-04-14 10:58:31 +00:00
queueItem [ ' failed ' ] + = 1
2020-04-15 12:49:40 +00:00
interface . send ( " updateQueue " , { ' uuid ' : queueItem [ ' uuid ' ] , ' failed ' : True } )
2020-04-12 12:12:43 +00:00
download_path = after_download_single ( result , settings , queueItem )
2020-04-10 14:12:21 +00:00
elif ' collection ' in queueItem :
print ( " Downloading collection " )
playlist = [ None ] * len ( queueItem [ ' collection ' ] )
with ThreadPoolExecutor ( settings [ ' queueConcurrency ' ] ) as executor :
for pos , track in enumerate ( queueItem [ ' collection ' ] , start = 0 ) :
2020-04-15 12:49:40 +00:00
playlist [ pos ] = executor . submit ( downloadTrackObj_wrap , dz , track , settings , bitrate , queueItem , interface = interface )
2020-04-12 12:12:43 +00:00
download_path = after_download ( playlist , settings , queueItem )
2020-04-15 12:49:40 +00:00
if interface :
2020-04-11 13:43:59 +00:00
if ' cancel ' in queueItem :
2020-04-15 12:49:40 +00:00
interface . send ( ' toast ' , { ' msg ' : " Current item cancelled. " , ' icon ' : ' done ' , ' dismiss ' : True , ' id ' : ' cancelling_ ' + queueItem [ ' uuid ' ] } )
interface . send ( " removedFromQueue " , queueItem [ ' uuid ' ] )
2020-04-11 13:43:59 +00:00
else :
2020-04-15 12:49:40 +00:00
interface . send ( " finishDownload " , queueItem [ ' uuid ' ] )
2020-04-10 14:12:21 +00:00
return {
' dz ' : dz ,
2020-04-15 12:49:40 +00:00
' interface ' : interface ,
2020-04-10 14:12:21 +00:00
' download_path ' : download_path
}
2020-04-12 12:12:43 +00:00
def after_download ( tracks , settings , queueItem ) :
2020-03-21 13:55:16 +00:00
extrasPath = None
playlist = [ None ] * len ( tracks )
errors = " "
2020-03-22 12:57:31 +00:00
searched = " "
2020-03-21 13:55:16 +00:00
for index in range ( len ( tracks ) ) :
result = tracks [ index ] . result ( )
2020-04-11 13:43:59 +00:00
if ' cancel ' in result :
return None
2020-03-21 13:55:16 +00:00
if ' error ' in result :
2020-04-15 09:13:55 +00:00
if not ' data ' in result [ ' error ' ] :
result [ ' error ' ] [ ' data ' ] = { ' id ' : 0 , ' title ' : ' Unknown ' , ' mainArtist ' : { ' name ' : ' Unknown ' } }
2020-03-21 13:55:16 +00:00
errors + = f " { result [ ' error ' ] [ ' data ' ] [ ' id ' ] } | { result [ ' error ' ] [ ' data ' ] [ ' mainArtist ' ] [ ' name ' ] } - { result [ ' error ' ] [ ' data ' ] [ ' title ' ] } | { result [ ' error ' ] [ ' message ' ] } \r \n "
2020-03-22 12:57:31 +00:00
if ' searched ' in result :
searched + = result [ ' searched ' ] + " \r \n "
2020-03-21 13:55:16 +00:00
if not extrasPath and ' extrasPath ' in result :
extrasPath = result [ ' extrasPath ' ]
2020-04-13 16:35:29 +00:00
if settings [ ' saveArtwork ' ] and ' albumPath ' in result :
2020-03-21 13:55:16 +00:00
downloadImage ( result [ ' albumURL ' ] , result [ ' albumPath ' ] )
2020-04-13 16:35:29 +00:00
if settings [ ' saveArtworkArtist ' ] and ' artistPath ' in result :
2020-03-21 13:55:16 +00:00
downloadImage ( result [ ' artistURL ' ] , result [ ' artistPath ' ] )
if ' playlistPosition ' in result :
playlist [ index ] = result [ ' playlistPosition ' ]
else :
playlist [ index ] = " "
2020-04-12 12:12:43 +00:00
if not extrasPath :
extrasPath = settings [ ' downloadLocation ' ]
if settings [ ' logErrors ' ] and errors != " " :
2020-03-21 13:55:16 +00:00
with open ( os . path . join ( extrasPath , ' errors.txt ' ) , ' w ' ) as f :
f . write ( errors )
2020-04-12 12:12:43 +00:00
if settings [ ' logSearched ' ] and searched != " " :
2020-03-22 12:57:31 +00:00
with open ( os . path . join ( extrasPath , ' searched.txt ' ) , ' w ' ) as f :
f . write ( searched )
2020-04-12 12:12:43 +00:00
if settings [ ' createM3U8File ' ] :
2020-03-21 13:55:16 +00:00
with open ( os . path . join ( extrasPath , ' playlist.m3u8 ' ) , ' w ' ) as f :
for line in playlist :
f . write ( line + " \n " )
2020-04-14 12:23:45 +00:00
if settings [ ' executeCommand ' ] != " " :
execute ( settings [ ' executeCommand ' ] . replace ( " %f older % " , extrasPath ) )
2020-04-14 14:48:13 +00:00
return extrasPath
2020-03-21 13:55:16 +00:00
2020-04-12 12:12:43 +00:00
def after_download_single ( track , settings , queueItem ) :
2020-04-11 13:43:59 +00:00
if ' cancel ' in track :
return None
2020-04-12 12:12:43 +00:00
if ' extrasPath ' not in track :
track [ ' extrasPath ' ] = settings [ ' downloadLocation ' ]
if settings [ ' logSearched ' ] and ' searched ' in track :
2020-03-22 15:52:17 +00:00
with open ( os . path . join ( track [ ' extrasPath ' ] , ' searched.txt ' ) , ' w+ ' ) as f :
2020-03-22 12:57:31 +00:00
orig = f . read ( )
2020-03-22 15:52:17 +00:00
if not track [ ' searched ' ] in orig :
2020-03-22 12:57:31 +00:00
if orig != " " :
orig + = " \r \n "
2020-03-22 15:52:17 +00:00
orig + = track [ ' searched ' ] + " \r \n "
2020-03-22 12:57:31 +00:00
f . write ( orig )
2020-04-14 12:23:45 +00:00
if settings [ ' executeCommand ' ] != " " :
execute ( settings [ ' executeCommand ' ] . replace ( " %f older % " , track [ ' extrasPath ' ] ) )
2020-04-12 12:12:43 +00:00
return track [ ' extrasPath ' ]
2020-04-11 13:43:59 +00:00
class downloadCancelled ( Exception ) :
""" Base class for exceptions in this module. """
pass