* Rework middlewares, separate management to `MiddlewareManager` class

* Rework middlewares

* Added changes description for redis

* Added changes description for redis

* Fixed tests with Redis // aioredis replacement

* Changed msg.<html/md>_text attributes behaviour

* Added changelog for spoilers

* Added possibility to get command magic result as handler arguments
This commit is contained in:
Alex Root Junior 2022-04-16 19:07:32 +03:00 committed by GitHub
parent 930bca0876
commit 286cf39c8a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 1380 additions and 804 deletions

View file

@ -0,0 +1,118 @@
==============================
Callback Data Factory & Filter
==============================
.. autoclass:: aiogram.dispatcher.filters.callback_data.CallbackData
:members:
:member-order: bysource
:undoc-members: False
Usage
=====
Create subclass of :code:`CallbackData`:
.. code-block:: python
class MyCallback(CallbackData, prefix="my"):
foo: str
bar: int
After that you can generate any callback based on this class, for example:
.. code-block:: python
cb1 = MyCallback(foo="demo", bar=42)
cb1.pack() # returns 'my:demo:42'
cb1.unpack('my:demo:42') # returns <MyCallback(foo="demo", bar=42)>
So... Now you can use this class to generate any callbacks with defined structure
.. code-block:: python
...
# Pass it into the markup
InlineKeyboardButton(
text="demo",
callback_data=MyCallback(foo="demo", bar="42").pack() # value should be packed to string
)
...
... and handle by specific rules
.. code-block:: python
# Filter callback by type and value of field :code:`foo`
@router.callback_query(MyCallback.filter(F.foo == "demo"))
async def my_callback_foo(query: CallbackQuery, callback_data: MyCallback):
await query.answer(...)
...
print("bar =", callback_data.bar)
Also can be used in :doc:`Keyboard builder </utils/keyboard>`:
.. code-block:: python
builder = InlineKeyboardBuilder()
builder.button(
text="demo",
callback_data=MyCallback(foo="demo", bar="42") # Value can be not packed to string inplace, because builder knows what to do with callback instance
)
Another abstract example:
.. code-block:: python
class Action(str, Enum):
ban = "ban"
kick = "kick"
warn = "warn"
class AdminAction(CallbackData, prefix="adm"):
action: Action
chat_id: int
user_id: int
...
# Inside handler
builder = InlineKeyboardBuilder()
for action in Action:
builder.button(
text=action.value.title(),
callback_data=AdminAction(action=action, chat_id=chat_id, user_id=user_id),
)
await bot.send_message(
chat_id=admins_chat,
text=f"What do you want to do with {html.quote(name)}",
reply_markup=builder.as_markup(),
)
...
@router.callback_query(AdminAction.filter(F.action == Action.ban))
async def ban_user(query: CallbackQuery, callback_data: AdminAction, bot: Bot):
await bot.ban_chat_member(
chat_id=callback_data.chat_id,
user_id=callback_data.user_id,
...
)
Known limitations
=================
Allowed types and their subclasses:
- :code:`str`
- :code:`int`
- :code:`bool`
- :code:`float`
- :code:`Decimal` (:code:`from decimal import Decimal`)
- :code:`Fraction` (:code:`from fractions import Fraction`)
- :code:`UUID` (:code:`from uuid import UUID`)
- :code:`Enum` (:code:`from enum import Enum`, only for string enums)
- :code:`IntEnum` (:code:`from enum import IntEnum`, only for int enums)
.. note::
Note that the integer Enum's should be always is subclasses of :code:`IntEnum` in due to parsing issues.

View file

@ -22,6 +22,7 @@ Here is list of builtin filters:
exception
magic_filters
magic_data
callback_data
Own filters specification
=========================