Найти в Дзене
Дойти до IT

MagicFilter — волшебная палочка для вашего бота

Основная задача обработчиков (хэндлеров) — обрабатывать сообщения, в том числе и от пользователей. Разберёмся, как это делать. Для этого импортируем модуль MagicFilter с классом F и воспользуемся его методами: F.text == '123' - Ловит определённый текст F.text.startswith('smth_') - Ловит определенный текст, который начинается с smth_ F.data == '123' - Ловит определенный Callback F.data.startswith('smth_') - Ловит определенный Callback который начинается с smth_ F.photo - Ловит только фото (все) F.document - Ловит только документы F.from_user.id == 123 - Ловит только от определенного юзера по его ID Пример использования: @dp.message(F.photo) async def get_photo(message: Message): await message.answer(f'ID фотографии: {message.photo[-1].file_id}') С помощью метода message.photo[-1].file_id можно получить ID фотографии. Этот идентификатор используется для хранения фото на сервере или отправки этого же изображения без повторной загрузки. Фото хранится на сервере Telegram, и нам не нуж
Оглавление

Основная задача обработчиков (хэндлеров) — обрабатывать сообщения, в том числе и от пользователей. Разберёмся, как это делать. Для этого импортируем модуль MagicFilter с классом F и воспользуемся его методами:

Описание фильтров:

F.text == '123' - Ловит определённый текст

F.text.startswith('smth_') - Ловит определенный текст, который начинается с smth_

F.data == '123' - Ловит определенный Callback

F.data.startswith('smth_') - Ловит определенный Callback который начинается с smth_

F.photo - Ловит только фото (все)

F.document - Ловит только документы

F.from_user.id == 123 - Ловит только от определенного юзера по его ID

Пример использования:

-2
@dp.message(F.photo)
async def get_photo(message: Message):
await message.answer(f'ID фотографии: {message.photo[-1].file_id}')

С помощью метода message.photo[-1].file_id можно получить ID фотографии. Этот идентификатор используется для хранения фото на сервере или отправки этого же изображения без повторной загрузки.

Фото хранится на сервере Telegram, и нам не нужно загружать его заново. Достаточно указать ID в аргументе photo метода message.answer_photo, и оно отправится. Однако это должно быть фото, которое хотя бы один раз было отправлено этому боту. Если бот о нём не знает, то он его не найдёт.

Индекс [-1] в этой конструкции означает, что мы получаем самое лучшее качество (последнее фото), так как Telegram сжимает картинки.

Сообщение было словлено этим методом и получено ID:

-3

Command()

Класс Command() используется для обработки команд, которые начинаются со слэша (например, /help).

-4
@dp.message(Command('help'))
async def cmd_help(message: Message):
await message.answer(f'{message.from_user.first_name}, вам нужна помощь?')
await message.answer(f'Ваш ID: {message.from_user.id}')

Из приведённого примера видно, что в класс Command была передана строка 'help', следовательно, мы можем использовать эту команду:

-5

При отправке сообщений можно использовать методы message.from_user.first_name и message.from_user.id. Первый метод выводит имя пользователя, а второй — ID пользователя в Telegram.

CommandObject()

-6
@dp.message(Command('get'))
async def cmd_get(message: Message, command: CommandObject):
await message.answer(f'Вы ввели команду get с аргументом {command.args}')

В некоторых случаях команда должна принимать аргументы, например /get 123. Для этого существует класс CommandObject. В данном примере был принят один аргумент:

-7

Можно принимать и несколько аргументов. В таком случае их необходимо разделить между собой и перебрать:

-8
@dp.message(Command('get'))
async def cmd_get(message: Message, command: CommandObject):
value1, value2 = command.args.split(' ', maxsplit=1)
await message.answer(f'Вы ввели команду get с аргументом {value1} {value2}')
-9

В этой конструкции могут быть недоработки. Рассмотрим все возможные варианты ошибок:

-10
@dp.message(Command('get'))
async def cmd_get(message: Message, command: CommandObject):
if not command.args:
await message.answer('Аргументы не переданы')
return
try:
value1, value2 = command.args.split(' ', maxsplit=1)
await message.answer(f'Вы ввели команду get с аргументом {value1} {value2}')
except:
await message.answer('Были введены неправильные аргументы')
-11

CommandStart()

Мы уже познакомились с фильтром CommandStart(), который предназначен для обработки команды /start. Однако его возможности не ограничиваются только этим. С помощью него можно также обрабатывать дополнительные параметры и, например, реализовать реферальную систему: t.me/bot?start=123. В этом случае бот получит сообщение в формате /start 123. Это называется deep links (дип-линкс). Обратите внимание, что здесь может быть передан только один аргумент!

-12
@dp.message(CommandStart(deep_link=True))
async def cmd_start(message: Message, command: CommandObject):
await message.answer(f'Привет! Ты пришел от {command.args}')

Команда принимает любые данные, переданные по ссылке. Давайте рассмотрим все возможные варианты и ограничим передачу данных только числами:

-13
@dp.message(CommandStart(deep_link=True))
async def cmd_start(message: Message, command: CommandObject):
if command.args.isdigit():
await message.answer(f'Привет! Ты пришел от {command.args}')
else:
await message.answer('Ошибка')

Если вы не хотите, чтобы появлялось сообщение об ошибке, можно использовать аргумент magic:

-14
@dp.message(CommandStart(deep_link=True, magic=F.args.isdigit()))
async def cmd_start(message: Message, command: CommandObject):
await message.answer(f'Привет! Ты пришел от {command.args}')

Здесь вы узнали основное о фильтрах. Если ваша цель — создать простого бота, то необязательно изучать всё. Возьмите для работы только то, что вам пригодится.

P.S. Даже если эта статья потеряет свою актуальность, она всё равно будет служить мне напоминанием о некоторых командах и избавит меня от необходимости искать их снова в интернете. Возможно, спустя пару лет я вернусь к этой статье и освежу свои знания. А тем, кто дочитал до конца, я желаю, чтобы ваши труды, проекты и творческие работы всегда оставались актуальными и востребованными! =)

Обязательно к прочтнению!