Filtering events#

Danger

Note that the design of filters will be changed in 3.0b5

Read more >>

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:

Own filters specification#

Filters can be:

  • Asynchronous function (async def my_filter(*args, **kwargs): pass)

  • Synchronous function (def my_filter(*args, **kwargs): pass)

  • Anonymous function (lambda event: True)

  • Any awaitable object

  • Subclass of aiogram.filters.base.BaseFilter

  • Instances of MagicFilter

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#

class aiogram.filters.base.BaseFilter[source]#

If you want to register own filters like builtin filters you will need to write subclass of this class 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.

abstract async __call__(*args: Any, **kwargs: Any) Union[bool, Dict[str, Any]][source]#

This method should be overridden.

Accepts incoming event and should return boolean or dict.

Returns

bool or Dict[str, Any]

For example if you need to make simple text filter:

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 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 private:

class ChatType(BaseFilter):
    chat_type: str = "private"

    async def __call__(self, message: Message , event_chat: Chat) -> bool:
        if event_chat:
            return event_chat.type == self.chat_type
        else:
            return False


router.message.bind_filter(ChatType)

@router.message()
async def my_handler(message: Message): ...