Последнее время, я заметил, что на мой блог все чаще переходят по запросам связанными с Telegram API. Да и сам я в последнее время увлекся разработкой Telegram-ботов и NodeJS. В данной статье, я хочу рассказать о том, как добавлять inline-keybord к сообщениям. Разница между ReplyKeyboardMarkup, незначительная. Однако, в этой статьи я опишу пример использования первого варианта с inline-keyboards
.
Пример данной клавиатуры, вы можете увидеть на скриншоте ниже. Данный бот публикует записи в мою группу Вконтакте с разных IT-сообществ.
Ничего сверхъестественного использовать мы не будем. Хочу отметить, что я работаю с пакетом [node-telegram-bot-api](https://github.com/yagop/node-telegram-bot-api)
. И в следующих статьях, как и в предыдущей про то, как создать своего телеграм бота на node.js, мы будем использовать только этот пакет. Советую прочесть данную статью, чтобы вы могли работать с командой npm
.
Первым делом, мы создаем файл server.js
и устанавливаем пакет node-telegram-bot-api
.
После чего, подключаем данный пакет и создаем первую команду. Если у вас еще нету своего бота, заранее создайте его.
Использовать inline-keyboards
можно следующим способом:
_13var options = {_13 reply_markup: JSON.stringify({_13 inline_keyboard: [_13 [{ text: 'Кнопка 1', callback_data: '1' }],_13 [{ text: 'Кнопка 2', callback_data: 'data 2' }],_13 [{ text: 'Кнопка 3', callback_data: 'text 3' }]_13 ]_13 })_13};_13_13bot.onText(/\/start_test/, function (msg, match) {_13 bot.sendMessage(msg.chat.id, 'Выберите любую кнопку:', options);_13});
Я не стал париться над тем, какого бота мы будем делать. В качестве примера решил написать бота для теста знаний JavaScript.
Вопросы я поместил в отдельный массив, который вы можете отредактировать сами. Отмечу, что это простой пример реализации подобного бота. Если вам понравилась идея, вы с уверенностью можете его доделать.
_32var questions = [_32 {_32 title:'Сколько параметров можно передать функции ?',_32 buttons: [_32 [{ text: 'Ровно столько, сколько указано в определении функции.', callback_data: '0_1' }],_32 [{ text: 'Сколько указано в определении функции или меньше.', callback_data: '0_2' }],_32 [{ text: 'Сколько указано в определении функции или больше.', callback_data: '0_3' }],_32 [{ text: 'Любое количество.', callback_data: '0_4' }]_32 ],_32 right_answer: 4_32 },_32 {_32 title:'Чему равна переменная name?\nvar name = "пупкин".replace("п", "д")',_32 buttons: [_32 [{ text: 'дудкин', callback_data: '1_1' }],_32 [{ text: 'дупкин', callback_data: '1_2' }],_32 [{ text: 'пупкин', callback_data: '1_3' }],_32 [{ text: 'ляпкин-тяпкин', callback_data: '1_4' }]_32 ],_32 right_answer: 2_32 },_32 {_32 title:'Чему равно 0 || "" || 2 || true ?',_32 buttons: [_32 [{ text: '0', callback_data: '2_1' }],_32 [{ text: '""', callback_data: '2_2' }],_32 [{ text: '2', callback_data: '2_3' }],_32 [{ text: 'true', callback_data: '2_4' }]_32 ],_32 right_answer: 3_32 },_32];
Разъясню еще один код.
_10[{ text: 'ТЕКСТ_КНОПКИ', callback_data: 'НОМЕР-ВОПРОСА_ВАРИАНТ-ОТВЕТА' }]
К примеру, если в вопрос по счету является 2-ым и у него 3 ответа, то варианты нужно прописывать так: 2_1, 2_2, 2_3. Можете сделать свой вариант ответа, но я решил разделять через нижнее подчеркивание.
Так же, я разработал две функции:
_15function getRandomQuestion(){_15 return questions[Math.floor(Math.random()*questions.length)];_15}_15_15function newQuestion(msg){_15 var arr = getRandomQuestion(); // Получаем случайный вопрос_15 var text = arr.title; // Вытаскиваем оттуда текст вопроса (Пример: title:'Чему равно 0 || "" || 2 || true ?')_15 var options = {_15 reply_markup: JSON.stringify({_15 inline_keyboard: arr.buttons, // Добавляем кнопки, которые есть в вопросе._15 })_15 };_15 chat = msg.hasOwnProperty('chat') ? msg.chat.id : msg.from.id; // Если сообщение отправлял пользователь, то свойство msg.chat.id, если же он кликал на кнопку, то msg.from.id_15 bot.sendMessage(chat, text, options); // Отправляем пользователю сообщение: id пользователя, текст вопроса, кнопки._15}
Главные функции у меня уже готовы, теперь осталось добавить событие на сообщение /start_test
. И еще одно событие, на получение ответа от кнопок.
_21// Отправив сообщение боту "/start_test", выполнится функция newQuestion(msg);_21bot.onText(/\/start_test/, function (msg, match) {_21 newQuestion(msg);_21});_21_21// Ответ от кнопок_21bot.on('callback_query', function (msg) {_21 var answer = msg.data.split('_'); // Делим ответ на две части, превратив в массив. Первый элемент номер вопроса, второй будет вариант ответа._21 var index = answer[0]; // Получаем номер вопроса_21 var button = answer[1]; // И вариант ответа_21_21 // Если присланный вариант совпадает с вариантом из массива_21 if (questions[index].right_answer==button) {_21 bot.sendMessage(msg.from.id, 'Ответ верный ✅');_21 } else {_21 bot.sendMessage(msg.from.id, 'Ответ неверный ❌');_21 }_21_21 // Отправляем еще один вопрос пользователю_21 newQuestion(msg);_21});
И вроде все. Теперь бот будет присылать вопросы пользователю, отправив команду /start_test
. При клике на кнопку, проверяется правильность варианта и отправляется новый вопрос.
Кстати, вы можете спокойно задавать свои команды. Неважно на русском или английском и не имеет разницы, имеется ли в команде слэш. Можно прописать хоть /дайка быстро мне тест/
и если такое сочетание найдено в сообщении, то выполнится функция генерации вопроса. Эти два слэша, нкжно ставить обязательно, так как это регулярное выражение
Пример нашего бота, вы можете увидеть ниже:
_76var TelegramBot = require('node-telegram-bot-api');_76_76// Устанавливаем токен, который выдавал нам бот._76var token = 'TELEGRAM_TOKEN';_76_76// Включить опрос сервера_76var bot = new TelegramBot(token, {polling: true});_76_76var questions = [_76 {_76 title:'Сколько параметров можно передать функции ?',_76 buttons: [_76 [{ text: 'Ровно столько, сколько указано в определении функции.', callback_data: '0_1' }],_76 [{ text: 'Сколько указано в определении функции или меньше.', callback_data: '0_2' }],_76 [{ text: 'Сколько указано в определении функции или больше.', callback_data: '0_3' }],_76 [{ text: 'Любое количество.', callback_data: '0_4' }]_76 ],_76 right_answer: 4_76 },_76 {_76 title:'Чему равна переменная name?\nvar name = "пупкин".replace("п", "д")',_76 buttons: [_76 [{ text: 'дудкин', callback_data: '1_1' }],_76 [{ text: 'дупкин', callback_data: '1_2' }],_76 [{ text: 'пупкин', callback_data: '1_3' }],_76 [{ text: 'ляпкин-тяпкин', callback_data: '1_4' }]_76 ],_76 right_answer: 2_76 },_76 {_76 title:'Чему равно 0 || "" || 2 || true ?',_76 buttons: [_76 [{ text: '0', callback_data: '2_1' }],_76 [{ text: '""', callback_data: '2_2' }],_76 [{ text: '2', callback_data: '2_3' }],_76 [{ text: 'true', callback_data: '2_4' }]_76 ],_76 right_answer: 3_76 },_76];_76_76function getRandomQuestion(){_76 return questions[Math.floor(Math.random()*questions.length)];_76}_76_76function newQuestion(msg){_76 var arr = getRandomQuestion();_76 var text = arr.title;_76 var options = {_76 reply_markup: JSON.stringify({_76 inline_keyboard: arr.buttons,_76 parse_mode: 'Markdown'_76 })_76 };_76 chat = msg.hasOwnProperty('chat') ? msg.chat.id : msg.from.id;_76 bot.sendMessage(chat, text, options);_76}_76_76bot.onText(/\/start_test/, function (msg, match) {_76 newQuestion(msg);_76});_76_76bot.on('callback_query', function (msg) {_76 var answer = msg.data.split('_');_76 var index = answer[0];_76 var button = answer[1];_76_76 if (questions[index].right_answer==button) {_76 bot.sendMessage(msg.from.id, 'Ответ верный ✅');_76 } else {_76 bot.sendMessage(msg.from.id, 'Ответ неверный ❌');_76 }_76_76 bot.answerCallbackQuery(msg.id, 'Вы выбрали: '+ msg.data, true);_76 newQuestion(msg);_76});