diff --git a/deemix/decryption.py b/deemix/decryption.py index 3315f74..f40a164 100644 --- a/deemix/decryption.py +++ b/deemix/decryption.py @@ -10,6 +10,7 @@ from deemix.utils.crypto import _md5, _ecbCrypt, _ecbDecrypt, generateBlowfishKe from deemix.utils import USER_AGENT_HEADER from deemix.types.DownloadObjects import Single +from deemix.errors import DownloadCanceled, DownloadEmpty logger = logging.getLogger('deemix') @@ -101,9 +102,3 @@ def streamTrack(outputStream, track, start=0, downloadObject=None, listener=None except (RequestsConnectionError, ReadTimeout, ChunkedEncodingError): sleep(2) streamTrack(outputStream, track, start, downloadObject, listener) - -class DownloadCanceled(Exception): - pass - -class DownloadEmpty(Exception): - pass diff --git a/deemix/downloader.py b/deemix/downloader.py index f8b6d56..f761dd5 100644 --- a/deemix/downloader.py +++ b/deemix/downloader.py @@ -18,14 +18,16 @@ from urllib3.exceptions import SSLError as u3SSLError from mutagen.flac import FLACNoHeaderError, error as FLACError from deezer import TrackFormats +from deezer.errors import WrongLicense from deemix.types.DownloadObjects import Single, Collection -from deemix.types.Track import Track, AlbumDoesntExists, MD5NotFound +from deemix.types.Track import Track from deemix.types.Picture import StaticPicture from deemix.utils import USER_AGENT_HEADER from deemix.utils.pathtemplates import generatePath, generateAlbumName, generateArtistName, generateDownloadObjectName from deemix.tagger import tagID3, tagFLAC -from deemix.decryption import generateCryptedStreamURL, streamTrack, DownloadCanceled +from deemix.decryption import generateCryptedStreamURL, streamTrack from deemix.settings import OverwriteOption +from deemix.errors import DownloadFailed, MD5NotFound, DownloadCanceled, PreferredBitrateNotFound, TrackNot360, AlbumDoesntExists, DownloadError, ErrorMessages logger = logging.getLogger('deemix') @@ -416,7 +418,7 @@ class Downloader: def downloadWrapper(self, extraData, track=None): trackAPI_gw = extraData['trackAPI_gw'] - if ('_EXTRA_TRACK' in trackAPI_gw): + if '_EXTRA_TRACK' in trackAPI_gw: extraData['trackAPI'] = trackAPI_gw['_EXTRA_TRACK'].copy() del extraData['trackAPI_gw']['_EXTRA_TRACK'] del trackAPI_gw['_EXTRA_TRACK'] @@ -459,7 +461,7 @@ class Downloader: }) return self.downloadWrapper(extraData, track) error.errid += "NoAlternative" - error.message = errorMessages[error.errid] + error.message = ErrorMessages[error.errid] result = {'error': { 'message': error.message, 'errid': error.errid, @@ -570,37 +572,3 @@ class Downloader: # Execute command after download if self.settings['executeCommand'] != "": execute(self.settings['executeCommand'].replace("%folder%", quote(str(self.extrasPath)))) - -class DownloadError(Exception): - """Base class for exceptions in this module.""" - -errorMessages = { - 'notOnDeezer': "Track not available on Deezer!", - 'notEncoded': "Track not yet encoded!", - 'notEncodedNoAlternative': "Track not yet encoded and no alternative found!", - 'wrongBitrate': "Track not found at desired bitrate.", - 'wrongBitrateNoAlternative': "Track not found at desired bitrate and no alternative found!", - 'wrongLicense': "Your account can't stream the track at the desired bitrate", - 'no360RA': "Track is not available in Reality Audio 360.", - 'notAvailable': "Track not available on deezer's servers!", - 'notAvailableNoAlternative': "Track not available on deezer's servers and no alternative found!", - 'noSpaceLeft': "No space left on target drive, clean up some space for the tracks", - 'albumDoesntExists': "Track's album does not exsist, failed to gather info" -} - -class DownloadFailed(DownloadError): - def __init__(self, errid, track=None): - super().__init__() - self.errid = errid - self.message = errorMessages[self.errid] - self.track = track - -class PreferredBitrateNotFound(DownloadError): - pass - -class TrackNot360(DownloadError): - pass - -class WrongLicense(DownloadError): - def __init__(self, format): - self.message = f"Your account doesn't have the license to stream {format}" diff --git a/deemix/errors.py b/deemix/errors.py new file mode 100644 index 0000000..10b5a70 --- /dev/null +++ b/deemix/errors.py @@ -0,0 +1,93 @@ +class DeemixError(Exception): + """Base exception for this module""" + +class GenerationError(DeemixError): + """Generation related errors""" + def __init__(self, link, message, errid=None): + super().__init__() + self.link = link + self.message = message + self.errid = errid + + def toDict(self): + return { + 'link': self.link, + 'error': self.message, + 'errid': self.errid + } + +class ISRCnotOnDeezer(GenerationError): + def __init__(self, link): + super().__init__(link, "Track ISRC is not available on deezer", "ISRCnotOnDeezer") + +class NotYourPrivatePlaylist(GenerationError): + def __init__(self, link): + super().__init__(link, "You can't download others private playlists.", "notYourPrivatePlaylist") + +class TrackNotOnDeezer(GenerationError): + def __init__(self, link): + super().__init__(link, "Track not found on deezer!", "trackNotOnDeezer") + +class AlbumNotOnDeezer(GenerationError): + def __init__(self, link): + super().__init__(link, "Album not found on deezer!", "albumNotOnDeezer") + +class InvalidID(GenerationError): + def __init__(self, link): + super().__init__(link, "Link ID is invalid!", "invalidID") + +class LinkNotSupported(GenerationError): + def __init__(self, link): + super().__init__(link, "Link is not supported.", "unsupportedURL") + +class LinkNotRecognized(GenerationError): + def __init__(self, link): + super().__init__(link, "Link is not recognized.", "invalidURL") + +class DownloadError(DeemixError): + """Download related errors""" + +ErrorMessages = { + 'notOnDeezer': "Track not available on Deezer!", + 'notEncoded': "Track not yet encoded!", + 'notEncodedNoAlternative': "Track not yet encoded and no alternative found!", + 'wrongBitrate': "Track not found at desired bitrate.", + 'wrongBitrateNoAlternative': "Track not found at desired bitrate and no alternative found!", + 'wrongLicense': "Your account can't stream the track at the desired bitrate", + 'no360RA': "Track is not available in Reality Audio 360.", + 'notAvailable': "Track not available on deezer's servers!", + 'notAvailableNoAlternative': "Track not available on deezer's servers and no alternative found!", + 'noSpaceLeft': "No space left on target drive, clean up some space for the tracks", + 'albumDoesntExists': "Track's album does not exsist, failed to gather info" +} + +class DownloadFailed(DownloadError): + def __init__(self, errid, track=None): + super().__init__() + self.errid = errid + self.message = ErrorMessages[self.errid] + self.track = track + +class PreferredBitrateNotFound(DownloadError): + pass + +class TrackNot360(DownloadError): + pass + +class DownloadCanceled(DownloadError): + pass + +class DownloadEmpty(DownloadError): + pass + +class TrackError(DeemixError): + """Track generation related errors""" + +class AlbumDoesntExists(TrackError): + pass + +class MD5NotFound(TrackError): + pass + +class NoDataToParse(TrackError): + pass diff --git a/deemix/itemgen.py b/deemix/itemgen.py index e0ddbf0..2676928 100644 --- a/deemix/itemgen.py +++ b/deemix/itemgen.py @@ -1,10 +1,12 @@ import logging -from deemix.types.DownloadObjects import Single, Collection -from deezer.gw import GWAPIError, LyricsStatus -from deezer.api import APIError +from deezer.gw import LyricsStatus +from deezer.errors import GWAPIError, APIError from deezer.utils import map_user_playlist +from deemix.types.DownloadObjects import Single, Collection +from deemix.errors import GenerationError, ISRCnotOnDeezer, InvalidID, NotYourPrivatePlaylist + logger = logging.getLogger('deemix') def generateTrackItem(dz, link_id, bitrate, trackAPI=None, albumAPI=None): @@ -263,45 +265,3 @@ def generateArtistTopItem(dz, link_id, bitrate): artistTopTracksAPI_gw = dz.gw.get_artist_toptracks(link_id) return generatePlaylistItem(dz, playlistAPI['id'], bitrate, playlistAPI=playlistAPI, playlistTracksAPI=artistTopTracksAPI_gw) - -class GenerationError(Exception): - def __init__(self, link, message, errid=None): - super().__init__() - self.link = link - self.message = message - self.errid = errid - - def toDict(self): - return { - 'link': self.link, - 'error': self.message, - 'errid': self.errid - } - -class ISRCnotOnDeezer(GenerationError): - def __init__(self, link): - super().__init__(link, "Track ISRC is not available on deezer", "ISRCnotOnDeezer") - -class NotYourPrivatePlaylist(GenerationError): - def __init__(self, link): - super().__init__(link, "You can't download others private playlists.", "notYourPrivatePlaylist") - -class TrackNotOnDeezer(GenerationError): - def __init__(self, link): - super().__init__(link, "Track not found on deezer!", "trackNotOnDeezer") - -class AlbumNotOnDeezer(GenerationError): - def __init__(self, link): - super().__init__(link, "Album not found on deezer!", "albumNotOnDeezer") - -class InvalidID(GenerationError): - def __init__(self, link): - super().__init__(link, "Link ID is invalid!", "invalidID") - -class LinkNotSupported(GenerationError): - def __init__(self, link): - super().__init__(link, "Link is not supported.", "unsupportedURL") - -class LinkNotRecognized(GenerationError): - def __init__(self, link): - super().__init__(link, "Link is not recognized.", "invalidURL") diff --git a/deemix/types/Track.py b/deemix/types/Track.py index af16e6f..9f86b42 100644 --- a/deemix/types/Track.py +++ b/deemix/types/Track.py @@ -2,8 +2,8 @@ from time import sleep import re import requests -from deezer.gw import GWAPIError -from deezer.api import APIError +from deezer.errors import APIError, GWAPIError +from deemix.errors import TrackError, NoDataToParse, AlbumDoesntExists from deemix.utils import removeFeatures, andCommaConcat, removeDuplicateArtists, generateReplayGainString, changeCase @@ -335,15 +335,3 @@ class Track: self.artistsString = separator.join(self.artist['Main']) else: self.artistsString = separator.join(self.artists) - -class TrackError(Exception): - """Base class for exceptions in this module.""" - -class AlbumDoesntExists(TrackError): - pass - -class MD5NotFound(TrackError): - pass - -class NoDataToParse(TrackError): - pass diff --git a/setup.py b/setup.py index 58a4386..de5d5da 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ setup( python_requires='>=3.7', packages=find_packages(exclude=("tests",)), include_package_data=True, - install_requires=["click", "pycryptodomex", "mutagen", "requests", "spotipy>=2.11.0", "deezer-py>=1.0.3"], + install_requires=["click", "pycryptodomex", "mutagen", "requests", "spotipy>=2.11.0", "deezer-py>=1.1.0"], entry_points={ "console_scripts": [ "deemix=deemix.__main__:download",