Вебхук уже работает, бот отвечает, заявки сыпятся. Но раз в неделю нужно поднять новый сервер, переехать на другой домен, проверить, что бот вообще живой, и прибрать лог апдейтов, который разросся на десятки мегабайт. Ходить в браузер к 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 эти сценарии уже собраны в готовые модули.