Telegram bot. Добавим интерактивности
Tags: telegram, node
Published: 2021-05-19 08:28:11

В [этой заметке](https://dev.to/slkarol/nodejs-2-1f56) я писал о том, как по команде бота выдаётся случайное фото, а если добавить параметр к команде, то будет целенаправленный выбор темы.
У меня в том боте, который я неспешно сейчас пишу, есть нечто подобное: по команде выбирается случайный канал и из него достаются картинки. Если указали канал, то выбор идёт из указанного. До какого-то момента это меня устраивало, пока список каналов не стал подходить к 10. И тогда я задумал сделать такую возможность: дать пользователю выбрать канал по нажатию на кнопку.

Вот примерно как это сделано у меня.
Не важно, что вы используете в качестве библиотеки обращения к api, важно понимание этого самого api. Мы будем работать с методом [sendMessage](https://core.telegram.org/bots/api#sendmessage)
```js
    this.bot.sendMessage(chatId, "Выберите канал:", {
      reply_markup: {
        resize_keyboard: true,
        inline_keyboard: [
          [{ text: "Случайно", callback_data: "random" }],
          [{ text: "Спорт", callback_data: "sport" }],
          [{ text: "Кино", callback_data: "cinema" }],
          [{ text: "Музыка", callback_data: "music" }],
        ],
      },
    });
```
Результат:
![Результат](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lzgy98wjyg5ma7gsbkyd.png)
Здесь у нас каждый массив с объектом- это строка с кнопкой. Можно и по-другому сделать, например так:
```js
    this.bot.sendMessage(chatId, "Выберите канал:", {
      reply_markup: {
        resize_keyboard: true,
        inline_keyboard: [
          [{ text: "Случайно", callback_data: "random" }],
          [
            { text: "Спорт", callback_data: "sport" },
            { text: "Кино", callback_data: "cinema" },
            { text: "Музыка", callback_data: "music" },
          ],
        ],
      },
    });
```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ng66ifeowgmvt5l0iap.png)

Осталось добавить обработчик нажатия на кнопку. В библиотеке node-telegram-bot-api можно это сделать используя функцию **on** - первый параметр задаёт событие бота, на которое реагировать, второй параметр- обработчик этого события.
```js
// После инициализации бота, задать обработчик 
   this.bot.on("callback_query", this.callbackQuery); 
// обработчик нажатия на кнопки
  callbackQuery = async (callbackQuery) => {
    const msg = callbackQuery.message;
    // Спрятать клавиатуру (оптимально)
    // await this.removeHisKeyboard(callbackQuery);
    // См. ниже пояснения
    await this.bot.answerCallbackQuery(callbackQuery.id);
    const { data = "" } = callbackQuery;
    //..
  };
  /**
   * Удалить вывод клавиатуры
   */
  removeHisKeyboard = (callbackQuery) => {
    const messageText = callbackQuery.message.text;
    const messageId = callbackQuery.message.message_id;
    return this.bot
      .editMessageText(messageText, {
        message_id: messageId,
        chat_id: callbackQuery.from.id,
        reply_markup: {
          inline_keyboard: [],
        },
      })      
  };
```
Про callbackQuery написано в [документации по api](https://core.telegram.org/bots/api#callbackquery) - там же объясняется, почему нужно вызывать _answerCallbackQuery_ . Функция _removeHisKeyboard_ здесь может и не нужна, но если Вы хотите скрыть клавиатуру, после того, как сделан выбор, то можно ей воспользоваться. Здесь бот редактирует своё сообщение с интерактивным выбором,- он просто очищает inline_keyboard.