version parity
This commit is contained in:
@ -1,5 +1,3 @@
|
||||
from deezer.gw import LyricsStatus
|
||||
|
||||
from deemix.utils import removeDuplicateArtists, removeFeatures
|
||||
from deemix.types.Artist import Artist
|
||||
from deemix.types.Date import Date
|
||||
@ -30,7 +28,7 @@ class Album:
|
||||
self.rootArtist = None
|
||||
self.variousArtists = None
|
||||
|
||||
self.playlistId = None
|
||||
self.playlistID = None
|
||||
self.owner = None
|
||||
self.isPlaylist = False
|
||||
|
||||
@ -39,8 +37,9 @@ class Album:
|
||||
|
||||
# Getting artist image ID
|
||||
# ex: https://e-cdns-images.dzcdn.net/images/artist/f2bc007e9133c946ac3c3907ddc5d2ea/56x56-000000-80-0-0.jpg
|
||||
art_pic = albumAPI['artist']['picture_small']
|
||||
art_pic = art_pic[art_pic.find('artist/') + 7:-24]
|
||||
art_pic = albumAPI['artist'].get('picture_small')
|
||||
if art_pic: art_pic = art_pic[art_pic.find('artist/') + 7:-24]
|
||||
else: art_pic = ""
|
||||
self.mainArtist = Artist(
|
||||
albumAPI['artist']['id'],
|
||||
albumAPI['artist']['name'],
|
||||
@ -83,52 +82,31 @@ class Album:
|
||||
self.barcode = albumAPI.get('upc', self.barcode)
|
||||
self.label = albumAPI.get('label', self.label)
|
||||
self.explicit = bool(albumAPI.get('explicit_lyrics', False))
|
||||
if 'release_date' in albumAPI:
|
||||
self.date.day = albumAPI["release_date"][8:10]
|
||||
self.date.month = albumAPI["release_date"][5:7]
|
||||
self.date.year = albumAPI["release_date"][0:4]
|
||||
release_date = albumAPI.get('release_date')
|
||||
if 'physical_release_date' in albumAPI:
|
||||
release_date = albumAPI['physical_release_date']
|
||||
if release_date:
|
||||
self.date.day = release_date[8:10]
|
||||
self.date.month = release_date[5:7]
|
||||
self.date.year = release_date[0:4]
|
||||
self.date.fixDayMonth()
|
||||
|
||||
self.discTotal = albumAPI.get('nb_disk')
|
||||
self.copyright = albumAPI.get('copyright')
|
||||
|
||||
if self.pic.md5 == "" and albumAPI.get('cover_small'):
|
||||
# Getting album cover MD5
|
||||
# ex: https://e-cdns-images.dzcdn.net/images/cover/2e018122cb56986277102d2041a592c8/56x56-000000-80-0-0.jpg
|
||||
alb_pic = albumAPI['cover_small']
|
||||
self.pic.md5 = alb_pic[alb_pic.find('cover/') + 6:-24]
|
||||
if self.pic.md5 == "":
|
||||
if albumAPI.get('md5_image'):
|
||||
self.pic.md5 = albumAPI['md5_image']
|
||||
elif albumAPI.get('cover_small'):
|
||||
# Getting album cover MD5
|
||||
# ex: https://e-cdns-images.dzcdn.net/images/cover/2e018122cb56986277102d2041a592c8/56x56-000000-80-0-0.jpg
|
||||
alb_pic = albumAPI['cover_small']
|
||||
self.pic.md5 = alb_pic[alb_pic.find('cover/') + 6:-24]
|
||||
|
||||
if albumAPI.get('genres') and len(albumAPI['genres'].get('data', [])) > 0:
|
||||
for genre in albumAPI['genres']['data']:
|
||||
self.genre.append(genre['name'])
|
||||
|
||||
def parseAlbumGW(self, albumAPI_gw):
|
||||
self.title = albumAPI_gw['ALB_TITLE']
|
||||
self.mainArtist = Artist(
|
||||
art_id = albumAPI_gw['ART_ID'],
|
||||
name = albumAPI_gw['ART_NAME'],
|
||||
role = "Main"
|
||||
)
|
||||
|
||||
self.artists = [albumAPI_gw['ART_NAME']]
|
||||
self.trackTotal = albumAPI_gw['NUMBER_TRACK']
|
||||
self.discTotal = albumAPI_gw['NUMBER_DISK']
|
||||
self.label = albumAPI_gw.get('LABEL_NAME', self.label)
|
||||
|
||||
explicitLyricsStatus = albumAPI_gw.get('EXPLICIT_ALBUM_CONTENT', {}).get('EXPLICIT_LYRICS_STATUS', LyricsStatus.UNKNOWN)
|
||||
self.explicit = explicitLyricsStatus in [LyricsStatus.EXPLICIT, LyricsStatus.PARTIALLY_EXPLICIT]
|
||||
|
||||
self.addExtraAlbumGWData(albumAPI_gw)
|
||||
|
||||
def addExtraAlbumGWData(self, albumAPI_gw):
|
||||
if self.pic.md5 == "" and albumAPI_gw.get('ALB_PICTURE'):
|
||||
self.pic.md5 = albumAPI_gw['ALB_PICTURE']
|
||||
if 'PHYSICAL_RELEASE_DATE' in albumAPI_gw:
|
||||
self.date.day = albumAPI_gw["PHYSICAL_RELEASE_DATE"][8:10]
|
||||
self.date.month = albumAPI_gw["PHYSICAL_RELEASE_DATE"][5:7]
|
||||
self.date.year = albumAPI_gw["PHYSICAL_RELEASE_DATE"][0:4]
|
||||
self.date.fixDayMonth()
|
||||
|
||||
def makePlaylistCompilation(self, playlist):
|
||||
self.variousArtists = playlist.variousArtists
|
||||
self.mainArtist = playlist.mainArtist
|
||||
|
@ -1,9 +1,9 @@
|
||||
from time import sleep
|
||||
import re
|
||||
import requests
|
||||
from datetime import datetime
|
||||
|
||||
from deezer.utils import map_track, map_album
|
||||
from deezer.errors import APIError, GWAPIError
|
||||
from deemix.errors import TrackError, NoDataToParse, AlbumDoesntExists
|
||||
from deemix.errors import NoDataToParse, AlbumDoesntExists
|
||||
|
||||
from deemix.utils import removeFeatures, andCommaConcat, removeDuplicateArtists, generateReplayGainString, changeCase
|
||||
|
||||
@ -24,8 +24,10 @@ class Track:
|
||||
self.MD5 = ""
|
||||
self.mediaVersion = ""
|
||||
self.trackToken = ""
|
||||
self.trackTokenExpiration = 0
|
||||
self.duration = 0
|
||||
self.fallbackID = "0"
|
||||
self.albumsFallback = []
|
||||
self.filesizes = {}
|
||||
self.local = False
|
||||
self.mainArtist = None
|
||||
@ -42,6 +44,7 @@ class Track:
|
||||
self.explicit = False
|
||||
self.ISRC = ""
|
||||
self.replayGain = ""
|
||||
self.rank = 0
|
||||
self.playlist = None
|
||||
self.position = None
|
||||
self.searched = False
|
||||
@ -53,79 +56,54 @@ class Track:
|
||||
self.featArtistsString = ""
|
||||
self.urls = {}
|
||||
|
||||
def parseEssentialData(self, trackAPI_gw, trackAPI=None):
|
||||
self.id = str(trackAPI_gw['SNG_ID'])
|
||||
self.duration = trackAPI_gw['DURATION']
|
||||
self.trackToken = trackAPI_gw['TRACK_TOKEN']
|
||||
self.MD5 = trackAPI_gw.get('MD5_ORIGIN')
|
||||
if not self.MD5:
|
||||
if trackAPI and trackAPI.get('md5_origin'):
|
||||
self.MD5 = trackAPI['md5_origin']
|
||||
#else:
|
||||
# raise MD5NotFound
|
||||
self.mediaVersion = trackAPI_gw['MEDIA_VERSION']
|
||||
def parseEssentialData(self, trackAPI):
|
||||
self.id = str(trackAPI['id'])
|
||||
self.duration = trackAPI['duration']
|
||||
self.trackToken = trackAPI['track_token']
|
||||
self.trackTokenExpiration = trackAPI['track_token_expire']
|
||||
self.MD5 = trackAPI.get('md5_origin')
|
||||
self.mediaVersion = trackAPI['media_version']
|
||||
self.fallbackID = "0"
|
||||
if 'FALLBACK' in trackAPI_gw:
|
||||
self.fallbackID = trackAPI_gw['FALLBACK']['SNG_ID']
|
||||
if 'fallback_id' in trackAPI:
|
||||
self.fallbackID = trackAPI['fallback_id']
|
||||
self.local = int(self.id) < 0
|
||||
self.urls = {}
|
||||
|
||||
def retriveFilesizes(self, dz):
|
||||
guest_sid = dz.session.cookies.get('sid')
|
||||
try:
|
||||
site = requests.post(
|
||||
"https://api.deezer.com/1.0/gateway.php",
|
||||
params={
|
||||
'api_key': "4VCYIJUCDLOUELGD1V8WBVYBNVDYOXEWSLLZDONGBBDFVXTZJRXPR29JRLQFO6ZE",
|
||||
'sid': guest_sid,
|
||||
'input': '3',
|
||||
'output': '3',
|
||||
'method': 'song_getData'
|
||||
},
|
||||
timeout=30,
|
||||
json={'sng_id': self.id},
|
||||
headers=dz.http_headers
|
||||
)
|
||||
result_json = site.json()
|
||||
except:
|
||||
sleep(2)
|
||||
self.retriveFilesizes(dz)
|
||||
if len(result_json['error']):
|
||||
raise TrackError(result_json.dumps(result_json['error']))
|
||||
response = result_json.get("results", {})
|
||||
filesizes = {}
|
||||
for key, value in response.items():
|
||||
if key.startswith("FILESIZE_"):
|
||||
filesizes[key] = int(value)
|
||||
filesizes[key+"_TESTED"] = False
|
||||
self.filesizes = filesizes
|
||||
def parseData(self, dz, track_id=None, trackAPI=None, albumAPI=None, playlistAPI=None):
|
||||
if track_id and (not trackAPI or trackAPI and not trackAPI.get('track_token')):
|
||||
trackAPI_new = dz.gw.get_track_with_fallback(track_id)
|
||||
trackAPI_new = map_track(trackAPI_new)
|
||||
if not trackAPI: trackAPI = {}
|
||||
trackAPI_new.update(trackAPI)
|
||||
trackAPI = trackAPI_new
|
||||
elif not trackAPI: raise NoDataToParse
|
||||
|
||||
def parseData(self, dz, track_id=None, trackAPI_gw=None, trackAPI=None, albumAPI_gw=None, albumAPI=None, playlistAPI=None):
|
||||
if track_id and not trackAPI_gw: trackAPI_gw = dz.gw.get_track_with_fallback(track_id)
|
||||
elif not trackAPI_gw: raise NoDataToParse
|
||||
if not trackAPI:
|
||||
try: trackAPI = dz.api.get_track(trackAPI_gw['SNG_ID'])
|
||||
except APIError: trackAPI = None
|
||||
self.parseEssentialData(trackAPI)
|
||||
|
||||
self.parseEssentialData(trackAPI_gw, trackAPI)
|
||||
# only public api has bpm
|
||||
if not trackAPI.get('bpm') and not self.local:
|
||||
try:
|
||||
trackAPI_new = dz.api.get_track(trackAPI['id'])
|
||||
trackAPI_new['release_date'] = trackAPI['release_date']
|
||||
trackAPI.update(trackAPI_new)
|
||||
except APIError: pass
|
||||
|
||||
if self.local:
|
||||
self.parseLocalTrackData(trackAPI_gw)
|
||||
self.parseLocalTrackData(trackAPI)
|
||||
else:
|
||||
self.retriveFilesizes(dz)
|
||||
self.parseTrackGW(trackAPI_gw)
|
||||
self.parseTrack(trackAPI)
|
||||
|
||||
# Get Lyrics data
|
||||
if not "LYRICS" in trackAPI_gw and self.lyrics.id != "0":
|
||||
try: trackAPI_gw["LYRICS"] = dz.gw.get_track_lyrics(self.id)
|
||||
if not trackAPI.get("lyrics") and self.lyrics.id != "0":
|
||||
try: trackAPI["lyrics"] = dz.gw.get_track_lyrics(self.id)
|
||||
except GWAPIError: self.lyrics.id = "0"
|
||||
if self.lyrics.id != "0": self.lyrics.parseLyrics(trackAPI_gw["LYRICS"])
|
||||
if self.lyrics.id != "0": self.lyrics.parseLyrics(trackAPI["lyrics"])
|
||||
|
||||
# Parse Album Data
|
||||
self.album = Album(
|
||||
alb_id = trackAPI_gw['ALB_ID'],
|
||||
title = trackAPI_gw['ALB_TITLE'],
|
||||
pic_md5 = trackAPI_gw.get('ALB_PICTURE')
|
||||
alb_id = trackAPI['album']['id'],
|
||||
title = trackAPI['album']['title'],
|
||||
pic_md5 = trackAPI['album'].get('md5_origin')
|
||||
)
|
||||
|
||||
# Get album Data
|
||||
@ -134,31 +112,31 @@ class Track:
|
||||
except APIError: albumAPI = None
|
||||
|
||||
# Get album_gw Data
|
||||
if not albumAPI_gw:
|
||||
try: albumAPI_gw = dz.gw.get_album(self.album.id)
|
||||
except GWAPIError: albumAPI_gw = None
|
||||
# Only gw has disk number
|
||||
if not albumAPI or albumAPI and not albumAPI.get('nb_disk'):
|
||||
try:
|
||||
albumAPI_gw = dz.gw.get_album(self.album.id)
|
||||
albumAPI_gw = map_album(albumAPI_gw)
|
||||
except GWAPIError: albumAPI_gw = {}
|
||||
if not albumAPI: albumAPI = {}
|
||||
albumAPI_gw.update(albumAPI)
|
||||
albumAPI = albumAPI_gw
|
||||
|
||||
if albumAPI:
|
||||
self.album.parseAlbum(albumAPI)
|
||||
elif albumAPI_gw:
|
||||
self.album.parseAlbumGW(albumAPI_gw)
|
||||
# albumAPI_gw doesn't contain the artist cover
|
||||
# Getting artist image ID
|
||||
# ex: https://e-cdns-images.dzcdn.net/images/artist/f2bc007e9133c946ac3c3907ddc5d2ea/56x56-000000-80-0-0.jpg
|
||||
if not albumAPI: raise AlbumDoesntExists
|
||||
|
||||
self.album.parseAlbum(albumAPI)
|
||||
# albumAPI_gw doesn't contain the artist cover
|
||||
# Getting artist image ID
|
||||
# ex: https://e-cdns-images.dzcdn.net/images/artist/f2bc007e9133c946ac3c3907ddc5d2ea/56x56-000000-80-0-0.jpg
|
||||
if not self.album.mainArtist.pic.md5 or self.album.mainArtist.pic.md5 == "":
|
||||
artistAPI = dz.api.get_artist(self.album.mainArtist.id)
|
||||
self.album.mainArtist.pic.md5 = artistAPI['picture_small'][artistAPI['picture_small'].find('artist/') + 7:-24]
|
||||
else:
|
||||
raise AlbumDoesntExists
|
||||
|
||||
# Fill missing data
|
||||
if albumAPI_gw: self.album.addExtraAlbumGWData(albumAPI_gw)
|
||||
if self.album.date and not self.date: self.date = self.album.date
|
||||
if not self.album.discTotal: self.album.discTotal = albumAPI_gw.get('NUMBER_DISK', "1")
|
||||
if not self.copyright: self.copyright = albumAPI_gw['COPYRIGHT']
|
||||
if 'GENRES' in trackAPI_gw:
|
||||
for genre in trackAPI_gw['GENRES']:
|
||||
if 'genres' in trackAPI:
|
||||
for genre in trackAPI['genres']:
|
||||
if genre not in self.album.genre: self.album.genre.append(genre)
|
||||
self.parseTrack(trackAPI)
|
||||
|
||||
# Remove unwanted charaters in track name
|
||||
# Example: track/127793
|
||||
@ -168,7 +146,7 @@ class Track:
|
||||
if len(self.artist['Main']) == 0:
|
||||
self.artist['Main'] = [self.mainArtist.name]
|
||||
|
||||
self.position = trackAPI_gw.get('POSITION')
|
||||
self.position = trackAPI.get('position')
|
||||
|
||||
# Add playlist data if track is in a playlist
|
||||
if playlistAPI: self.playlist = Playlist(playlistAPI)
|
||||
@ -176,63 +154,52 @@ class Track:
|
||||
self.generateMainFeatStrings()
|
||||
return self
|
||||
|
||||
def parseLocalTrackData(self, trackAPI_gw):
|
||||
def parseLocalTrackData(self, trackAPI):
|
||||
# Local tracks has only the trackAPI_gw page and
|
||||
# contains only the tags provided by the file
|
||||
self.title = trackAPI_gw['SNG_TITLE']
|
||||
self.album = Album(title=trackAPI_gw['ALB_TITLE'])
|
||||
self.title = trackAPI['title']
|
||||
self.album = Album(title=trackAPI['album']['title'])
|
||||
self.album.pic = Picture(
|
||||
md5 = trackAPI_gw.get('ALB_PICTURE', ""),
|
||||
md5 = trackAPI.get('md5_image', ""),
|
||||
pic_type = "cover"
|
||||
)
|
||||
self.mainArtist = Artist(name=trackAPI_gw['ART_NAME'], role="Main")
|
||||
self.artists = [trackAPI_gw['ART_NAME']]
|
||||
self.mainArtist = Artist(name=trackAPI['artist']['name'], role="Main")
|
||||
self.artists = [trackAPI['artist']['name']]
|
||||
self.artist = {
|
||||
'Main': [trackAPI_gw['ART_NAME']]
|
||||
'Main': [trackAPI['artist']['name']]
|
||||
}
|
||||
self.album.artist = self.artist
|
||||
self.album.artists = self.artists
|
||||
self.album.date = self.date
|
||||
self.album.mainArtist = self.mainArtist
|
||||
|
||||
def parseTrackGW(self, trackAPI_gw):
|
||||
self.title = trackAPI_gw['SNG_TITLE'].strip()
|
||||
if trackAPI_gw.get('VERSION') and not trackAPI_gw['VERSION'].strip() in self.title:
|
||||
self.title += f" {trackAPI_gw['VERSION'].strip()}"
|
||||
|
||||
self.discNumber = trackAPI_gw.get('DISK_NUMBER')
|
||||
self.explicit = bool(int(trackAPI_gw.get('EXPLICIT_LYRICS', "0")))
|
||||
self.copyright = trackAPI_gw.get('COPYRIGHT')
|
||||
if 'GAIN' in trackAPI_gw: self.replayGain = generateReplayGainString(trackAPI_gw['GAIN'])
|
||||
self.ISRC = trackAPI_gw.get('ISRC')
|
||||
self.trackNumber = trackAPI_gw['TRACK_NUMBER']
|
||||
self.contributors = trackAPI_gw['SNG_CONTRIBUTORS']
|
||||
self.rank = trackAPI_gw['RANK_SNG']
|
||||
|
||||
self.lyrics = Lyrics(trackAPI_gw.get('LYRICS_ID', "0"))
|
||||
|
||||
self.mainArtist = Artist(
|
||||
art_id = trackAPI_gw['ART_ID'],
|
||||
name = trackAPI_gw['ART_NAME'],
|
||||
role = "Main",
|
||||
pic_md5 = trackAPI_gw.get('ART_PICTURE')
|
||||
)
|
||||
|
||||
if 'PHYSICAL_RELEASE_DATE' in trackAPI_gw:
|
||||
self.date.day = trackAPI_gw["PHYSICAL_RELEASE_DATE"][8:10]
|
||||
self.date.month = trackAPI_gw["PHYSICAL_RELEASE_DATE"][5:7]
|
||||
self.date.year = trackAPI_gw["PHYSICAL_RELEASE_DATE"][0:4]
|
||||
self.date.fixDayMonth()
|
||||
|
||||
def parseTrack(self, trackAPI):
|
||||
self.title = trackAPI['title']
|
||||
|
||||
self.discNumber = trackAPI.get('disk_number')
|
||||
self.explicit = trackAPI.get('explicit_lyrics', False)
|
||||
self.copyright = trackAPI.get('copyright')
|
||||
if 'gain' in trackAPI: self.replayGain = generateReplayGainString(trackAPI['gain'])
|
||||
self.ISRC = trackAPI.get('isrc')
|
||||
self.trackNumber = trackAPI['track_position']
|
||||
self.contributors = trackAPI.get('song_contributors')
|
||||
self.rank = trackAPI['rank']
|
||||
self.bpm = trackAPI['bpm']
|
||||
|
||||
if not self.replayGain and 'gain' in trackAPI:
|
||||
self.replayGain = generateReplayGainString(trackAPI['gain'])
|
||||
if not self.explicit:
|
||||
self.explicit = trackAPI['explicit_lyrics']
|
||||
if not self.discNumber:
|
||||
self.discNumber = trackAPI['disk_number']
|
||||
self.lyrics = Lyrics(trackAPI.get('lyrics_id', "0"))
|
||||
|
||||
self.mainArtist = Artist(
|
||||
art_id = trackAPI['artist']['id'],
|
||||
name = trackAPI['artist']['name'],
|
||||
role = "Main",
|
||||
pic_md5 = trackAPI['artist'].get('md5_image')
|
||||
)
|
||||
|
||||
if 'physical_release_date' in trackAPI:
|
||||
self.date.day = trackAPI["physical_release_date"][8:10]
|
||||
self.date.month = trackAPI["physical_release_date"][5:7]
|
||||
self.date.year = trackAPI["physical_release_date"][0:4]
|
||||
self.date.fixDayMonth()
|
||||
|
||||
for artist in trackAPI['contributors']:
|
||||
isVariousArtists = str(artist['id']) == VARIOUS_ARTISTS
|
||||
@ -249,6 +216,11 @@ class Track:
|
||||
self.artist[artist['role']] = []
|
||||
self.artist[artist['role']].append(artist['name'])
|
||||
|
||||
if 'alternative_albums' in trackAPI and trackAPI['alternative_albums']:
|
||||
for album in trackAPI['alternative_albums']['data']:
|
||||
if 'RIGHTS' in album and album['RIGHTS'].get('STREAM_ADS_AVAILABLE') or album['RIGHTS'].get('STREAM_SUB_AVAILABLE'):
|
||||
self.albumsFallback.append(album['ALB_ID'])
|
||||
|
||||
def removeDuplicateArtists(self):
|
||||
(self.artist, self.artists) = removeDuplicateArtists(self.artist, self.artists)
|
||||
|
||||
@ -267,6 +239,14 @@ class Track:
|
||||
if 'Featured' in self.artist:
|
||||
self.featArtistsString = "feat. "+andCommaConcat(self.artist['Featured'])
|
||||
|
||||
def checkAndRenewTrackToken(self, dz):
|
||||
now = datetime.now()
|
||||
expiration = datetime.fromtimestamp(self.trackTokenExpiration)
|
||||
if now > expiration:
|
||||
newTrack = dz.gw.get_track_with_fallback(self.id)
|
||||
self.trackToken = newTrack['TRACK_TOKEN']
|
||||
self.trackTokenExpiration = newTrack['TRACK_TOKEN_EXPIRE']
|
||||
|
||||
def applySettings(self, settings):
|
||||
|
||||
# Check if should save the playlist as a compilation
|
||||
|
Reference in New Issue
Block a user