from typing import Any, Optional
from aiogram.methods import TelegramMethod
from aiogram.methods.base import TelegramType
from aiogram.utils.link import docs_url
[docs]
class AiogramError(Exception):
"""
Base exception for all aiogram errors.
"""
[docs]
class DetailedAiogramError(AiogramError):
"""
Base exception for all aiogram errors with detailed message.
"""
url: Optional[str] = None
def __init__(self, message: str) -> None:
self.message = message
def __str__(self) -> str:
message = self.message
if self.url:
message += f"\n(background on this error at: {self.url})"
return message
def __repr__(self) -> str:
return f"{type(self).__name__}('{self}')"
[docs]
class CallbackAnswerException(AiogramError):
"""
Exception for callback answer.
"""
[docs]
class SceneException(AiogramError):
"""
Exception for scenes.
"""
[docs]
class UnsupportedKeywordArgument(DetailedAiogramError):
"""
Exception raised when a keyword argument is passed as filter.
"""
url = docs_url("migration_2_to_3.html", fragment_="filtering-events")
[docs]
class TelegramAPIError(DetailedAiogramError):
"""
Base exception for all Telegram API errors.
"""
label: str = "Telegram server says"
def __init__(
self,
method: TelegramMethod[TelegramType],
message: str,
) -> None:
super().__init__(message=message)
self.method = method
def __str__(self) -> str:
original_message = super().__str__()
return f"{self.label} - {original_message}"
[docs]
class TelegramNetworkError(TelegramAPIError):
"""
Base exception for all Telegram network errors.
"""
label = "HTTP Client says"
[docs]
class TelegramRetryAfter(TelegramAPIError):
"""
Exception raised when flood control exceeds.
"""
url = "https://core.telegram.org/bots/faq#my-bot-is-hitting-limits-how-do-i-avoid-this"
def __init__(
self,
method: TelegramMethod[TelegramType],
message: str,
retry_after: int,
) -> None:
description = f"Flood control exceeded on method {type(method).__name__!r}"
if chat_id := getattr(method, "chat_id", None):
description += f" in chat {chat_id}"
description += f". Retry in {retry_after} seconds."
description += f"\nOriginal description: {message}"
super().__init__(method=method, message=description)
self.retry_after = retry_after
[docs]
class TelegramMigrateToChat(TelegramAPIError):
"""
Exception raised when chat has been migrated to a supergroup.
"""
url = "https://core.telegram.org/bots/api#responseparameters"
def __init__(
self,
method: TelegramMethod[TelegramType],
message: str,
migrate_to_chat_id: int,
) -> None:
description = f"The group has been migrated to a supergroup with id {migrate_to_chat_id}"
if chat_id := getattr(method, "chat_id", None):
description += f" from {chat_id}"
description += f"\nOriginal description: {message}"
super().__init__(method=method, message=message)
self.migrate_to_chat_id = migrate_to_chat_id
[docs]
class TelegramBadRequest(TelegramAPIError):
"""
Exception raised when request is malformed.
"""
[docs]
class TelegramNotFound(TelegramAPIError):
"""
Exception raised when chat, message, user, etc. not found.
"""
[docs]
class TelegramConflictError(TelegramAPIError):
"""
Exception raised when bot token is already used by another application in polling mode.
"""
[docs]
class TelegramUnauthorizedError(TelegramAPIError):
"""
Exception raised when bot token is invalid.
"""
[docs]
class TelegramForbiddenError(TelegramAPIError):
"""
Exception raised when bot is kicked from chat or etc.
"""
[docs]
class TelegramServerError(TelegramAPIError):
"""
Exception raised when Telegram server returns 5xx error.
"""
[docs]
class RestartingTelegram(TelegramServerError):
"""
Exception raised when Telegram server is restarting.
It seems like this error is not used by Telegram anymore,
but it's still here for backward compatibility.
Currently, you should expect that Telegram can raise RetryAfter (with timeout 5 seconds)
error instead of this one.
"""
[docs]
class ClientDecodeError(AiogramError):
"""
Exception raised when client can't decode response. (Malformed response, etc.)
"""
def __init__(self, message: str, original: Exception, data: Any) -> None:
self.message = message
self.original = original
self.data = data
def __str__(self) -> str:
original_type = type(self.original)
return (
f"{self.message}\n"
f"Caused from error: "
f"{original_type.__module__}.{original_type.__name__}: {self.original}\n"
f"Content: {self.data}"
)