Skip to content

Aiogram 3: командный фильтр

https://habr.com/ru/articles/821085/

Фильтры в aiogram нужны для того, чтобы бот понимал, как реагировать на то или иное событие (действие, сообщение или тип сообщения). Приведу несколько примеров.

Фильтры по типу сообщения

На более высоком уровне мы указываем фильтры в декораторе перед функцией после роутера или диспетчера. Из наиболее часто используемых:

  • .message Срабатывает на сообщения в личном чате с ботом или в группах (в каналах работать не будет). Здесь обрабатываются текстовые, фото, видео сообщения и сообщения с документами.
  • .callback_query Срабатывает на сообщения, содержащие callback дату.
  • .channel_post Срабатывает на сообщения в канале, который администрирует бот.

Продолжим изучение фильтров и их применения, чтобы ваши боты стали еще более функциональными и гибкими в работе.

Встроенные командные фильтры.

Существует два встроенных командных фильтра: CommandStart и Command.

python
from aiogram.filters import CommandStart, Command
  • CommandStart реагирует на команду /start и записывается таким образом:

    python
    @start_router.message(CommandStart())

    Как вы видите, здесь не указывается явно команда /start, но бот все равно будет реагировать на эту команду.

  • Command реагирует на команду, которую вы в него передали. Запись имеет такой вид:

    python
    @start_router.message(Command('test'))

    Это указывает боту, что данный хендлер должен реагировать на команду /test.

    Кроме одиночного аргумента, данный фильтр может принимать список команд, на которые должен реагировать бот. Это полезная функция в связке с CommandObject.

    Запись в таком случае будет выглядеть так:

    python
    @start_router.message(Command(commands=["settings", "config"]))

Давайте ещё немного освежим свои знания и напишем хендлер, который будет реагировать на метку в команде. Для этого нам нужно будет использовать CommandObject.

Импорт будет выглядеть так:

python
from aiogram.filters import CommandStart, Command, CommandObject

Пишем хендлер, который будет реагировать на команды /settings и /about:

python
@start_router.message(Command(commands=["settings", "about"]))
async def univers_cmd_handler(message: Message, command: CommandObject):
    command_args: str = command.args
    command_name = 'settings' if 'settings' in message.text else 'about'
    response = f'Была вызвана команда /{command_name}'
    if command_args:
        response += f' с меткой <b>{command_args}</b>'
    else:
        response += ' без метки'
    await message.answer(response)

Вот так можно обработать сразу несколько команд. Такое бывает полезно в админ панели. Например, если нужно быстро забанить пользователя /ban user_id или выполнить другую команду без прописывания большого сценария через FSM или без создания кнопок.

Давайте разберем код.

python
@start_router.message(Command(commands=["settings", "about"]))

Здесь мы прописали хендлер для сообщений, который использует фильтр Command. В него мы передали аргумент commands со списком команд, на которые должен реагировать хендлер.

Далее мы настроили нашу функцию, указав, что она должна обрабатывать сообщение и что там будут аргументы (как минимум она будет их пытаться получить, а иначе присвоит значение None).

command_args: str = command.args Этой строкой мы достаем аргументы из команды, а затем прописываем простое условие, на основании которого генерируем ответное сообщение:

python
command_name = 'settings' if 'settings' in message.text else 'about'
response = f'Была вызвана команда /{command_name}'
if command_args:
    response += f' с меткой <b>{command_args}</b>'
else:
    response += ' без метки'

Сообщение мы форматируем простым образом (делаем тег метки жирным, если она есть) и отправляем пользователю.

img.png

Возможно, это выглядит не особо красиво, но реализация достаточно функциональная и иногда бывает очень удобно использовать именно такой подход. Конечно, заказчику лучше отрисовывать клавиатуры, но мы, как опытные разработчики, понимаем, что главное — это простота вызова команды, правда?

Contacts: teffal@mail.ru