Что видит человек и что получает бот
Один и тот же бот «Клуб XL» (его код — во вкладке «Пример бота» на странице Подключение кода) глазами человека, который с ним переписывается, и запросы, которые бот в этот момент получил или отправил.
Скриншоты сняты на тестовом сервере (адреса …:liza.local), имена людей
скрыты. Меню «/» и кнопки без цифры «1» в чате работают в новой версии
приложения Liza. В старых версиях человек отвечает на кнопку цифрой, но бот
всё равно получает обычный callback_query, так что код менять не нужно.
Глазами клиента
Человек вводит «/» — видит меню команд
Меню берётся из setMyCommands: команда и описание. Человек выбирает пункт, и
команда отправляется боту. Меню есть в личном чате с ботом.

Что вызвал бот — POST https://bot.tech.liza.ru/bot<ТОКЕН>/setMyCommands:
{
"commands": [
{ "command": "start", "description": "Главное меню клуба" },
{ "command": "shop", "description": "Каталог курсов" },
{ "command": "help", "description": "Помощь" }
]
}
/start → бот отвечает меню с кнопками
Команда приходит с entities типа bot_command, поэтому
CommandHandler("start") срабатывает как в Telegram. В ответе бот показал
логин человека из from.liza_user_id (на скриншоте скрыт) — тот самый, по
которому позже можно написать первым. Под сообщением — две
кнопки: с callback_data и со ссылкой (url).

Что получил бот:
{
"update_id": 2,
"message": {
"message_id": 1,
"from": { "id": 1419716922, "is_bot": false, "first_name": "Анна",
"username": "anna", "liza_user_id": "@anna:liza.local" },
"chat": { "id": 1419716922, "type": "private" },
"date": 1790946248,
"text": "/start",
"entities": [{ "type": "bot_command", "offset": 0, "length": 6 }]
}
}
Нажал «Каталог курсов» → бот поменял сообщение
Нажатие пришло как callback_query. Бот ответил editMessageText с новыми
кнопками: сообщение поменялось на месте, значок ✎ показывает, что оно
отредактировано. Цифры «1» в чате нет.

Что получил бот:
{
"update_id": 3,
"callback_query": {
"id": "1419716922_1005452822",
"from": { "id": 1419716922, "is_bot": false, "first_name": "Анна",
"username": "anna", "liza_user_id": "@anna:liza.local" },
"message": { "message_id": 2, "chat": { "id": 1419716922, "type": "private" } },
"chat_instance": "1419716922",
"data": "catalog"
}
}
Голосовое → бот получает voice с file_id
Голосовое приходит в message.voice с длительностью и file_id. Скачать его
можно через getFile — библиотеки делают это сами. На том же скриншоте выше бот
ответил с цитатой голосового.
{
"update_id": 4,
"message": {
"message_id": 3,
"from": { "id": 1419716922, "is_bot": false, "first_name": "Анна",
"username": "anna", "liza_user_id": "@anna:liza.local" },
"chat": { "id": 1419716922, "type": "private" },
"voice": { "file_id": "mxc://liza.local/EHSSyNbuKiU…", "duration": 4,
"mime_type": "audio/ogg" }
}
}
Нажатая кнопка отмечена галочкой
Человек нажал «Курс «Продажи»». На кнопке появилась ✓, в чат ничего лишнего не
ушло, а бот ответил новым сообщением с цитатой (reply_to_message_id).

{
"update_id": 5,
"callback_query": {
"id": "1419716922_1668151358",
"from": { "id": 1419716922, "is_bot": false, "first_name": "Анна",
"username": "anna", "liza_user_id": "@anna:liza.local" },
"message": { "message_id": 2, "chat": { "id": 1419716922, "type": "private" } },
"data": "course_sales"
}
}
Что получает бот — по действиям
Выберите, что делает человек в Лизе, и посмотрите, какой апдейт придёт в
getUpdates или на вебхук. Пример реакции — на python-telegram-bot.
- Команда /start
- Нажатие кнопки
- Голосовое
- Ответ на сообщение
- Правка сообщения
- Сообщение в группе
- Пишет другой бот
- Бота пригласили в чат
{
"update_id": 2,
"message": {
"message_id": 1,
"from": { "id": 1419716922, "is_bot": false, "first_name": "Анна",
"username": "anna", "liza_user_id": "@anna:liza.local" },
"chat": { "id": 1419716922, "type": "private" },
"date": 1790946248,
"text": "/start",
"entities": [{ "type": "bot_command", "offset": 0, "length": 6 }]
}
}
entities с типом bot_command — по ним библиотеки запускают
CommandHandler. Работает и форма /cmd@логин_бота.
await update.message.reply_text("Добро пожаловать!", reply_markup=menu)
{
"update_id": 3,
"callback_query": {
"id": "1419716922_1005452822",
"from": { "id": 1419716922, "is_bot": false, "first_name": "Анна",
"username": "anna", "liza_user_id": "@anna:liza.local" },
"message": { "message_id": 2, "chat": { "id": 1419716922, "type": "private" } },
"chat_instance": "1419716922",
"data": "catalog"
}
}
data — ваш callback_data с кнопки, message — сообщение бота, под
которым была кнопка. Подтвердите нажатие через answerCallbackQuery — не
позже 15 минут и один раз. Ответ видит только нажавший: text —
всплывающее уведомление, с show_alert=true — диалог, url открывается как у
url-кнопки. В чат ничего не пишется. Показ ответа появится в следующей версии
приложения; в текущей человек ответа не увидит, но вызывать
answerCallbackQuery всё равно нужно.
await update.callback_query.answer()
await update.callback_query.edit_message_text("Каталог курсов", reply_markup=catalog)
{
"update_id": 4,
"message": {
"message_id": 3,
"from": { "id": 1419716922, "is_bot": false, "first_name": "Анна",
"username": "anna", "liza_user_id": "@anna:liza.local" },
"chat": { "id": 1419716922, "type": "private" },
"date": 1790946618,
"voice": { "file_id": "mxc://liza.local/EHSSyNbuKiU…", "duration": 4,
"mime_type": "audio/ogg" }
}
}
Фото, документы, видео и аудио приходят так же: photo / document /
video / audio, подпись — в caption, поля text у них нет. file_id
можно сразу отправить снова (sendVoice(file_id)) или скачать через getFile.
f = await update.message.voice.get_file()
await f.download_to_drive("voice.ogg")
{
"update_id": 6,
"message": {
"message_id": 5,
"from": { "id": 1419716922, "is_bot": false, "first_name": "Анна",
"username": "anna", "liza_user_id": "@anna:liza.local" },
"chat": { "id": 1419716922, "type": "private" },
"text": "Хочу курс по CRM",
"reply_to_message": {
"message_id": 2,
"from": { "id": 2, "is_bot": true, "first_name": "Клуб XL",
"username": "club_xl_bot" },
"chat": { "id": 1419716922, "type": "private" },
"text": "Каталог курсов"
}
}
}
reply_to_message — сообщение, на которое ответил человек. Чтобы самому
ответить с цитатой, передайте reply_to_message_id или reply_parameters.
await update.message.reply_text("Записал!", reply_to_message_id=update.message.message_id)
{
"update_id": 7,
"edited_message": {
"message_id": 5,
"from": { "id": 1419716922, "is_bot": false, "first_name": "Анна",
"username": "anna", "liza_user_id": "@anna:liza.local" },
"chat": { "id": 1419716922, "type": "private" },
"edit_date": 1790946900,
"text": "Хочу курс по продажам"
}
}
Правка приходит как edited_message с тем же message_id, что и исходное
сообщение.
app.add_handler(MessageHandler(filters.UpdateType.EDITED_MESSAGE, on_edit))
{
"update_id": 8,
"message": {
"message_id": 9,
"from": { "id": 880122431, "is_bot": false, "first_name": "Анна",
"username": "anna", "liza_user_id": "@anna:liza.local" },
"chat": { "id": 2087163340, "type": "group", "title": "Клуб XL — поток 5" },
"text": "Всем привет"
}
}
chat.type: private — бот и один человек, group — больше участников.
Отвечать нужно в chat.id: в группе он не совпадает с from.id.
if update.effective_chat.type == "group": ...
{
"update_id": 9,
"message": {
"message_id": 10,
"from": { "id": 551203877, "is_bot": true, "first_name": "Другой бот",
"username": "other_bot", "liza_user_id": "@other_bot:bots.liza.ru" },
"chat": { "id": 2087163340, "type": "group" },
"text": "Привет, я тоже бот"
}
}
is_bot: true — пишет бот. Не отвечайте ботам, иначе два бота зациклятся
и засыпят чат сообщениями.
if update.effective_user.is_bot:
return # не отвечаем ботам
{
"update_id": 1,
"message": {
"message_id": 0,
"from": { "id": 777000, "is_bot": false, "first_name": "System" },
"chat": { "id": 1419716922, "type": "private" },
"text": "Bot is now active in this chat"
}
}
Когда бота приглашают в чат, первым приходит служебное сообщение от
from.id = 777000. Его можно просто пропустить.
if update.effective_user.id == 777000:
return
Сообщения
- Тип чата и отправитель:
chat.type—privateдля чата бота с одним человеком,groupдля трёх участников и больше.from.is_bot = true, если пишет другой бот.from.liza_user_id— полный Matrix ID человека (его принимаетstartChat). - Входящие: текст, фото (
photo), голосовые (voice), аудио (audio), файлы (document), видео (video) с подписьюcaption; ответы приходят сreply_to_message, правки пользователя — отдельным обновлениемedited_message. - Отправка:
sendMessage— до 4096 символов,parse_modeHTML или Markdown. message_idстабилен и растёт в пределах чата. По нему работаютeditMessage*,deleteMessage,reply_to_message_idиreply_parameters. Значения, сохранённые до 1 октября 2026 года, недействительны.- Ответы с цитатой: если сообщения для
reply_to_message_id/reply_parametersнет (неизвестное или старше 30 дней), сообщение уходит без цитаты; 400 — только при явномallow_sending_without_reply=false. При цитате ответsend*содержитreply_to_message. - Правка: медиа правкой не заменяется —
editMessageCaptionменяет только подпись. Правка без изменений — 400message is not modified. - «Печатает…»:
sendChatActionпоказывает статус на 5 секунд для любого из действий Telegram; неизвестныйaction— 400. file_id— адресmxc://…. По нему работаетgetFile, и его можно передать вsendPhoto/sendDocument/ … для отправки без повторной загрузки. Для файлов, которые бот получил или отправил начиная с версии 1.3, сохраняются имя, mimetype, размер и размеры;file_id, выданные раньше, работают как прежде (без метаданных);file_idневерного формата — 400. Ответsend*содержитfile_size,mime_type,file_name(у фото —width/height).
Кнопки и меню «/»
- Обычная клавиатура (
keyboard): нажатие приходит сообщением с текстом кнопки, как в Telegram. - Inline-кнопки с
callback_dataприходят боту какcallback_query, когда человек нажимает кнопку в приложении Liza (в старых версиях приложения он отвечает номером или названием кнопки — бот получает тот жеcallback_query).callback_query.message— сообщение бота с этой кнопкой. Кнопки сurlоткрывают ссылку прямо в Лизе. answerCallbackQueryотвечает только нажавшему:text(до 200 символов) — всплывающее уведомление, сshow_alert=true— диалог,urlоткрывается как у url-кнопки. В чат ничего не пишется.callback_query_idобязателен и принимается только выданный этому боту, один раз и не позже 15 минут после нажатия — иначе 400. Показ ответа у человека — в следующей версии приложения.- Кнопки к медиа показываются под ним; правка
(
editMessageReplyMarkup) и удаление (deleteMessage) поmessage_idмедиа затрагивают и их. - Несколько ботов в чате: ответ номером кнопки (старые версии приложения) получает только тот бот, чьи кнопки показаны последними.
- Меню «/» задаёт
setMyCommands: команды появляются подсказками при вводе «/» в личном чате с ботом (в новой версии приложения), а в следующей версии — ещё и кнопкой меню у поля ввода. Команда — от 1 до 32 символов: латиница в нижнем регистре, цифры и подчёркивание, без «/» и пробелов; описание — от 1 до 256 символов; иначе 400. ПослеsetMyCommandsменю у человека обновляется не сразу: API отдаёт его с кэшем до 1 минуты, а приложение перечитывает при повторном открытии чата. - Команды бота важнее встроенных. Если бот задал команду, совпадающую со
встроенной командой приложения (например,
/leaveили/logout), в чате с этим ботом она уходит боту текстом, а не выполняется приложением (в новой версии приложения).