More detailed exceptions.

This commit is contained in:
Alex Root Junior 2018-03-30 19:32:23 +03:00
parent 8cac7c3303
commit 5571f3d4ec
4 changed files with 205 additions and 10 deletions

View file

@ -1,12 +1,12 @@
import os
import logging
import os
from http import HTTPStatus
import aiohttp
from .. import types
from ..utils import json
from ..utils import exceptions
from ..utils import json
from ..utils.helper import Helper, HelperMode, Item
# Main aiogram logger
@ -67,10 +67,48 @@ 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()
raise exceptions.BadRequest(description)
elif response.status == HTTPStatus.NOT_FOUND:
if exceptions.MethodNotKnown.check(description):
exceptions.MethodNotKnown.throw()
raise exceptions.NotFound(description)
elif response.status == HTTPStatus.CONFLICT:
if exceptions.TerminatedByOtherGetUpdates.match(description):
exceptions.TerminatedByOtherGetUpdates.throw()
if exceptions.CantGetUpdates.match(description):
exceptions.CantGetUpdates.throw()
raise exceptions.ConflictError(description)
elif response.status in [HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN]:
if exceptions.BotKicked.match(description):
exceptions.BotKicked.throw()
elif exceptions.BotBlocked.match(description):
exceptions.BotBlocked.throw()
elif exceptions.UserDeactivated.match(description):
exceptions.UserDeactivated.throw()
raise exceptions.Unauthorized(description)
elif response.status == HTTPStatus.REQUEST_ENTITY_TOO_LARGE:
raise exceptions.NetworkError('File too large for uploading. '

View file

@ -1,5 +1,8 @@
import typing
from ..utils.deprecated import warn_deprecated as warn
from ..utils.exceptions import FSMStorageWarning
# Leak bucket
KEY = 'key'
LAST_CALL = 'called_at'
@ -324,22 +327,29 @@ class DisabledStorage(BaseStorage):
chat: typing.Union[str, int, None] = None,
user: typing.Union[str, int, None] = None,
default: typing.Optional[str] = None) -> typing.Dict:
self._warn()
return {}
async def update_data(self, *,
chat: typing.Union[str, int, None] = None,
user: typing.Union[str, int, None] = None,
data: typing.Dict = None, **kwargs):
pass
self._warn()
async def set_state(self, *,
chat: typing.Union[str, int, None] = None,
user: typing.Union[str, int, None] = None,
state: typing.Optional[typing.AnyStr] = None):
pass
self._warn()
async def set_data(self, *,
chat: typing.Union[str, int, None] = None,
user: typing.Union[str, int, None] = None,
data: typing.Dict = None):
pass
self._warn()
@staticmethod
def _warn():
warn(f"You havent set any storage yet so no states and no data will be saved. \n"
f"You can connect MemoryStorage for debug purposes or non-essential data.",
FSMStorageWarning, 5)

View file

@ -69,7 +69,7 @@ def deprecated(reason):
raise TypeError(repr(type(reason)))
def warn_deprecated(message, warning=DeprecationWarning):
def warn_deprecated(message, warning=DeprecationWarning, stacklevel=2):
warnings.simplefilter('always', warning)
warnings.warn(message, category=warning, stacklevel=2)
warnings.warn(message, category=warning, stacklevel=stacklevel)
warnings.simplefilter('default', warning)

View file

@ -1,6 +1,42 @@
"""
TelegramAPIError
ValidationError
Throttled
BadRequest
MessageError
MessageNotModified
MessageToForwardNotFound
MessageToDeleteNotFound
MessageIdentifierNotSpecified
ChatNotFound
InvalidQueryID
InvalidPeerID
InvalidHTTPUrlContent
WrongFileIdentifier
GroupDeactivated
BadWebhook
WebhookRequireHTTPS
BadWebhookPort
CantParseUrl
NotFound
MethodNotKnown
ConflictError
TerminatedByOtherGetUpdates
CantGetUpdates
Unauthorized
BotKicked
BotBlocked
UserDeactivated
NetworkError
RetryAfter
MigrateToChat
AIOGramWarning
TimeoutWarning
"""
import time
_PREFIXES = ['Error: ', '[Error]: ', 'Bad Request: ', 'Conflict: ']
_PREFIXES = ['Error: ', '[Error]: ', 'Bad Request: ', 'Conflict: ', 'Not Found: ']
def _clean_message(text):
@ -11,10 +47,23 @@ def _clean_message(text):
class TelegramAPIError(Exception):
def __init__(self, message):
def __init__(self, message=None):
super(TelegramAPIError, self).__init__(_clean_message(message))
class _MatchErrorMixin:
match = ''
text = None
@classmethod
def check(cls, message):
return cls.match in message
@classmethod
def throw(cls):
raise cls(cls.text or cls.match)
class AIOGramWarning(Warning):
pass
@ -23,6 +72,10 @@ class TimeoutWarning(AIOGramWarning):
pass
class FSMStorageWarning(AIOGramWarning):
pass
class ValidationError(TelegramAPIError):
pass
@ -31,14 +84,108 @@ class BadRequest(TelegramAPIError):
pass
class MessageError(BadRequest):
pass
class MessageNotModified(MessageError, _MatchErrorMixin):
match = 'message is not modified'
class MessageToForwardNotFound(MessageError, _MatchErrorMixin):
match = 'message to forward not found'
class MessageToDeleteNotFound(MessageError, _MatchErrorMixin):
match = 'message to delete not found'
class MessageIdentifierNotSpecified(MessageError, _MatchErrorMixin):
match = 'message identifier is not specified'
class ChatNotFound(BadRequest, _MatchErrorMixin):
match = 'chat not found'
class InvalidQueryID(BadRequest, _MatchErrorMixin):
match = 'QUERY_ID_INVALID'
text = 'Invalid query ID'
class InvalidPeerID(BadRequest, _MatchErrorMixin):
match = 'PEER_ID_INVALID'
text = 'Invalid peer ID'
class InvalidHTTPUrlContent(BadRequest, _MatchErrorMixin):
match = 'Failed to get HTTP URL content'
class WrongFileIdentifier(BadRequest, _MatchErrorMixin):
match = 'wrong file identifier/HTTP URL specified'
class GroupDeactivated(BadRequest, _MatchErrorMixin):
match = 'group is deactivated'
class BadWebhook(BadRequest):
pass
class WebhookRequireHTTPS(BadRequest, _MatchErrorMixin):
match = 'HTTPS url must be provided for webhook'
text = 'bad webhook: ' + match
class BadWebhookPort(BadRequest, _MatchErrorMixin):
match = 'Webhook can be set up only on ports 80, 88, 443 or 8443'
text = 'bad webhook: ' + match
class CantParseUrl(BadRequest, _MatchErrorMixin):
match = 'can\'t parse URL'
class NotFound(TelegramAPIError):
pass
class MethodNotKnown(NotFound, _MatchErrorMixin):
match = 'method not found'
class ConflictError(TelegramAPIError):
pass
class TerminatedByOtherGetUpdates(ConflictError, _MatchErrorMixin):
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):
match = 'can\'t use getUpdates method while webhook is active'
class Unauthorized(TelegramAPIError):
pass
class BotKicked(Unauthorized, _MatchErrorMixin):
match = 'Bot was kicked from a chat'
class BotBlocked(Unauthorized, _MatchErrorMixin):
match = 'bot was blocked by the user'
class UserDeactivated(Unauthorized, _MatchErrorMixin):
match = 'user is deactivated'
class NetworkError(TelegramAPIError):
pass
@ -55,7 +202,7 @@ class MigrateToChat(TelegramAPIError):
self.migrate_to_chat_id = chat_id
class Throttled(Exception):
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, '<None>')