Фильтры¶
Фильтры определяют, когда должен сработать обработчик. Можно использовать несколько фильтров одновременно.
MagicFilter (F)¶
Гибкая система фильтрации через объект F:
from maxapi import F
# Только текстовые сообщения
@dp.message_created(F.message.body.text)
async def text_handler(event: MessageCreated):
...
# Сообщения с вложениями
@dp.message_created(F.message.body.attachments)
async def attachment_handler(event: MessageCreated):
...
# Комбинация условий
from maxapi.enums.chat_type import ChatType
# ⚠️ Скобки обязательны: & и | имеют более высокий приоритет, чем ==
@dp.message_created(F.message.body.text & (F.message.chat.type == ChatType.DIALOG))
async def dialog_text_handler(event: MessageCreated):
...
Для личных сообщений используйте ChatType.DIALOG.
Command фильтр¶
from maxapi.types import Command
# Одна команда
@dp.message_created(Command('start'))
async def start_handler(event: MessageCreated):
...
# Несколько команд
@dp.message_created(Command(['start', 'help', 'info']))
async def commands_handler(event: MessageCreated):
...
Callback Payload фильтр¶
from maxapi.filters.callback_payload import CallbackPayload
# Простой payload (строка)
@dp.message_callback(F.callback.payload == 'button_click')
async def callback_handler(event: MessageCallback):
...
# Структурированный payload (класс)
class MyPayload(CallbackPayload, prefix='mypayload'):
action: str
value: int
# Без дополнительных условий
@dp.message_callback(MyPayload.filter())
async def callback_handler(event: MessageCallback, payload: MyPayload):
await event.answer(f"Action: {payload.action}, Value: {payload.value}")
# С дополнительным фильтром
@dp.message_callback(MyPayload.filter(F.action == 'edit'))
async def callback_handler(event: MessageCallback, payload: MyPayload):
await event.answer(f"Edit action: {payload.value}")
ContactFilter (сообщения с контактом)¶
Фильтр срабатывает на MessageCreated и MessageEdited, если в сообщении есть
вложение типа contact. При совпадении возвращает dict с ключом contact,
который будет прокинут в хэндлер как аргумент.
from maxapi.filters.contact import ContactFilter
from maxapi.types.attachments.contact import Contact
@dp.message_created(ContactFilter())
async def on_contact(event, contact: Contact):
# contact.payload.vcf_info — исходная VCF строка (не изменяется)
# contact.payload.vcf — высокоуровневый доступ к распарсенному vCard
full_name = contact.payload.vcf.full_name
phone = contact.payload.vcf.phone
await event.message.answer(f"{full_name=}, {phone=}")
Если нужно разобрать VCF вручную, можно использовать parse_vcf_info:
from maxapi.utils.vcf import parse_vcf_info
info = parse_vcf_info(contact.payload.vcf_info)
print(info.full_name, info.phones)
ChannelPostFilter (посты из канала)¶
Фильтр срабатывает на MessageCreated и MessageEdited, если сообщение пришло
из канала (то есть recipient.chat_type == ChatType.CHANNEL).
from maxapi.filters.channel_post import ChannelPostFilter
from maxapi.types import MessageCreated
@dp.message_created(ChannelPostFilter())
async def on_channel_post(event: MessageCreated):
await event.message.answer("Пост из канала получен")
Комбинация фильтров¶
Приоритет операторов
Операторы & и | имеют более высокий приоритет, чем ==.
Без скобок выражение F.x == "a" | F.x == "b" парсится как
F.x == ("a" | F.x) == "b" — что является ошибкой.
Всегда оборачивайте каждое сравнение в скобки.
# И (AND) — скобки обязательны при использовании ==
F.message.body.text & (F.message.chat.type == ChatType.DIALOG)
# Или (OR) — скобки обязательны при использовании ==
(F.callback.payload == "ru") | (F.callback.payload == "en")
# Для множественных значений удобнее .in_()
F.callback.payload.in_({"ru", "en"})
# Проверка на истинность (без ==) — скобки не нужны
F.message.body.text | F.message.body.attachments
# Отрицание (NOT)
~F.message.body.text
# Несколько фильтров в декораторе (все объединяются через AND)
@dp.message_created(F.message.body.text, Command('start'), Form.name)
async def handler(event: MessageCreated):
...
Базовые фильтры (BaseFilter)¶
Можно создать собственный фильтр, наследуясь от BaseFilter: