From f0b1c4171caca0d8696d552ec6bf112dfbaf9850 Mon Sep 17 00:00:00 2001 From: oribafi <82863310+oribafi@users.noreply.github.com> Date: Tue, 20 Apr 2021 23:30:45 +0200 Subject: [PATCH 1/4] Introduce distinct API exception types --- myjdapi/__init__.py | 39 ++++++- myjdapi/const.py | 36 ++++++ myjdapi/exception.py | 266 +++++++++++++++++++++++++++++++++++++++++++ myjdapi/myjdapi.py | 20 ++-- 4 files changed, 351 insertions(+), 10 deletions(-) create mode 100644 myjdapi/const.py create mode 100644 myjdapi/exception.py diff --git a/myjdapi/__init__.py b/myjdapi/__init__.py index b79833e..6244c8f 100644 --- a/myjdapi/__init__.py +++ b/myjdapi/__init__.py @@ -1,2 +1,37 @@ -from .myjdapi import Myjdapi -__version__ = '1.0.6' +from .myjdapi import Myjdapi +from .exception import ( + MYJDException, + MYJDConnectionException, + MYJDDeviceNotFoundException, + MYJDDecodeException, + MYJDApiException, + MYJDApiCommandNotFoundException, + MYJDApiInterfaceNotFoundException, + MYJDAuthFailedException, + MYJDBadParametersException, + MYJDBadRequestException, + MYJDChallengeFailedException, + MYJDEmailForbiddenException, + MYJDEmailInvalidException, + MYJDErrorEmailNotConfirmedException, + MYJDFailedException, + MYJDFileNotFoundException, + MYJDInternalServerErrorException, + MYJDMaintenanceException, + MYJDMethodForbiddenException, + MYJDOfflineException, + MYJDOutdatedException, + MYJDOverloadException, + MYJDSessionException, + MYJDStorageAlreadyExistsException, + MYJDStorageInvalidKeyException, + MYJDStorageInvalidStorageIdException, + MYJDStorageKeyNotFoundException, + MYJDStorageLimitReachedException, + MYJDStorageNotFoundException, + MYJDTokenInvalidException, + MYJDTooManyRequestsException, + MYJDUnknownException, +) + +__version__ = "1.0.6" diff --git a/myjdapi/const.py b/myjdapi/const.py new file mode 100644 index 0000000..c1cf110 --- /dev/null +++ b/myjdapi/const.py @@ -0,0 +1,36 @@ +"""Constants of the MyJDownloader API.""" + +# API Documentation: https://my.jdownloader.org/developers + +# MyJdownloader exception source +EXCEPTION_MYJD = "MYJD" +EXCEPTION_DEVICE = "DEVICE" + +# MyJdownloader exception type +EXCEPTION_API_COMMAND_NOT_FOUND = "API_COMMAND_NOT_FOUND" +EXCEPTION_API_INTERFACE_NOT_FOUND = "API_INTERFACE_NOT_FOUND" +EXCEPTION_AUTH_FAILED = "AUTH_FAILED" +EXCEPTION_BAD_PARAMETERS = "BAD_PARAMETERS" +EXCEPTION_BAD_REQUEST = "BAD_REQUEST" +EXCEPTION_CHALLENGE_FAILED = "CHALLENGE_FAILED" +EXCEPTION_EMAIL_FORBIDDEN = "EMAIL_FORBIDDEN" +EXCEPTION_EMAIL_INVALID = "EMAIL_INVALID" +EXCEPTION_ERROR_EMAIL_NOT_CONFIRMED = "ERROR_EMAIL_NOT_CONFIRMED" +EXCEPTION_FAILED = "FAILED" +EXCEPTION_FILE_NOT_FOUND = "FILE_NOT_FOUND" +EXCEPTION_INTERNAL_SERVER_ERROR = "INTERNAL_SERVER_ERROR" +EXCEPTION_MAINTENANCE = "MAINTENANCE" +EXCEPTION_METHOD_FORBIDDEN = "METHOD_FORBIDDEN" +EXCEPTION_OFFLINE = "OFFLINE" +EXCEPTION_OUTDATED = "OUTDATED" +EXCEPTION_OVERLOAD = "OVERLOAD" +EXCEPTION_SESSION = "SESSION" +EXCEPTION_STORAGE_ALREADY_EXISTS = "STORAGE_ALREADY_EXISTS" +EXCEPTION_STORAGE_INVALID_KEY = "STORAGE_INVALID_KEY" +EXCEPTION_STORAGE_INVALID_STORAGEID = "STORAGE_INVALID_STORAGEID" +EXCEPTION_STORAGE_KEY_NOT_FOUND = "STORAGE_KEY_NOT_FOUND" +EXCEPTION_STORAGE_LIMIT_REACHED = "STORAGE_LIMIT_REACHED" +EXCEPTION_STORAGE_NOT_FOUND = "STORAGE_NOT_FOUND" +EXCEPTION_TOKEN_INVALID = "TOKEN_INVALID" +EXCEPTION_TOO_MANY_REQUESTS = "TOO_MANY_REQUESTS" +EXCEPTION_UNKNOWN = "UNKNOWN" diff --git a/myjdapi/exception.py b/myjdapi/exception.py new file mode 100644 index 0000000..ec93a39 --- /dev/null +++ b/myjdapi/exception.py @@ -0,0 +1,266 @@ +"""Exceptions of the MyJDownloader API.""" + +from .const import ( + EXCEPTION_API_COMMAND_NOT_FOUND, + EXCEPTION_API_INTERFACE_NOT_FOUND, + EXCEPTION_AUTH_FAILED, + EXCEPTION_BAD_PARAMETERS, + EXCEPTION_BAD_REQUEST, + EXCEPTION_CHALLENGE_FAILED, + EXCEPTION_EMAIL_FORBIDDEN, + EXCEPTION_EMAIL_INVALID, + EXCEPTION_ERROR_EMAIL_NOT_CONFIRMED, + EXCEPTION_FAILED, + EXCEPTION_FILE_NOT_FOUND, + EXCEPTION_INTERNAL_SERVER_ERROR, + EXCEPTION_MAINTENANCE, + EXCEPTION_METHOD_FORBIDDEN, + EXCEPTION_OFFLINE, + EXCEPTION_OUTDATED, + EXCEPTION_OVERLOAD, + EXCEPTION_SESSION, + EXCEPTION_STORAGE_ALREADY_EXISTS, + EXCEPTION_STORAGE_INVALID_KEY, + EXCEPTION_STORAGE_INVALID_STORAGEID, + EXCEPTION_STORAGE_KEY_NOT_FOUND, + EXCEPTION_STORAGE_LIMIT_REACHED, + EXCEPTION_STORAGE_NOT_FOUND, + EXCEPTION_TOKEN_INVALID, + EXCEPTION_TOO_MANY_REQUESTS, + EXCEPTION_UNKNOWN, +) + + +class MYJDException(BaseException): + """Base MyJDownloader Exception.""" + + pass + + +class MYJDConnectionException(MYJDException): + """Connection Exception.""" + + pass + + +class MYJDDeviceNotFoundException(MYJDException): + """Device not found Exception.""" + + pass + + +class MYJDDecodeException(MYJDException): + """Decode Exception.""" + + pass + + +class MYJDApiException(MYJDException): + """Base MyJDownloader API Exception.""" + + @classmethod + def get_exception( + cls, exception_source, exception_type=EXCEPTION_UNKNOWN, *args, **kwargs + ): + """Get exception object from MyJDownloader exception type.""" + return EXCEPTION_CLASSES.get(exception_type.upper(), MYJDUnknownException)( + exception_source, *args, **kwargs + ) + + def __init__(self, exception_source, *args, **kwargs): + """Initialize MyJDownloader API exception.""" + self.source = exception_source.upper() + super().__init__(*args, **kwargs) + + +class MYJDApiCommandNotFoundException(MYJDApiException): + """MyJDownloader command not found API Exception.""" + + pass + + +class MYJDApiInterfaceNotFoundException(MYJDApiException): + """MyJDownloader interface not found API Exception.""" + + pass + + +class MYJDAuthFailedException(MYJDApiException): + """MyJDownloader auth failed API Exception.""" + + pass + + +class MYJDBadParametersException(MYJDApiException): + """MyJDownloader bad parameters API Exception.""" + + pass + + +class MYJDBadRequestException(MYJDApiException): + """MyJDownloader bad request API Exception.""" + + pass + + +class MYJDChallengeFailedException(MYJDApiException): + """MyJDownloader challenge failed API Exception.""" + + pass + + +class MYJDEmailForbiddenException(MYJDApiException): + """MyJDownloader email forbidden API Exception.""" + + pass + + +class MYJDEmailInvalidException(MYJDApiException): + """MyJDownloader email invalid API Exception.""" + + pass + + +class MYJDErrorEmailNotConfirmedException(MYJDApiException): + """MyJDownloader email not confirmed API Exception.""" + + pass + + +class MYJDFailedException(MYJDApiException): + """MyJDownloader failed API Exception.""" + + pass + + +class MYJDFileNotFoundException(MYJDApiException): + """MyJDownloader file not found API Exception.""" + + pass + + +class MYJDInternalServerErrorException(MYJDApiException): + """MyJDownloader internal server error API Exception.""" + + pass + + +class MYJDMaintenanceException(MYJDApiException): + """MyJDownloader maintenance API Exception.""" + + pass + + +class MYJDMethodForbiddenException(MYJDApiException): + """MyJDownloader method forbidden API Exception.""" + + pass + + +class MYJDOfflineException(MYJDApiException): + """MyJDownloader offline API Exception.""" + + pass + + +class MYJDOutdatedException(MYJDApiException): + """MyJDownloader outdated API Exception.""" + + pass + + +class MYJDOverloadException(MYJDApiException): + """MyJDownloader overload API Exception.""" + + pass + + +class MYJDSessionException(MYJDApiException): + """MyJDownloader session API Exception.""" + + pass + + +class MYJDStorageAlreadyExistsException(MYJDApiException): + """MyJDownloader storage already exists API Exception.""" + + pass + + +class MYJDStorageInvalidKeyException(MYJDApiException): + """MyJDownloader storage invalid key API Exception.""" + + pass + + +class MYJDStorageInvalidStorageIdException(MYJDApiException): + """MyJDownloader storage invalid storage id API Exception.""" + + pass + + +class MYJDStorageKeyNotFoundException(MYJDApiException): + """MyJDownloader storage key not found API Exception.""" + + pass + + +class MYJDStorageLimitReachedException(MYJDApiException): + """MyJDownloader storage limit reached API Exception.""" + + pass + + +class MYJDStorageNotFoundException(MYJDApiException): + """MyJDownloader storage not found API Exception.""" + + pass + + +class MYJDTokenInvalidException(MYJDApiException): + """MyJDownloader token invalid API Exception.""" + + pass + + +class MYJDTooManyRequestsException(MYJDApiException): + """MyJDownloader too many request API Exception.""" + + pass + + +class MYJDUnknownException(MYJDApiException): + """MyJDownloader unknown API Exception.""" + + pass + + +EXCEPTION_CLASSES = { + EXCEPTION_API_COMMAND_NOT_FOUND: MYJDApiCommandNotFoundException, + EXCEPTION_API_INTERFACE_NOT_FOUND: MYJDApiInterfaceNotFoundException, + EXCEPTION_AUTH_FAILED: MYJDAuthFailedException, + EXCEPTION_BAD_PARAMETERS: MYJDBadParametersException, + EXCEPTION_BAD_REQUEST: MYJDBadRequestException, + EXCEPTION_CHALLENGE_FAILED: MYJDChallengeFailedException, + EXCEPTION_EMAIL_FORBIDDEN: MYJDEmailForbiddenException, + EXCEPTION_EMAIL_INVALID: MYJDEmailInvalidException, + EXCEPTION_ERROR_EMAIL_NOT_CONFIRMED: MYJDErrorEmailNotConfirmedException, + EXCEPTION_FAILED: MYJDFailedException, + EXCEPTION_FILE_NOT_FOUND: MYJDFileNotFoundException, + EXCEPTION_INTERNAL_SERVER_ERROR: MYJDInternalServerErrorException, + EXCEPTION_MAINTENANCE: MYJDMaintenanceException, + EXCEPTION_METHOD_FORBIDDEN: MYJDMethodForbiddenException, + EXCEPTION_OFFLINE: MYJDOfflineException, + EXCEPTION_OUTDATED: MYJDOutdatedException, + EXCEPTION_OVERLOAD: MYJDOverloadException, + EXCEPTION_SESSION: MYJDSessionException, + EXCEPTION_STORAGE_ALREADY_EXISTS: MYJDStorageAlreadyExistsException, + EXCEPTION_STORAGE_INVALID_KEY: MYJDStorageInvalidKeyException, + EXCEPTION_STORAGE_INVALID_STORAGEID: MYJDStorageInvalidStorageIdException, + EXCEPTION_STORAGE_KEY_NOT_FOUND: MYJDStorageKeyNotFoundException, + EXCEPTION_STORAGE_LIMIT_REACHED: MYJDStorageLimitReachedException, + EXCEPTION_STORAGE_NOT_FOUND: MYJDStorageNotFoundException, + EXCEPTION_TOKEN_INVALID: MYJDTokenInvalidException, + EXCEPTION_TOO_MANY_REQUESTS: MYJDTooManyRequestsException, + EXCEPTION_UNKNOWN: MYJDUnknownException, +} diff --git a/myjdapi/myjdapi.py b/myjdapi/myjdapi.py index 5517f5c..d1d7f88 100644 --- a/myjdapi/myjdapi.py +++ b/myjdapi/myjdapi.py @@ -14,11 +14,15 @@ import requests from Crypto.Cipher import AES -BS = 16 +from .exception import ( + MYJDApiException, + MYJDConnectionException, + MYJDDecodeException, + MYJDDeviceNotFoundException +) -class MYJDException(BaseException): - pass +BS = 16 def PAD(s): @@ -1003,7 +1007,7 @@ def get_device(self, device_name=None, device_id=None): :param deviceid: """ if not self.is_connected(): - raise (MYJDException("No connection established\n")) + raise (MYJDConnectionException("No connection established\n")) if device_id is not None: for device in self.__devices: if device["id"] == device_id: @@ -1012,7 +1016,7 @@ def get_device(self, device_name=None, device_id=None): for device in self.__devices: if device["name"] == device_name: return Jddevice(self, device) - raise (MYJDException("Device not found\n")) + raise (MYJDDeviceNotFoundException("Device not found\n")) def request_api(self, path, @@ -1033,7 +1037,7 @@ def request_api(self, api = self.__api_url data = None if not self.is_connected() and path != "/my/connect": - raise (MYJDException("No connection established\n")) + raise (MYJDConnectionException("No connection established\n")) if http_method == "GET": query = [path + "?"] if params is not None: @@ -1100,7 +1104,7 @@ def request_api(self, try: error_msg = json.loads(self.__decrypt(self.__device_encryption_token, encrypted_response.text)) except json.JSONDecodeError: - raise MYJDException("Failed to decode response: {}", encrypted_response.text) + raise MYJDDecodeException("Failed to decode response: {}", encrypted_response.text) msg = "\n\tSOURCE: " + error_msg["src"] + "\n\tTYPE: " + \ error_msg["type"] + "\n------\nREQUEST_URL: " + \ api + path @@ -1109,7 +1113,7 @@ def request_api(self, msg += "\n" if data is not None: msg += "DATA:\n" + data - raise (MYJDException(msg)) + raise (MYJDApiException.get_exception(error_msg["src"], error_msg["type"], msg)) if action is None: if not self.__server_encryption_token: response = self.__decrypt(self.__login_secret, From cf8720991a1631c930539c71b1ef16339b0197c1 Mon Sep 17 00:00:00 2001 From: oribafi <82863310+oribafi@users.noreply.github.com> Date: Fri, 23 Apr 2021 18:14:39 +0200 Subject: [PATCH 2/4] Make MYJDException importable with previous import path --- myjdapi/myjdapi.py | 1 + 1 file changed, 1 insertion(+) diff --git a/myjdapi/myjdapi.py b/myjdapi/myjdapi.py index d1d7f88..be72b26 100644 --- a/myjdapi/myjdapi.py +++ b/myjdapi/myjdapi.py @@ -15,6 +15,7 @@ from Crypto.Cipher import AES from .exception import ( + MYJDException, MYJDApiException, MYJDConnectionException, MYJDDecodeException, From 973087c6767e3fb79da2d53cd4c16ddad3537485 Mon Sep 17 00:00:00 2001 From: Marc Marquez Santamaria Date: Sat, 1 May 2021 08:34:40 +0200 Subject: [PATCH 3/4] Update myjdapi/exception.py --- myjdapi/exception.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/myjdapi/exception.py b/myjdapi/exception.py index ec93a39..dd307eb 100644 --- a/myjdapi/exception.py +++ b/myjdapi/exception.py @@ -70,7 +70,7 @@ def get_exception( def __init__(self, exception_source, *args, **kwargs): """Initialize MyJDownloader API exception.""" self.source = exception_source.upper() - super().__init__(*args, **kwargs) + super(MYJDApiException, self).__init__(*args, **kwargs) class MYJDApiCommandNotFoundException(MYJDApiException): From 900f15b50b71118ee5f79e5adee30e547564b167 Mon Sep 17 00:00:00 2001 From: Marc Marquez Santamaria Date: Sat, 1 May 2021 08:50:52 +0200 Subject: [PATCH 4/4] Changed version and removed useless comments. --- myjdapi/__init__.py | 2 +- myjdapi/myjdapi.py | 2 -- setup.py | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/myjdapi/__init__.py b/myjdapi/__init__.py index 6244c8f..32ae807 100644 --- a/myjdapi/__init__.py +++ b/myjdapi/__init__.py @@ -34,4 +34,4 @@ MYJDUnknownException, ) -__version__ = "1.0.6" +__version__ = "1.0.7" diff --git a/myjdapi/myjdapi.py b/myjdapi/myjdapi.py index be72b26..c043315 100644 --- a/myjdapi/myjdapi.py +++ b/myjdapi/myjdapi.py @@ -762,7 +762,6 @@ def action(self, path, params=(), http_action="POST"): connection = conn['conn'] api = "http://" + connection["ip"] + ":" + str( connection["port"]) - # if self.myjd.request_api("/device/ping", "POST", None, self.__action_url(), api): response = self.myjd.request_api(path, http_action, params, action_url, api) if response is not None: @@ -1067,7 +1066,6 @@ def request_api(self, if params is not None: for param in params: if not isinstance(param, list): - # params_request+=[str(param).replace("'",'\"').replace("True","true").replace("False","false").replace('None',"null")] params_request += [json.dumps(param)] else: params_request += [param] diff --git a/setup.py b/setup.py index 025b2fd..dfe781f 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ long_description = f.read() setup( name='myjdapi', - version='1.0.6', + version='1.0.7', description='Library to use My.Jdownloader API in an easy way.', long_description=long_description, url='https://github.com/mmarquezs/My.Jdownloader-API-Python-Library/', @@ -31,6 +31,5 @@ ], keywords='myjdapi jdownloader my.jdownloader api development', packages=find_packages(exclude=['contrib', 'docs', 'tests']), - # py_modules=["libgenapi"], install_requires=['requests','pycryptodome'], )