Консольная команда Yii2 для setWebhook, deleteWebh

Вебхук уже работает, бот отвечает, заявки сыпятся. Но раз в неделю нужно поднять новый сервер, переехать на другой домен, проверить, что бот вообще живой, и прибрать лог апдейтов, который разросся на десятки мегабайт. Ходить в браузер к api.telegram.org ради каждой мелочи — путь к ошибкам. Проще собрать одну консольную команду Yii2 и закрыть эти задачи из терминала.

Что должна уметь команда обслуживания

Минимальный набор для продакшена:

  • webhook:set — установить вебхук с secret_token и списком апдейтов.
  • webhook:delete — снять вебхук (например, перед деплоем или переносом).
  • me — health-check через getMe: вернуть username, can_join_groups, is_bot.
  • logs:rotate — ротация файла с сырыми апдейтами по размеру/дате.

Делать одну команду с подкомандами через Console::parseArg удобнее, чем четыре отдельных контроллера: одна точка входа, общий хелпер для запросов к Bot API.

Заготовка команды и хелпер для запросов

Команда наследуется от yii\console\Controller. Токен берём из параметра params.php или getenv('TG_BOT_TOKEN') — в коде его быть не должно. Все запросы к Telegram — через cURL, с проверкой HTTP-кода, json_last_error и поля ok.

Хелпер bot() возвращает result и сам валит процесс с ненулевым кодом при любой сетевой или логической проблеме. Для скриптов обслуживания это правильное поведение: cron-алёрты сработают по коду выхода.

Установка и снятие вебхука

При setWebhook обязательно передавайте secret_token (рандомная строка 16–64 символа bin2hex(random_bytes(16))) — Telegram будет слать его в заголовке X-Telegram-Bot-Api-Secret-Token, и ваш контроллер сможет отбрасывать мусорные POST. Список allowed_updates ограничивает типы апдейтов: меньше шума — меньше нагрузка и короче лог.

Типичные грабли: URL должен отвечать 200 на POST с пустым телом ещё до того, как контроллер Yii2 что-то сделает. Иначе Telegram при первом setWebhook запишет last_error_message: HTTPClientError и будет долбиться. Проверьте, что перед роутингом у вас нет CSRF-фильтра, а request не парсит JSON как форму.

Health-check через getMe

Простейший liveness-пинг: если getMe не ответил за 2 секунды — бот недоступен. Можно дёргать из cron каждые 5 минут и слать алёрт в отдельный канал, если код выхода не равен нулю.

Поле can_join_groups важно проверить сразу: если вы планируете добавлять бота в групповые чаты для поддержки, а оно выключено — апдейты из групп просто не придут. Бот создаётся приватным по умолчанию.

Ротация логов апдейтов

Сырой JSON апдейтов полезно складывать в файл на время отладки и инцидентов, но без ротации он съест диск. Простая стратегия: при превышении размера (например, 20 МБ) переименовываем в updates-YYYY-MM-DD.jsonl и начинаем новый, храним последние 7 файлов.

Запись в tg-updates.jsonl делает ваш webhook-контроллер одной строкой: file_put_contents($file, json_encode($update) . "\n", FILE_APPEND | LOCK_EX). На SSD при размере 20 МБ это тысячи апдейтов — для продакшена хватает на 2–3 часа активной переписки.

Подключение и запуск

В console.php контроллер подхватится автоматически из app\commands. Проверяем:

В cron — две задачи: health-check раз в 5 минут, ротация каждый час. Перед деплоем на новый сервер — tg/webhook-delete на старом и tg/webhook-set на новом, иначе Telegram будет отдавать last_error_message: Connection refused и копить pending_updates.

Что важно помнить

  • Токен — только в env/params, не в репозитории.
  • Всегда проверяйте HTTP-код и ok:false — Telegram возвращает 200 даже при логической ошибке.
  • setWebhook с новым secret_token требует обновить и проверку в контроллере, иначе Telegram не сможет достучаться после первой же несовпадающей подписи.
  • Перед деплоем нового кода — deleteWebhook либо setWebhook с drop_pending_updates:true, чтобы не разгребать хвост после простоя.

Команда занимает около 80 строк, но закрывает все рутинные операции, ради которых разработчик обычно лезет в браузер или пишет ad-hoc-скрипты. После неё бот обслуживается из терминала так же, как база данных или очередь.

Если у вас несколько ботов на одном сервере — вынесите токен и URL в массив params['telegram']['bots'] и принимайте имя бота аргументом actionIndex($bot = 'main'), тогда одна команда покроет весь зоопарк.

Сэкономить время на типовых операциях с Telegram Bot API — webhook, getMe, ротация логов — можно и без своего кода: в BotCreator эти сценарии уже собраны в готовые модули.

Новые статьи — в Telegram

Разбираем, что автоматизировать в бизнесе и как это работает на практике. Без спама.