Телеграм-бот на NodeJS. Создание справки
Tags: telegram, node
Published: 2021-04-02 11:06:03

В этой заметке я расскажу о том, как сделал справку по командам бота, показанную на скриншоте.
Когда программист будет знать, какие команды понимает его бот, то он может задать команды используя бота BotFather для того, чтобы задать эти команды. Задаём ему команду **/help**, чтобы увидеть список команд, далее видим **/setcoomands**, запустив её, выбираем своего бота и далее заводим эти команды.
![BotFather](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w7sllfnw0il86m1yzhk3.png)
Я вижу такие минусы в этом способе: 
- Этот способ задаёт команды для авто подстановки, но не даёт возможность задать содержимое команды /help *(да и новый бот не знает такую команду)*
- Когда изменится текст/список команд, то придётся снова его вводить. 

Тогда предлагаю такой способ: Завести команды в программе, используя метод [setMyCommands](https://core.telegram.org/bots/api#setmycommands). И сразу же, не отходя далеко, напишем команду **/help**.

Сперва нам нужно задать константу, в которой будут команды бота:
```js
const COMMANDS = [
  {
    command: "friday",
    description: "Показать пятничную подборку",
  },
  {
    command: "video",
    description: "Найти и показать видеоконтент",
  },
  {
    command: "subscribe",
    description:
      "Подписаться на пятничную подборку (рассылка выходит по пятницам)",
  },
  {
    command: "unsubscribe",
    description: "Отписаться от рассылки",
  },
  {
    command: "help",
    description: "Показать справку",
  },
  {
    command: "quit",
    description: "Отписаться от рассылки, выйти из чата",
  },
];

module.exports = COMMANDS;
```

Затем, после инициализации бота _(об этом я писал в предыдущих заметках)_ , сделайте такую команду:
```js
// Импортировать массив
const COMMANDS = require("../const/commands");
// Задать команды боту
bot.setMyCommands(COMMANDS);
```
Пару слов о содержимом этого массива. Это не произвольный массив объектов, эти объекты должны соответствовать типу [BotCommand](https://core.telegram.org/bots/api#botcommand):
_command_ это название команды, 
_description_ - её описание.

Второй шаг- научить бота эти команды показывать по команде help.
Для этого нужно составить текст вывода по этой команде, основываясь на массиве COMMANDS. Я так сделал:
```js
const getHelp = () => {
  let helpText = `Телеграм-бот, созданный для развлечения, а не для работы.\n*Доступные команды:*\n`;
  helpText += COMMANDS.map(
    (command) => `*/${command.command}* ${command.description}`
  ).join(`\n`);
  return helpText;
};


bot.command("audio", (ctx) => {
  return ctx.replyWithMarkdown(getHelp());
});
```

Сейчас я не использую библиотеку telegraf, о которой я ранее писал, я использую **node-telegram-bot-api** текст функции у меня выглядит по-другому, вот её полный текст:
```js
const TelegramBot = require("node-telegram-bot-api");

const COMMANDS = require("../const/commands");

/**
 * Генератор содержимого команды help
 * @param {string|number} chatId
 * @param {TelegramBot} bot
 */
const help = (chatId, bot) => {
  let helpText = `Телеграм-бот, созданный для развлечения, а не для работы.\n*Доступные команды:*\n`;
  helpText += COMMANDS.map(
    (command) => `*/${command.command}* ${command.description}`
  ).join(`\n`);
  return bot.sendMessage(chatId, helpText, {
    parse_mode: "Markdown",
  });
};

module.exports = help;
```

Что ещё можно сделать по оформлению справки? - Можно для массива COMMANDS сделать немного другое наполнение, например такое:
```js
const COMMANDS = [
  {
    command: "friday",
    description: "Показать пятничную подборку",
    hint: true,    
  },
  {
    command: "video",
    description: "Найти и показать видеоконтент",
    hint: true,
    help: true,
  },
  {
    command: "subscribe",
    description:
      "Подписаться на пятничную подборку (рассылка выходит по пятницам)",
  },
///
```
Добавить два поля: hint и help. И если значение в них true то выводить содержимое соответственно в подсказке командной строки или в окне справки. Для этого нам пригодятся методы массива [filter](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) и [map](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/map) или можно обойтись одним методом - [reduce](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce).

P.S.
В дальнейших заметках я буду приводить примеры используя только "node-telegram-bot-api" - мне эта библиотека показалась более удобной, чем telegraf.