From 8f45ebc9ed9723b851855587d53cff5038187c67 Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Wed, 2 May 2018 18:08:36 +0300 Subject: [PATCH] Refactoring the detection of error types --- aiogram/bot/api.py | 61 ++------------------- aiogram/utils/exceptions.py | 104 +++++++++++++++++++++++------------- 2 files changed, 71 insertions(+), 94 deletions(-) diff --git a/aiogram/bot/api.py b/aiogram/bot/api.py index d80cd235..f5abfc23 100644 --- a/aiogram/bot/api.py +++ b/aiogram/bot/api.py @@ -60,7 +60,6 @@ async def _check_result(method_name, response): description = result_json.get('description') or body - # TODO: refactor the detection of error types if HTTPStatus.OK <= response.status <= HTTPStatus.IM_USED: return result_json.get('result') elif 'retry_after' in result_json: @@ -68,65 +67,13 @@ async def _check_result(method_name, response): elif 'migrate_to_chat_id' in result_json: raise exceptions.MigrateToChat(result_json['migrate_to_chat_id']) elif response.status == HTTPStatus.BAD_REQUEST: - if exceptions.MessageNotModified.check(description): - exceptions.MessageNotModified.throw() - elif exceptions.MessageToForwardNotFound.check(description): - exceptions.MessageToForwardNotFound.throw() - elif exceptions.MessageIdentifierNotSpecified.check(description): - exceptions.MessageIdentifierNotSpecified.throw() - elif exceptions.ChatNotFound.check(description): - exceptions.ChatNotFound.throw() - elif exceptions.InvalidQueryID.check(description): - exceptions.InvalidQueryID.throw() - elif exceptions.InvalidHTTPUrlContent.check(description): - exceptions.InvalidHTTPUrlContent.throw() - elif exceptions.GroupDeactivated.check(description): - exceptions.GroupDeactivated.throw() - elif exceptions.WrongFileIdentifier.check(description): - exceptions.WrongFileIdentifier.throw() - elif exceptions.InvalidPeerID.check(description): - exceptions.InvalidPeerID.throw() - elif exceptions.WebhookRequireHTTPS.check(description): - exceptions.WebhookRequireHTTPS.throw() - elif exceptions.BadWebhookPort.check(description): - exceptions.BadWebhookPort.throw() - elif exceptions.CantParseUrl.check(description): - exceptions.CantParseUrl.throw() - elif exceptions.PhotoAsInputFileRequired.check(description): - exceptions.PhotoAsInputFileRequired.throw() - elif exceptions.ToMuchMessages.check(description): - exceptions.ToMuchMessages.throw() - elif exceptions.InvalidStickersSet.check(description): - exceptions.InvalidStickersSet.throw() - elif exceptions.ChatAdminRequired.check(description): - exceptions.ChatAdminRequired.throw() - elif exceptions.PhotoDimensions.check(description): - exceptions.PhotoDimensions.throw() - elif exceptions.UnavailableMembers.check(description): - exceptions.UnavailableMembers.throw() - elif exceptions.TypeOfFileMismatch.check(description): - exceptions.TypeOfFileMismatch.throw() - raise exceptions.BadRequest(description) + exceptions.BadRequest.detect(description) elif response.status == HTTPStatus.NOT_FOUND: - if exceptions.MethodNotKnown.check(description): - exceptions.MethodNotKnown.throw() - raise exceptions.NotFound(description) + exceptions.NotFound.detect(description) elif response.status == HTTPStatus.CONFLICT: - if exceptions.TerminatedByOtherGetUpdates.check(description): - exceptions.TerminatedByOtherGetUpdates.throw() - if exceptions.CantGetUpdates.check(description): - exceptions.CantGetUpdates.throw() - raise exceptions.ConflictError(description) + exceptions.ConflictError.detect(description) elif response.status in [HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN]: - if exceptions.BotKicked.check(description): - exceptions.BotKicked.throw() - elif exceptions.BotBlocked.check(description): - exceptions.BotBlocked.throw() - elif exceptions.UserDeactivated.check(description): - exceptions.UserDeactivated.throw() - elif exceptions.CantInitiateConversation.check(description): - exceptions.UserDeactivated.throw() - raise exceptions.Unauthorized(description) + exceptions.Unauthorized.detect(description) elif response.status == HTTPStatus.REQUEST_ENTITY_TOO_LARGE: raise exceptions.NetworkError('File too large for uploading. ' 'Check telegram api limits https://core.telegram.org/bots/api#senddocument') diff --git a/aiogram/utils/exceptions.py b/aiogram/utils/exceptions.py index fa846ca3..99b174a1 100644 --- a/aiogram/utils/exceptions.py +++ b/aiogram/utils/exceptions.py @@ -63,14 +63,43 @@ class _MatchErrorMixin: match = '' text = None + __subclasses = [] + + def __init_subclass__(cls, **kwargs): + super(_MatchErrorMixin, cls).__init_subclass__(**kwargs) + # cls.match = cls.match.lower() if cls.match else '' + if not hasattr(cls, f"_{cls.__name__}__group"): + cls.__subclasses.append(cls) + @classmethod - def check(cls, message): - return cls.match in message + def check(cls, message) -> bool: + """ + Compare pattern with message + + :param message: always must be in lowercase + :return: bool + """ + return cls.match.lower() in message @classmethod def throw(cls): + """ + Throw a error + + :raise: this + """ raise cls(cls.text or cls.match) + @classmethod + def detect(cls, description): + description = description.lower() + for err in cls.__subclasses: + if err is cls: + continue + if err.check(description): + err.throw() + raise cls(description) + class AIOGramWarning(Warning): pass @@ -88,36 +117,37 @@ class ValidationError(TelegramAPIError): pass -class BadRequest(TelegramAPIError): - pass +class BadRequest(TelegramAPIError, _MatchErrorMixin): + __group = True class MessageError(BadRequest): + __group = True pass -class MessageNotModified(MessageError, _MatchErrorMixin): +class MessageNotModified(MessageError): """ Will be raised when you try to set new text is equals to current text. """ match = 'message is not modified' -class MessageToForwardNotFound(MessageError, _MatchErrorMixin): +class MessageToForwardNotFound(MessageError): """ Will be raised when you try to forward very old or deleted or unknown message. """ match = 'message to forward not found' -class MessageToDeleteNotFound(MessageError, _MatchErrorMixin): +class MessageToDeleteNotFound(MessageError): """ Will be raised when you try to delete very old or deleted or unknown message. """ match = 'message to delete not found' -class MessageIdentifierNotSpecified(MessageError, _MatchErrorMixin): +class MessageIdentifierNotSpecified(MessageError): match = 'message identifier is not specified' @@ -125,122 +155,122 @@ class ChatNotFound(BadRequest, _MatchErrorMixin): match = 'chat not found' -class InvalidQueryID(BadRequest, _MatchErrorMixin): +class InvalidQueryID(BadRequest): match = 'QUERY_ID_INVALID' text = 'Invalid query ID' -class InvalidPeerID(BadRequest, _MatchErrorMixin): +class InvalidPeerID(BadRequest): match = 'PEER_ID_INVALID' text = 'Invalid peer ID' -class InvalidHTTPUrlContent(BadRequest, _MatchErrorMixin): +class InvalidHTTPUrlContent(BadRequest): match = 'Failed to get HTTP URL content' -class WrongFileIdentifier(BadRequest, _MatchErrorMixin): +class WrongFileIdentifier(BadRequest): match = 'wrong file identifier/HTTP URL specified' -class GroupDeactivated(BadRequest, _MatchErrorMixin): +class GroupDeactivated(BadRequest): match = 'group is deactivated' -class PhotoAsInputFileRequired(BadRequest, _MatchErrorMixin): +class PhotoAsInputFileRequired(BadRequest): """ Will be raised when you try to set chat photo from file ID. """ match = 'Photo should be uploaded as an InputFile' -class ToMuchMessages(BadRequest, _MatchErrorMixin): +class ToMuchMessages(BadRequest): """ Will be raised when you try to send media group with more than 10 items. """ match = 'Too much messages to send as an album' -class InvalidStickersSet(BadRequest, _MatchErrorMixin): +class InvalidStickersSet(BadRequest): match = 'STICKERSET_INVALID' text = 'Stickers set is invalid' -class ChatAdminRequired(BadRequest, _MatchErrorMixin): +class ChatAdminRequired(BadRequest): match = 'CHAT_ADMIN_REQUIRED' text = 'Admin permissions is required!' -class PhotoDimensions(BadRequest, _MatchErrorMixin): +class PhotoDimensions(BadRequest): match = 'PHOTO_INVALID_DIMENSIONS' text = 'Invalid photo dimensions' -class UnavailableMembers(BadRequest, _MatchErrorMixin): +class UnavailableMembers(BadRequest): match = 'supergroup members are unavailable' -class TypeOfFileMismatch(BadRequest, _MatchErrorMixin): +class TypeOfFileMismatch(BadRequest): match = 'type of file mismatch' class BadWebhook(BadRequest): - pass + __group = True -class WebhookRequireHTTPS(BadWebhook, _MatchErrorMixin): +class WebhookRequireHTTPS(BadWebhook): match = 'HTTPS url must be provided for webhook' text = 'bad webhook: ' + match -class BadWebhookPort(BadWebhook, _MatchErrorMixin): +class BadWebhookPort(BadWebhook): match = 'Webhook can be set up only on ports 80, 88, 443 or 8443' text = 'bad webhook: ' + match -class CantParseUrl(BadRequest, _MatchErrorMixin): +class CantParseUrl(BadRequest): match = 'can\'t parse URL' -class NotFound(TelegramAPIError): - pass +class NotFound(TelegramAPIError, _MatchErrorMixin): + __group = True -class MethodNotKnown(NotFound, _MatchErrorMixin): +class MethodNotKnown(NotFound): match = 'method not found' -class ConflictError(TelegramAPIError): - pass +class ConflictError(TelegramAPIError, _MatchErrorMixin): + __group = True -class TerminatedByOtherGetUpdates(ConflictError, _MatchErrorMixin): +class TerminatedByOtherGetUpdates(ConflictError): match = 'terminated by other getUpdates request' text = 'Terminated by other getUpdates request; ' \ 'Make sure that only one bot instance is running' -class CantGetUpdates(ConflictError, _MatchErrorMixin): +class CantGetUpdates(ConflictError): match = 'can\'t use getUpdates method while webhook is active' -class Unauthorized(TelegramAPIError): - pass +class Unauthorized(TelegramAPIError, _MatchErrorMixin): + __group = True -class BotKicked(Unauthorized, _MatchErrorMixin): +class BotKicked(Unauthorized): match = 'Bot was kicked from a chat' -class BotBlocked(Unauthorized, _MatchErrorMixin): +class BotBlocked(Unauthorized): match = 'bot was blocked by the user' -class UserDeactivated(Unauthorized, _MatchErrorMixin): +class UserDeactivated(Unauthorized): match = 'user is deactivated' -class CantInitiateConversation(Unauthorized, _MatchErrorMixin): +class CantInitiateConversation(Unauthorized): match = 'bot can\'t initiate conversation with a user'