Исходный код raito.plugins.scenes.registry

from __future__ import annotations

from typing import TYPE_CHECKING, Any

from aiogram.dispatcher.flags import extract_flags_from_object
from aiogram.filters import StateFilter

if TYPE_CHECKING:
    from collections.abc import Callable

    from aiogram.dispatcher.event.handler import CallbackType
    from aiogram.dispatcher.event.telegram import TelegramEventObserver
    from aiogram.fsm.state import State

    from .manager import SceneManager
    from .middleware import SceneMiddleware

__all__ = ("SceneRegistry",)


[документация] class SceneRegistry: """Registers a scene's handlers for one aiogram event type. A scene exposes one of these per event as ``scene.on_message``, ``scene.on_callback_query``, and ``scene.on_edited_message``. Call it with a step's state to handle that step, use :meth:`any` for a handler that runs on every step, or use :meth:`enter` to start the scene. Its :class:`SceneMiddleware` is installed on the observer only when the first handler is added, so an event type without scene handlers is never touched. """ def __init__( self, scene: SceneManager[Any], observer: TelegramEventObserver, name: str, middleware: SceneMiddleware, ) -> None: """Bind the registry to one observer of the scene's router. :param scene: scene the handlers belong to :param observer: aiogram event observer to register on :param name: event name, also the handler's event argument :param middleware: middleware installed on first registration """ self._scene = scene self._observer = observer self._name = name self._middleware = middleware self._installed = False def __call__( self, state: State, *filters: CallbackType ) -> Callable[[CallbackType], CallbackType]: """Register a handler for the ``state`` step. :param state: step to handle, a state of the scene's ``StatesGroup`` :param filters: extra filters applied on top of the step's state :return: decorator for the step handler :raises ValueError: if ``state`` is not a step of this scene """ self._scene.steps.ensure(state) return self._register((StateFilter(state), *filters), entry=False)
[документация] def any(self, *filters: CallbackType) -> Callable[[CallbackType], CallbackType]: """Register a handler that runs on any active step of this scene. Useful for something that should work no matter where the user is in the dialog, e.g. a ``/cancel`` command or a persistent "Cancel" button: .. code-block:: python @mute.on_message.any(filters.Command("cancel")) async def cancel_anywhere(scene: Scene[MuteData]) -> None: await scene.cancel() :param filters: filters applied on top of "any step of this scene" :return: decorator for the handler """ return self._register((StateFilter(*self._scene.steps.states), *filters), entry=False)
[документация] def enter(self, *filters: CallbackType) -> Callable[[CallbackType], CallbackType]: """Register a handler that starts the scene from a fresh draft. :param filters: filters that trigger the scene, e.g. ``Command("mute")`` :return: decorator for the entry handler """ return self._register(filters, entry=True)
def _register( self, filters: tuple[CallbackType, ...], *, entry: bool, ) -> Callable[[CallbackType], CallbackType]: if not self._installed: self._observer.outer_middleware(self._middleware) self._installed = True def decorator(callback: CallbackType) -> CallbackType: handler = self._scene.build_handler(callback, self._name, entry=entry) self._observer.register(handler, *filters, flags=extract_flags_from_object(callback)) return callback return decorator