Перейти к содержимому

Обработчики событий (Маршрутизация)

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

Каждый метод-обработчик создает уникальный "маршрут" (route) с заданным ID и возвращает объект класса Action, который позволяет настроить ответ или действие для этого маршрута.

Команды

Эти обработчики реагируют на текстовые команды.

onBotCommand()

Срабатывает, когда пользователь отправляет стандартную команду, начинающуюся со слеша (/). Например, /start или /help.

Сигнатура:

php
public function onBotCommand(string $id, array|string $command = null): Action

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

php
// Обработка команды /start
$bot->onBotCommand('start', '/start')->func(function (ZG $tg) {
    $tg->msg('Привет! Я бот')->send();
});

// Обработка команды с аргументом (например: /gift user123)
// Аргументы автоматически парсятся и передаются в функцию
$bot->onBotCommand('gift', '/gift')->func(function (ZG $tg, $username) {
    $tg->msg("Подарок отправлен пользователю {$username}!")->send();
});

onCommand()

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

  • %s — строка (захватывает весь текст до конца).
  • %w — слово (одно слово без пробелов).
  • %n — число (только цифры).

Сигнатура:

php
public function onCommand(string $id, array|string $command = null): Action

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

php
// Простая команда !ping
$bot->onCommand('ping', '!ping')->text('Pong!');

// Команда бана: !ban 12345 причина
$bot->onCommand('ban', '!ban {user_id} {reason}')
    ->func(function(ZG $tg, $user_id, string $reason) {
        // $user_id = 12345 (int|string)
        // $reason = "причина" (string)
        $tg->msg("Пользователь {$user_id} забанен. Причина: {$reason}")->send();
    });

onStart()

Специализированный обработчик для команды /start.

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

php
$bot->onStart()->text('Добро пожаловать в бота!');

onReferral()

Срабатывает, когда пользователь переходит по реферальной ссылке (например, t.me/bot?start=ref123).

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

php
$bot->onReferral()->func(function (ZG $tg, $refCode) {
    $tg->msg("Вы приглашены пользователем с кодом: {$refCode}")->send();
});

Текстовые сообщения

onText()

Срабатывает при точном совпадении текста. Идеально для обработки кнопок Reply-клавиатуры.

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

php
// Создаем Reply-клавиатуру
$bot->onBotCommand('menu', '/menu')
    ->text('Выберите пункт:')
    ->kbd([
        ['ℹ️ О нас', '📞 Контакты']
    ]);

// Обрабатываем нажатие кнопки "ℹ️ О нас"
$bot->onText('about', 'ℹ️ О нас')
    ->text('Мы — лучшая компания!');

onTextPreg()

Срабатывает, если текст совпадает с регулярным выражением. Найденные совпадения (matches) передаются в функцию.

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

php
// Поиск email в сообщении
$bot->onTextPreg('email', '/[\w\.]+@[\w\.]+/')
    ->func(function (ZG $tg, $matches) {
        $email = $matches[0];
        $tg->msg("Email принят: {$email}")->send();
    });

Кнопки (Callback Query)

Обработка нажатий на Inline-кнопки.

Вот обновленный раздел для onCallback(). Я добавил описание плейсхолдеров и примеры их использования. Это отличная альтернатива регулярным выражениям (onCallbackPreg) для простых динамических кнопок.

onCallback()

Срабатывает при совпадении callback_data. Поддерживает как точное совпадение, так и использование плейсхолдеров для передачи аргументов:

  • %n — число (цифры).
  • %w — слово (буквы и цифры без пробелов).
  • %s — строка (весь оставшийся хвост данных).

Пример 1: Точное совпадение

php
use ZenithGram\ZenithGram\Button;

// Отправляем кнопку
$bot->onBotCommand('test', '/test')
    ->text('Нажми кнопку:')
    ->inlineKbd([
        [Button::cb('Показать профиль', 'profile_btn')]
    ]);

// Обрабатываем нажатие
$bot->onCallback('profile_handler', 'profile_btn')
    ->func(function (ZG $tg) {
        $tg->answerCallbackQuery();
        $tg->msg("Это ваш профиль!")->send();
    });

Пример 2: Использование плейсхолдеров (Динамические кнопки)

Это удобнее, чем Regex, если структура данных простая.

php
use ZenithGram\ZenithGram\Button;

// Генерируем кнопки с параметрами
// Структура data: "action_ID_TYPE"
$bot->onBotCommand('actions', '/actions')
    ->text('Выберите действие:')
    ->inlineKbd([
        [Button::cb('Бан User 55', 'ban_55_spam')],
        [Button::cb('Бан User 77', 'ban_77_flood')]
    ]);

// Ловим паттерн: слово_число_слово
$bot->onCallback('ban_handler', 'ban_{user_id}_{reason}')
    ->func(function (ZG $tg, string $user_id, string $reason) {
        // Аргументы автоматически попадают в функцию в нужном порядке
        // $user_id = 55
        // $reason = "spam"
        $tg->answerCallbackQuery($tg->getQueryId(), ['text' => "Забанен!"]);
        $tg->msg("Пользователь #{$user_id} заблокирован за {$reason}.")->send();
    });

onCallbackPreg()

Срабатывает, если callback_data совпадает с регулярным выражением. Незаменимо для пагинации или динамических действий (например, buy_item_54, buy_item_55).

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

php
use ZenithGram\ZenithGram\Button;

// Генерируем кнопки товаров
$bot->onBotCommand('shop', '/shop')
    ->text('Каталог:')
    ->inlineKbd([
        [Button::cb('Купить Товар 1', 'buy_1')],
        [Button::cb('Купить Товар 2', 'buy_2')]
    ]);

// Один обработчик для всех покупок
$bot->onCallbackPreg('buy_handler', '/^buy_(\d+)$/')
    ->func(function (ZG $tg, $itemId) {
        // $itemId будет содержать ID товара (1 или 2)
        $tg->answerCallbackQuery(['text' => "Товар #{$itemId} добавлен в корзину"]);
    });

Inline-запросы

onInline()

Срабатывает на любой входящий Inline Query (когда бота вызывают через @botname).

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

php
$bot->onInline()
    ->func(function(ZG $tg) {
        $query = $tg->getText(); // Текст запроса пользователя
        
        $results = [
            $tg->inline('article')
                ->id('1')
                ->title('Эхо')
                ->description("Вы написали: $query")
                ->text($query)
                ->create(),
        ];
        
        $tg->answerInlineQuery($results);
    });

Медиа и сервисные сообщения

Эти обработчики не требуют параметров сравнения (кроме ID маршрута), так как реагируют на тип контента.

МетодОписание
onPhotoПолучено изображение
onVideoПолучено видео
onAudioПолучен аудиофайл (музыка)
onVoiceПолучено голосовое сообщение
onVideoNoteПолучен "кружочек" (video note)
onDocumentПолучен файл/документ
onStickerПолучен стикер
onEditedMessageПользователь отредактировал свое сообщение

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

php
// Сохраняем все фото, которые присылает юзер
$bot->onPhoto('photo_saver')->func(function (ZG $tg) {
    $fileId = File::getFileId($tg->getUpdate());
    $tg->msg("Фото получено! ID: {$fileId}")->send();
});

// Реакция на кружочек
$bot->onVideoNote()->text('Классный кружочек!');

Обработка участников чата

Для событий входа и выхода используются специальные обработчики, которые передают объекты UserDto.

php
use ZenithGram\ZenithGram\Dto\UserDto;

// Приветствие новых участников
$bot->onNewChatMember()
    ->func(function (ZG $tg, UserDto ...$users) {
        foreach ($users as $user) {
            $name = $user->firstName;
            $tg->msg("Добро пожаловать, {$name}!")->send();
        }
    });

// Прощание
$bot->onLeftChatMember()
    ->func(function (ZG $tg, UserDto $user) {
        $tg->msg("Пользователь {$user->firstName} покинул чат.")->send();
    });

Fallback (Резервные обработчики)

Срабатывают, если ни один из вышеперечисленных маршрутов не подошел.

onMessage()

Срабатывает на любое текстовое сообщение, которое не было обработано другими командами или onText.

php
$bot->onMessage()->text('Я не понимаю этот текст. Используйте /menu.');

onDefault()

Самый низкий приоритет. Срабатывает на вообще любое необработанное событие (неизвестный тип медиа, системное сообщение и т.д.).

php
$bot->onDefault()->func(function(ZG $tg) {
    error_log("Получено неизвестное обновление: " . print_r($tg->getUpdate(), true));
});

Опубликовано под лицензией MIT.