Наш магазин на eBay Наш магазин на AliExpress Наш канал в telegram

Инструкция по созданию Telegram ботов. Часть 6. Делаем пользовательскую клавиатуру для бота

Сегодняшняя статья будет посвящена тому, каким образом можно создать для бота пользовательскую клавиатуру, что это даёт и как со всем этим работать. Все приводимые в статье примеры кода будут на php.

Какие вообще бывают пользовательские клавиатуры

Пользовательские клавиатуры в Telegram бывают двух видов: Inline и Reply.

Inline (встроенные)-клавиатуры просто добавляют кнопки внизу сообщения, вот так:

inline-клавиатура

Эти клавиатуры привязаны к конкретному сообщению (как бы встроены в чат) и не подменяют собой традиционную клавиатуру, которая всё так же всплывает при нажатии на поле ввода текста. Главная особенность inline-клавиатур заключается в том, что нажатие на их кнопки не вызывает отправку в чат каких-либо сообщений, вместо этого генерируется некоторое «закулисное» событие: обратный вызов (callback), открытие URL или другого чата во встроенном режиме.

Интересной фишкой подобных клавиатур является возможность правки «на лету» сообщений, к которым они привязаны.

Reply-клавиатуры (клавиатуры для ответа) напротив, не привязаны к конкретному сообщению и подменяют (или дополняют) в чате с ботом традиционную клавиатуру. Эти клавиатуры вызывают отправку сообщений в чат и выглядят вот так:

reply-клавиатура

Как сгенерировать и удалить клавиатуру

Для того, чтобы сгенерировать какую-либо пользовательскую клавиатуру — нужно при обращении к одному из предназначенных для отправки данных API-методов (например, при к SendMessage) задать параметр reply_markup, описывающий объект типа InlineKeyboardMarkup — для создания inline-клавиатуры, или объект типа ReplyKeyboardMarkup — для создания reply-клавиатуры. Подробнее о том, к каким методам можно прицепить reply_markup, а к каким — нет, можно прочитать в документации.

Описывающие клавиатуры объекты представляют собой многомерные массивы, содержащие наборы записей о каждой из кнопок (подпись, данные колбэка, открываемый при нажатии url и так далее).

Таким образом, для генерирования клавиатуры нам нужно сформировать в коде соответствующего типа объект, описывающий создаваемую клавиатуру (назовём этот объект, например, $keyboard), закодировать этот объект в виде json-строки и добавить эту json-строку в качестве параметра reply_markup при отправке запроса (GET или POST) telegram-боту.

Пример создания inline-клавиатуры (php)


// создаём $keyboard - объект, описывающий клавиатуру
$keyboard = [
"inline_keyboard" =>
[ /* первый ряд кнопок - массив из наборов {подпись кнопки, даные для колбэка} */
[ /* первые две кнопки вызывают колбэк, а третья - открытие url-а */
[ "text" => "button 1",
"callback_data" => "data 1"
],
[ "text" => "button 2",
"callback_data" => "data 2"
],
[ "text" => "button 3",
"url" => $any_url
]
]
/* здесь мог бы быть второй массив для второго ряда кнопок и так далее */
]
];
...
...
// далее нужно просто добавить этот параметр в запрос (GET или POST) в качестве параметра reply_markup
// например, при использовании в GET-запросе:
$keyboard_json = json_encode($keyboard); // перекодируем в json
// формируем url для get-запроса и добавляем к этому url-у параметр reply_markup с описанием нашей клавиатуры
$url=$telegram_api_url.$bot_token.'/sendMessage?chat_id='.$chat_id.'&text='.urlencode($text_message).'&parse_mode=HTML'.'&reply_markup='.$keyboard_json;

// осталось только выполнить GET-запрос, например с помощью file_get_contents (ну или curl :))
file_get_contents($url); // отправляем get-запрос на сформированный url

[свернуть]
Пример создания reply-клавиатуры (php)


// создаём $keyboard - объект, описывающий клавиатуру
$keyboard = [
"keyboard" =>
[ /* первый ряд кнопок - массив из наборов {подпись кнопки} */
[ /* перва кнопка отправляет команду /any_command в виде текстового сообщения, вторая - данные геолокации */
[ "text" => "/any_command"
],
[ "text" => "my location",
"request_location" => true
]
]
/* здесь мог бы быть второй массив для второго ряда кнопок и так далее */
]
];
...
...
// далее нужно просто добавить этот параметр в запрос (GET или POST) в качестве параметра reply_markup
// например, при использовании в GET-запросе:
$keyboard_json = json_encode($keyboard); // перекодируем в json
// формируем url для get-запроса и добавляем к этому url-у параметр reply_markup с описанием нашей клавиатуры
$url=$telegram_api_url.$bot_token.'/sendMessage?chat_id='.$chat_id.'&text='.urlencode($text_message).'&parse_mode=HTML'.'&reply_markup='.$keyboard_json;

// осталось только выполнить GET-запрос, например с помощью file_get_contents (ну или curl :))
file_get_contents($url); // отправляем get-запрос на сформированный url

[свернуть]

Поскольку inline-клавиатуры привязаны к конкретным сообщениям, то с каждым новым сообщением нужно генерировать новую inline-клавиатуру. С reply-клавиатурами ничего подобного делать не нужно. Будучи однажды сгенерированной, такая клавиатура будет заменять дефолтную до тех пор, пока её не удалят или не заменят другой reply-клавиатурой.

Для удаления reply-клавиатуры нужно в параметре reply_markup послать объект, типа ReplyKeyboardRemove.

Пример удаления reply-клавиатуры (php)


// создаём $remove_keyboard - объект, описывающий удаление reply-клавиатуры
$remove_keyboard = [
"remove_keyboard" => true
];
...
...
// далее нужно просто добавить этот объект в запрос (GET или POST) в качестве параметра reply_markup
// например, при использовании в GET-запросе:
$remove_keyboard_json = json_encode($remove_keyboard); // перекодируем в json
// формируем url для get-запроса и добавляем к этому url-у параметр reply_markup с описывающим удаление клавиатуры объектом
$url=$telegram_api_url.$bot_token.'/sendMessage?chat_id='.$chat_id.'&text='.urlencode($text_message).'&parse_mode=HTML'.'&reply_markup='.$remove_keyboard_json;

// осталось только выполнить GET-запрос, например с помощью file_get_contents (ну или curl :))
file_get_contents($url); // отправляем get-запрос на сформированный url

[свернуть]

Правка сообщений «на лету»

Одна из прикольных фишек inline-клавиатур — возможность «на лету» править сообщения, к которым эти клавиатуры привязаны. Как я уже писал выше, нажатие на кнопки inline-клавиатур не вызывает отправку сообщений в чат, но то же время, получив callback мы всегда можем понять, к какому сообщению была привязана нажатая кнопка. Остаётся только исправить это сообщение при помощи одного из методов Updating messages.

Как получить callback? Для этого просто нужно запросить, получить и обработать очередной update, если бот работает через longpolling, или выполнить только два последних пункта, если бот работает через webhook (в этом случае, как вы помните, ничего запрашивать не нужно, так как телега сама знает по какому адресу отправлять апдейты). Данные колбэка будут содержаться в поле «callback_query» полученного апдейта.

Пример апдейта, полученного после нажатия на одну из кнопок inline-клавиатуры

"{"ok":true,"result":
[
{
"update_id":xxxxxxxxxx,
"callback_query":
{
"id":"xxxxxxxxxxx",
"from":
{
"id":xxxxxxxxx,
"first_name":"xxxxxxx",
"last_name":"xxxxxxx",
"username":"xxxxxxxxx",
"language_code":"ru"
},
"message":
{
"message_id":xxxx,
"from":
{
"id":xxxxxxxxx,
"first_name":"xxxxxxxx",
"username":"xxxxxxx"
},
"chat":
{
"id":xxxxxxxx,
"first_name":"xxxxxxx",
"last_name":"xxxxxxxx",
"username":"xxxxxxx",
"type":"private"
},
"date":1499854111,
"text":"test"
},
"chat_instance":"xxxxxxxxxxxx",
"data":"1"
}
}
]
}"

[свернуть]

Остаётся только выделить из апдейта данные, однозначно указывающие на само это сообщение (идентификатор чата и идентификатор сообщения), а также на нажатую кнопку и, собственно, отредактировать исходное сообщение. Понять какую именно кнопку нажали можно по содержимому поля «data» в полученном «callback_query». В этом поле будет содержаться информация, которую мы вписали
в поле «callback_data» для соответствующей кнопки при создании inline-клавиатуры.

Пример редактирования сообщения налету


// если мы определили, что нам прилетел именно колбэк (по наличию поля "callback_query"), то:
// выделяем из этого колбэка необходимые для редактирования сообщения данные
$chat_id = $input_array['callback_query']['message']['chat']['id']; // идентификатор чата
$message_id = $input_array['callback_query']['message']['message_id']; //идентификатор сообщения
$data = $input_array['callback_query']['data']; // данные, которые были отправлены при нажатии на кнопку
...
...
// далее нужно просто выполнить запрос (GET или POST), обратившись, например, к методу editMessageText
$url=$telegram_api_url.$bot_token.'/editMessageText?chat_id='.$chat_id.'&message_id='.$message_id.'&text='.urlencode($edited_message).'&reply_markup='.$keyboard_json;
// $edited_message - отредактированный текст сообщения
// $keyboard_json - клавиатура, которая будет содержаться в отредактированном сообщении
file_get_contents($url); // отправляем get-запрос на сформированный url

[свернуть]

Вот и всё. Как видите, всё достаточно просто и понятно. В telegram вообще всегда всё просто, понятно и подробно описано. Вообще не понимаю, зачем нужны всякие библиотеки и фреймворки. Все они выглядят гораздо страшнее и монструознее, чем исходные описания из API. Это при том, что все эти фреймворки добавляют коду веса, ошибок и нестабильности. Уф, надо вступить в какое-нибудь движение за чистоту кода. Ну ладно, это я уже отвлёкся. Пока!

  1. Часть 1. Что такое Telegram боты и как они работают
  2. Часть 2. Регистрация аккаунтов Telegram ботов в картинках
  3. Часть 3. Пишем простого чат-бота для Telegram на чистом php (webhook)
  4. Часть 4. Прикручиваем MySQL к чат-боту для Telegram на php (webhook)
  5. Часть 5. Пишем Telegram бота на php для работы через longpolling
  6. Часть 6. Делаем пользовательскую клавиатуру для бота
  7. Дополнение. Как отправлять правильные https-запросы через curl и при чём здесь SSL-cертификаты

Комментарии 2

  • Делал всё по-написанному не работает…
    Нет ли у Вас рабочего кода?
    Спасибо.

  • Ну, так то это рабочий код от бота моего сына. Вот, можете попробовать, там до сих пор что-то работает: @memkoinbot
    Просто выложенные куски кода немного обезличены (типа реальные подписи заменены на button1, button2 и так далее), ну и код нарезан на ломтики (показано только то, что касается непосредственно клавиатур).
    Если создадите на форуме тему и выложите свой код, — попробуем разобраться в чём проблема. Только всякие токены / логины / пароли не забудьте вырезать!

Добавить комментарий