Обработчики и фильтры¶
vk-bot предоставляет декораторы для обработки различных событий:
сообщений, нажатий на inline-кнопки и middleware-прослоек.
Каждый декоратор принимает набор фильтров, определяющих, какие события
будет обрабатывать функция.
Обработчики сообщений¶
Декоратор @bot.message_handler() регистрирует функцию для обработки
входящих сообщений. Без фильтров обработчик срабатывает на все сообщения.
@bot.message_handler()
def handle_all(message: types.Message):
bot.send_message(message.from_id, f"Получено: {message.text}")
Важно
Обработчики проверяются по порядку регистрации. Первый подходящий обработчик выполняется, остальные - пропускаются. Поэтому более специфичные обработчики следует регистрировать раньше общих.
Фильтр commands¶
Реагирует на команды вида /start, /help, и т.д.
Слэш в начале не указывается:
@bot.message_handler(commands=["start", "help"])
def handle_commands(message: types.Message):
bot.send_message(message.from_id, "Добро пожаловать!")
Чтобы получить аргументы команды, используйте утилиту extract_command:
from vk_bot.handlers import extract_command
@bot.message_handler(commands=["echo"])
def handle_echo(message: types.Message):
cmd, args = extract_command(message.text)
bot.send_message(message.from_id, args or "Нет аргументов")
# Сообщение "/echo привет мир" → args = "привет мир"
Фильтр regexp¶
Срабатывает при совпадении текста сообщения с регулярным выражением:
@bot.message_handler(regexp=r"привет|здравствуй")
def handle_greeting(message: types.Message):
bot.send_message(message.from_id, "Привет!")
Фильтр func¶
Произвольная функция-предикат, принимающая Message и возвращающая bool:
@bot.message_handler(func=lambda m: m.text and m.text.startswith("!"))
def handle_exclamation(message: types.Message):
bot.send_message(message.from_id, "Обнаружена команда с '!'")
# Пример с именованной функцией
def is_admin(message: types.Message) -> bool:
return message.from_id in [123456, 789012]
@bot.message_handler(func=is_admin)
def handle_admin(message: types.Message):
bot.send_message(message.from_id, "Вы администратор")
Фильтр content_types¶
Фильтрация по типу содержимого сообщения:
@bot.message_handler(content_types=["photo"])
def handle_photo(message: types.Message):
photos = message.get_photos()
bot.send_message(message.from_id, f"Получено {len(photos)} фото")
@bot.message_handler(content_types=["doc"])
def handle_doc(message: types.Message):
docs = message.get_documents()
bot.send_message(message.from_id, f"Документ: {docs[0].title}")
Доступные типы содержимого:
text- текстовое сообщениеphoto- фотографияdoc- документvideo- видеоaudio- аудиоsticker- стикерwall- запись со стены
Фильтр chat_types¶
Ограничивает обработчик определёнными типами чатов:
@bot.message_handler(chat_types=["private"])
def handle_private(message: types.Message):
bot.send_message(message.from_id, "Это личное сообщение")
@bot.message_handler(chat_types=["group"])
def handle_group(message: types.Message):
bot.send_message(message.peer_id, "Сообщение из беседы")
Фильтр state¶
Срабатывает только когда пользователь находится в определённом состоянии FSM:
from vk_bot.state.group import StatesGroup
from vk_bot.state.manager import State
class Form(StatesGroup):
waiting_name = State()
waiting_age = State()
@bot.message_handler(state=Form.waiting_name)
def handle_name(message: types.Message, state: StateContext):
state.update(name=message.text)
state.set(Form.waiting_age)
bot.send_message(message.from_id, "Сколько вам лет?")
Совет
Когда обработчик принимает второй аргумент state: StateContext,
библиотека автоматически передаёт контекст состояния пользователя.
Можно указать несколько состояний списком:
@bot.message_handler(state=[Form.waiting_name, Form.waiting_age])
def handle_any_form_step(message: types.Message, state: StateContext):
...
Комбинирование фильтров¶
Фильтры комбинируются через логическое И - все условия должны совпасть:
@bot.message_handler(
content_types=["text"],
chat_types=["private"],
func=lambda m: len(m.text or "") > 10,
)
def handle_long_private_text(message: types.Message):
bot.send_message(message.from_id, "Длинное сообщение!")
Обработчики callback-запросов¶
Декоратор @bot.callback_query_handler() обрабатывает нажатия на
inline-кнопки:
@bot.callback_query_handler(data="confirm")
def handle_confirm(callback: types.CallbackQuery):
bot.answer_callback_query(
callback_query_id=callback.id,
user_id=callback.from_id,
peer_id=callback.peer_id,
text="Подтверждено!",
)
Фильтр data¶
Может быть строкой (точное совпадение) или регулярным выражением:
import re
# Точное совпадение
@bot.callback_query_handler(data="btn_like")
def on_like(callback: types.CallbackQuery):
...
# Регулярное выражение
@bot.callback_query_handler(data=re.compile(r"^page_\d+$"))
def on_page(callback: types.CallbackQuery):
page = callback.data.split("_")[1]
...
Фильтр func¶
Произвольная функция-предикат:
@bot.callback_query_handler(func=lambda cb: cb.from_id == 12345)
def on_admin_callback(callback: types.CallbackQuery):
...
Фильтр state¶
Аналогичен фильтру состояния для сообщений:
@bot.callback_query_handler(data="next_step", state=Form.waiting_confirm)
def on_confirm(callback: types.CallbackQuery, state: StateContext):
state.finish()
bot.answer_callback_query(
callback.id, callback.from_id, callback.peer_id,
text="Готово!",
)
Middleware¶
Middleware - функции, которые выполняются до обработчиков.
Если middleware возвращает False, обработка события прекращается.
@bot.middleware_handler()
def log_all_events(bot_instance, update: types.Update):
print(f"Событие: {update.type}")
# Не возвращаем False - обработка продолжится
@bot.middleware_handler(update_types=["message_new"])
def check_ban_list(bot_instance, update: types.Update):
if update.message and update.message.from_id in BANNED_USERS:
return False # Блокируем обработку
Параметр update_types¶
Ограничивает middleware определёнными типами событий. Если не указан - middleware срабатывает на все события:
@bot.middleware_handler(update_types=["message_new", "message_event"])
def only_messages(bot_instance, update: types.Update):
print("Только сообщения и callback-события")
Вспомогательные функции¶
Модуль vk_bot.handlers предоставляет утилиты для работы с текстом сообщений:
from vk_bot.handlers import extract_command, extract_mentions, is_group_event
# Парсинг команд
cmd, args = extract_command("/start hello world")
# cmd = "start", args = "hello world"
cmd, args = extract_command("просто текст")
# cmd = None, args = None
# Извлечение упоминаний
user_ids = extract_mentions("Привет [id123|Иван] и @id456")
# user_ids = [123, 456]
# Проверка группового события
is_group_event("group_join") # True
is_group_event("message_new") # False