diff --git a/aiogram/dispatcher/flags/getter.py b/aiogram/dispatcher/flags/getter.py index 13568251..0c2c90dd 100644 --- a/aiogram/dispatcher/flags/getter.py +++ b/aiogram/dispatcher/flags/getter.py @@ -13,6 +13,12 @@ def extract_flags_from_object(obj: Any) -> Dict[str, Any]: def extract_flags(handler: Union["HandlerObject", Dict[str, Any]]) -> Dict[str, Any]: + """ + Extract flags from handler or middleware context data + + :param handler: handler object or data + :return: dictionary with all handler flags + """ if isinstance(handler, dict) and "handler" in handler: handler = handler["handler"] if not hasattr(handler, "flags"): @@ -26,10 +32,25 @@ def get_flag( *, default: Optional[Any] = None, ) -> Any: + """ + Get flag by name + + :param handler: handler object or data + :param name: name of the flag + :param default: default value (None) + :return: value of the flag or default + """ flags = extract_flags(handler) return flags.get(name, default) def check_flags(handler: Union["HandlerObject", Dict[str, Any]], magic: MagicFilter) -> Any: + """ + Check flags via magic filter + + :param handler: handler object or data + :param magic: instance of the magic + :return: the result of magic filter check + """ flags = extract_flags(handler) return magic.resolve(AttrDict(flags)) diff --git a/docs/dispatcher/flags.rst b/docs/dispatcher/flags.rst new file mode 100644 index 00000000..f4e5e118 --- /dev/null +++ b/docs/dispatcher/flags.rst @@ -0,0 +1,89 @@ +===== +Flags +===== + +Flags is a markers for handlers that can be used in `middlewares <#use-in-middlewares>`_ +or special `utilities <#use-in-utilities>`_ to make classification of the handlers. + +Flags can be added to the handler via `decorators <#via-decorators>`_, +`handlers registration <#via-handler-registration-method>`_ or +`filters `_. + +Via decorators +============== + +For example mark handler with `chat_action` flag + +.. code-block:: python + + from aiogram import flags + + @flags.chat_action + async def my_handler(message: Message) + +Or just for rate-limit or something else + +.. code-block:: python + + from aiogram import flags + + @flags.rate_limit(rate=2, key="something") + async def my_handler(message: Message) + +Via handler registration method +=============================== + +.. code-block:: python + + @router.message(..., flags={'chat_action': 'typing', 'rate_limit': {'rate': 5}}) + +Via filters +=========== + +.. code-block:: python + + class Command(BaseFilter): + ... + + def update_handler_flags(self, flags: Dict[str, Any]) -> None: + commands = flags.setdefault("commands", []) + commands.append(self) + + + +Use in middlewares +================== + +.. automodule:: aiogram.dispatcher.flags.getter + :members: + +Example in middlewares +---------------------- + +.. code-block:: python + + async def my_middleware(handler, event, data): + typing = get_flag(data, "typing") # Check that handler marked with `typing` flag + if not typing: + return await handler(event, data) + + async with ChatActionSender.typing(chat_id=event.chat.id): + return await handler(event, data) + +Use in utilities +================ + +For example you can collect all registered commands with handler description and then it can be used for generating commands help + +.. code-block:: python + + def collect_commands(router: Router) -> Generator[Tuple[Command, str], None, None]: + for handler in router.message.handlers: + if "commands" not in handler.flags: # ignore all handler without commands + continue + # the Command filter adds the flag with list of commands attached to the handler + for command in handler.flags["commands"]: + yield command, handler.callback.__doc__ or "" + # Recursively extract commands from nested routers + for sub_router in router.sub_routers: + yield from collect_commands(sub_router) diff --git a/docs/dispatcher/index.rst b/docs/dispatcher/index.rst index 935522b2..c684ba36 100644 --- a/docs/dispatcher/index.rst +++ b/docs/dispatcher/index.rst @@ -24,3 +24,4 @@ Dispatcher is subclass of router and should be always is root router. filters/index middlewares finite_state_machine/index + flags