The webhook is already running, the bot is responding, and requests are pouring in. But once a week, you need to raise a new server, move to another domain, check that the bot is alive at all, and remove the update log, which has grown by tens of megabytes. Go to the browser cr api.telegram.org for the sake of every little thing — the path to mistakes. It is easier to assemble one Yii2 console command and close these tasks from the terminal.
What the service team should be able to do
Minimum set for production:
- webhook:set — install webhook from
User Secret Tokenand a list of updates. - webhook:delete — remove the webhook (for example, before deploying or transferring).
- ME — health-check via
getMe: return username, can_join_groups, is_bot. - logs:rotate — rotation of the file with raw updates by size/date.
Make one team with subcommands via Console::parseArg more convenient than four separate controllers: one entry point, a common helper for Bot API requests.
Preparing a command and a helper for requests
The command is inherited from yii\console\controller. We take the token from the parameter params.php or getenv('TG_BOT_TOKEN') — it should not be in the code. All requests to Telegram — via cURL, with HTTP code verification, json_last_error and fields ok.
Helper bot. method returns result and crashes the process itself with a non-zero code for any network or logical problem. For maintenance scripts, this is the correct behavior: cron alerts will be triggered by the output code.
Installing and removing a webhook
When setWebhook be sure to transmit User Secret Token (random string 16–64 characters bin2hex(random_bytes(16))) — Telegram will send it in the header X-Telegram-Bot-Api-Secret-Token, and your controller will be able to discard garbage POST. List allowed_updates limits the types of updates: less noise — less load and shorter log.
Typical rake: URL should answer 200 on POST WITH empty body even before the Yii2 controller does anything. Otherwise, Telegram at the first setWebhook will record last_error_message: HTTPClientError and will hammer. Make sure you do not have a CSRF filter before routing, and request. does not parse JSON as a form.
Health-check via getMe
The simplest liveness ping: if getMe didn't respond in 2 seconds — the bot is unavailable. You can pull from the cron every 5 minutes and send the alert to a separate channel if the output code is not zero.
Field can_join_groups it is important to check right away: if you plan to add the bot to group chats for support, and it is disabled, updates from groups simply will not come. The bot is created private by default.
Rotation of update logs
It is useful to stack raw JSON updates in a file for the time of debugging and incidents, but without rotation, it will eat the disk. Simple strategy: if the size is exceeded (for example, 20 MB), rename to updates-YYYY-MM-DD.jsonl and start a new one, store the last 7 files.
Post in tg-updates.jsonl makes your webhook controller a single line: file_put_contents($file, json_encode($update) . "\n", FILE_APPEND | lock_EX)On an SSD with a size of 20 MB, there are thousands of updates — 2–3 hours of active correspondence is enough for production.
Connection and start-up
In console.php controller will pick up automatically from app\commandsПроверяем.
In cron, there are two tasks: health-check every 5 minutes, rotation every hour. Before deploying to a new server — tg/webhook-delete on the old and tg/webhook-set on a new one, otherwise Telegram will give last_error_message: Connection refused and save pending_updates.
Important things to remember
- Token — only in
env/params, not in the repository. - Always check the HTTP code and
ok = false;— Telegram returns 200 even if there is a logical error. setWebhookwith the newUser Secret Tokenrequires updating and verification in the controller, otherwise Telegram will not be able to reach after the first mismatched signature.- Before deploying the new code —
deleteWebhookorsetWebhookthe scalp.drop_pending_updates:trueto avoid raking the tail after idle time.
The command takes about 80 lines, but closes all routine operations, for which the developer usually crawls into the browser or writes ad-hoc scripts. After that, the bot is serviced from the terminal in the same way as a database or queue.
If you have several bots on the same server, take out the token and URL to the arrayparams['telegram']['bots']and accept the bot name with the argumentactionIndex($bot = 'main'), then one team will cover the entire zoo.
You can save time on typical operations with the Telegram Bot API — webhook, getMe, log rotation — without your own code: in [[BC_link_1]] these scenarios are already collected in ready-made modules.