From 09448f1b7189fb1f332aded69bcfb15607058b18 Mon Sep 17 00:00:00 2001 From: andrew000 <11490628+andrew000@users.noreply.github.com> Date: Sat, 10 Sep 2022 01:30:38 +0300 Subject: [PATCH] Added a new argument `once` to the error handler registration that decides whether the following callback notifications should be made after a successful callback notification before in loop --- aiogram/dispatcher/dispatcher.py | 21 +++++++++++++++++---- aiogram/dispatcher/handler.py | 8 ++++++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/aiogram/dispatcher/dispatcher.py b/aiogram/dispatcher/dispatcher.py index 22f6700c..813a9dee 100644 --- a/aiogram/dispatcher/dispatcher.py +++ b/aiogram/dispatcher/dispatcher.py @@ -1200,32 +1200,45 @@ class Dispatcher(DataMixin, ContextInstanceMixin): return decorator - def register_errors_handler(self, callback, *custom_filters, exception=None, run_task=None, **kwargs): + def register_errors_handler(self, + callback, + *custom_filters, + exception=None, + run_task=None, + once: typing.Optional[bool] = None, + **kwargs): """ Register handler for errors :param callback: :param exception: you can make handler for specific errors type :param run_task: run callback in task (no wait results) + :param once: run handler only once """ filters_set = self.filters_factory.resolve(self.errors_handlers, *custom_filters, exception=exception, **kwargs) - self.errors_handlers.register(self._wrap_async_task(callback, run_task), filters_set) + self.errors_handlers.register(self._wrap_async_task(callback, run_task), filters_set, once) - def errors_handler(self, *custom_filters, exception=None, run_task=None, **kwargs): + def errors_handler(self, + *custom_filters, + exception=None, + run_task=None, + once: typing.Optional[bool] = None, + **kwargs): """ Decorator for errors handler :param exception: you can make handler for specific errors type :param run_task: run callback in task (no wait results) + :param once: run handler only once :return: """ def decorator(callback): self.register_errors_handler(self._wrap_async_task(callback, run_task), - *custom_filters, exception=exception, **kwargs) + *custom_filters, exception=exception, once=once, **kwargs) return callback return decorator diff --git a/aiogram/dispatcher/handler.py b/aiogram/dispatcher/handler.py index 4efc2e07..344e3b87 100644 --- a/aiogram/dispatcher/handler.py +++ b/aiogram/dispatcher/handler.py @@ -43,7 +43,7 @@ class Handler: self.handlers: typing.List[Handler.HandlerObj] = [] self.middleware_key = middleware_key - def register(self, handler, filters=None, index=None): + def register(self, handler, filters=None, index=None, once: typing.Optional[bool] = None): """ Register callback @@ -52,6 +52,7 @@ class Handler: :param handler: coroutine :param filters: list of filters :param index: you can reorder handlers + :param once: if True, handler will be called only once """ from .filters import get_filters_spec @@ -67,6 +68,9 @@ class Handler: else: self.handlers.insert(index, record) + if once is not None: + self.once = once + def unregister(self, handler): """ Remove handler @@ -116,7 +120,7 @@ class Handler: response = await handler_obj.handler(*args, **partial_data) if response is not None: results.append(response) - if self.once: + if self.once is True: break except SkipHandler: continue