Время прочтения: 6 мин.

С чего начать?

Одна из популярных библиотек для создания телеграм-ботов на JavaScript — это Telegraf.js (простая и гибкая, облегчает разработку телеграм-ботов на основе JS).

Первое, что нужно сделать при создании телеграм-бота — обратиться к специальному сервису @BotFather (Рис. 1) социальной сети Telegram. После того, как я указала адрес и уникальное имя пользователя, которое заканчивается на “bot”, в диалоге с @BotFather мне предоставили уникальный токен для управления моим телеграм-ботом. Его необходимо хранить в безопасности, чтобы избежать несанкционированного доступа к боту. Если возникнет необходимость, всегда можно изменить токен или настроить другие параметры бота, обратившись к @BotFather.

Создание проекта  У меня уже был установлен Node.JS, поэтому я сразу приступила к инициализации проекта

npm init –yes

Затем я установила фреймворк для Node.js, который позволяет разрабатывать веб-приложения и API-Express.js

npm i express

Далее я установила библиотеку Telegraf, которую упоминала выше:

npm install telegraf --save

В отдельный файл config.js для безопасности я вынесла порт сервера и токен, который получила выше. В файле app.js я реализовала приветствие, которое выводит бот при вводе команды /start:

import express from 'express'
import { PORT, TOKEN } from './config.js'
import { Telegraf } from "telegraf";
const app = express()
const Tbot = new Telegraf(TOKEN)


Tbot.start((context) => {
  context.replyWithHTML(
    "Добро пожаловать в <b>to-do list</b>\n\n" +
      "Для добавления задачи необходимо ее <b>написать</b> и отправить боту"
  );
});
Tbot.launch()
app.listen(PORT, () => console.log(`Сервер запущен. Порт: ${PORT}`));

Требования к боту

Мне было важно, чтобы бот добавлял задачу в перечень не по нажатию кнопки, а при получении сообщения от пользователя при отправке текста боту. Нужно, чтобы он умел выводить список всех задач и удалять, какую мне необходимо. Также я хотела, чтобы была какая-то инструкция для пользователя и по запросу выводилась мотивационная картинка.

Я создала файл db.js, в котором хранится массив с задачами:

export let missionList = []

Создание клавиатурыВ файле keyboards.js я импортировала класс Markup из модуля telegraf и использовала его для создания клавиатурной разметки с кнопками. Клавиатура автоматически масштабируется под размер экрана пользователя (Рис. 3).  
Функция getMenu создает клавиатуру с тремя кнопками: «Моя задача», «Добавить задачу» и » Получить мотивацию»

import { Markup } from "telegraf";

export function getMenu() {
  return Markup.keyboard([
    ["Мои задачи",  "Инструкция"],["Получить мотивацию"],
  ]).resize();
}

Далее я вернулась в файл app.js. Логично, что функция getMenu должна вызывать при старте бота. Поэтому я ее импортировала и добавила в действие при команде /start.

import express from 'express'
import { PORT, TOKEN } from './config.js'
import { Telegraf } from "telegraf";
import { getMenu} from "./keyboards.js";
const app = express()
const Tbot = new Telegraf(TOKEN)


Tbot.start((context) => {
  context.replyWithHTML(
    "Добро пожаловать в <b>to-do list</b>\n\n" +
      "Для добавления задачи необходимо ее <b>написать</b> и отправить боту",
    getMenu()
  );
});
Tbot.launch()
app.listen(PORT, () => console.log(`Сервер запущен. Порт: ${PORT}`));

Реализация логики бота

Перед тем как начинать реализовывать логику бота далее, важно знать, какие методы бывают.
Метод hears() вызывает обработчика, который реагирует на введенный текст. А метод reply() содержит ответ бота пользователю.

Tbot.hears("Мои задачи", async (context) => {
  const missions = await getMyMissions();
  let results = "";

  for (let i = 0; i < missions.length; i++) {
    results = results + `${i + 1}. ${missions[i]}\n`;
  }

  if (results !== "") {
    context.replyWithHTML("<b>Перечень задач:</b>\n\n" + `${results}`);
  } else {
    context.replyWithHTML("<b>Перечень задач пуст</b>");
  }
});

Tbot.hears("Инструкция", (context) => {
  context.replyWithHTML(
  `Чтобы удалить задачу отправьте фразу <b>"удалить"</b> с указанием порядкового номера задачи. ` +
      `Например, <b>"удалить 3"</b>:\n\n ` +
      `Чтобы добавить новую задачу, просто напишите ее и отправьте боту. `
    );
});

Tbot.hears(/^удалить\s(\d+)$/, (context) => {
  const id = Number(+/\d+/.exec(context.message.text)) - 1;
  deleteMission(id);
  context.reply("Задача успешно удалена");
});
Tbot.on("text", (context) => {
  if (!context.session) context.session = {};

  context.session.missionText = context.message.text;

  context.replyWithHTML(
    `Вы действительно хотите добавить задачу:\n\n` +
      `<i>${context.message.text}</i>`,
    noYesKeyboard()
  );
});

Tbot.action(["true", "false"], (context) => {
  if (context.callbackQuery.data === "true") {
    addMission(context.session.missionText);
    context.editMessageText("Задача успешно добавлена");
  } else {
    context.deleteMessage();
  }
});

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

export function noYesKeyboard() {
  return Markup.inlineKeyboard(
    [ Markup.button.callback("Да", "true"),Markup.button.callback("Нет", "false")],    { columns: 2 }
  );
}

Также я добавила функции вывода, добавления и удаления для базы данных в файле db.js.

export function getMyMissions() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(missionList);
    }, 500);
  });
}

export function addMission(text) {
  missionList.push(text);
}

export function deleteMission(id) {
  missionList.splice(id, 1);
}

Что же делает кнопка «Получить мотивацию»? При нажатии выводятся «рандомные» картинки, которые я храню в папке и подписи, которые хранятся в массиве:

function getRandomImageWithCaption() {
  const imagesFolderPath = "./images";
  const captions = [
Список цитат
  ];
  const imageFiles = fs.readdirSync(imagesFolderPath);
  const randomIndex = Math.floor(Math.random() * imageFiles.length);
  const randomImage = imageFiles[randomIndex];
  const randomCaption = captions[Math.floor(Math.random() * captions.length)];
  return { image: randomImage, caption: randomCaption };
}
Tbot.hears("Получить мотивацию", (context) => {
  const { image, caption } = getRandomImageWithCaption();
  const imagePath = `./images/${image}`;

  context.replyWithPhoto(
    { source: imagePath },
    {
      caption: caption,
    }
  );
});

Заключение Созданный телеграм-бот всегда находится под рукой, помогает планировать и управлять повседневными задачами, показывая изображения для мотивации. Это поможет вам сохранять продуктивность на протяжении всего дня. Для управления ботом используется клавиатура, что делает использование приложения максимально простым и интуитивным. Надеюсь, что мой телеграм-бот станет для вас надежным помощником в организации рабочих и личных дел, всегда готовым помочь и поддержать.
Полный код: https://github.com/SVErmol/Telegram-bot