Even more rework on the library

This commit is contained in:
RemixDev 2021-03-24 17:41:03 +01:00
parent dc6adc7887
commit eda8fd3d13
No known key found for this signature in database
GPG Key ID: B33962B465BDB51C
7 changed files with 95 additions and 129 deletions

View File

@ -23,13 +23,13 @@ def parseLink(link):
if '/track' in link: if '/track' in link:
type = 'track' type = 'track'
id = link[link.rfind("/") + 1:] id = re.search("\/track\/(.+)", link).group(1)
elif '/playlist' in link: elif '/playlist' in link:
type = 'playlist' type = 'playlist'
id = re.search("\/playlist\/(\d+)", link).group(1) id = re.search("\/playlist\/(\d+)", link).group(1)
elif '/album' in link: elif '/album' in link:
type = 'album' type = 'album'
id = link[link.rfind("/") + 1:] id = re.search("\/album\/(.+)", link).group(1)
elif re.search("\/artist\/(\d+)\/top_track", link): elif re.search("\/artist\/(\d+)\/top_track", link):
type = 'artist_top' type = 'artist_top'
id = re.search("\/artist\/(\d+)\/top_track", link).group(1) id = re.search("\/artist\/(\d+)\/top_track", link).group(1)
@ -42,7 +42,7 @@ def parseLink(link):
return (link, type, id) return (link, type, id)
def generateDownloadItem(dz, link, bitrate): def generateDownloadObject(dz, link, bitrate):
(link, type, id) = parseLink(link) (link, type, id) = parseLink(link)
if type == None or id == None: return None if type == None or id == None: return None

View File

@ -5,7 +5,7 @@ from pathlib import Path
from deezer import Deezer from deezer import Deezer
from deezer import TrackFormats from deezer import TrackFormats
from deemix import generateDownloadItem from deemix import generateDownloadObject
from deemix.settings import loadSettings from deemix.settings import loadSettings
from deemix.utils import getBitrateNumberFromText from deemix.utils import getBitrateNumberFromText
import deemix.utils.localpaths as localpaths import deemix.utils.localpaths as localpaths
@ -49,8 +49,8 @@ def download(url, bitrate, portable, path):
links.append(link) links.append(link)
for link in links: for link in links:
downloadItem = generateDownloadItem(dz, link, bitrate) downloadObject = generateDownloadObject(dz, link, bitrate)
Downloader(dz, downloadItem, settings).start() Downloader(dz, downloadObject, settings).start()
if path is not None: if path is not None:
if path == '': path = '.' if path == '': path = '.'

View File

@ -321,9 +321,9 @@ class Downloader:
raise DownloadCancelled raise DownloadCancelled
except (requests.exceptions.HTTPError, DownloadEmpty): except (requests.exceptions.HTTPError, DownloadEmpty):
if writepath.is_file(): writepath.unlink() if writepath.is_file(): writepath.unlink()
if track.fallbackId != "0": if track.fallbackID != "0":
logger.warn(f"[{track.mainArtist.name} - {track.title}] Track not available, using fallback id") logger.warn(f"[{track.mainArtist.name} - {track.title}] Track not available, using fallback id")
newTrack = self.dz.gw.get_track_with_fallback(track.fallbackId) newTrack = self.dz.gw.get_track_with_fallback(track.fallbackID)
track.parseEssentialData(newTrack) track.parseEssentialData(newTrack)
track.retriveFilesizes(self.dz) track.retriveFilesizes(self.dz)
return False return False
@ -418,9 +418,9 @@ class Downloader:
except DownloadFailed as error: except DownloadFailed as error:
if error.track: if error.track:
track = error.track track = error.track
if track.fallbackId != "0": if track.fallbackID != "0":
logger.warn(f"[{track.mainArtist.name} - {track.title}] {error.message} Using fallback id") logger.warn(f"[{track.mainArtist.name} - {track.title}] {error.message} Using fallback id")
newTrack = self.dz.gw.get_track_with_fallback(track.fallbackId) newTrack = self.dz.gw.get_track_with_fallback(track.fallbackID)
track.parseEssentialData(newTrack) track.parseEssentialData(newTrack)
track.retriveFilesizes(self.dz) track.retriveFilesizes(self.dz)
return self.downloadWrapper(trackAPI_gw, trackAPI, albumAPI, playlistAPI, track) return self.downloadWrapper(trackAPI_gw, trackAPI, albumAPI, playlistAPI, track)

View File

@ -42,18 +42,20 @@ def generateTrackItem(dz, id, bitrate, trackAPI=None, albumAPI=None):
title += f" {trackAPI_gw['VERSION']}".strip() title += f" {trackAPI_gw['VERSION']}".strip()
explicit = bool(int(trackAPI_gw.get('EXPLICIT_LYRICS', 0))) explicit = bool(int(trackAPI_gw.get('EXPLICIT_LYRICS', 0)))
return Single( return Single({
'track', 'type': 'track',
id, 'id': id,
bitrate, 'bitrate': bitrate,
title, 'title': title,
trackAPI_gw['ART_NAME'], 'artist': trackAPI_gw['ART_NAME'],
f"https://e-cdns-images.dzcdn.net/images/cover/{trackAPI_gw['ALB_PICTURE']}/75x75-000000-80-0-0.jpg", 'cover': f"https://e-cdns-images.dzcdn.net/images/cover/{trackAPI_gw['ALB_PICTURE']}/75x75-000000-80-0-0.jpg",
explicit, 'explicit': explicit,
trackAPI_gw, 'single': {
trackAPI, 'trackAPI_gw': trackAPI_gw,
albumAPI 'trackAPI': trackAPI,
) 'albumAPI': albumAPI
}
})
def generateAlbumItem(dz, id, bitrate, rootArtist=None): def generateAlbumItem(dz, id, bitrate, rootArtist=None):
# Get essential album info # Get essential album info
@ -93,18 +95,20 @@ def generateAlbumItem(dz, id, bitrate, rootArtist=None):
explicit = albumAPI_gw.get('EXPLICIT_ALBUM_CONTENT', {}).get('EXPLICIT_LYRICS_STATUS', LyricsStatus.UNKNOWN) in [LyricsStatus.EXPLICIT, LyricsStatus.PARTIALLY_EXPLICIT] explicit = albumAPI_gw.get('EXPLICIT_ALBUM_CONTENT', {}).get('EXPLICIT_LYRICS_STATUS', LyricsStatus.UNKNOWN) in [LyricsStatus.EXPLICIT, LyricsStatus.PARTIALLY_EXPLICIT]
return Collection( return Collection({
'album', 'type': 'album',
id, 'id': id,
bitrate, 'bitrate': bitrate,
albumAPI['title'], 'title': albumAPI['title'],
albumAPI['artist']['name'], 'artist': albumAPI['artist']['name'],
cover, 'cover': cover,
explicit, 'explicit': explicit,
totalSize, 'size': totalSize,
tracks_gw=collection, 'collection': {
albumAPI=albumAPI 'tracks_gw': collection,
) 'albumAPI': albumAPI
}
})
def generatePlaylistItem(dz, id, bitrate, playlistAPI=None, playlistTracksAPI=None): def generatePlaylistItem(dz, id, bitrate, playlistAPI=None, playlistTracksAPI=None):
if not playlistAPI: if not playlistAPI:
@ -146,18 +150,20 @@ def generatePlaylistItem(dz, id, bitrate, playlistAPI=None, playlistTracksAPI=No
if not 'explicit' in playlistAPI: playlistAPI['explicit'] = False if not 'explicit' in playlistAPI: playlistAPI['explicit'] = False
return Collection( return Collection({
'playlist', 'type': 'playlist',
id, 'id': id,
bitrate, 'bitrate': bitrate,
playlistAPI['title'], 'title': playlistAPI['title'],
playlistAPI['creator']['name'], 'artist': playlistAPI['creator']['name'],
playlistAPI['picture_small'][:-24] + '/75x75-000000-80-0-0.jpg', 'cover': playlistAPI['picture_small'][:-24] + '/75x75-000000-80-0-0.jpg',
playlistAPI['explicit'], 'explicit': playlistAPI['explicit'],
totalSize, 'size': totalSize,
tracks_gw=collection, 'collection': {
playlistAPI=playlistAPI 'tracks_gw': collection,
) 'playlistAPI': playlistAPI
}
})
def generateArtistItem(dz, id, bitrate, interface=None): def generateArtistItem(dz, id, bitrate, interface=None):
# Get essential artist info # Get essential artist info

View File

@ -1,33 +1,18 @@
class IDownloadObject: class IDownloadObject:
def __init__(self, type=None, id=None, bitrate=None, title=None, artist=None, cover=None, explicit=False, size=None, dictItem=None): def __init__(self, obj):
if dictItem: self.type = obj['type']
self.type = dictItem['type'] self.id = obj['id']
self.id = dictItem['id'] self.bitrate = obj['bitrate']
self.bitrate = dictItem['bitrate'] self.title = obj['title']
self.title = dictItem['title'] self.artist = obj['artist']
self.artist = dictItem['artist'] self.cover = obj['cover']
self.cover = dictItem['cover'] self.explicit = obj.get('explicit', False)
self.explicit = dictItem.get('explicit', False) self.size = obj['size']
self.size = dictItem['size'] self.downloaded = obj.get('downloaded', 0)
self.downloaded = dictItem['downloaded'] self.failed = obj.get('failed', 0)
self.failed = dictItem['failed'] self.progress = obj.get('progress', 0)
self.progress = dictItem['progress'] self.errors = obj.get('errors', [])
self.errors = dictItem['errors'] self.files = obj.get('files', [])
self.files = dictItem['files']
else:
self.type = type
self.id = id
self.bitrate = bitrate
self.title = title
self.artist = artist
self.cover = cover
self.explicit = explicit
self.size = size
self.downloaded = 0
self.failed = 0
self.progress = 0
self.errors = []
self.files = []
self.progressNext = 0 self.progressNext = 0
self.uuid = f"{self.type}_{self.id}_{self.bitrate}" self.uuid = f"{self.type}_{self.id}_{self.bitrate}"
self.ack = None self.ack = None
@ -76,17 +61,10 @@ class IDownloadObject:
if interface: interface.send("updateQueue", {'uuid': self.uuid, 'progress': self.progress}) if interface: interface.send("updateQueue", {'uuid': self.uuid, 'progress': self.progress})
class Single(IDownloadObject): class Single(IDownloadObject):
def __init__(self, type=None, id=None, bitrate=None, title=None, artist=None, cover=None, explicit=False, trackAPI_gw=None, trackAPI=None, albumAPI=None, dictItem=None): def __init__(self, obj):
if dictItem: super().__init__(obj)
super().__init__(dictItem=dictItem) self.size = 1
self.single = dictItem['single'] self.single = obj['single']
else:
super().__init__(type, id, bitrate, title, artist, cover, explicit, 1)
self.single = {
'trackAPI_gw': trackAPI_gw,
'trackAPI': trackAPI,
'albumAPI': albumAPI
}
self.__type__ = "Single" self.__type__ = "Single"
def toDict(self): def toDict(self):
@ -103,17 +81,9 @@ class Single(IDownloadObject):
self.updateProgress(interface) self.updateProgress(interface)
class Collection(IDownloadObject): class Collection(IDownloadObject):
def __init__(self, type=None, id=None, bitrate=None, title=None, artist=None, cover=None, explicit=False, size=None, tracks_gw=None, albumAPI=None, playlistAPI=None, dictItem=None): def __init__(self, obj):
if dictItem: super().__init__(obj)
super().__init__(dictItem=dictItem) self.collection = obj['collection']
self.collection = dictItem['collection']
else:
super().__init__(type, id, bitrate, title, artist, cover, explicit, size)
self.collection = {
'tracks_gw': tracks_gw,
'albumAPI': albumAPI,
'playlistAPI': playlistAPI
}
self.__type__ = "Collection" self.__type__ = "Collection"
def toDict(self): def toDict(self):
@ -130,15 +100,10 @@ class Collection(IDownloadObject):
self.updateProgress(interface) self.updateProgress(interface)
class Convertable(Collection): class Convertable(Collection):
def __init__(self, type=None, id=None, bitrate=None, title=None, artist=None, cover=None, explicit=False, size=None, plugin=None, conversion_data=None, dictItem=None): def __init__(self, obj):
if dictItem: super().__init__(obj)
super().__init__(dictItem=dictItem) self.plugin = obj['plugin']
self.plugin = dictItem['plugin'] self.conversion_data = obj['conversion_data']
self.conversion_data = dictItem['conversion_data']
else:
super().__init__(type, id, bitrate, title, artist, cover, explicit, size)
self.plugin = plugin
self.conversion_data = conversion_data
self.__type__ = "Convertable" self.__type__ = "Convertable"
def toDict(self): def toDict(self):

View File

@ -14,10 +14,9 @@ class Picture:
) )
if format.startswith("jpg"): if format.startswith("jpg"):
quality = 80
if '-' in format: if '-' in format:
quality = format[4:] quality = format[4:]
else:
quality = 80
format = 'jpg' format = 'jpg'
return url + f'-000000-{quality}-0-0.jpg' return url + f'-000000-{quality}-0-0.jpg'
if format == 'png': if format == 'png':

View File

@ -1,12 +1,9 @@
from time import sleep
import requests import requests
from time import sleep
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('deemix')
from deezer.gw import GWAPIError from deezer.gw import GWAPIError
from deezer.api import APIError from deezer.api import APIError
from deemix.utils import removeFeatures, andCommaConcat, removeDuplicateArtists, generateReplayGainString, changeCase from deemix.utils import removeFeatures, andCommaConcat, removeDuplicateArtists, generateReplayGainString, changeCase
from deemix.types.Album import Album from deemix.types.Album import Album
@ -24,7 +21,7 @@ class Track:
self.MD5 = "" self.MD5 = ""
self.mediaVersion = "" self.mediaVersion = ""
self.duration = 0 self.duration = 0
self.fallbackId = "0" self.fallbackID = "0"
self.filesizes = {} self.filesizes = {}
self.localTrack = False self.localTrack = False
self.mainArtist = None self.mainArtist = None
@ -46,7 +43,7 @@ class Track:
self.searched = False self.searched = False
self.selectedFormat = 0 self.selectedFormat = 0
self.singleDownload = False self.singleDownload = False
self.dateString = None self.dateString = ""
self.artistsString = "" self.artistsString = ""
self.mainArtistsString = "" self.mainArtistsString = ""
self.featArtistsString = "" self.featArtistsString = ""
@ -61,14 +58,14 @@ class Track:
else: else:
raise MD5NotFound raise MD5NotFound
self.mediaVersion = trackAPI_gw['MEDIA_VERSION'] self.mediaVersion = trackAPI_gw['MEDIA_VERSION']
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.localTrack = int(self.id) < 0 self.localTrack = int(self.id) < 0
def retriveFilesizes(self, dz): def retriveFilesizes(self, dz):
guest_sid = dz.session.cookies.get('sid')
try: try:
guest_sid = dz.session.cookies.get('sid')
site = requests.post( site = requests.post(
"https://api.deezer.com/1.0/gateway.php", "https://api.deezer.com/1.0/gateway.php",
params={ params={
@ -97,8 +94,7 @@ class Track:
self.filesizes = filesizes self.filesizes = filesizes
def parseData(self, dz, id=None, trackAPI_gw=None, trackAPI=None, albumAPI_gw=None, albumAPI=None, playlistAPI=None): def parseData(self, dz, id=None, trackAPI_gw=None, trackAPI=None, albumAPI_gw=None, albumAPI=None, playlistAPI=None):
if id: if id and not trackAPI_gw: trackAPI_gw = dz.gw.get_track_with_fallback(id)
if not trackAPI_gw: trackAPI_gw = dz.gw.get_track_with_fallback(id)
elif not trackAPI_gw: raise NoDataToParse elif not trackAPI_gw: raise NoDataToParse
if not trackAPI: if not trackAPI:
try: trackAPI = dz.api.get_track(trackAPI_gw['SNG_ID']) try: trackAPI = dz.api.get_track(trackAPI_gw['SNG_ID'])
@ -110,15 +106,15 @@ class Track:
self.parseLocalTrackData(trackAPI_gw) self.parseLocalTrackData(trackAPI_gw)
else: else:
self.retriveFilesizes(dz) self.retriveFilesizes(dz)
self.parseTrackGW(trackAPI_gw) self.parseTrackGW(trackAPI_gw)
# Get Lyrics data # Get Lyrics data
if not "LYRICS" in trackAPI_gw and self.lyrics.id != "0": if not "LYRICS" in trackAPI_gw and self.lyrics.id != "0":
try: trackAPI_gw["LYRICS"] = dz.gw.get_track_lyrics(self.id) try: trackAPI_gw["LYRICS"] = dz.gw.get_track_lyrics(self.id)
except GWAPIError: self.lyrics.id = "0" except GWAPIError: self.lyrics.id = "0"
if self.lyrics.id != "0": self.lyrics.parseLyrics(trackAPI_gw["LYRICS"]) if self.lyrics.id != "0": self.lyrics.parseLyrics(trackAPI_gw["LYRICS"])
# Parse Album data # Parse Album Data
self.album = Album( self.album = Album(
id = trackAPI_gw['ALB_ID'], id = trackAPI_gw['ALB_ID'],
title = trackAPI_gw['ALB_TITLE'], title = trackAPI_gw['ALB_TITLE'],
@ -161,7 +157,7 @@ class Track:
if not len(self.artist['Main']): if not len(self.artist['Main']):
self.artist['Main'] = [self.mainArtist['name']] self.artist['Main'] = [self.mainArtist['name']]
self.singleDownload = trackAPI_gw.get('SINGLE_TRACK', False) self.singleDownload = trackAPI_gw.get('SINGLE_TRACK', False) # TODO: To change
self.position = trackAPI_gw.get('POSITION') self.position = trackAPI_gw.get('POSITION')
# Add playlist data if track is in a playlist # Add playlist data if track is in a playlist
@ -184,16 +180,16 @@ class Track:
self.artist = { self.artist = {
'Main': [trackAPI_gw['ART_NAME']] 'Main': [trackAPI_gw['ART_NAME']]
} }
self.date = Date()
self.album.artist = self.artist self.album.artist = self.artist
self.album.artists = self.artists self.album.artists = self.artists
self.album.date = self.date self.album.date = self.date
self.album.mainArtist = self.mainArtist self.album.mainArtist = self.mainArtist
self.date = Date()
def parseTrackGW(self, trackAPI_gw): def parseTrackGW(self, trackAPI_gw):
self.title = trackAPI_gw['SNG_TITLE'].strip() self.title = trackAPI_gw['SNG_TITLE'].strip()
if trackAPI_gw.get('VERSION') and not trackAPI_gw['VERSION'] in trackAPI_gw['SNG_TITLE']: if trackAPI_gw.get('VERSION') and not trackAPI_gw['VERSION'].strip() in this.title:
self.title += " " + trackAPI_gw['VERSION'].strip() self.title += f" {trackAPI_gw['VERSION'].strip()}"
self.discNumber = trackAPI_gw.get('DISK_NUMBER') self.discNumber = trackAPI_gw.get('DISK_NUMBER')
self.explicit = bool(int(trackAPI_gw.get('EXPLICIT_LYRICS', "0"))) self.explicit = bool(int(trackAPI_gw.get('EXPLICIT_LYRICS', "0")))
@ -215,7 +211,7 @@ class Track:
day = trackAPI_gw["PHYSICAL_RELEASE_DATE"][8:10] day = trackAPI_gw["PHYSICAL_RELEASE_DATE"][8:10]
month = trackAPI_gw["PHYSICAL_RELEASE_DATE"][5:7] month = trackAPI_gw["PHYSICAL_RELEASE_DATE"][5:7]
year = trackAPI_gw["PHYSICAL_RELEASE_DATE"][0:4] year = trackAPI_gw["PHYSICAL_RELEASE_DATE"][0:4]
self.date = Date(year, month, day) self.date = Date(day, month, year)
def parseTrack(self, trackAPI): def parseTrack(self, trackAPI):
self.bpm = trackAPI['bpm'] self.bpm = trackAPI['bpm']
@ -250,8 +246,8 @@ class Track:
return removeFeatures(self.title) return removeFeatures(self.title)
def getFeatTitle(self): def getFeatTitle(self):
if self.featArtistsString and not "(feat." in self.title.lower(): if self.featArtistsString and not "feat." in self.title.lower():
return self.title + " ({})".format(self.featArtistsString) return f"{self.title} ({self.featArtistsString})"
return self.title return self.title
def generateMainFeatStrings(self): def generateMainFeatStrings(self):