Повідомлення
Редагування та видалення
В ботах динамический интерфейс строится не на отправке десятков новых сообщений, а на изменении уже существующих. В Telegram Bot API для этого предусмотрена группа методов семейства editMessage* и метод deleteMessage. Это позволяет обновлять статус заказа, анимировать процесс обработки, менять кнопки на лету и сохранять чистый чат пользователя без лишнего спама.
editMessageText: изменение текста сообщения
Если сообщение было отправлено через sendMessage, его текст и клавиатуру можно отредактировать с помощью метода editMessageText. Обязательные параметры: text и один из способов идентификации сообщения: пара chat_id + message_id (для обычных чатов) или inline_message_id (для сообщений из инлайн-режима — см. раздел Inline mode).
Используем функцию telegramApi(), которую мы написали в главе Первый запрос: getMe. Здесь только вызываем её — реализацию не копируем.
<?php
$token = getenv('TELEGRAM_BOT_TOKEN');
$chatId = 123456789;
// 1. Отправляем начальное сообщение и сохраняем message_id
$sent = telegramApi($token, 'sendMessage', [
'chat_id' => $chatId,
'text' => 'Заявка #142: <b>создана</b>',
'parse_mode' => 'HTML',
]);
$messageId = $sent['result']['message_id'];
echo "Отправлено сообщение ID: {$messageId}\n";
// 2. Имитируем паузу в 2 секунды и редактируем текст
sleep(2);
$edited = telegramApi($token, 'editMessageText', [
'chat_id' => $chatId,
'message_id' => $messageId,
'text' => 'Заявка #142: <b>в работе</b>',
'parse_mode' => 'HTML',
]);
// Выводим ответ API в консоль для проверки
print_r($edited);
Пример ответа Telegram API на вызов editMessageText:
{
"ok": true,
"result": {
"message_id": 57,
"from": {
"id": 987654321,
"is_bot": true,
"first_name": "MyBot",
"username": "my_sample_bot"
},
"chat": {
"id": 123456789,
"first_name": "Ivan",
"type": "private"
},
"date": 1724501234,
"edit_date": 1724501236,
"text": "Заявка #142: в работе",
"entities": [
{
"offset": 13,
"length": 8,
"type": "bold"
}
]
}
}Разбор JSON-ответа: Поле ok: true подтверждает успешность выполнения запроса. В ключе result приходят актуальные данные объекта Message. Обратите внимание на появление поля edit_date — это UNIX-timestamp времени последнего редактирования. Поле entities подтверждает, что разметка HTML применилась корректно (символы с 13 по 21 стали bold).
editMessageReplyMarkup: изменение только клавиатуры
Когда текст сообщения менять не требуется, а нужно добавить, обновить или полностью убрать инлайн-кнопки под ним, используйте метод editMessageReplyMarkup. Это экономит трафик и избавляет от повторного форматирования основного текста.
Используем функцию telegramApi(), которую мы создали в главе Первый запрос: getMe. Здесь только вызываем её — реализацию не копируем.
<?php
$token = getenv('TELEGRAM_BOT_TOKEN');
$chatId = 123456789;
$messageId = 57;
// Добавляем или обновляем клавиатуру под сообщением
telegramApi($token, 'editMessageReplyMarkup', [
'chat_id' => $chatId,
'message_id' => $messageId,
'reply_markup' => [
'inline_keyboard' => [
[
['text' => '✅ Подтвердить', 'callback_data' => 'confirm_142'],
['text' => '❌ Отклонить', 'callback_data' => 'cancel_142'],
],
],
],
]);
// Чтобы полностью удалить клавиатуру — передаём пустой массив inline_keyboard
telegramApi($token, 'editMessageReplyMarkup', [
'chat_id' => $chatId,
'message_id' => $messageId,
'reply_markup' => [
'inline_keyboard' => [],
],
]);
editMessageCaption: подписи к фото и документам
Для медиа-сообщений (картинки, файлы, видео, отправленные через методы из главы Фото, документы, media group) изменить текст методом editMessageText нельзя — API вернёт ошибку. Для них предназначен метод editMessageCaption.
Используем функцию telegramApi() из главы Первый запрос: getMe. Здесь только вызываем её — реализацию не копируем.
<?php
$token = getenv('TELEGRAM_BOT_TOKEN');
$chatId = 123456789;
$photoMessageId = 58;
$response = telegramApi($token, 'editMessageCaption', [
'chat_id' => $chatId,
'message_id' => $photoMessageId,
'caption' => 'Новая подпись к фото с <b>HTML-разметкой</b>',
'parse_mode' => 'HTML',
]);
var_dump($response['ok']); // bool(true)
deleteMessage: удаление сообщений
Метод deleteMessage окончательно удаляет сообщение из чата. Бот может гарантированно удалять собственные сообщения. Сообщения пользователей бот может удалять только в группах и каналах при наличии прав администратора can_delete_messages.
Используем функцию telegramApi(), созданную в главе Первый запрос: getMe. Здесь только вызываем её — реализацию не копируем.
<?php
$token = getenv('TELEGRAM_BOT_TOKEN');
$chatId = 123456789;
$messageId = 57;
$result = telegramApi($token, 'deleteMessage', [
'chat_id' => $chatId,
'message_id' => $messageId,
]);
// При успехе Telegram возвращает boolean true в поле result
var_dump($result['result']); // bool(true)
Ответ API при успешном удалении сообщения выглядит так:
{
"ok": true,
"result": true
}Частые ошибки и их обработка
При активном изменении сообщений Telegram Bot API может возвращать ошибки с HTTP-кодом 400. Рассмотрим самые распространённые:
- Bad Request: message is not modified — попытка записать в текст или клавиатуру ровно то же самое содержимое, которое там уже лежит. Ошибка не критична, её нужно игнорировать.
- Bad Request: message can't be edited — прошло более 48 часов с момента отправки сообщения, либо бот пытается отредактировать чужое сообщение.
- Bad Request: message to edit not found — указан несуществующий
message_idили сообщение уже было удалено пользователем. - Bad Request: message can't be deleted — сообщение слишком старое или у бота нет прав на удаление сообщений в данном чате.
Безопасная обёртка safeEditMessageText
Чтобы сценарий бота не ломался при повторных кликах пользователей по инлайн-кнопкам, оборачиваем editMessageText в безопасную функцию с обработкой исключений:
Используем функцию telegramApi(), реализованную в главе Первый запрос: getMe. Здесь только вызываем её — реализацию не копируем.
<?php
function safeEditMessageText(string $token, int $chatId, int $messageId, string $text): bool {
try {
telegramApi($token, 'editMessageText', [
'chat_id' => $chatId,
'message_id' => $messageId,
'text' => $text,
'parse_mode' => 'HTML',
]);
return true;
} catch (RuntimeException $e) {
$errorMessage = $e->getMessage();
// Если контент не изменился — считаем это успехом
if (str_contains($errorMessage, 'message is not modified')) {
return true;
}
// Если отредактировать нельзя (прошло 48ч) — удаляем старое и отправляем новое
if (str_contains($errorMessage, "message can't be edited")) {
try {
telegramApi($token, 'deleteMessage', [
'chat_id' => $chatId,
'message_id' => $messageId,
]);
} catch (Exception $ignored) {}
telegramApi($token, 'sendMessage', [
'chat_id' => $chatId,
'text' => $text,
'parse_mode' => 'HTML',
]);
return true;
}
throw $e;
}
}
Практический паттерн: Интерактивный статус заказа
Ниже приведён законченный PHP-скрипт, который демонстрирует паттерн «одно живое сообщение». Бот публикует заказ, меняет его статус по шагам и аккуратно удаляет кнопки в конце процедуры.
Используем функцию telegramApi() из главы Первый запрос: getMe. Здесь только вызываем её — реализацию не копируем.
<?php
$token = getenv('TELEGRAM_BOT_TOKEN');
$managerChatId = 123456789;
$orderId = 5081;
// Шаг 1: Создаём сообщение о новом заказе с кнопкой
$response = telegramApi($token, 'sendMessage', [
'chat_id' => $managerChatId,
'text' => "📦 <b>Заказ #{$orderId}</b>\nСтатус: <i>Новый</i>",
'parse_mode' => 'HTML',
'reply_markup' => [
'inline_keyboard' => [
[['text' => '🚀 Взять в работу', 'callback_data' => "process_{$orderId}"]],
],
],
]);
$messageId = $response['result']['message_id'];
echo "Сообщение создано: ID {$messageId}\n";
// Симулируем паузу на реакцию менеджера
sleep(3);
// Шаг 2: Менеджер взял заказ — обновляем текст и меняем кнопку
telegramApi($token, 'editMessageText', [
'chat_id' => $managerChatId,
'message_id' => $messageId,
'text' => "📦 <b>Заказ #{$orderId}</b>\nСтатус: ⚙️ <i>В сборке</i>\nОтветственный: Алексей",
'parse_mode' => 'HTML',
'reply_markup' => [
'inline_keyboard' => [
[['text' => '✅ Завершить заказ', 'callback_data' => "finish_{$orderId}"]],
],
],
]);
echo "Статус обновлен: В сборке\n";
// Симулируем процесс сборки
sleep(3);
// Шаг 3: Заказ выполнен — обновляем текст и удаляем клавиатуру
telegramApi($token, 'editMessageText', [
'chat_id' => $managerChatId,
'message_id' => $messageId,
'text' => "📦 <b>Заказ #{$orderId}</b>\nСтатус: ✅ <b>Выполнен</b>\nВремя: " . date('H:i:s'),
'parse_mode' => 'HTML',
]);
telegramApi($token, 'editMessageReplyMarkup', [
'chat_id' => $managerChatId,
'message_id' => $messageId,
'reply_markup' => [
'inline_keyboard' => [],
],
]);
echo "Заказ завершен, кнопки удалены.\n";
Дальше: переходим к детальному разбору создания кнопок в главе Inline Keyboard.