mirror of
https://github.com/aiogram/aiogram.git
synced 2025-12-12 10:11:52 +00:00
Remove MkDocs
This commit is contained in:
parent
7dd80d281f
commit
e1cd7268a1
442 changed files with 4 additions and 9429 deletions
26
docs/dispatcher/class_based_handlers/base.rst
Normal file
26
docs/dispatcher/class_based_handlers/base.rst
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
.. _cbh-base-handler:
|
||||
|
||||
===========
|
||||
BaseHandler
|
||||
===========
|
||||
|
||||
Base handler is generic abstract class and should be used in all other class-based handlers.
|
||||
|
||||
Import: :code:`from aiogram.handler import BaseHandler`
|
||||
|
||||
By default you will need to override only method :code:`async def handle(self) -> Any: ...`
|
||||
|
||||
This class is also have an default initializer and you don't need to change it.
|
||||
Initializer accepts current event and all contextual data and which
|
||||
can be accessed from the handler through attributes: :code:`event: TelegramEvent` and :code:`data: Dict[Any, str]`
|
||||
|
||||
If instance of the bot is specified in context data or current context it can be accessed through *bot* class attribute.
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class MyHandler(BaseHandler[Message]):
|
||||
async def handle(self) -> Any:
|
||||
await self.event.answer("Hello!")
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
# Overview
|
||||
|
||||
A handler is a async callable which takes a event with contextual data and returns a response.
|
||||
In `aiogram` this can be more than just an async function, these allow you to use classes which can be used as Telegram event handlers to structure your event handlers and reuse code by harnessing inheritance and mixins.
|
||||
|
||||
There are some base class based handlers what you need to use in your own handlers:
|
||||
|
||||
- [BaseHandler](#basehandler)
|
||||
- [MessageHandler](message.md)
|
||||
- [CallbackQueryHandler](callback_query.md)
|
||||
- [ChosenInlineResultHandler](chosen_inline_result.md)
|
||||
- [InlineQueryHandler](inline_query.md)
|
||||
- [PollHandler](poll.md)
|
||||
- [PreCheckoutQueryHandler](pre_checkout_query.md)
|
||||
- [ShippingQueryHandler](shipping_query.md)
|
||||
|
||||
## BaseHandler
|
||||
|
||||
Base handler is generic abstract class and should be used in all other class-based handlers.
|
||||
|
||||
Import: `#!python3 from aiogram.hanler import BaseHandler`
|
||||
|
||||
By default you will need to override only method `#!python3 async def handle(self) -> Any: ...`
|
||||
|
||||
This class is also have an default initializer and you don't need to change it.
|
||||
Initializer accepts current event and all contextual data and which can be accessed from the handler through attributes: `event: TelegramEvent` and `data: Dict[Any, str]`
|
||||
|
||||
If instance of the bot is specified in context data or current context it can be accessed through `bot` class attribute.
|
||||
|
||||
|
||||
### For example:
|
||||
```python3
|
||||
class MyHandler(BaseHandler[Message]):
|
||||
async def handle(self) -> Any:
|
||||
await self.event.answer("Hello!")
|
||||
```
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
# CallbackQueryHandler
|
||||
|
||||
There is base class for callback query handlers.
|
||||
|
||||
## Simple usage:
|
||||
```pyhton3
|
||||
from aiogram.handlers import CallbackQueryHandler
|
||||
|
||||
...
|
||||
|
||||
@router.callback_query()
|
||||
class MyHandler(CallbackQueryHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
```
|
||||
|
||||
## Extension
|
||||
|
||||
This base handler is subclass of [BaseHandler](basics.md#basehandler) with some extensions:
|
||||
|
||||
- `self.from_user` is alias for `self.event.from_user`
|
||||
- `self.message` is alias for `self.event.message`
|
||||
- `self.callback_data` is alias for `self.event.data`
|
||||
|
||||
## Related pages
|
||||
|
||||
- [BaseHandler](basics.md#basehandler)
|
||||
- [CallbackQuery](../../api/types/callback_query.md)
|
||||
- [Router.callback_query](../router.md#callback-query)
|
||||
9
docs/dispatcher/class_based_handlers/callback_query.rst
Normal file
9
docs/dispatcher/class_based_handlers/callback_query.rst
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
####################
|
||||
CallbackQueryHandler
|
||||
####################
|
||||
|
||||
|
||||
.. automodule:: aiogram.dispatcher.handler.callback_query
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:undoc-members: True
|
||||
28
docs/dispatcher/class_based_handlers/chat_member.rst
Normal file
28
docs/dispatcher/class_based_handlers/chat_member.rst
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
=================
|
||||
ChatMemberHandler
|
||||
=================
|
||||
|
||||
There is base class for chat member updated events.
|
||||
|
||||
Simple usage
|
||||
============
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from aiogram.handlers import ChatMemberHandler
|
||||
|
||||
...
|
||||
|
||||
@router.chat_member()
|
||||
@router.my_chat_member()
|
||||
class MyHandler(ChatMemberHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
|
||||
Extension
|
||||
=========
|
||||
|
||||
This base handler is subclass of :ref:`BaseHandler <cbh-base-handler>` with some extensions:
|
||||
|
||||
- :code:`self.chat` is alias for :code:`self.event.chat`
|
||||
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
# ChosenInlineResultHandler
|
||||
|
||||
There is base class for chosen inline result handlers.
|
||||
|
||||
## Simple usage:
|
||||
```pyhton3
|
||||
from aiogram.handlers import ChosenInlineResultHandler
|
||||
|
||||
...
|
||||
|
||||
@router.chosen_inline_result()
|
||||
class MyHandler(ChosenInlineResultHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
```
|
||||
|
||||
## Extension
|
||||
|
||||
This base handler is subclass of [BaseHandler](basics.md#basehandler) with some extensions:
|
||||
|
||||
- `self.chat` is alias for `self.event.chat`
|
||||
- `self.from_user` is alias for `self.event.from_user`
|
||||
|
||||
## Related pages
|
||||
|
||||
- [BaseHandler](basics.md#basehandler)
|
||||
- [ChosenInlineResult](../../api/types/chosen_inline_result.md)
|
||||
- [Router.chosen_inline_result](../router.md#chosen-inline-query)
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
=========================
|
||||
ChosenInlineResultHandler
|
||||
=========================
|
||||
|
||||
There is base class for chosen inline result handlers.
|
||||
|
||||
Simple usage
|
||||
============
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from aiogram.handlers import ChosenInlineResultHandler
|
||||
|
||||
...
|
||||
|
||||
@router.chosen_inline_result()
|
||||
class MyHandler(ChosenInlineResultHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
|
||||
Extension
|
||||
=========
|
||||
|
||||
This base handler is subclass of :ref:`BaseHandler <cbh-base-handler>` with some extensions:
|
||||
|
||||
- :code:`self.chat` is alias for :code:`self.event.chat`
|
||||
- :code:`self.from_user` is alias for :code:`self.event.from_user`
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
# ErrorHandler
|
||||
|
||||
There is base class for error handlers.
|
||||
|
||||
## Simple usage:
|
||||
```pyhton3
|
||||
from aiogram.handlers import ErrorHandler
|
||||
|
||||
...
|
||||
|
||||
@router.errors()
|
||||
class MyHandler(ErrorHandler):
|
||||
async def handle(self) -> Any:
|
||||
log.exception(
|
||||
"Cause unexpected exception %s: %s",
|
||||
self.exception_name,
|
||||
self.exception_message
|
||||
)
|
||||
```
|
||||
|
||||
## Extension
|
||||
|
||||
This base handler is subclass of [BaseHandler](basics.md#basehandler) with some extensions:
|
||||
|
||||
- `#!python3 self.exception_name` is alias for `#!python3 self.event.__class__.__name__`
|
||||
- `#!python3 self.exception_message` is alias for `#!python3 str(self.event)`
|
||||
|
||||
## Related pages
|
||||
|
||||
- [BaseHandler](basics.md#basehandler)
|
||||
- [Router.errors](../router.md#errors)
|
||||
- [Filters](../filters/exception.md)
|
||||
32
docs/dispatcher/class_based_handlers/error.rst
Normal file
32
docs/dispatcher/class_based_handlers/error.rst
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
============
|
||||
ErrorHandler
|
||||
============
|
||||
|
||||
There is base class for error handlers.
|
||||
|
||||
Simple usage
|
||||
============
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from aiogram.handlers import ErrorHandler
|
||||
|
||||
...
|
||||
|
||||
@router.errors()
|
||||
class MyHandler(ErrorHandler):
|
||||
async def handle(self) -> Any:
|
||||
log.exception(
|
||||
"Cause unexpected exception %s: %s",
|
||||
self.exception_name,
|
||||
self.exception_message
|
||||
)
|
||||
|
||||
Extension
|
||||
=========
|
||||
|
||||
This base handler is subclass of :ref:`BaseHandler <cbh-base-handler>` with some extensions:
|
||||
|
||||
- :code:`self.exception_name` is alias for :code:`self.event.__class__.__name__`
|
||||
- :code:`self.exception_message` is alias for :code:`str(self.event)`
|
||||
23
docs/dispatcher/class_based_handlers/index.rst
Normal file
23
docs/dispatcher/class_based_handlers/index.rst
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
====================
|
||||
Class based handlers
|
||||
====================
|
||||
|
||||
A handler is a async callable which takes a event with contextual data and returns a response.
|
||||
|
||||
In **aiogram** it can be more than just an async function, these allow you to use classes
|
||||
which can be used as Telegram event handlers to structure your event handlers and reuse code by harnessing inheritance and mixins.
|
||||
|
||||
There are some base class based handlers what you need to use in your own handlers:
|
||||
|
||||
.. toctree::
|
||||
|
||||
base
|
||||
callback_query
|
||||
chosen_inline_result
|
||||
error
|
||||
inline_query
|
||||
message
|
||||
poll
|
||||
pre_checkout_query
|
||||
shipping_query
|
||||
chat_member
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
# InlineQueryHandler
|
||||
There is base class for inline query handlers.
|
||||
|
||||
## Simple usage:
|
||||
```pyhton3
|
||||
from aiogram.handlers import InlineQueryHandler
|
||||
|
||||
...
|
||||
|
||||
@router.inline_query()
|
||||
class MyHandler(InlineQueryHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
```
|
||||
|
||||
## Extension
|
||||
|
||||
This base handler is subclass of [BaseHandler](basics.md#basehandler) with some extensions:
|
||||
|
||||
- `self.chat` is alias for `self.event.chat`
|
||||
- `self.query` is alias for `self.event.query`
|
||||
|
||||
## Related pages
|
||||
|
||||
- [BaseHandler](basics.md#basehandler)
|
||||
- [InlineQuery](../../api/types/inline_query.md)
|
||||
- [Router.inline_query_handler](../router.md#inline-query)
|
||||
27
docs/dispatcher/class_based_handlers/inline_query.rst
Normal file
27
docs/dispatcher/class_based_handlers/inline_query.rst
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
==================
|
||||
InlineQueryHandler
|
||||
==================
|
||||
|
||||
There is base class for inline query handlers.
|
||||
|
||||
Simple usage
|
||||
============
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from aiogram.handlers import InlineQueryHandler
|
||||
|
||||
...
|
||||
|
||||
@router.inline_query()
|
||||
class MyHandler(InlineQueryHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
|
||||
Extension
|
||||
=========
|
||||
|
||||
This base handler is subclass of :ref:`BaseHandler <cbh-base-handler>` with some extensions:
|
||||
|
||||
- :code:`self.chat` is alias for :code:`self.event.chat`
|
||||
- :code:`self.query` is alias for :code:`self.event.query`
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
# MessageHandler
|
||||
|
||||
There is base class for message handlers.
|
||||
|
||||
## Simple usage:
|
||||
```pyhton3
|
||||
from aiogram.handlers import MessageHandler
|
||||
|
||||
...
|
||||
|
||||
@router.message()
|
||||
class MyHandler(MessageHandler):
|
||||
async def handle(self) -> Any:
|
||||
return SendMessage(chat_id=self.chat.id, text="PASS")
|
||||
|
||||
```
|
||||
|
||||
## Extension
|
||||
|
||||
This base handler is subclass of [BaseHandler](basics.md#basehandler) with some extensions:
|
||||
|
||||
- `self.chat` is alias for `self.event.chat`
|
||||
- `self.from_user` is alias for `self.event.from_user`
|
||||
|
||||
## Related pages
|
||||
|
||||
- [BaseHandler](basics.md#basehandler)
|
||||
- [Message](../../api/types/message.md)
|
||||
- [Router.message](../router.md#message)
|
||||
- [Router.edited_message](../router.md#edited-message)
|
||||
- [Router.channel_post](../router.md#channel-post)
|
||||
- [Router.edited_channel_post](../router.md#edited-channel-post)
|
||||
27
docs/dispatcher/class_based_handlers/message.rst
Normal file
27
docs/dispatcher/class_based_handlers/message.rst
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
==============
|
||||
MessageHandler
|
||||
==============
|
||||
|
||||
There is base class for message handlers.
|
||||
|
||||
Simple usage
|
||||
============
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from aiogram.handlers import MessageHandler
|
||||
|
||||
...
|
||||
|
||||
@router.message()
|
||||
class MyHandler(MessageHandler):
|
||||
async def handle(self) -> Any:
|
||||
return SendMessage(chat_id=self.chat.id, text="PASS")
|
||||
|
||||
Extension
|
||||
=========
|
||||
|
||||
This base handler is subclass of [BaseHandler](basics.md#basehandler) with some extensions:
|
||||
|
||||
- :code:`self.chat` is alias for :code:`self.event.chat`
|
||||
- :code:`self.from_user` is alias for :code:`self.event.from_user`
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
# PollHandler
|
||||
|
||||
There is base class for poll handlers.
|
||||
|
||||
## Simple usage:
|
||||
```pyhton3
|
||||
from aiogram.handlers import PollHandler
|
||||
|
||||
...
|
||||
|
||||
@router.poll()
|
||||
class MyHandler(PollHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
```
|
||||
|
||||
## Extension
|
||||
|
||||
This base handler is subclass of [BaseHandler](basics.md#basehandler) with some extensions:
|
||||
|
||||
- `self.question` is alias for `self.event.question`
|
||||
- `self.options` is alias for `self.event.options`
|
||||
|
||||
## Related pages
|
||||
|
||||
- [BaseHandler](basics.md#basehandler)
|
||||
- [Poll](../../api/types/poll.md)
|
||||
- [Router.poll](../router.md#poll)
|
||||
26
docs/dispatcher/class_based_handlers/poll.rst
Normal file
26
docs/dispatcher/class_based_handlers/poll.rst
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
===========
|
||||
PollHandler
|
||||
===========
|
||||
|
||||
There is base class for poll handlers.
|
||||
|
||||
Simple usage
|
||||
============
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from aiogram.handlers import PollHandler
|
||||
|
||||
...
|
||||
|
||||
@router.poll()
|
||||
class MyHandler(PollHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
Extension
|
||||
=========
|
||||
|
||||
This base handler is subclass of :ref:`BaseHandler <cbh-base-handler>` with some extensions:
|
||||
|
||||
- :code:`self.question` is alias for :code:`self.event.question`
|
||||
- :code:`self.options` is alias for :code:`self.event.options`
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
# PreCheckoutQueryHandler
|
||||
|
||||
There is base class for callback query handlers.
|
||||
|
||||
## Simple usage:
|
||||
```pyhton3
|
||||
from aiogram.handlers import PreCheckoutQueryHandler
|
||||
|
||||
...
|
||||
|
||||
@router.pre_checkout_query()
|
||||
class MyHandler(PreCheckoutQueryHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
```
|
||||
|
||||
## Extension
|
||||
|
||||
This base handler is subclass of [BaseHandler](basics.md#basehandler) with some extensions:
|
||||
|
||||
- `self.from_user` is alias for `self.event.from_user`
|
||||
|
||||
## Related pages
|
||||
|
||||
- [BaseHandler](basics.md#basehandler)
|
||||
- [PreCheckoutQuery](../../api/types/pre_checkout_query.md)
|
||||
- [Router.pre_checkout_query](../router.md#pre-checkout-query)
|
||||
25
docs/dispatcher/class_based_handlers/pre_checkout_query.rst
Normal file
25
docs/dispatcher/class_based_handlers/pre_checkout_query.rst
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
=======================
|
||||
PreCheckoutQueryHandler
|
||||
=======================
|
||||
|
||||
There is base class for callback query handlers.
|
||||
|
||||
Simple usage
|
||||
============
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from aiogram.handlers import PreCheckoutQueryHandler
|
||||
|
||||
...
|
||||
|
||||
@router.pre_checkout_query()
|
||||
class MyHandler(PreCheckoutQueryHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
Extension
|
||||
=========
|
||||
|
||||
This base handler is subclass of :ref:`BaseHandler <cbh-base-handler>` with some extensions:
|
||||
|
||||
- :code:`self.from_user` is alias for :code:`self.event.from_user`
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
# ShippingQueryHandler
|
||||
|
||||
There is base class for callback query handlers.
|
||||
|
||||
## Simple usage:
|
||||
```pyhton3
|
||||
from aiogram.handlers import ShippingQueryHandler
|
||||
|
||||
...
|
||||
|
||||
@router.shipping_query()
|
||||
class MyHandler(ShippingQueryHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
```
|
||||
|
||||
## Extension
|
||||
|
||||
This base handler is subclass of [BaseHandler](basics.md#basehandler) with some extensions:
|
||||
|
||||
- `self.from_user` is alias for `self.event.from_user`
|
||||
|
||||
## Related pages
|
||||
|
||||
- [BaseHandler](basics.md#basehandler)
|
||||
- [ShippingQuery](../../api/types/shipping_query.md)
|
||||
- [Router.shipping_query](../router.md#shipping-query)
|
||||
25
docs/dispatcher/class_based_handlers/shipping_query.rst
Normal file
25
docs/dispatcher/class_based_handlers/shipping_query.rst
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
====================
|
||||
ShippingQueryHandler
|
||||
====================
|
||||
|
||||
There is base class for callback query handlers.
|
||||
|
||||
Simple usage
|
||||
============
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from aiogram.handlers import ShippingQueryHandler
|
||||
|
||||
...
|
||||
|
||||
@router.shipping_query()
|
||||
class MyHandler(ShippingQueryHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
Extension
|
||||
=========
|
||||
|
||||
This base handler is subclass of :ref:`BaseHandler <cbh-base-handler>` with some extensions:
|
||||
|
||||
- :code:`self.from_user` is alias for :code:`self.event.from_user`
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
# Dispatcher
|
||||
Imports:
|
||||
|
||||
- Recommended: `#!python3 from aiogram import Dispatcher`
|
||||
- Real location: `#!python3 from aiogram.dispatcher.dispatcher import Dispatcher`
|
||||
|
||||
In code Dispatcher can be used directly for routing updates or attach another routers into dispatcher.
|
||||
|
||||
!!! warning
|
||||
|
||||
Dispatcher is root [Router](router.md) and can not be included into another routers.
|
||||
|
||||
|
||||
Here is only listed base information about Dispatcher. All about writing handlers, filters and etc. you can found in next pages:
|
||||
|
||||
- [Router](router.md).
|
||||
- [Observer](observer.md).
|
||||
|
||||
## Simple usage
|
||||
Example:
|
||||
```python3
|
||||
dp = Dispatcher()
|
||||
|
||||
@dp.message()
|
||||
async def message_handler(message: types.Message) -> None:
|
||||
await SendMessage(chat_id=message.from_user.id, text=message.text)
|
||||
```
|
||||
|
||||
|
||||
## Including routers
|
||||
Example:
|
||||
```python3
|
||||
dp = Dispatcher()
|
||||
router1 = Router()
|
||||
dp.include_router(router1)
|
||||
```
|
||||
|
||||
|
||||
## Handling updates
|
||||
All updates can be propagated to the dispatcher by `feed_update` method:
|
||||
|
||||
```python3
|
||||
bot = Bot(...)
|
||||
dp = Dispathcher()
|
||||
|
||||
...
|
||||
|
||||
async for result in dp.feed_update(bot=bot, update=incoming_update):
|
||||
print(result)
|
||||
```
|
||||
|
||||
**Method specification**:
|
||||
|
||||
| Argument | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `bot` | `Bot` | Bot instance related with current update object |
|
||||
| `update` | `Update` | Update object |
|
||||
| `**kwargs` | `Any` | Context related data. Will be propagated to handlers, filters and middlewares |
|
||||
|
||||
### Polling
|
||||
...
|
||||
|
||||
### Webhook
|
||||
...
|
||||
54
docs/dispatcher/dispatcher.rst
Normal file
54
docs/dispatcher/dispatcher.rst
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
##########
|
||||
Dispathcer
|
||||
##########
|
||||
|
||||
Dispatcher is root :obj:`Router` and in code Dispatcher can be used directly for routing updates or attach another routers into dispatcher.
|
||||
|
||||
Here is only listed base information about Dispatcher. All about writing handlers, filters and etc. you can found in next pages:
|
||||
|
||||
- `Router <router.html>`__
|
||||
- `Observer <observer.html>`__
|
||||
|
||||
|
||||
.. autoclass:: aiogram.dispatcher.dispatcher.Dispatcher
|
||||
:members: __init__, feed_update, feed_raw_update, feed_webhook_update, start_polling, run_polling
|
||||
|
||||
|
||||
Simple usage
|
||||
============
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
dp = Dispatcher()
|
||||
|
||||
@dp.message()
|
||||
async def message_handler(message: types.Message) -> None:
|
||||
await SendMessage(chat_id=message.from_user.id, text=message.text)
|
||||
|
||||
|
||||
Including routers
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
dp = Dispatcher()
|
||||
router1 = Router()
|
||||
dp.include_router(router1)
|
||||
|
||||
Handling updates
|
||||
================
|
||||
|
||||
All updates can be propagated to the dispatcher by :obj:`Dispatcher.feed_update(bot=..., update=...)` method:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
bot = Bot(...)
|
||||
dp = Dispathcher()
|
||||
|
||||
...
|
||||
|
||||
result = await dp.feed_update(bot=bot, update=incoming_update)
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
# Command
|
||||
|
||||
This filter can be helpful for handling commands from the text messages.
|
||||
|
||||
Works only with [Message](../../api/types/message.md) events which have the `text`.
|
||||
|
||||
## Specification
|
||||
| Argument | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `commands` | `#!python3 Union[Sequence[Union[str, re.Pattern]], Union[str, re.Pattern]]` | List of commands (string or compiled regexp patterns) |
|
||||
| `commands_prefix` | `#!python3 str` | Prefix for command. Prefix is always is single char but here you can pass all of allowed prefixes, for example: `"/!"` will work with commands prefixed by `"/"` or `"!"` (Default: `"/"`). |
|
||||
| `commands_ignore_case` | `#!python3 bool` | Ignore case (Does not work with regexp, use flags instead. Default: `False`) |
|
||||
| `commands_ignore_mention` | `#!python3 bool` | Ignore bot mention. By default bot can not handle commands intended for other bots (Default: `False`) |
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
1. Filter single variant of commands: `#!python3 Command(commands=["start"])` or `#!python3 Command(commands="start")`
|
||||
1. Handle command by regexp pattern: `#!python3 Command(commands=[re.compile(r"item_(\d+)")])`
|
||||
1. Match command by multiple variants: `#!python3 Command(commands=["item", re.compile(r"item_(\d+)")])`
|
||||
1. Handle commands in public chats intended for other bots: `#!python3 Command(commands=["command"], commands)`
|
||||
1. As keyword argument in registerer: `#!python3 @router.message(commands=["help"])`
|
||||
|
||||
!!! warning
|
||||
Command cannot include spaces or any whitespace
|
||||
|
||||
## Allowed handlers
|
||||
|
||||
Allowed update types for this filter:
|
||||
|
||||
- `message`
|
||||
- `edited_message`
|
||||
37
docs/dispatcher/filters/command.rst
Normal file
37
docs/dispatcher/filters/command.rst
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
=======
|
||||
Command
|
||||
=======
|
||||
|
||||
.. autoclass:: aiogram.dispatcher.filters.command.Command
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:undoc-members: False
|
||||
|
||||
When filter is passed the :class:`aiogram.dispatcher.filters.command.CommandObject` will be passed to the handler argument :code:`command`
|
||||
|
||||
.. autoclass:: aiogram.dispatcher.filters.command.CommandObject
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:undoc-members: False
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
1. Filter single variant of commands: :code:`Command(commands=["start"])` or :code:`Command(commands="start")`
|
||||
2. Handle command by regexp pattern: :code:`Command(commands=[re.compile(r"item_(\d+)")])`
|
||||
3. Match command by multiple variants: :code:`Command(commands=["item", re.compile(r"item_(\d+)")])`
|
||||
4. Handle commands in public chats intended for other bots: :code:`Command(commands=["command"], commands)`
|
||||
5. As keyword argument in registerer: :code:`@router.message(commands=["help"])`
|
||||
|
||||
.. warning::
|
||||
|
||||
Command cannot include spaces or any whitespace
|
||||
|
||||
Allowed handlers
|
||||
================
|
||||
|
||||
Allowed update types for this filter:
|
||||
|
||||
- `message`
|
||||
- `edited_message`
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
# ContentTypesFilter
|
||||
|
||||
Is useful for handling specific types of messages (For example separate text and stickers handlers).
|
||||
This is always automatically adds to the filters list for message handlers.
|
||||
|
||||
Can be imported:
|
||||
|
||||
- `#!python3 from aiogram.dispatcher.filters.content_types import ContentTypesFilter`
|
||||
- `#!python3 from aiogram.dispatcher.filters import ContentTypesFilter`
|
||||
- `#!python3 from aiogram.filters import ContentTypesFilter`
|
||||
|
||||
Or used from filters factory by passing corresponding arguments to handler registration line
|
||||
|
||||
!!! warning "Please be patient!"
|
||||
If no one content type filter is specified the `["text"]` value is automatically will be used.
|
||||
|
||||
|
||||
## Specification
|
||||
|
||||
| Argument | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `content_types` | `#!python3 Optional[Union[Sequence[str], str]]` | List of allowed content types |
|
||||
|
||||
## Usage
|
||||
|
||||
1. Single content type: `#!python3 ContentTypesFilter(content_types=["sticker"])` or `#!python3 ContentTypesFilter(content_types="sticker")`
|
||||
1. Multiple content types: `#!python3 ContentTypesFilter(content_types=["sticker", "photo"])`
|
||||
1. Recommended: With usage of `ContentType` helper: `#!python3 ContentTypesFilter(content_types=[ContentType.PHOTO])`
|
||||
1. Any content type: `#!python3 ContentTypesFilter(content_types=[ContentType.ANY])`
|
||||
|
||||
## Allowed handlers
|
||||
|
||||
Allowed update types for this filter:
|
||||
|
||||
- `message`
|
||||
- `edited_message`
|
||||
- `channel_post`
|
||||
- `edited_channel_post`
|
||||
39
docs/dispatcher/filters/content_types.rst
Normal file
39
docs/dispatcher/filters/content_types.rst
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
==================
|
||||
ContentTypesFilter
|
||||
==================
|
||||
|
||||
.. autoclass:: aiogram.dispatcher.filters.content_types.ContentTypesFilter
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:undoc-members: False
|
||||
|
||||
Can be imported:
|
||||
|
||||
- :code:`from aiogram.dispatcher.filters.content_types import ContentTypesFilter`
|
||||
- :code:`from aiogram.dispatcher.filters import ContentTypesFilter`
|
||||
- :code:`from aiogram.filters import ContentTypesFilter`
|
||||
|
||||
Or used from filters factory by passing corresponding arguments to handler registration line
|
||||
|
||||
.. warning::
|
||||
**Please be patient!**
|
||||
|
||||
If no one content type filter is specified the :code:`["text"]` value is automatically will be used.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
1. Single content type: :code:`ContentTypesFilter(content_types=["sticker"])` or :code:`ContentTypesFilter(content_types="sticker")`
|
||||
2. Multiple content types: :code:`ContentTypesFilter(content_types=["sticker", "photo"])`
|
||||
3. Recommended: With usage of `ContentType` helper: :code:`ContentTypesFilter(content_types=[ContentType.PHOTO])`
|
||||
4. Any content type: :code:`ContentTypesFilter(content_types=[ContentType.ANY])`
|
||||
|
||||
Allowed handlers
|
||||
================
|
||||
|
||||
Allowed update types for this filter:
|
||||
|
||||
- :code:`message`
|
||||
- :code:`edited_message`
|
||||
- :code:`channel_post`
|
||||
- :code:`edited_channel_post`
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
# Exceptions
|
||||
This filters can be helpful for handling errors from the text messages.
|
||||
|
||||
## ExceptionTypeFilter
|
||||
|
||||
Allow to match exception by type
|
||||
|
||||
### Specification
|
||||
| Argument | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `exception` | `#!python3 Union[Type[Exception], Tuple[Type[Exception]]]` | Exception type(s) |
|
||||
|
||||
|
||||
## ExceptionMessageFilter
|
||||
|
||||
Allow to match exception by message
|
||||
|
||||
### Specification
|
||||
| Argument | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `match` | `#!python3 Union[str, Pattern[str]]` | Regexp pattern |
|
||||
|
||||
## Allowed handlers
|
||||
|
||||
Allowed update types for this filters:
|
||||
|
||||
- `error`
|
||||
22
docs/dispatcher/filters/exception.rst
Normal file
22
docs/dispatcher/filters/exception.rst
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
==========
|
||||
Exceptions
|
||||
==========
|
||||
|
||||
This filters can be helpful for handling errors from the text messages.
|
||||
|
||||
.. autoclass:: aiogram.dispatcher.filters.exception.ExceptionTypeFilter
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:undoc-members: False
|
||||
|
||||
.. autoclass:: aiogram.dispatcher.filters.exception.ExceptionMessageFilter
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:undoc-members: False
|
||||
|
||||
Allowed handlers
|
||||
================
|
||||
|
||||
Allowed update types for this filters:
|
||||
|
||||
- :code:`error`
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
# Basics
|
||||
|
||||
Filters is needed for routing updates to the specific handler.
|
||||
Searching of handler is always stops on first match set of filters are pass.
|
||||
|
||||
`aiogram` has some builtin useful filters.
|
||||
|
||||
## Builtin filters
|
||||
|
||||
Here is list of builtin filters and event types where it can be used:
|
||||
|
||||
| Filter | update | message | edited_message | channel_post | edited_channel_post | inline_query | chosen_inline_result | callback_query | shipping_query | pre_checkout_query | poll |
|
||||
| ----------------------------------------- |:------:|:-------:|:--------------:|:------------:|:-------------------:|:------------:|:--------------------:|:--------------:|:--------------:|:------------------:|:----:|
|
||||
| [Text](text.md) | | + | + | + | + | + | | + | | | + |
|
||||
| [ContentTypesFilter](content_types.md) | | + | + | + | + | | | | | | |
|
||||
| [Command](command.md) | | + | | | | | | | | | |
|
||||
| | | | | | | | | | | | |
|
||||
|
||||
|
||||
## Own filters specification
|
||||
|
||||
Filters can be:
|
||||
|
||||
- Asynchronous function (`#!python3 async def my_filter(*args, **kwargs): pass`)
|
||||
- Synchronous function (`#!python3 def my_filter(*args, **kwargs): pass`)
|
||||
- Anonymous function (`#!python3 lambda event: True`)
|
||||
- Any awaitable object
|
||||
- Subclass of `BaseFilter`
|
||||
|
||||
Filters should return bool or dict.
|
||||
If the dictionary is passed as result of filter - resulted data will be propagated to the next
|
||||
filters and handler as keywords arguments.
|
||||
|
||||
## Writing bound filters
|
||||
|
||||
If you want to register own filters like builtin filters you will need to write subclass
|
||||
of BaseFilter (`#!python3 from aiogram.filters import BaseFilter`) with overriding the `__call__`
|
||||
method and adding filter attributes.
|
||||
|
||||
BaseFilter is subclass of `pydantic.BaseModel` that's mean all subclasses of BaseFilter has
|
||||
the validators based on class attributes and custom validator.
|
||||
|
||||
For example if you need to make simple text filter:
|
||||
|
||||
```python3
|
||||
from aiogram.filters import BaseFilter
|
||||
|
||||
|
||||
class MyText(BaseFilter):
|
||||
my_text: str
|
||||
|
||||
async def __call__(self, message: Message) -> bool:
|
||||
return message.text == self.my_text
|
||||
|
||||
|
||||
router.message.bind_filter(MyText)
|
||||
|
||||
@router.message(my_text="hello")
|
||||
async def my_handler(message: Message): ...
|
||||
```
|
||||
|
||||
!!! info
|
||||
Bound filters is always recursive propagates to the nested routers.
|
||||
73
docs/dispatcher/filters/index.rst
Normal file
73
docs/dispatcher/filters/index.rst
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
================
|
||||
Filtering events
|
||||
================
|
||||
|
||||
Filters is needed for routing updates to the specific handler.
|
||||
Searching of handler is always stops on first match set of filters are pass.
|
||||
|
||||
*aiogram* has some builtin useful filters.
|
||||
|
||||
Builtin filters
|
||||
===============
|
||||
|
||||
Here is list of builtin filters:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
command
|
||||
content_types
|
||||
text
|
||||
exception
|
||||
|
||||
Or you can do :ref:`✨ some magic <magic-filters>`
|
||||
|
||||
Own filters specification
|
||||
=========================
|
||||
|
||||
Filters can be:
|
||||
|
||||
- Asynchronous function (:code:`async def my_filter(*args, **kwargs): pass`)
|
||||
|
||||
- Synchronous function (:code:`def my_filter(*args, **kwargs): pass`)
|
||||
|
||||
- Anonymous function (:code:`lambda event: True`)
|
||||
|
||||
- Any awaitable object
|
||||
|
||||
- Subclass of :ref:`BaseFilter <filters-base>`
|
||||
|
||||
Filters should return bool or dict.
|
||||
If the dictionary is passed as result of filter - resulted data will be propagated to the next
|
||||
filters and handler as keywords arguments.
|
||||
|
||||
Writing bound filters
|
||||
=====================
|
||||
|
||||
.. autoclass:: aiogram.dispatcher.filters.base.BaseFilter
|
||||
:members: __call__
|
||||
:member-order: bysource
|
||||
:undoc-members: False
|
||||
|
||||
For example if you need to make simple text filter:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from aiogram.filters import BaseFilter
|
||||
|
||||
|
||||
class MyText(BaseFilter):
|
||||
my_text: str
|
||||
|
||||
async def __call__(self, message: Message) -> bool:
|
||||
return message.text == self.my_text
|
||||
|
||||
|
||||
router.message.bind_filter(MyText)
|
||||
|
||||
@router.message(my_text="hello")
|
||||
async def my_handler(message: Message): ...
|
||||
|
||||
.. note::
|
||||
|
||||
Bound filters is always recursive propagates to the nested routers.
|
||||
146
docs/dispatcher/filters/magic_filters.rst
Normal file
146
docs/dispatcher/filters/magic_filters.rst
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
.. _magic-filters:
|
||||
|
||||
=============
|
||||
Magic filters
|
||||
=============
|
||||
|
||||
.. note::
|
||||
|
||||
This page still in progress. Has many incorrectly worded sentences.
|
||||
|
||||
Is external package maintained by *aiogram* core team.
|
||||
|
||||
By default installs with *aiogram* and also is available on `PyPi - magic-filter <https://pypi.org/project/magic-filter/>`_.
|
||||
That's mean you can install it and use with any other libraries and in own projects without depending *aiogram* installed.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
The **magic_filter** package implements class shortly named :class:`magic_filter.F` that's mean :code:`F` can be imported from :code:`magic_filter`. :class:`F` is alias for :class:`MagicFilter`.
|
||||
|
||||
The :class:`MagicFilter` object is callable, supports :ref:`some actions <magic-filter-possible-actions>`
|
||||
and memorize the attributes chain and the action which should be checked on demand.
|
||||
|
||||
So that's mean you can chain attribute getters, describe simple data validations
|
||||
and then call the resulted object passing single object as argument,
|
||||
for example make attributes chain :code:`F.foo.bar.baz` then add
|
||||
action ':code:`F.foo.bar.baz == 'spam'` and then call the resulted object - :code:`(F.foo.bar.baz == 'spam')(obj)`
|
||||
|
||||
.. _magic-filter-possible-actions:
|
||||
|
||||
Possible actions
|
||||
================
|
||||
|
||||
Magic filter object supports some of basic logical operations over object attributes
|
||||
|
||||
Exists or not None
|
||||
------------------
|
||||
|
||||
Default actions.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
F.photo # lambda message: message.photo
|
||||
|
||||
Equals
|
||||
------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
F.text == 'hello' # lambda message: message.text == 'hello'
|
||||
F.from_user.id == 42 # lambda message: message.from_user.id == 42
|
||||
|
||||
Is one of
|
||||
---------
|
||||
|
||||
Can be used as method named :code:`in_` or as matmul operator :code:`@` with any iterable
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
F.from_user.id.in_(42, 1000, 123123) # lambda query: query.from_user.id in {42, 1000, 123123}
|
||||
F.data.in_('foo', 'bar', 'baz') # lambda query: query.data in {'foo', 'bar', 'baz'}
|
||||
F.text @ {'foo', 'bar'} # lambda message: message.text in {'foo', 'bar'}
|
||||
|
||||
Contains
|
||||
--------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
F.text.contains('foo') # lambda message: 'foo' in message.text
|
||||
|
||||
String startswith/endswith
|
||||
--------------------------
|
||||
|
||||
Can be applied only for text attributes
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
F.text.startswith('foo') # lambda message: message.text.startswith('foo')
|
||||
F.text.endswith('bar') # lambda message: message.text.startswith('bar')
|
||||
|
||||
Regexp
|
||||
------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
F.text.regexp(r'Hello, .+') # lambda message: re.match(r'Hello, .+', message.text)
|
||||
|
||||
Custom function
|
||||
---------------
|
||||
|
||||
Accepts any callable. Callback will be called when filter checks result
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
F.chat.func(lambda chat: chat.id == -42) # lambda message: (lambda chat: chat.id == -42)(message.chat)
|
||||
|
||||
Inverting result
|
||||
----------------
|
||||
|
||||
Any of available operation can be inverted by bitwise inversion - :code:`~`
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
~(F.text == 'spam') # lambda message: message.text != 'spam'
|
||||
~F.text.startswith('spam') # lambda message: not message.text.startswith('spam')
|
||||
|
||||
Combining
|
||||
---------
|
||||
|
||||
All operations can be combined via bitwise and/or operators - :code:`&`/:code:`|`
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
(F.from_user.id == 42) & (F.text == 'admin')
|
||||
F.text.startswith('a') | F.text.endswith('b')
|
||||
(F.from_user.id @ {42, 777, 911}) & (F.text.startswith('!') | F.text.startswith('/')) & F.text.contains('ban')
|
||||
|
||||
|
||||
Attribute modifiers - string manipulations
|
||||
------------------------------------------
|
||||
|
||||
Make text upper- or lower-case
|
||||
|
||||
Can be used only with string attributes.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
F.text__lower == 'test' # lambda message: message.text.lower() == 'test'
|
||||
F.text__upper.in_('FOO', 'BAR') # lambda message: message.text.upper() in {'FOO', 'BAR'}
|
||||
F.text__len == 5 # lambda message: len(message.text) == 5
|
||||
|
||||
|
||||
Usage in *aiogram*
|
||||
==================
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.message(F.text == 'hello')
|
||||
@router.inline_query(F.data == 'button:1')
|
||||
@router.message(F.text.startswith('foo'))
|
||||
@router.message(F.content_type.in_('text', 'sticker'))
|
||||
@router.message(F.text.regexp(r'\d+'))
|
||||
|
||||
...
|
||||
|
||||
# Many others cases when you will need to check any of available event attribute
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
# Text
|
||||
|
||||
Is useful for filtering text [Message](../../api/types/message.md),
|
||||
any [CallbackQuery](../../api/types/callback_query.md) with `data`,
|
||||
[InlineQuery](../../api/types/inline_query.md) or
|
||||
[Poll](../../api/types/poll.md) question.
|
||||
|
||||
Can be imported:
|
||||
|
||||
- `#!python3 from aiogram.dispatcher.filters.text import Text`
|
||||
- `#!python3 from aiogram.dispatcher.filters import Text`
|
||||
- `#!python3 from aiogram.filters import Text`
|
||||
|
||||
Or used from filters factory by passing corresponding arguments to handler registration line
|
||||
|
||||
|
||||
## Specification
|
||||
|
||||
| Argument | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `text` | `#!python3 Optional[Union[Sequence[str], str]]` | Text equals value or one of values |
|
||||
| `text_contains` | `#!python3 Optional[Union[Sequence[str], str]]` | Text contains value or one of values |
|
||||
| `text_startswith` | `#!python3 Optional[Union[Sequence[str], str]]` | Text starts with value or one of values |
|
||||
| `text_endswith` | `#!python3 Optional[Union[Sequence[str], str]]` | Text ends with value or one of values |
|
||||
| `text_ignore_case` | `#!python3 bool` | Ignore case when checks (Default: `#!python3 False`) |
|
||||
|
||||
!!! warning
|
||||
|
||||
Only one of `text`, `text_contains`, `text_startswith` or `text_endswith` argument can be used at once.
|
||||
Any of that arguments can be string, list, set or tuple of strings.
|
||||
|
||||
## Usage
|
||||
|
||||
1. Text equals with the specified value: `#!python3 Text(text="text") # value == 'text'`
|
||||
1. Text starts with the specified value: `#!python3 Text(text_startswith="text") # value.startswith('text')`
|
||||
1. Text ends with the specified value: `#!python3 Text(text_endswith="text") # value.endswith('text')`
|
||||
1. Text contains the specified value: `#!python3 Text(text_endswith="text") # value in 'text'`
|
||||
1. Any of previous listed filters can be list, set or tuple of strings that's mean any of listed value should be equals/startswith/endswith/contains: `#!python3 Text(text=["text", "spam"])`
|
||||
1. Ignore case can be combined with any previous listed filter: `#!python3 Text(text="Text", text_ignore_case=True) # value.lower() == 'text'.lower()`
|
||||
|
||||
## Allowed handlers
|
||||
|
||||
Allowed update types for this filter:
|
||||
|
||||
- `message`
|
||||
- `edited_message`
|
||||
- `channel_post`
|
||||
- `edited_channel_post`
|
||||
- `inline_query`
|
||||
- `callback_query`
|
||||
38
docs/dispatcher/filters/text.rst
Normal file
38
docs/dispatcher/filters/text.rst
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
====
|
||||
Text
|
||||
====
|
||||
|
||||
.. autoclass:: aiogram.dispatcher.filters.text.Text
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:undoc-members: False
|
||||
|
||||
Can be imported:
|
||||
|
||||
- :code:`from aiogram.dispatcher.filters.text import Text`
|
||||
- :code:`from aiogram.dispatcher.filters import Text`
|
||||
- :code:`from aiogram.filters import Text`
|
||||
|
||||
Or used from filters factory by passing corresponding arguments to handler registration line
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
#. Text equals with the specified value: :code:`Text(text="text") # value == 'text'`
|
||||
#. Text starts with the specified value: :code:`Text(text_startswith="text") # value.startswith('text')`
|
||||
#. Text ends with the specified value: :code:`Text(text_endswith="text") # value.endswith('text')`
|
||||
#. Text contains the specified value: :code:`Text(text_contains="text") # value in 'text'`
|
||||
#. Any of previous listed filters can be list, set or tuple of strings that's mean any of listed value should be equals/startswith/endswith/contains: :code:`Text(text=["text", "spam"])`
|
||||
#. Ignore case can be combined with any previous listed filter: :code:`Text(text="Text", text_ignore_case=True) # value.lower() == 'text'.lower()`
|
||||
|
||||
Allowed handlers
|
||||
================
|
||||
|
||||
Allowed update types for this filter:
|
||||
|
||||
- :code:`message`
|
||||
- :code:`edited_message`
|
||||
- :code:`channel_post`
|
||||
- :code:`edited_channel_post`
|
||||
- :code:`inline_query`
|
||||
- :code:`callback_query`
|
||||
|
|
@ -1,13 +1,26 @@
|
|||
# Overview
|
||||
===============
|
||||
Handling events
|
||||
===============
|
||||
|
||||
Dispatcher is needed for handling incoming updates from Telegram. With dispatcher you can do:
|
||||
*aiogram* imcludes Dispatcher mechanism.
|
||||
Dispatcher is needed for handling incoming updates from Telegram.
|
||||
|
||||
With dispatcher you can do:
|
||||
|
||||
- Handle incoming updates;
|
||||
- Filter incoming events before it will be processed by specific handler;
|
||||
- Modify event and related data in middlewares;
|
||||
- Separate bot functionality between different handlers, modules and packages
|
||||
|
||||
Manually dispatcher has the router role and can include another routers.
|
||||
|
||||
Dispatcher is also separated into two entities - Router and Dispatcher.
|
||||
Dispatcher is subclass of router and should be always is root router.
|
||||
|
||||
.. toctree::
|
||||
|
||||
observer
|
||||
router
|
||||
dispatcher
|
||||
class_based_handlers/index
|
||||
filters/index
|
||||
filters/magic_filters
|
||||
middlewares
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
# Middlewares
|
||||
|
||||
**aiogram** provides powerful mechanism for customizing event handlers via middlewares.
|
||||
|
||||
Middlewares in bot framework seems like Middlewares mechanism in web-frameworks
|
||||
(like [aiohttp](https://docs.aiohttp.org/en/stable/web_advanced.html#aiohttp-web-middlewares),
|
||||
[fastapi](https://fastapi.tiangolo.com/tutorial/middleware/),
|
||||
[Django](https://docs.djangoproject.com/en/3.0/topics/http/middleware/) or etc.)
|
||||
with small difference - here is implemented two layers of middlewares (before and after filters).
|
||||
|
||||
!!! info
|
||||
Middleware is function that triggered on every event received from
|
||||
Telegram Bot API in many points on processing pipeline.
|
||||
|
||||
## Base theory
|
||||
|
||||
As many books and other literature in internet says:
|
||||
> Middleware is reusable software that leverages patterns and frameworks to bridge
|
||||
> the gap between the functional requirements of applications and the underlying operating systems,
|
||||
> network protocol stacks, and databases.
|
||||
|
||||
Middleware can modify, extend or reject processing event in many places of pipeline.
|
||||
|
||||
## Basics
|
||||
|
||||
Middleware instance can be applied for every type of Telegram Event (Update, Message, etc.) in two places
|
||||
|
||||
1. Outer scope - before processing filters (`#!python <router>.<event>.outer_middleware(...)`)
|
||||
2. Inner scope - after processing filters but before handler (`#!python <router>.<event>.middleware(...)`)
|
||||
|
||||
[](../assets/images/basics_middleware.png)
|
||||
|
||||
_(Click on image to zoom it)_
|
||||
|
||||
!!! warning
|
||||
|
||||
Middleware should be subclass of `BaseMiddleware` (`#!python3 from aiogram import BaseMiddleware`) or any async callable
|
||||
|
||||
## Arguments specification
|
||||
| Argument | Type | Description |
|
||||
| - | - | - |
|
||||
| `handler` | `#!python Callable[[T, Dict[str, Any]], Awaitable[Any]]` | Wrapped handler in middlewares chain |
|
||||
| `event` | `#!python T` | Incoming event (Subclass of `TelegramObject`) |
|
||||
| `data` | `#!python Dict[str, Any]` | Contextual data. Will be mapped to handler arguments |
|
||||
|
||||
## Examples
|
||||
|
||||
!!! danger
|
||||
|
||||
Middleware should always call `#!python await handler(event, data)` to propagate event for next middleware/handler
|
||||
|
||||
### Class-based
|
||||
```python3
|
||||
from aiogram import BaseMiddleware
|
||||
from aiogram.api.types import Message
|
||||
|
||||
|
||||
class CounterMiddleware(BaseMiddleware[Message]):
|
||||
def __init__(self) -> None:
|
||||
self.counter = 0
|
||||
|
||||
async def __call__(
|
||||
self,
|
||||
handler: Callable[[Message, Dict[str, Any]], Awaitable[Any]],
|
||||
event: Message,
|
||||
data: Dict[str, Any]
|
||||
) -> Any:
|
||||
self.counter += 1
|
||||
data['counter'] = self.counter
|
||||
return await handler(event, data)
|
||||
```
|
||||
and then
|
||||
```python3
|
||||
router = Router()
|
||||
router.message.middleware(CounterMiddleware())
|
||||
```
|
||||
|
||||
### Function-based
|
||||
```python3
|
||||
@dispatcher.update.outer_middleware()
|
||||
async def database_transaction_middleware(
|
||||
handler: Callable[[Update, Dict[str, Any]], Awaitable[Any]],
|
||||
event: Update,
|
||||
data: Dict[str, Any]
|
||||
) -> Any:
|
||||
async with database.transaction():
|
||||
return await handler(event, data)
|
||||
```
|
||||
|
||||
## Facts
|
||||
|
||||
1. Middlewares from outer scope will be called on every incoming event
|
||||
1. Middlewares from inner scope will be called only when filters pass
|
||||
1. Inner middlewares is always calls for `Update` event type in due to all incoming updates going to specific event type handler through built in update handler
|
||||
|
||||
113
docs/dispatcher/middlewares.rst
Normal file
113
docs/dispatcher/middlewares.rst
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
===========
|
||||
Middlewares
|
||||
===========
|
||||
|
||||
**aiogram** provides powerful mechanism for customizing event handlers via middlewares.
|
||||
|
||||
Middlewares in bot framework seems like Middlewares mechanism in web-frameworks
|
||||
like `aiohttp <https://docs.aiohttp.org/en/stable/web_advanced.html#aiohttp-web-middlewares>`_,
|
||||
`fastapi <https://fastapi.tiangolo.com/tutorial/middleware/>`_,
|
||||
`Django <https://docs.djangoproject.com/en/3.0/topics/http/middleware/>`_ or etc.)
|
||||
with small difference - here is implemented two layers of middlewares (before and after filters).
|
||||
|
||||
.. note::
|
||||
|
||||
Middleware is function that triggered on every event received from
|
||||
Telegram Bot API in many points on processing pipeline.
|
||||
|
||||
Base theory
|
||||
===========
|
||||
|
||||
As many books and other literature in internet says:
|
||||
|
||||
Middleware is reusable software that leverages patterns and frameworks to bridge
|
||||
the gap between the functional requirements of applications and the underlying operating systems,
|
||||
network protocol stacks, and databases.
|
||||
|
||||
Middleware can modify, extend or reject processing event in many places of pipeline.
|
||||
|
||||
Basics
|
||||
======
|
||||
|
||||
Middleware instance can be applied for every type of Telegram Event (Update, Message, etc.) in two places
|
||||
|
||||
1. Outer scope - before processing filters (:code:`<router>.<event>.outer_middleware(...)`)
|
||||
2. Inner scope - after processing filters but before handler (:code:`<router>.<event>.middleware(...)`)
|
||||
|
||||
.. image:: ../_static/basics_middleware.png
|
||||
:alt: Middleware basics
|
||||
|
||||
.. attention::
|
||||
|
||||
Middleware should be subclass of :code:`BaseMiddleware` (:code:`from aiogram import BaseMiddleware`) or any async callable
|
||||
|
||||
Arguments specification
|
||||
=======================
|
||||
|
||||
.. autoclass:: aiogram.dispatcher.middlewares.base.BaseMiddleware
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:member-order: bysource
|
||||
:special-members: __init__, __call__
|
||||
:undoc-members: True
|
||||
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
.. danger::
|
||||
|
||||
Middleware should always call :code:`await handler(event, data)` to propagate event for next middleware/handler
|
||||
|
||||
|
||||
Class-based
|
||||
-----------
|
||||
.. code-block:: python
|
||||
|
||||
from aiogram import BaseMiddleware
|
||||
from aiogram.api.types import Message
|
||||
|
||||
|
||||
class CounterMiddleware(BaseMiddleware[Message]):
|
||||
def __init__(self) -> None:
|
||||
self.counter = 0
|
||||
|
||||
async def __call__(
|
||||
self,
|
||||
handler: Callable[[Message, Dict[str, Any]], Awaitable[Any]],
|
||||
event: Message,
|
||||
data: Dict[str, Any]
|
||||
) -> Any:
|
||||
self.counter += 1
|
||||
data['counter'] = self.counter
|
||||
return await handler(event, data)
|
||||
|
||||
and then
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
router = Router()
|
||||
router.message.middleware(CounterMiddleware())
|
||||
|
||||
|
||||
Function-based
|
||||
--------------
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
@dispatcher.update.outer_middleware()
|
||||
async def database_transaction_middleware(
|
||||
handler: Callable[[Update, Dict[str, Any]], Awaitable[Any]],
|
||||
event: Update,
|
||||
data: Dict[str, Any]
|
||||
) -> Any:
|
||||
async with database.transaction():
|
||||
return await handler(event, data)
|
||||
|
||||
|
||||
Facts
|
||||
=====
|
||||
|
||||
1. Middlewares from outer scope will be called on every incoming event
|
||||
2. Middlewares from inner scope will be called only when filters pass
|
||||
3. Inner middlewares is always calls for :class:`aiogram.types.update.Update` event type in due to all incoming updates going to specific event type handler through built in update handler
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
# Observer
|
||||
|
||||
Observer is used for filtering and handling different events. That is part of internal API with some public methods and is recommended to don't use methods is not listed here.
|
||||
|
||||
In `aiogram` framework is available two variants of observer:
|
||||
|
||||
1. [EventObserver](#eventobserver)
|
||||
1. [TelegramEventObserver](#telegrameventobserver)
|
||||
|
||||
|
||||
## EventObserver
|
||||
Reference: `#!python3 aiogram.dispatcher.event.observer.EventObserver`
|
||||
|
||||
That is base observer for all events.
|
||||
|
||||
### Base registering method
|
||||
Method: `<observer>.register()`
|
||||
|
||||
| Argument | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `callback` | `#!python3 Callable[[Any], Awaitable[Any]]` | Event handler |
|
||||
|
||||
Will return original callback.
|
||||
|
||||
|
||||
### Decorator-style registering method
|
||||
|
||||
Usage:
|
||||
```python3
|
||||
@<observer>()
|
||||
async def handler(*args, **kwargs):
|
||||
pass
|
||||
```
|
||||
|
||||
## TelegramEventObserver
|
||||
Is subclass of [EventObserver](#eventobserver) with some differences.
|
||||
Here you can register handler with filters or bounded filters which can be used as keyword arguments instead of writing full references when you register new handlers.
|
||||
This observer will stops event propagation when first handler is pass.
|
||||
|
||||
### Registering bound filters
|
||||
|
||||
Bound filter should be subclass of [BaseFilter](filters/index.md)
|
||||
|
||||
`#!python3 <observer>.bind_filter(MyFilter)`
|
||||
|
||||
### Registering handlers
|
||||
Method: `TelegramEventObserver.register(callback, filter1, filter2, ..., bound_filter=value, ...)`
|
||||
In this method is added bound filters keywords interface.
|
||||
|
||||
| Argument | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `callback` | `#!python3 Callable[[Any], Awaitable[Any]]` | Event handler |
|
||||
| `*filters` | `#!python3 Union[Callable[[Any], Any], Callable[[Any], Awaitable[Any]], BaseFilter]` | Ordered filters set |
|
||||
| `**bound_filters` | `#!python3 Any` | Bound filters |
|
||||
|
||||
|
||||
### Decorator-style registering event handler with filters
|
||||
|
||||
Usage:
|
||||
```python3
|
||||
@<observer>(filter1, filter2, ...)
|
||||
async def handler(*args, **kwargs):
|
||||
pass
|
||||
```
|
||||
26
docs/dispatcher/observer.rst
Normal file
26
docs/dispatcher/observer.rst
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
########
|
||||
Observer
|
||||
########
|
||||
|
||||
Observer is used for filtering and handling different events. That is part of internal API with some public methods and is recommended to don't use methods is not listed here.
|
||||
|
||||
In `aiogram` framework is available two variants of observer:
|
||||
|
||||
- `EventObserver <#eventobserver>`__
|
||||
- `TelegramEventObserver <#telegrameventobserver>`__
|
||||
|
||||
|
||||
EventObserver
|
||||
=============
|
||||
|
||||
.. autoclass:: aiogram.dispatcher.event.event.EventObserver
|
||||
:members: register, trigger, __call__
|
||||
:member-order: bysource
|
||||
|
||||
|
||||
TelegramEventObserver
|
||||
=====================
|
||||
|
||||
.. autoclass:: aiogram.dispatcher.event.telegram.TelegramEventObserver
|
||||
:members: register, trigger, __call__, bind_filter, middleware, outer_middleware
|
||||
:member-order: bysource
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
# Router
|
||||
Imports:
|
||||
|
||||
- Recommended: `#!python3 from aiogram import Router`
|
||||
- Real location: `#!python3 from aiogram.dispatcher.dispatcher import Router`
|
||||
|
||||
|
||||
## Initializer specification
|
||||
| Argument | Type | Description |
|
||||
| - | - | - |
|
||||
| `use_builtin_filters` | `#!python3 bool` | Register builtin filters in filters factory. Has no effect when filters is already registered in parent router. (default: `#!python3 True`) |
|
||||
|
||||
Example:
|
||||
```python3
|
||||
router = Router()
|
||||
```
|
||||
|
||||
Router can route update and it nested update types like messages, callback query, polls and all other event types.
|
||||
|
||||
## Event observers
|
||||
Here is used event-observer pattern. (Read more on [observer page >>](observer.md))
|
||||
|
||||
Event handlers can be registered in observer by two ways:
|
||||
|
||||
1. By observer method - `#!python3 router.<event_type>.register(handler, <filters, ...>)`
|
||||
1. By decorator - `#!python3 @router.<event_type>(<filters, ...>)`
|
||||
|
||||
!!! warning
|
||||
|
||||
All handlers is always should be an asynchronous.
|
||||
Name of handler function is not important. Event argument name is also is not important but is recommended to don't overlap the name with contextual data in due to function can not accept two arguments with the same name.
|
||||
|
||||
Here is list of available observers and examples how to register handlers (In examples used only @decorator-style):
|
||||
|
||||
### Update
|
||||
```python3
|
||||
@router.update()
|
||||
async def message_handler(update: types.Update) -> Any: pass
|
||||
```
|
||||
Should be used for handling [updates](../api/types/update.md). By default Router is already have an update handler which route all event types to another observers.
|
||||
|
||||
### Message
|
||||
```python3
|
||||
@router.message()
|
||||
async def message_handler(message: types.Message) -> Any: pass
|
||||
```
|
||||
Is useful for handling [message](../api/types/message.md)
|
||||
|
||||
### Edited message
|
||||
```python3
|
||||
@router.edited_message()
|
||||
async def edited_message_handler(edited_message: types.Message) -> Any: pass
|
||||
```
|
||||
Is useful for handling [edited messages](../api/types/message.md)
|
||||
|
||||
### Channel post
|
||||
```python3
|
||||
@router.channel_post()
|
||||
async def channel_post_handler(channel_post: types.Message) -> Any: pass
|
||||
```
|
||||
Is useful for handling [channel posts](../api/types/message.md)
|
||||
|
||||
### Edited channel post
|
||||
```python3
|
||||
@router.edited_channel_post()
|
||||
async def edited_channel_post_handler(edited_channel_post: types.Message) -> Any: pass
|
||||
```
|
||||
Is useful for handling [edited channel posts](../api/types/message.md)
|
||||
|
||||
### Inline query
|
||||
```python3
|
||||
@router.inline_query()
|
||||
async def inline_query_handler(inline_query: types.Message) -> Any: pass
|
||||
```
|
||||
Is useful for handling [inline query](../api/types/inline_query.md)
|
||||
|
||||
### Chosen inline query
|
||||
```python3
|
||||
@router.chosen_inline_result()
|
||||
async def chosen_inline_result_handler(chosen_inline_result: types.ChosenInlineResult) -> Any: pass
|
||||
```
|
||||
Is useful for handling [chosen inline query](../api/types/chosen_inline_result.md)
|
||||
|
||||
### Callback query
|
||||
```python3
|
||||
@router.callback_query()
|
||||
async def callback_query_handler(callback_query: types.CallbackQuery) -> Any: pass
|
||||
```
|
||||
Is useful for handling [callback query's](../api/types/callback_query.md)
|
||||
|
||||
### Shipping query
|
||||
```python3
|
||||
@router.shipping_query()
|
||||
async def shipping_query_handler(shipping_query: types.ShippingQuery) -> Any: pass
|
||||
```
|
||||
Is useful for handling [shipping query](../api/types/shipping_query.md)
|
||||
|
||||
### Pre checkout query
|
||||
```python3
|
||||
@router.pre_checkout_query()
|
||||
async def pre_checkout_query_handler(pre_checkout_query: types.PreCheckoutQuery) -> Any: pass
|
||||
```
|
||||
Is useful for handling [pre-checkout query](../api/types/pre_checkout_query.md)
|
||||
|
||||
### Poll
|
||||
```python3
|
||||
@router.poll()
|
||||
async def poll_handler(poll: types.Poll) -> Any: pass
|
||||
```
|
||||
Is useful for handling [polls](../api/types/poll.md)
|
||||
|
||||
### Poll answer
|
||||
```python3
|
||||
@router.poll_answer()
|
||||
async def poll_answer_handler(poll_answer: types.PollAnswer) -> Any: pass
|
||||
```
|
||||
Is useful for handling [polls answers](../api/types/poll_answer.md)
|
||||
|
||||
### Errors
|
||||
```python3
|
||||
@router.errors()
|
||||
async def error_handler(exception: Exception) -> Any: pass
|
||||
```
|
||||
Is useful for handling errors from other handlers
|
||||
|
||||
|
||||
## Nested routers
|
||||
|
||||
!!! warning
|
||||
Routers by the way can be nested to an another routers with some limitations:
|
||||
|
||||
1. Router **CAN NOT** include itself
|
||||
1. Routers **CAN NOT** be used for circular including (router 1 include router 2, router 2 include router 3, router 3 include router 1)
|
||||
|
||||
|
||||
Example:
|
||||
```python3
|
||||
# module_1.py
|
||||
router1 = Router()
|
||||
router2 = Router()
|
||||
|
||||
router2.include_router(router1)
|
||||
```
|
||||
|
||||
|
||||
## How it works?
|
||||
|
||||
For example dispatcher has 2 routers, last one router is also have one nested router:
|
||||
|
||||
[](../assets/images/nested_routers_example.png)
|
||||
_(Click on image to zoom it)_
|
||||
|
||||
In this case update propagation flow will have form:
|
||||
|
||||
[](../assets/images/update_propagation_flow.png)
|
||||
_(Click on image to zoom it)_
|
||||
|
||||
181
docs/dispatcher/router.rst
Normal file
181
docs/dispatcher/router.rst
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
######
|
||||
Router
|
||||
######
|
||||
|
||||
.. autoclass:: aiogram.dispatcher.router.Router
|
||||
:members: __init__, include_router
|
||||
:show-inheritance:
|
||||
|
||||
|
||||
Event observers
|
||||
===============
|
||||
|
||||
.. warning::
|
||||
|
||||
All handlers is always should be an asynchronous.
|
||||
Name of handler function is not important. Event argument name is also is not important but is recommended to don't overlap the name with contextual data in due to function can not accept two arguments with the same name.
|
||||
|
||||
Here is list of available observers and examples how to register handlers (In examples used only @decorator-style):
|
||||
|
||||
For examples used decorator-style registering handlers but if you dont like @decorators just use :obj:`<event type>.register(...)` method instead.
|
||||
|
||||
Update
|
||||
------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.update()
|
||||
async def message_handler(update: types.Update) -> Any: pass
|
||||
|
||||
.. note::
|
||||
|
||||
By default Router is already have an update handler which route all event types to another observers.
|
||||
|
||||
|
||||
Message
|
||||
-------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.message()
|
||||
async def message_handler(message: types.Message) -> Any: pass
|
||||
|
||||
|
||||
Edited message
|
||||
--------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.edited_message()
|
||||
async def edited_message_handler(edited_message: types.Message) -> Any: pass
|
||||
|
||||
Channel post
|
||||
------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.channel_post()
|
||||
async def channel_post_handler(channel_post: types.Message) -> Any: pass
|
||||
|
||||
Edited channel post
|
||||
-------------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.edited_channel_post()
|
||||
async def edited_channel_post_handler(edited_channel_post: types.Message) -> Any: pass
|
||||
|
||||
|
||||
Inline query
|
||||
------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.inline_query()
|
||||
async def inline_query_handler(inline_query: types.Message) -> Any: pass
|
||||
|
||||
Chosen inline query
|
||||
-------------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.chosen_inline_result()
|
||||
async def chosen_inline_result_handler(chosen_inline_result: types.ChosenInlineResult) -> Any: pass
|
||||
|
||||
Callback query
|
||||
--------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.callback_query()
|
||||
async def callback_query_handler(callback_query: types.CallbackQuery) -> Any: pass
|
||||
|
||||
Shipping query
|
||||
--------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.shipping_query()
|
||||
async def shipping_query_handler(shipping_query: types.ShippingQuery) -> Any: pass
|
||||
|
||||
Pre checkout query
|
||||
------------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.pre_checkout_query()
|
||||
async def pre_checkout_query_handler(pre_checkout_query: types.PreCheckoutQuery) -> Any: pass
|
||||
|
||||
Poll
|
||||
----
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.poll()
|
||||
async def poll_handler(poll: types.Poll) -> Any: pass
|
||||
|
||||
Poll answer
|
||||
-----------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.poll_answer()
|
||||
async def poll_answer_handler(poll_answer: types.PollAnswer) -> Any: pass
|
||||
|
||||
Errors
|
||||
------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.errors()
|
||||
async def error_handler(exception: Exception) -> Any: pass
|
||||
|
||||
Is useful for handling errors from other handlers
|
||||
|
||||
|
||||
Nested routers
|
||||
==============
|
||||
|
||||
.. warning::
|
||||
|
||||
Routers by the way can be nested to an another routers with some limitations:
|
||||
|
||||
1. Router **CAN NOT** include itself
|
||||
1. Routers **CAN NOT** be used for circular including (router 1 include router 2, router 2 include router 3, router 3 include router 1)
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
:caption: module_2.py
|
||||
:name: module_2
|
||||
|
||||
router2 = Router()
|
||||
|
||||
@router2.message()
|
||||
...
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
:caption: module_12.py
|
||||
:name: module_1
|
||||
|
||||
from module_2 import router2
|
||||
|
||||
|
||||
router1 = Router()
|
||||
router1.include_router(router2)
|
||||
|
||||
|
||||
How it works?
|
||||
-------------
|
||||
|
||||
For example dispatcher has 2 routers, last one router is also have one nested router:
|
||||
|
||||
.. image:: ../_static/nested_routers_example.png
|
||||
:alt: Nested routers example
|
||||
|
||||
In this case update propagation flow will have form:
|
||||
|
||||
.. image:: ../_static/update_propagation_flow.png
|
||||
:alt: Nested routers example
|
||||
Loading…
Add table
Add a link
Reference in a new issue