From 2451b88ff5830d3d25ed5d20378b956a2826f772 Mon Sep 17 00:00:00 2001 From: jrootjunior Date: Wed, 11 Dec 2019 15:25:28 +0200 Subject: [PATCH] Disable old API exceptions --- aiogram/utils/exceptions.py | 948 +++++++++++------------ tests/test_dispatcher/test_dispatcher.py | 1 + 2 files changed, 474 insertions(+), 475 deletions(-) diff --git a/aiogram/utils/exceptions.py b/aiogram/utils/exceptions.py index b164be4d..3efe7032 100644 --- a/aiogram/utils/exceptions.py +++ b/aiogram/utils/exceptions.py @@ -82,484 +82,482 @@ - AIOGramWarning - TimeoutWarning """ -import time - -# TODO: Use exceptions detector from `aiograph`. -# TODO: aiogram.utils.exceptions.BadRequest: Bad request: can't parse entities: unsupported start tag "function" at byte offset 0 -# TODO: aiogram.utils.exceptions.TelegramAPIError: Gateway Timeout - -_PREFIXES = ["error: ", "[error]: ", "bad request: ", "conflict: ", "not found: "] - - -def _clean_message(text): - for prefix in _PREFIXES: - if text.startswith(prefix): - text = text[len(prefix) :] - return (text[0].upper() + text[1:]).strip() class TelegramAPIError(Exception): - def __init__(self, message=None): - super(TelegramAPIError, self).__init__(_clean_message(message)) - - -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) -> bool: - """ - Compare pattern with message - - :param message: always must be in lowercase - :return: bool - """ - return cls.match.lower() in message - - @classmethod - def detect(cls, description): - description = description.lower() - for err in cls.__subclasses: - if err is cls: - continue - if err.check(description): - raise err(cls.text or description) - raise cls(description) - - -class AIOGramWarning(Warning): pass -class TimeoutWarning(AIOGramWarning): - pass - - -class FSMStorageWarning(AIOGramWarning): - pass - - -class ValidationError(TelegramAPIError): - pass - - -class BadRequest(TelegramAPIError, _MatchErrorMixin): - __group = True - - -class MessageError(BadRequest): - __group = True - - -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): - """ - Will be raised when you try to forward very old or deleted or unknown message. - """ - - match = "message to forward not found" - - -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 MessageToReplyNotFound(MessageError): - """ - Will be raised when you try to reply to very old or deleted or unknown message. - """ - - match = "message to reply not found" - - -class MessageIdentifierNotSpecified(MessageError): - match = "message identifier is not specified" - - -class MessageTextIsEmpty(MessageError): - match = "Message text is empty" - - -class MessageCantBeEdited(MessageError): - match = "message can't be edited" - - -class MessageCantBeDeleted(MessageError): - match = "message can't be deleted" - - -class MessageToEditNotFound(MessageError): - match = "message to edit not found" - - -class MessageIsTooLong(MessageError): - match = "message is too long" - - -class ToMuchMessages(MessageError): - """ - 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 ObjectExpectedAsReplyMarkup(BadRequest): - match = "object expected as reply markup" - - -class InlineKeyboardExpected(BadRequest): - match = "inline keyboard expected" - - -class PollError(BadRequest): - __group = True - - -class PollCantBeStopped(PollError): - match = "poll can't be stopped" - - -class PollHasAlreadyBeenClosed(PollError): - match = "poll has already been closed" - - -class PollsCantBeSentToPrivateChats(PollError): - match = "polls can't be sent to private chats" - - -class PollSizeError(PollError): - __group = True - - -class PollMustHaveMoreOptions(PollSizeError): - match = "poll must have at least 2 option" - - -class PollCantHaveMoreOptions(PollSizeError): - match = "poll can't have more than 10 options" - - -class PollOptionsMustBeNonEmpty(PollSizeError): - match = "poll options must be non-empty" - - -class PollQuestionMustBeNonEmpty(PollSizeError): - match = "poll question must be non-empty" - - -class PollOptionsLengthTooLong(PollSizeError): - match = "poll options length must not exceed 100" - - -class PollQuestionLengthTooLong(PollSizeError): - match = "poll question length must not exceed 255" - - -class MessageWithPollNotFound(PollError, MessageError): - """ - Will be raised when you try to stop poll with message without poll - """ - - match = "message with poll to stop not found" - - -class MessageIsNotAPoll(PollError, MessageError): - """ - Will be raised when you try to stop poll with message without poll - """ - - match = "message is not a poll" - - -class ChatNotFound(BadRequest): - match = "chat not found" - - -class ChatIdIsEmpty(BadRequest): - match = "chat_id is empty" - - -class InvalidUserId(BadRequest): - match = "user_id_invalid" - text = "Invalid user id" - - -class ChatDescriptionIsNotModified(BadRequest): - match = "chat description is not modified" - - -class InvalidQueryID(BadRequest): - match = "query is too old and response timeout expired or query id is invalid" - - -class InvalidPeerID(BadRequest): - match = "PEER_ID_INVALID" - text = "Invalid peer ID" - - -class InvalidHTTPUrlContent(BadRequest): - match = "Failed to get HTTP URL content" - - -class ButtonURLInvalid(BadRequest): - match = "BUTTON_URL_INVALID" - text = "Button URL invalid" - - -class URLHostIsEmpty(BadRequest): - match = "URL host is empty" - - -class StartParamInvalid(BadRequest): - match = "START_PARAM_INVALID" - text = "Start param invalid" - - -class ButtonDataInvalid(BadRequest): - match = "BUTTON_DATA_INVALID" - text = "Button data invalid" - - -class WrongFileIdentifier(BadRequest): - match = "wrong file identifier/HTTP URL specified" - - -class GroupDeactivated(BadRequest): - match = "group is deactivated" - - -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 InvalidStickersSet(BadRequest): - match = "STICKERSET_INVALID" - text = "Stickers set is invalid" - - -class NoStickerInRequest(BadRequest): - match = "there is no sticker in the request" - - -class ChatAdminRequired(BadRequest): - match = "CHAT_ADMIN_REQUIRED" - text = "Admin permissions is required!" - - -class NeedAdministratorRightsInTheChannel(BadRequest): - match = "need administrator rights in the channel chat" - text = "Admin permissions is required!" - - -class NotEnoughRightsToPinMessage(BadRequest): - match = "not enough rights to pin a message" - - -class MethodNotAvailableInPrivateChats(BadRequest): - match = "method is available only for supergroups and channel" - - -class CantDemoteChatCreator(BadRequest): - match = "can't demote chat creator" - - -class CantRestrictSelf(BadRequest): - match = "can't restrict self" - text = "Admin can't restrict self." - - -class NotEnoughRightsToRestrict(BadRequest): - match = "not enough rights to restrict/unrestrict chat member" - - -class PhotoDimensions(BadRequest): - match = "PHOTO_INVALID_DIMENSIONS" - text = "Invalid photo dimensions" - - -class UnavailableMembers(BadRequest): - match = "supergroup members are unavailable" - - -class TypeOfFileMismatch(BadRequest): - match = "type of file mismatch" - - -class WrongRemoteFileIdSpecified(BadRequest): - match = "wrong remote file id specified" - - -class PaymentProviderInvalid(BadRequest): - match = "PAYMENT_PROVIDER_INVALID" - text = "payment provider invalid" - - -class CurrencyTotalAmountInvalid(BadRequest): - match = "currency_total_amount_invalid" - text = "currency total amount invalid" - - -class BadWebhook(BadRequest): - __group = True - - -class WebhookRequireHTTPS(BadWebhook): - match = "HTTPS url must be provided for webhook" - text = "bad webhook: " + match - - -class BadWebhookPort(BadWebhook): - match = "Webhook can be set up only on ports 80, 88, 443 or 8443" - text = "bad webhook: " + match - - -class BadWebhookAddrInfo(BadWebhook): - match = "getaddrinfo: Temporary failure in name resolution" - text = "bad webhook: " + match - - -class BadWebhookNoAddressAssociatedWithHostname(BadWebhook): - match = "failed to resolve host: no address associated with hostname" - - -class CantParseUrl(BadRequest): - match = "can't parse URL" - - -class UnsupportedUrlProtocol(BadRequest): - match = "unsupported URL protocol" - - -class CantParseEntities(BadRequest): - match = "can't parse entities" - - -class ResultIdDuplicate(BadRequest): - match = "result_id_duplicate" - text = "Result ID duplicate" - - -class BotDomainInvalid(BadRequest): - match = "bot_domain_invalid" - text = "Invalid bot domain" - - -class NotFound(TelegramAPIError, _MatchErrorMixin): - __group = True - - -class MethodNotKnown(NotFound): - match = "method not found" - - -class ConflictError(TelegramAPIError, _MatchErrorMixin): - __group = True - - -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): - match = "can't use getUpdates method while webhook is active" - - -class Unauthorized(TelegramAPIError, _MatchErrorMixin): - __group = True - - -class BotKicked(Unauthorized): - match = "bot was kicked from a chat" - - -class BotBlocked(Unauthorized): - match = "bot was blocked by the user" - - -class UserDeactivated(Unauthorized): - match = "user is deactivated" - - -class CantInitiateConversation(Unauthorized): - match = "bot can't initiate conversation with a user" - - -class CantTalkWithBots(Unauthorized): - match = "bot can't send messages to bots" - - -class NetworkError(TelegramAPIError): - pass - - -class RestartingTelegram(TelegramAPIError): - def __init__(self): - super(RestartingTelegram, self).__init__( - "The Telegram Bot API service is restarting. Wait few second." - ) - - -class RetryAfter(TelegramAPIError): - def __init__(self, retry_after): - super(RetryAfter, self).__init__( - f"Flood control exceeded. Retry in {retry_after} seconds." - ) - self.timeout = retry_after - - -class MigrateToChat(TelegramAPIError): - def __init__(self, chat_id): - super(MigrateToChat, self).__init__( - f"The group has been migrated to a supergroup. New id: {chat_id}." - ) - self.migrate_to_chat_id = chat_id - - -class Throttled(TelegramAPIError): - def __init__(self, **kwargs): - from ..dispatcher.storage import DELTA, EXCEEDED_COUNT, KEY, LAST_CALL, RATE_LIMIT, RESULT - - self.key = kwargs.pop(KEY, "") - self.called_at = kwargs.pop(LAST_CALL, time.time()) - self.rate = kwargs.pop(RATE_LIMIT, None) - self.result = kwargs.pop(RESULT, False) - self.exceeded_count = kwargs.pop(EXCEEDED_COUNT, 0) - self.delta = kwargs.pop(DELTA, 0) - self.user = kwargs.pop("user", None) - self.chat = kwargs.pop("chat", None) - - def __str__(self): - return ( - f"Rate limit exceeded! (Limit: {self.rate} s, " - f"exceeded: {self.exceeded_count}, " - f"time delta: {round(self.delta, 3)} s)" - ) +# _PREFIXES = ["error: ", "[error]: ", "bad request: ", "conflict: ", "not found: "] +# + +# def _clean_message(text): +# for prefix in _PREFIXES: +# if text.startswith(prefix): +# text = text[len(prefix) :] +# return (text[0].upper() + text[1:]).strip() +# + + +# +# +# 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) -> bool: +# """ +# Compare pattern with message +# +# :param message: always must be in lowercase +# :return: bool +# """ +# return cls.match.lower() in message +# +# @classmethod +# def detect(cls, description): +# description = description.lower() +# for err in cls.__subclasses: +# if err is cls: +# continue +# if err.check(description): +# raise err(cls.text or description) +# raise cls(description) +# +# +# class AIOGramWarning(Warning): +# pass +# +# +# class TimeoutWarning(AIOGramWarning): +# pass +# +# +# class FSMStorageWarning(AIOGramWarning): +# pass +# +# +# class ValidationError(TelegramAPIError): +# pass +# +# +# class BadRequest(TelegramAPIError, _MatchErrorMixin): +# __group = True +# +# +# class MessageError(BadRequest): +# __group = True +# +# +# 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): +# """ +# Will be raised when you try to forward very old or deleted or unknown message. +# """ +# +# match = "message to forward not found" +# +# +# 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 MessageToReplyNotFound(MessageError): +# """ +# Will be raised when you try to reply to very old or deleted or unknown message. +# """ +# +# match = "message to reply not found" +# +# +# class MessageIdentifierNotSpecified(MessageError): +# match = "message identifier is not specified" +# +# +# class MessageTextIsEmpty(MessageError): +# match = "Message text is empty" +# +# +# class MessageCantBeEdited(MessageError): +# match = "message can't be edited" +# +# +# class MessageCantBeDeleted(MessageError): +# match = "message can't be deleted" +# +# +# class MessageToEditNotFound(MessageError): +# match = "message to edit not found" +# +# +# class MessageIsTooLong(MessageError): +# match = "message is too long" +# +# +# class ToMuchMessages(MessageError): +# """ +# 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 ObjectExpectedAsReplyMarkup(BadRequest): +# match = "object expected as reply markup" +# +# +# class InlineKeyboardExpected(BadRequest): +# match = "inline keyboard expected" +# +# +# class PollError(BadRequest): +# __group = True +# +# +# class PollCantBeStopped(PollError): +# match = "poll can't be stopped" +# +# +# class PollHasAlreadyBeenClosed(PollError): +# match = "poll has already been closed" +# +# +# class PollsCantBeSentToPrivateChats(PollError): +# match = "polls can't be sent to private chats" +# +# +# class PollSizeError(PollError): +# __group = True +# +# +# class PollMustHaveMoreOptions(PollSizeError): +# match = "poll must have at least 2 option" +# +# +# class PollCantHaveMoreOptions(PollSizeError): +# match = "poll can't have more than 10 options" +# +# +# class PollOptionsMustBeNonEmpty(PollSizeError): +# match = "poll options must be non-empty" +# +# +# class PollQuestionMustBeNonEmpty(PollSizeError): +# match = "poll question must be non-empty" +# +# +# class PollOptionsLengthTooLong(PollSizeError): +# match = "poll options length must not exceed 100" +# +# +# class PollQuestionLengthTooLong(PollSizeError): +# match = "poll question length must not exceed 255" +# +# +# class MessageWithPollNotFound(PollError, MessageError): +# """ +# Will be raised when you try to stop poll with message without poll +# """ +# +# match = "message with poll to stop not found" +# +# +# class MessageIsNotAPoll(PollError, MessageError): +# """ +# Will be raised when you try to stop poll with message without poll +# """ +# +# match = "message is not a poll" +# +# +# class ChatNotFound(BadRequest): +# match = "chat not found" +# +# +# class ChatIdIsEmpty(BadRequest): +# match = "chat_id is empty" +# +# +# class InvalidUserId(BadRequest): +# match = "user_id_invalid" +# text = "Invalid user id" +# +# +# class ChatDescriptionIsNotModified(BadRequest): +# match = "chat description is not modified" +# +# +# class InvalidQueryID(BadRequest): +# match = "query is too old and response timeout expired or query id is invalid" +# +# +# class InvalidPeerID(BadRequest): +# match = "PEER_ID_INVALID" +# text = "Invalid peer ID" +# +# +# class InvalidHTTPUrlContent(BadRequest): +# match = "Failed to get HTTP URL content" +# +# +# class ButtonURLInvalid(BadRequest): +# match = "BUTTON_URL_INVALID" +# text = "Button URL invalid" +# +# +# class URLHostIsEmpty(BadRequest): +# match = "URL host is empty" +# +# +# class StartParamInvalid(BadRequest): +# match = "START_PARAM_INVALID" +# text = "Start param invalid" +# +# +# class ButtonDataInvalid(BadRequest): +# match = "BUTTON_DATA_INVALID" +# text = "Button data invalid" +# +# +# class WrongFileIdentifier(BadRequest): +# match = "wrong file identifier/HTTP URL specified" +# +# +# class GroupDeactivated(BadRequest): +# match = "group is deactivated" +# +# +# 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 InvalidStickersSet(BadRequest): +# match = "STICKERSET_INVALID" +# text = "Stickers set is invalid" +# +# +# class NoStickerInRequest(BadRequest): +# match = "there is no sticker in the request" +# +# +# class ChatAdminRequired(BadRequest): +# match = "CHAT_ADMIN_REQUIRED" +# text = "Admin permissions is required!" +# +# +# class NeedAdministratorRightsInTheChannel(BadRequest): +# match = "need administrator rights in the channel chat" +# text = "Admin permissions is required!" +# +# +# class NotEnoughRightsToPinMessage(BadRequest): +# match = "not enough rights to pin a message" +# +# +# class MethodNotAvailableInPrivateChats(BadRequest): +# match = "method is available only for supergroups and channel" +# +# +# class CantDemoteChatCreator(BadRequest): +# match = "can't demote chat creator" +# +# +# class CantRestrictSelf(BadRequest): +# match = "can't restrict self" +# text = "Admin can't restrict self." +# +# +# class NotEnoughRightsToRestrict(BadRequest): +# match = "not enough rights to restrict/unrestrict chat member" +# +# +# class PhotoDimensions(BadRequest): +# match = "PHOTO_INVALID_DIMENSIONS" +# text = "Invalid photo dimensions" +# +# +# class UnavailableMembers(BadRequest): +# match = "supergroup members are unavailable" +# +# +# class TypeOfFileMismatch(BadRequest): +# match = "type of file mismatch" +# +# +# class WrongRemoteFileIdSpecified(BadRequest): +# match = "wrong remote file id specified" +# +# +# class PaymentProviderInvalid(BadRequest): +# match = "PAYMENT_PROVIDER_INVALID" +# text = "payment provider invalid" +# +# +# class CurrencyTotalAmountInvalid(BadRequest): +# match = "currency_total_amount_invalid" +# text = "currency total amount invalid" +# +# +# class BadWebhook(BadRequest): +# __group = True +# +# +# class WebhookRequireHTTPS(BadWebhook): +# match = "HTTPS url must be provided for webhook" +# text = "bad webhook: " + match +# +# +# class BadWebhookPort(BadWebhook): +# match = "Webhook can be set up only on ports 80, 88, 443 or 8443" +# text = "bad webhook: " + match +# +# +# class BadWebhookAddrInfo(BadWebhook): +# match = "getaddrinfo: Temporary failure in name resolution" +# text = "bad webhook: " + match +# +# +# class BadWebhookNoAddressAssociatedWithHostname(BadWebhook): +# match = "failed to resolve host: no address associated with hostname" +# +# +# class CantParseUrl(BadRequest): +# match = "can't parse URL" +# +# +# class UnsupportedUrlProtocol(BadRequest): +# match = "unsupported URL protocol" +# +# +# class CantParseEntities(BadRequest): +# match = "can't parse entities" +# +# +# class ResultIdDuplicate(BadRequest): +# match = "result_id_duplicate" +# text = "Result ID duplicate" +# +# +# class BotDomainInvalid(BadRequest): +# match = "bot_domain_invalid" +# text = "Invalid bot domain" +# +# +# class NotFound(TelegramAPIError, _MatchErrorMixin): +# __group = True +# +# +# class MethodNotKnown(NotFound): +# match = "method not found" +# +# +# class ConflictError(TelegramAPIError, _MatchErrorMixin): +# __group = True +# +# +# 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): +# match = "can't use getUpdates method while webhook is active" +# +# +# class Unauthorized(TelegramAPIError, _MatchErrorMixin): +# __group = True +# +# +# class BotKicked(Unauthorized): +# match = "bot was kicked from a chat" +# +# +# class BotBlocked(Unauthorized): +# match = "bot was blocked by the user" +# +# +# class UserDeactivated(Unauthorized): +# match = "user is deactivated" +# +# +# class CantInitiateConversation(Unauthorized): +# match = "bot can't initiate conversation with a user" +# +# +# class CantTalkWithBots(Unauthorized): +# match = "bot can't send messages to bots" +# +# +# class NetworkError(TelegramAPIError): +# pass +# +# +# class RestartingTelegram(TelegramAPIError): +# def __init__(self): +# super(RestartingTelegram, self).__init__( +# "The Telegram Bot API service is restarting. Wait few second." +# ) +# +# +# class RetryAfter(TelegramAPIError): +# def __init__(self, retry_after): +# super(RetryAfter, self).__init__( +# f"Flood control exceeded. Retry in {retry_after} seconds." +# ) +# self.timeout = retry_after +# +# +# class MigrateToChat(TelegramAPIError): +# def __init__(self, chat_id): +# super(MigrateToChat, self).__init__( +# f"The group has been migrated to a supergroup. New id: {chat_id}." +# ) +# self.migrate_to_chat_id = chat_id +# +# +# class Throttled(TelegramAPIError): +# def __init__(self, **kwargs): +# from ..dispatcher.storage import DELTA, EXCEEDED_COUNT, KEY, LAST_CALL, RATE_LIMIT, RESULT +# +# self.key = kwargs.pop(KEY, "") +# self.called_at = kwargs.pop(LAST_CALL, time.time()) +# self.rate = kwargs.pop(RATE_LIMIT, None) +# self.result = kwargs.pop(RESULT, False) +# self.exceeded_count = kwargs.pop(EXCEEDED_COUNT, 0) +# self.delta = kwargs.pop(DELTA, 0) +# self.user = kwargs.pop("user", None) +# self.chat = kwargs.pop("chat", None) +# +# def __str__(self): +# return ( +# f"Rate limit exceeded! (Limit: {self.rate} s, " +# f"exceeded: {self.exceeded_count}, " +# f"time delta: {round(self.delta, 3)} s)" +# ) diff --git a/tests/test_dispatcher/test_dispatcher.py b/tests/test_dispatcher/test_dispatcher.py index edcb7b74..bc032d35 100644 --- a/tests/test_dispatcher/test_dispatcher.py +++ b/tests/test_dispatcher/test_dispatcher.py @@ -92,6 +92,7 @@ class TestDispatcher: index += 1 if index == 42: break + assert index == 42 @pytest.mark.asyncio async def test_silent_call_request(self, bot: MockedBot, caplog):