Фильтры¶
Фильтры определяют, какие события будет обрабатывать конкретный обработчик.
Базовый принцип¶
Фильтры передаются как аргументы декоратора:
Все фильтры должны вернуть True (или dict) — работает как логическое И.
MagicFilter (F)¶
Объект F — декларативный фильтр на основе magic-filter:
from maxgram import F
# Точное совпадение текста
@router.message(F.body.text == "hello")
# Проверка начала строки
@router.message(F.body.text.startswith("/"))
# Проверка отправителя
@router.message(F.sender.is_bot == False)
# Callback payload
@router.message_callback(F.payload == "action:like")
@router.message_callback(F.payload.startswith("vote:"))
# Проверка наличия поля
@router.message(F.body.attachments)
Command¶
Фильтр для текстовых команд (сообщения, начинающиеся с /):
from maxgram.filters import Command, CommandObject
@router.message(Command("help"))
async def help_handler(message, bot):
pass
@router.message(Command("echo"))
async def echo_handler(message, command: CommandObject, bot):
print(command.command) # "echo"
print(command.args) # текст после команды
print(command.prefix) # "/"
Параметры Command:
| Параметр | Тип | Описание |
|---|---|---|
commands |
str \| list[str] |
Имена команд (без /) |
prefix |
str |
Префикс команды (по умолчанию "/") |
ignore_case |
bool |
Игнорировать регистр (False) |
ignore_mention |
bool |
Игнорировать упоминание бота (False) |
magic |
MagicFilter \| None |
Дополнительный фильтр magic-filter |
CommandObject¶
Результат парсинга команды, инъектируется в обработчик:
| Поле | Тип | Описание |
|---|---|---|
prefix |
str |
Префикс ("/") |
command |
str |
Имя команды ("help") |
mention |
str \| None |
Упоминание бота |
args |
str \| None |
Аргументы после команды |
regexp_match |
re.Match \| None |
Результат регулярного выражения |
magic_result |
Any |
Результат magic-filter |
CallbackData¶
Структурированные callback-данные на основе Pydantic:
from maxgram.filters import CallbackData
class ProductAction(CallbackData, prefix="product"):
id: int
action: str
# Упаковка (при создании кнопки)
payload = ProductAction(id=42, action="buy").pack()
# Результат: "product:42:buy"
# Фильтр
@router.message_callback(ProductAction.filter())
async def on_product(callback, callback_data: ProductAction, bot):
print(callback_data.id) # 42
print(callback_data.action) # "buy"
Warning
Максимальная длина payload — 128 байт. Учитывайте это при проектировании структуры CallbackData.
Поддерживаемые типы полей:
str,int,floatboolEnumUUIDDecimal,Fraction
StateFilter¶
Фильтр по текущему состоянию FSM:
from maxgram.filters import StateFilter
from maxgram.fsm.state import State, StatesGroup
class Form(StatesGroup):
name = State()
age = State()
@router.message(StateFilter(Form.name))
async def get_name(message, state, bot):
pass
# Любое состояние
@router.message(StateFilter("*"))
async def any_state(message, bot):
pass
# Без состояния (по умолчанию)
@router.message(StateFilter(None))
async def no_state(message, bot):
pass
ExceptionTypeFilter¶
Фильтр ошибок по типу исключения:
from maxgram.filters import ExceptionTypeFilter
@router.error(ExceptionTypeFilter(ValueError))
async def handle_value_error(error, bot):
pass
ExceptionMessageFilter¶
Фильтр ошибок по тексту сообщения (regex):
from maxgram.filters import ExceptionMessageFilter
@router.error(ExceptionMessageFilter(r"timeout"))
async def handle_timeout(error, bot):
pass
MagicData¶
Фильтр по данным middleware:
from maxgram.filters import MagicData
@router.message(MagicData(F.event_from_user.is_bot == False))
async def humans_only(message, bot):
pass
Логические комбинаторы¶
from maxgram.filters import and_f, or_f, invert_f
# ИЛИ
@router.message(or_f(Command("help"), Command("start")))
# И
@router.message(and_f(Filter1(), Filter2()))
# НЕ (инверсия)
@router.message(invert_f(Command("admin")))
# Через оператор ~
@router.message(~Command("admin"))
Пользовательские фильтры¶
from maxgram.filters import Filter
class IsAdmin(Filter):
def __init__(self, admin_ids: set[int]):
self.admin_ids = admin_ids
async def __call__(self, message, **kwargs) -> bool:
if message.sender:
return message.sender.user_id in self.admin_ids
return False
# Использование
@router.message(IsAdmin({123, 456}), Command("ban"))
async def ban(message, bot):
pass
Фильтр может возвращать dict для передачи данных в обработчик: