Even more rework on the library
This commit is contained in:
parent
dc6adc7887
commit
eda8fd3d13
|
@ -23,13 +23,13 @@ def parseLink(link):
|
|||
|
||||
if '/track' in link:
|
||||
type = 'track'
|
||||
id = link[link.rfind("/") + 1:]
|
||||
id = re.search("\/track\/(.+)", link).group(1)
|
||||
elif '/playlist' in link:
|
||||
type = 'playlist'
|
||||
id = re.search("\/playlist\/(\d+)", link).group(1)
|
||||
elif '/album' in link:
|
||||
type = 'album'
|
||||
id = link[link.rfind("/") + 1:]
|
||||
id = re.search("\/album\/(.+)", link).group(1)
|
||||
elif re.search("\/artist\/(\d+)\/top_track", link):
|
||||
type = 'artist_top'
|
||||
id = re.search("\/artist\/(\d+)\/top_track", link).group(1)
|
||||
|
@ -42,7 +42,7 @@ def parseLink(link):
|
|||
|
||||
return (link, type, id)
|
||||
|
||||
def generateDownloadItem(dz, link, bitrate):
|
||||
def generateDownloadObject(dz, link, bitrate):
|
||||
(link, type, id) = parseLink(link)
|
||||
|
||||
if type == None or id == None: return None
|
||||
|
|
|
@ -5,7 +5,7 @@ from pathlib import Path
|
|||
from deezer import Deezer
|
||||
from deezer import TrackFormats
|
||||
|
||||
from deemix import generateDownloadItem
|
||||
from deemix import generateDownloadObject
|
||||
from deemix.settings import loadSettings
|
||||
from deemix.utils import getBitrateNumberFromText
|
||||
import deemix.utils.localpaths as localpaths
|
||||
|
@ -49,8 +49,8 @@ def download(url, bitrate, portable, path):
|
|||
links.append(link)
|
||||
|
||||
for link in links:
|
||||
downloadItem = generateDownloadItem(dz, link, bitrate)
|
||||
Downloader(dz, downloadItem, settings).start()
|
||||
downloadObject = generateDownloadObject(dz, link, bitrate)
|
||||
Downloader(dz, downloadObject, settings).start()
|
||||
|
||||
if path is not None:
|
||||
if path == '': path = '.'
|
||||
|
|
|
@ -321,9 +321,9 @@ class Downloader:
|
|||
raise DownloadCancelled
|
||||
except (requests.exceptions.HTTPError, DownloadEmpty):
|
||||
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")
|
||||
newTrack = self.dz.gw.get_track_with_fallback(track.fallbackId)
|
||||
newTrack = self.dz.gw.get_track_with_fallback(track.fallbackID)
|
||||
track.parseEssentialData(newTrack)
|
||||
track.retriveFilesizes(self.dz)
|
||||
return False
|
||||
|
@ -418,9 +418,9 @@ class Downloader:
|
|||
except DownloadFailed as error:
|
||||
if 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")
|
||||
newTrack = self.dz.gw.get_track_with_fallback(track.fallbackId)
|
||||
newTrack = self.dz.gw.get_track_with_fallback(track.fallbackID)
|
||||
track.parseEssentialData(newTrack)
|
||||
track.retriveFilesizes(self.dz)
|
||||
return self.downloadWrapper(trackAPI_gw, trackAPI, albumAPI, playlistAPI, track)
|
||||
|
|
|
@ -42,18 +42,20 @@ def generateTrackItem(dz, id, bitrate, trackAPI=None, albumAPI=None):
|
|||
title += f" {trackAPI_gw['VERSION']}".strip()
|
||||
explicit = bool(int(trackAPI_gw.get('EXPLICIT_LYRICS', 0)))
|
||||
|
||||
return Single(
|
||||
'track',
|
||||
id,
|
||||
bitrate,
|
||||
title,
|
||||
trackAPI_gw['ART_NAME'],
|
||||
f"https://e-cdns-images.dzcdn.net/images/cover/{trackAPI_gw['ALB_PICTURE']}/75x75-000000-80-0-0.jpg",
|
||||
explicit,
|
||||
trackAPI_gw,
|
||||
trackAPI,
|
||||
albumAPI
|
||||
)
|
||||
return Single({
|
||||
'type': 'track',
|
||||
'id': id,
|
||||
'bitrate': bitrate,
|
||||
'title': title,
|
||||
'artist': trackAPI_gw['ART_NAME'],
|
||||
'cover': f"https://e-cdns-images.dzcdn.net/images/cover/{trackAPI_gw['ALB_PICTURE']}/75x75-000000-80-0-0.jpg",
|
||||
'explicit': explicit,
|
||||
'single': {
|
||||
'trackAPI_gw': trackAPI_gw,
|
||||
'trackAPI': trackAPI,
|
||||
'albumAPI': albumAPI
|
||||
}
|
||||
})
|
||||
|
||||
def generateAlbumItem(dz, id, bitrate, rootArtist=None):
|
||||
# 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]
|
||||
|
||||
return Collection(
|
||||
'album',
|
||||
id,
|
||||
bitrate,
|
||||
albumAPI['title'],
|
||||
albumAPI['artist']['name'],
|
||||
cover,
|
||||
explicit,
|
||||
totalSize,
|
||||
tracks_gw=collection,
|
||||
albumAPI=albumAPI
|
||||
)
|
||||
return Collection({
|
||||
'type': 'album',
|
||||
'id': id,
|
||||
'bitrate': bitrate,
|
||||
'title': albumAPI['title'],
|
||||
'artist': albumAPI['artist']['name'],
|
||||
'cover': cover,
|
||||
'explicit': explicit,
|
||||
'size': totalSize,
|
||||
'collection': {
|
||||
'tracks_gw': collection,
|
||||
'albumAPI': albumAPI
|
||||
}
|
||||
})
|
||||
|
||||
def generatePlaylistItem(dz, id, bitrate, playlistAPI=None, playlistTracksAPI=None):
|
||||
if not playlistAPI:
|
||||
|
@ -146,18 +150,20 @@ def generatePlaylistItem(dz, id, bitrate, playlistAPI=None, playlistTracksAPI=No
|
|||
|
||||
if not 'explicit' in playlistAPI: playlistAPI['explicit'] = False
|
||||
|
||||
return Collection(
|
||||
'playlist',
|
||||
id,
|
||||
bitrate,
|
||||
playlistAPI['title'],
|
||||
playlistAPI['creator']['name'],
|
||||
playlistAPI['picture_small'][:-24] + '/75x75-000000-80-0-0.jpg',
|
||||
playlistAPI['explicit'],
|
||||
totalSize,
|
||||
tracks_gw=collection,
|
||||
playlistAPI=playlistAPI
|
||||
)
|
||||
return Collection({
|
||||
'type': 'playlist',
|
||||
'id': id,
|
||||
'bitrate': bitrate,
|
||||
'title': playlistAPI['title'],
|
||||
'artist': playlistAPI['creator']['name'],
|
||||
'cover': playlistAPI['picture_small'][:-24] + '/75x75-000000-80-0-0.jpg',
|
||||
'explicit': playlistAPI['explicit'],
|
||||
'size': totalSize,
|
||||
'collection': {
|
||||
'tracks_gw': collection,
|
||||
'playlistAPI': playlistAPI
|
||||
}
|
||||
})
|
||||
|
||||
def generateArtistItem(dz, id, bitrate, interface=None):
|
||||
# Get essential artist info
|
||||
|
|
|
@ -1,33 +1,18 @@
|
|||
class IDownloadObject:
|
||||
def __init__(self, type=None, id=None, bitrate=None, title=None, artist=None, cover=None, explicit=False, size=None, dictItem=None):
|
||||
if dictItem:
|
||||
self.type = dictItem['type']
|
||||
self.id = dictItem['id']
|
||||
self.bitrate = dictItem['bitrate']
|
||||
self.title = dictItem['title']
|
||||
self.artist = dictItem['artist']
|
||||
self.cover = dictItem['cover']
|
||||
self.explicit = dictItem.get('explicit', False)
|
||||
self.size = dictItem['size']
|
||||
self.downloaded = dictItem['downloaded']
|
||||
self.failed = dictItem['failed']
|
||||
self.progress = dictItem['progress']
|
||||
self.errors = dictItem['errors']
|
||||
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 = []
|
||||
def __init__(self, obj):
|
||||
self.type = obj['type']
|
||||
self.id = obj['id']
|
||||
self.bitrate = obj['bitrate']
|
||||
self.title = obj['title']
|
||||
self.artist = obj['artist']
|
||||
self.cover = obj['cover']
|
||||
self.explicit = obj.get('explicit', False)
|
||||
self.size = obj['size']
|
||||
self.downloaded = obj.get('downloaded', 0)
|
||||
self.failed = obj.get('failed', 0)
|
||||
self.progress = obj.get('progress', 0)
|
||||
self.errors = obj.get('errors', [])
|
||||
self.files = obj.get('files', [])
|
||||
self.progressNext = 0
|
||||
self.uuid = f"{self.type}_{self.id}_{self.bitrate}"
|
||||
self.ack = None
|
||||
|
@ -76,17 +61,10 @@ class IDownloadObject:
|
|||
if interface: interface.send("updateQueue", {'uuid': self.uuid, 'progress': self.progress})
|
||||
|
||||
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):
|
||||
if dictItem:
|
||||
super().__init__(dictItem=dictItem)
|
||||
self.single = dictItem['single']
|
||||
else:
|
||||
super().__init__(type, id, bitrate, title, artist, cover, explicit, 1)
|
||||
self.single = {
|
||||
'trackAPI_gw': trackAPI_gw,
|
||||
'trackAPI': trackAPI,
|
||||
'albumAPI': albumAPI
|
||||
}
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
self.size = 1
|
||||
self.single = obj['single']
|
||||
self.__type__ = "Single"
|
||||
|
||||
def toDict(self):
|
||||
|
@ -103,17 +81,9 @@ class Single(IDownloadObject):
|
|||
self.updateProgress(interface)
|
||||
|
||||
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):
|
||||
if dictItem:
|
||||
super().__init__(dictItem=dictItem)
|
||||
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
|
||||
}
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
self.collection = obj['collection']
|
||||
self.__type__ = "Collection"
|
||||
|
||||
def toDict(self):
|
||||
|
@ -130,15 +100,10 @@ class Collection(IDownloadObject):
|
|||
self.updateProgress(interface)
|
||||
|
||||
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):
|
||||
if dictItem:
|
||||
super().__init__(dictItem=dictItem)
|
||||
self.plugin = dictItem['plugin']
|
||||
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
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
self.plugin = obj['plugin']
|
||||
self.conversion_data = obj['conversion_data']
|
||||
self.__type__ = "Convertable"
|
||||
|
||||
def toDict(self):
|
||||
|
|
|
@ -14,10 +14,9 @@ class Picture:
|
|||
)
|
||||
|
||||
if format.startswith("jpg"):
|
||||
quality = 80
|
||||
if '-' in format:
|
||||
quality = format[4:]
|
||||
else:
|
||||
quality = 80
|
||||
format = 'jpg'
|
||||
return url + f'-000000-{quality}-0-0.jpg'
|
||||
if format == 'png':
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
from time import sleep
|
||||
import requests
|
||||
|
||||
import logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger('deemix')
|
||||
from time import sleep
|
||||
|
||||
from deezer.gw import GWAPIError
|
||||
from deezer.api import APIError
|
||||
|
||||
from deemix.utils import removeFeatures, andCommaConcat, removeDuplicateArtists, generateReplayGainString, changeCase
|
||||
|
||||
from deemix.types.Album import Album
|
||||
|
@ -24,7 +21,7 @@ class Track:
|
|||
self.MD5 = ""
|
||||
self.mediaVersion = ""
|
||||
self.duration = 0
|
||||
self.fallbackId = "0"
|
||||
self.fallbackID = "0"
|
||||
self.filesizes = {}
|
||||
self.localTrack = False
|
||||
self.mainArtist = None
|
||||
|
@ -46,7 +43,7 @@ class Track:
|
|||
self.searched = False
|
||||
self.selectedFormat = 0
|
||||
self.singleDownload = False
|
||||
self.dateString = None
|
||||
self.dateString = ""
|
||||
self.artistsString = ""
|
||||
self.mainArtistsString = ""
|
||||
self.featArtistsString = ""
|
||||
|
@ -61,14 +58,14 @@ class Track:
|
|||
else:
|
||||
raise MD5NotFound
|
||||
self.mediaVersion = trackAPI_gw['MEDIA_VERSION']
|
||||
self.fallbackId = "0"
|
||||
self.fallbackID = "0"
|
||||
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
|
||||
|
||||
def retriveFilesizes(self, dz):
|
||||
try:
|
||||
guest_sid = dz.session.cookies.get('sid')
|
||||
try:
|
||||
site = requests.post(
|
||||
"https://api.deezer.com/1.0/gateway.php",
|
||||
params={
|
||||
|
@ -97,8 +94,7 @@ class Track:
|
|||
self.filesizes = filesizes
|
||||
|
||||
def parseData(self, dz, id=None, trackAPI_gw=None, trackAPI=None, albumAPI_gw=None, albumAPI=None, playlistAPI=None):
|
||||
if id:
|
||||
if not trackAPI_gw: trackAPI_gw = dz.gw.get_track_with_fallback(id)
|
||||
if id and not trackAPI_gw: trackAPI_gw = dz.gw.get_track_with_fallback(id)
|
||||
elif not trackAPI_gw: raise NoDataToParse
|
||||
if not trackAPI:
|
||||
try: trackAPI = dz.api.get_track(trackAPI_gw['SNG_ID'])
|
||||
|
@ -110,15 +106,15 @@ class Track:
|
|||
self.parseLocalTrackData(trackAPI_gw)
|
||||
else:
|
||||
self.retriveFilesizes(dz)
|
||||
|
||||
self.parseTrackGW(trackAPI_gw)
|
||||
|
||||
# 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)
|
||||
except GWAPIError: self.lyrics.id = "0"
|
||||
if self.lyrics.id != "0": self.lyrics.parseLyrics(trackAPI_gw["LYRICS"])
|
||||
|
||||
# Parse Album data
|
||||
# Parse Album Data
|
||||
self.album = Album(
|
||||
id = trackAPI_gw['ALB_ID'],
|
||||
title = trackAPI_gw['ALB_TITLE'],
|
||||
|
@ -161,7 +157,7 @@ class Track:
|
|||
if not len(self.artist['Main']):
|
||||
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')
|
||||
|
||||
# Add playlist data if track is in a playlist
|
||||
|
@ -184,16 +180,16 @@ class Track:
|
|||
self.artist = {
|
||||
'Main': [trackAPI_gw['ART_NAME']]
|
||||
}
|
||||
self.date = Date()
|
||||
self.album.artist = self.artist
|
||||
self.album.artists = self.artists
|
||||
self.album.date = self.date
|
||||
self.album.mainArtist = self.mainArtist
|
||||
self.date = Date()
|
||||
|
||||
def parseTrackGW(self, trackAPI_gw):
|
||||
self.title = trackAPI_gw['SNG_TITLE'].strip()
|
||||
if trackAPI_gw.get('VERSION') and not trackAPI_gw['VERSION'] in trackAPI_gw['SNG_TITLE']:
|
||||
self.title += " " + trackAPI_gw['VERSION'].strip()
|
||||
if trackAPI_gw.get('VERSION') and not trackAPI_gw['VERSION'].strip() in this.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")))
|
||||
|
@ -215,7 +211,7 @@ class Track:
|
|||
day = trackAPI_gw["PHYSICAL_RELEASE_DATE"][8:10]
|
||||
month = trackAPI_gw["PHYSICAL_RELEASE_DATE"][5:7]
|
||||
year = trackAPI_gw["PHYSICAL_RELEASE_DATE"][0:4]
|
||||
self.date = Date(year, month, day)
|
||||
self.date = Date(day, month, year)
|
||||
|
||||
def parseTrack(self, trackAPI):
|
||||
self.bpm = trackAPI['bpm']
|
||||
|
@ -250,8 +246,8 @@ class Track:
|
|||
return removeFeatures(self.title)
|
||||
|
||||
def getFeatTitle(self):
|
||||
if self.featArtistsString and not "(feat." in self.title.lower():
|
||||
return self.title + " ({})".format(self.featArtistsString)
|
||||
if self.featArtistsString and not "feat." in self.title.lower():
|
||||
return f"{self.title} ({self.featArtistsString})"
|
||||
return self.title
|
||||
|
||||
def generateMainFeatStrings(self):
|
||||
|
|
Loading…
Reference in New Issue