mirror of
https://github.com/aiogram/aiogram.git
synced 2026-04-08 16:37:47 +00:00
Partial update docs
This commit is contained in:
parent
d9f9ff74fe
commit
4db765f3a7
17 changed files with 81 additions and 123 deletions
|
|
@ -62,14 +62,16 @@ Features
|
|||
- Asynchronous (`asyncio docs <https://docs.python.org/3/library/asyncio.html>`_, :pep:`492`)
|
||||
- Has type hints (:pep:`484`) and can be used with `mypy <http://mypy-lang.org/>`_
|
||||
- Supports `PyPy <https://www.pypy.org/>`_
|
||||
- Supports `Telegram Bot API 5.3 <https://core.telegram.org/bots/api>`_
|
||||
- Supports `Telegram Bot API 6.3 <https://core.telegram.org/bots/api>`_ and gets fast updates to the latest versions of the Bot API
|
||||
- Telegram Bot API integration code was `autogenerated <https://github.com/aiogram/tg-codegen>`_ and can be easily re-generated when API gets updated
|
||||
- Updates router (Blueprints)
|
||||
- Has Finite State Machine
|
||||
- Uses powerful :ref:`magic filters <magic-filters>`
|
||||
- Middlewares (incoming updates and API calls)
|
||||
- Provides `Replies into Webhook <https://core.telegram.org/bots/faq#how-can-i-make-requests-in-response-to-updates>`_
|
||||
- Integrated I18n/L10n support with GNU Gettext (or Fluent)
|
||||
|
||||
|
||||
.. warning::
|
||||
|
||||
It is strongly advised that you have prior experience working
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class Router:
|
|||
- By decorator - :obj:`@router.<event_type>(<filters, ...>)`
|
||||
"""
|
||||
|
||||
def __init__(self, name: Optional[str] = None) -> None:
|
||||
def __init__(self, *, name: Optional[str] = None) -> None:
|
||||
"""
|
||||
:param name: Optional router name, can be useful for debugging
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -34,6 +34,11 @@ class Filter(ABC):
|
|||
return invert_f(self)
|
||||
|
||||
def update_handler_flags(self, flags: Dict[str, Any]) -> None:
|
||||
"""
|
||||
Also if you want to extend handler flags with using this filter you should implement this method
|
||||
|
||||
:param flags: existing flags, can be updated directly
|
||||
"""
|
||||
pass
|
||||
|
||||
def _signature_to_string(self, *args: Any, **kwargs: Any) -> str:
|
||||
|
|
|
|||
|
|
@ -3,8 +3,14 @@ from aiogram.types.base import MutableTelegramObject
|
|||
|
||||
|
||||
class ErrorEvent(MutableTelegramObject):
|
||||
"""
|
||||
Internal event, should be used to receive errors while processing Updates from Telegram
|
||||
"""
|
||||
|
||||
update: Update
|
||||
"""Received update"""
|
||||
exception: Exception
|
||||
"""Exception"""
|
||||
|
||||
class Config:
|
||||
arbitrary_types_allowed = True
|
||||
|
|
|
|||
9
docs/api/types/error_event.rst
Normal file
9
docs/api/types/error_event.rst
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
##########
|
||||
ErrorEvent
|
||||
##########
|
||||
|
||||
|
||||
.. automodule:: aiogram.types.error_event
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:undoc-members: True
|
||||
|
|
@ -189,3 +189,12 @@ Games
|
|||
game
|
||||
callback_game
|
||||
game_high_score
|
||||
|
||||
|
||||
Internal events
|
||||
===============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
error_event
|
||||
|
|
|
|||
|
|
@ -62,3 +62,5 @@ texinfo_documents = [
|
|||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
||||
add_module_names = False
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ CallbackQueryHandler
|
|||
####################
|
||||
|
||||
|
||||
.. automodule:: aiogram.handler.callback_query
|
||||
.. automodule:: aiogram.handlers.callback_query
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:undoc-members: True
|
||||
|
|
|
|||
|
|
@ -86,10 +86,10 @@ Handle user leave or join events
|
|||
|
||||
from aiogram.filters import IS_MEMBER, IS_NOT_MEMBER
|
||||
|
||||
@router.chat_member(ChatMemberUpdatedFilter(member_status_changed=IS_MEMBER >> IS_NOT_MEMBER))
|
||||
@router.chat_member(ChatMemberUpdatedFilter(IS_MEMBER >> IS_NOT_MEMBER))
|
||||
async def on_user_leave(event: ChatMemberUpdated): ...
|
||||
|
||||
@router.chat_member(ChatMemberUpdatedFilter(member_status_changed=IS_NOT_MEMBER >> IS_MEMBER))
|
||||
@router.chat_member(ChatMemberUpdatedFilter(IS_NOT_MEMBER >> IS_MEMBER))
|
||||
async def on_user_join(event: ChatMemberUpdated): ...
|
||||
|
||||
Or construct your own terms via using pre-defined set of statuses and transitions.
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ Usage
|
|||
2. Handle command by regexp pattern: :code:`Command(re.compile(r"item_(\d+)"))`
|
||||
3. Match command by multiple variants: :code:`Command("item", re.compile(r"item_(\d+)"))`
|
||||
4. Handle commands in public chats intended for other bots: :code:`Command("command", ignore_mention=True)`
|
||||
5. Use :class:`aiogram.types.bot_command.BotCommand` object as command reference :code:`Command(BotCommand(command="command", description="My awesome command")`
|
||||
|
||||
.. warning::
|
||||
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
==================
|
||||
ContentTypesFilter
|
||||
==================
|
||||
|
||||
.. autoclass:: aiogram.filters.content_types.ContentTypesFilter
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:undoc-members: False
|
||||
|
||||
Can be imported:
|
||||
|
||||
- :code:`from aiogram.filters.content_types import ContentTypesFilter`
|
||||
- :code:`from aiogram.filters import ContentTypesFilter`
|
||||
|
||||
Or used from filters factory by passing corresponding arguments to handler registration line
|
||||
|
||||
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`
|
||||
|
|
@ -2,13 +2,6 @@
|
|||
Filtering events
|
||||
================
|
||||
|
||||
|
||||
.. danger::
|
||||
|
||||
Note that the design of filters will be changed in 3.0b5
|
||||
|
||||
`Read more >> <https://github.com/aiogram/aiogram/issues/942>`_
|
||||
|
||||
Filters is needed for routing updates to the specific handler.
|
||||
Searching of handler is always stops on first match set of filters are pass.
|
||||
|
||||
|
|
@ -23,91 +16,40 @@ Here is list of builtin filters:
|
|||
:maxdepth: 1
|
||||
|
||||
command
|
||||
content_types
|
||||
text
|
||||
chat_member_updated
|
||||
exception
|
||||
magic_filters
|
||||
magic_data
|
||||
callback_data
|
||||
exception
|
||||
|
||||
Own filters specification
|
||||
Writing own filters
|
||||
=========================
|
||||
|
||||
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 :class:`aiogram.filters.base.BaseFilter`
|
||||
|
||||
- Subclass of :class:`aiogram.filters.base.Filter`
|
||||
- Instances of :ref:`MagicFilter <magic-filters>`
|
||||
|
||||
Filters should return bool or dict.
|
||||
and 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
|
||||
=====================
|
||||
Base class for own filters
|
||||
--------------------------
|
||||
|
||||
.. autoclass:: aiogram.filters.base.BaseFilter
|
||||
:members: __call__
|
||||
.. autoclass:: aiogram.filters.base.Filter
|
||||
:members: __call__,update_handler_flags
|
||||
:member-order: bysource
|
||||
:undoc-members: False
|
||||
|
||||
Own filter example
|
||||
------------------
|
||||
|
||||
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 but will be available
|
||||
in nested routers only after attaching routers so that's mean you will need to
|
||||
include routers before registering handlers.
|
||||
|
||||
Resolving filters with default value
|
||||
====================================
|
||||
|
||||
Bound Filters with only default arguments will be automatically applied with default values
|
||||
to each handler in the router and nested routers to which this filter is bound.
|
||||
|
||||
For example, although we do not specify :code:`chat_type` in the handler filters,
|
||||
but since the filter has a default value, the filter will be applied to the handler
|
||||
with a default value :code:`private`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class ChatType(BaseFilter):
|
||||
chat_type: str = "private"
|
||||
|
||||
async def __call__(self, message: Message , event_chat: Chat) -> bool:
|
||||
if event_chat:
|
||||
return event_chat.type == chat_type
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
router.message.bind_filter(ChatType)
|
||||
|
||||
@router.message()
|
||||
async def my_handler(message: Message): ...
|
||||
.. literalinclude:: ../../../examples/own_filter.py
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ MagicData
|
|||
|
||||
Can be imported:
|
||||
|
||||
- :code:`from aiogram.filters.magic_data import MagicData`
|
||||
- :code:`from aiogram.filters import MagicData`
|
||||
|
||||
Or used from filters factory by passing corresponding arguments to handler registration line
|
||||
|
|
@ -17,7 +16,7 @@ Or used from filters factory by passing corresponding arguments to handler regis
|
|||
Usage
|
||||
=====
|
||||
|
||||
#. :code:`MagicData(magic_data=F.event.from_user.id == F.config.admin_id)` (Note that :code:`config` should be passed from middleware)
|
||||
#. :code:`MagicData(F.event.from_user.id == F.config.admin_id)` (Note that :code:`config` should be passed from middleware)
|
||||
|
||||
|
||||
Allowed handlers
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ Can be imported:
|
|||
|
||||
- :code:`from aiogram.filters.text import Text`
|
||||
- :code:`from aiogram.filters import Text`
|
||||
- :code:`from.filters import Text`
|
||||
|
||||
Or used from filters factory by passing corresponding arguments to handler registration line
|
||||
|
||||
|
|
@ -19,11 +18,11 @@ 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'`
|
||||
#. Text starts with the specified value: :code:`Text(startswith="text") # value.startswith('text')`
|
||||
#. Text ends with the specified value: :code:`Text(endswith="text") # value.endswith('text')`
|
||||
#. Text contains the specified value: :code:`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()`
|
||||
#. Ignore case can be combined with any previous listed filter: :code:`Text(text="Text", ignore_case=True) # value.lower() == 'text'.lower()`
|
||||
|
||||
Allowed handlers
|
||||
================
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ Via filters
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
class Command(BaseFilter):
|
||||
class Command(Filter):
|
||||
...
|
||||
|
||||
def update_handler_flags(self, flags: Dict[str, Any]) -> None:
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ Message
|
|||
|
||||
(For example text, sticker and document are always of different content types of message)
|
||||
|
||||
Recommended way to check field availability before usage or use
|
||||
:class:`aiogram.filters.content_types.ContentTypesFilter`
|
||||
Recommended way to check field availability before usage, for example via :ref:`magic filter <magic-filters>`:
|
||||
:code:`F.text` to handle text, :code:`F.sticker` to handle stickers only and etc.
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
|
@ -141,7 +141,7 @@ Errors
|
|||
.. code-block:: python
|
||||
|
||||
@router.errors()
|
||||
async def error_handler(exception: Exception) -> Any: pass
|
||||
async def error_handler(exception: ErrorEvent) -> Any: pass
|
||||
|
||||
Is useful for handling errors from other handlers
|
||||
|
||||
|
|
@ -152,9 +152,8 @@ 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)
|
||||
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:
|
||||
|
|
@ -170,7 +169,7 @@ Example:
|
|||
|
||||
|
||||
.. code-block:: python
|
||||
:caption: module_12.py
|
||||
:caption: module_2.py
|
||||
:name: module_1
|
||||
|
||||
from module_2 import router2
|
||||
|
|
|
|||
18
examples/own_filter.py
Normal file
18
examples/own_filter.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
from aiogram import Router
|
||||
from aiogram.filters import Filter
|
||||
from aiogram.types import Message
|
||||
|
||||
router = Router()
|
||||
|
||||
|
||||
class MyFilter(Filter):
|
||||
def __init__(self, my_text: str) -> None:
|
||||
self.my_text = my_text
|
||||
|
||||
async def __call__(self, message: Message) -> bool:
|
||||
return message.text == self.my_text
|
||||
|
||||
|
||||
@router.message(MyFilter("hello"))
|
||||
async def my_handler(message: Message):
|
||||
...
|
||||
Loading…
Add table
Add a link
Reference in a new issue