Skip to content

Instantly share code, notes, and snippets.

@antibagr
Last active December 13, 2020 12:47
Show Gist options
  • Save antibagr/329f4bf0d91e890b07ddbc81402a7d66 to your computer and use it in GitHub Desktop.
Save antibagr/329f4bf0d91e890b07ddbc81402a7d66 to your computer and use it in GitHub Desktop.
from functools import wraps
from typing import Callable, Awaitable, Any, Union
from aiogram import types
# sends to user when handler raises exception
ERROR_MESSAGE = "No, I'm dying. Please tell BotFather I love him ..."
def wrap_exception(f: Awaitable) -> Awaitable:
"""
Decorates f with handling exception.
If any handler raises an exception, a user will receive ERROR_MESSAGE
And then exception will be raised again to go up to errors_handler
"""
@wraps(f)
async def decorator(trg: Union[types.Message, types.CallbackQuery], *args, **kwargs) -> Any:
try:
return await f(trg, *args, **kwargs)
except Exception:
user = trg if isinstance(trg, types.Message) else trg.message
await user.answer(ERROR_MESSAGE)
# Exception will be raised after a user has received
# information about something bad happened
# on a server side.
raise
return decorator
def get_updated_handler(original_handler: Callable):
"""
What do we do here is wrapping every handler in a whole bot application
with a wrap_exception decorator which simply tries to execute function
And if something bad happend it will nofity whoever called the function
That something bad happended and after it exception will be raised up
to the Dispatcher error handler.
:param Callable original_handler: .
"""
def updated_handler(*handler_args, **handler_kwargs) -> Callable:
"""
A function will be called instead of dp.message_handler
And will return updated_decorator instead of inner aiogram
Decorator
"""
def updated_decorator(f: Awaitable) -> Awaitable:
"""
Actially this function is returned when some handler
called @dp.message_handler().
A function still may think that it's the same as before
But what actually happens is that we wrap it with our wrap_exception
decorator.
So when it will be called and if it will raise exception
We can be sure about a user received an information about this exception
Instead of waiting forever without knowning nobody gonna answer him.
"""
handler_decorator = original_handler(*handler_args, **handler_kwargs)
safe_call = handler_decorator(wrap_exception(f))
return safe_call
return updated_decorator
return updated_handler
"""
How to use it anyway ?
import aiogram
bot = aiogram.Bot(token=BOT_TOKEN)
dp = aiogram.Dispatcher(bot)
dp.message_handler = get_updated_handler(dp.message_handler)
dp.callback_query_handler = get_updated_handler(dp.callback_query_handler)
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment