Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
February 26, 2022 10:36 am GMT

Telegraf VS Node-Telegram-Bot-API

Today the most popular ways to build telegram chat bots in node js are Telegraf and Node-Telegram-Bot-Api. The second is more popular by weekly downloads(250.000), but in this post I don't want to equalize them by stats. I want to talk about my experience with them, in which cases I used them and show you really nice guide, especially for Telegraf, cause they haven't readable docs for newbies or people who don't use typescript.

Node Telegram Bot API

So, let's start with this package. It is really easy, but due to it we can't use it in really big projects, cause it will be hard to understand structure of bot without comments or million javascript files.

To download type:

npm i node-telegram-bot-api

After this, as said in documentation, you need to initialize it with your telegram token, which you received from Bot Father

const TelegramBot = require('node-telegram-bot-api');const token = 'YOUR_TELEGRAM_BOT_TOKEN';// Create a bot that uses 'polling' to fetch new updatesconst bot = new TelegramBot(token, {polling: true});

And there are two main methods in this package - bot.sendMessage(chatId, message, options) and bot.on("one of params from api like message or text", function which contains message param and returns response)

bot.on('message', (msg) => {  const chatId = msg.chat.id;  // send a message to the chat acknowledging receipt of their message  bot.sendMessage(chatId, 'Received your message');});

Here is message object with all fields. So, if we need to react on /start command we need to make something like this:

bot.on("message", async function (msg) {  const text = msg.text;  const chatId = msg.chat.id;  if (text === "/start") {    bot.sendMessage(chatId, `Hello ${msg.from.username}! Choose your language...`,    reply_markup: {       one_time_keyboard: true,       keyboard: [["ua"], ["en"]],   },);  }});

We checked if our text is equal to our command and responded with message. It is all main logic from this package, more sendMessage methods or params you can see here. Also we used reply_markup option in which we can use our keyboard, which will be sent with our message. And then we can check if text equal to "en" we will change our language to english and response with message.

In addition, if you have a question like can you send message without getting message from user - you can do it. All that you need is to save your user to database like MongoDB with chatId field and use something like express to make CRUD methods to send your message. Here is my example of this 'bot mailer':

app.get("/", async (req, res) => {  await TelegramUser.find()    .cursor()    .eachAsync(async (user) => {      bot.sendMessage(user.chatId, "<b>Hi!</b>", {        parse_mode: "HTML",        disable_web_page_preview: false,      });    });});

So here we sent our message "Hi" in async forEach mongodb method when we got request to our app. TelegramUser is a mongodb model, where I store user chatId. Also you can see two the most useful options from this package - parse_mode, which parses our message to HTML(but can't parse all tags, like img, video, cause there are methods like sendPhoto, sendVideo) and disable_web_page_preview, which you can use when in message you send link and you don't want to see preview of it.
I hope you got it, let's move to telegraf.

Telegraf

Let's talk about telegram bot library which I prefer to use in big projects.
To download:

npm i telegraf

In this library we can see similar methods with node-telegram-bot-api:

const { Telegraf } = require('telegraf')const bot = new Telegraf(process.env.BOT_TOKEN)bot.start((ctx) => ctx.reply('Welcome'))bot.help((ctx) => ctx.reply('Send me a sticker'))bot.on('sticker', (ctx) => ctx.reply(''))bot.hears('hi', (ctx) => ctx.reply('Hey there'))bot.launch()

To initialize we use new Telegraf(token). To react on /start command we type bot.start which is more readable than in previous package. Here instead of message object we have ctx - context object, which almost doesn't have big difference from first one but has many another methods.
ctx.reply is function with response message, here if we want to parse HTML or reply with audio or photo etc. we can use methods like ctx.replyWithHTML or ctx.replyWithPhoto, all methods you can see in previous link.
bot.on is the same as in node-telegram-bot-api, all params which can receive this function you can see here.
bot.hears is just a function which reacts on user's message.
And to launch our bot we use bot.launch()
It would seem that it is the end, but in fact it is one part of opportunities which this library gives. Here you can use scenes.

Telegraf Scenes

Let's imagine that telegram bot is a theatre with one viewer - our user. When performance starts, the first scene is beginning, let's name it start scene. There are some actions take place in this scene for some time and then the scene ends, in another words we left the scene. So this interval from beginning of our scene and ending is our scene.
Telegraf Scene is the same, but let's display it in code.
This library has two types of scene: Base Scene and Wizard Scene.

To set up our scenes we need to register them with Stage. Let's do it in our main file.

app.js

const { Scenes, Telegraf } = require("telegraf");const start = require("./controllers/start"); // scene file const about = require("./controllers/about"); // scene file const settings = require("./controllers/settings"); // scene file const contact = require("./controllers/contact"); // scene file const search = require("./controllers/search"); // scene file const bot = new Telegraf(process.env.TELEGRAM_TOKEN);const stage = new Scenes.Stage([start, about, settings, contact, search]); // Register our scenesbot.use(stage.middleware()); // Stage middlewarebot.hears("settings", Scenes.Stage.enter("settings")); // Entering the settings scene when listener worked

Here we imported our scenes and registered them in array. Also we added a stage middleware without which our scenes won't work. And to enter our scene we set bot listener with bot.hears and then as a first param we type our scene id(see in next paragraph) and then we enter the scene with Scenes.Stage.enter.

Base Scene

Here is an example of this scene:
settings.js

const { Scenes } = require("telegraf");const Scene = Scenes.BaseScene;const { getMainKeyboard, getBackKeyboard } = require("../../util/keyboards");const { leave } = Scenes.Stage;const settings = new Scene("settings");settings.enter(async (ctx) => {  const { backKeyboard } = getBackKeyboard();  await ctx.reply("settings.what_to_change", backKeyboard);});settings.leave(async (ctx) => {  const { mainKeyboard } = getMainKeyboard();  await ctx.reply("shared.what_next", mainKeyboard);  await ctx.scene.leave();});settings.hears("Back", leave());settings.action("backButtonId", console.log("Back button was clicked"));module.exports = settings;

../../util/keyboards

const { Markup } = require("telegraf");exports.getMainKeyboard = () => {  let mainKeyboard = Markup.keyboard([    ["Movies", "Settings"],  ]);  mainKeyboard = mainKeyboard.oneTime();  return mainKeyboard;};exports.getBackKeyboard = () => {  let backKeyboard = Markup.keyboard(["Back"]);  backKeyboard = backKeyboard.oneTime();  return backKeyboard;};

It is file with our settings scene. To initialize it, we use new Scene("scene id"). When user entered our scene he will receive response from settings.enter(async function(ctx)), in which we make our first step of scene. Then all actions in our scene will be in settings.on or in settings.hears. Then, when scene is ending we use settings.leave in which we have function with moving back to default scene(start scene) and ctx.scene.leave(), which is required to leave scene. Without it you have a risk to stay in this scene forever.
Also, if we have keyboard, which can be created by Markup.keyboard, all our buttons there are strings in array. If we want to make many rows in our keyboard, we can make many arrays, like if we have two arrays with two strings(buttons), we will get keyboard with 2 rows with 2 buttons in each.
When we tap on button, we can handle this tap in scene.action(buttonId), where buttonId is our button's second param in Markup.button.callback. Also we can create inline keyboard with Markup.inlineKeyboard

Markup.inlineKeyboard(  [    Markup.button.callback("Back", "backButtonId"),  ],  {})  .oneTime()  .resize();

Wizard Scene

All logic of this scene is the same as in previous, but here we have a chain with scene's steps. To go to our next step we use ctx.wizard.next and ctx.wizard.steps[ctx.wizard.cursor](ctx) too, cause in last versions of Telegraf without it our step won't change. To leave from scene we use ctx.scene.leave

const { Scenes } = require("telegraf");const { getMainKeyboard } = require("../../util/keyboards");const Wizard = Scenes.WizardScene;const about = new Wizard(  "about", // Our wizard scene id, which we will use to enter the scene  async (ctx) => {    await ctx.reply(ctx.i18n.t("scenes.about.main"));    ctx.wizard.next();    return ctx.wizard.steps[ctx.wizard.cursor](ctx);  },  async (ctx) => {    const { mainKeyboard } = getMainKeyboard(ctx);    await ctx.reply(ctx.i18n.t("shared.what_next"), mainKeyboard);    return ctx.scene.leave();  });module.exports = about;

Session

And the last main thing in this library is session. It is like local storage in web but for telegram bots. Here we can save params that we need to save and use them in future. To set up, let's change our main file:

const { Scenes, session, Telegraf } = require("telegraf");const start = require("./controllers/start"); // scene file const about = require("./controllers/about"); // scene file const settings = require("./controllers/settings"); // scene file const contact = require("./controllers/contact"); // scene file const search = require("./controllers/search"); // scene file const bot = new Telegraf(process.env.TELEGRAM_TOKEN);const stage = new Scenes.Stage([start, about, settings, contact, search]); // Register our scenesbot.use(session()); // Session middlewarebot.use(stage.middleware()); // Stage middlewarebot.hears("settings", Scenes.Stage.enter("settings")); // Entering the settings scene when listener worked

Here we imported our session from telegraf and made a session middleware. Then we can use it in our scenes. For example:

const { Scenes, session } = require("telegraf");const { getMainKeyboard, getBackKeyboard } = require("../../util/keyboards");const { User } = require("../../models");const { getMoviesBySearch, getMovieKeyboard } = require("./helpers");const Base = Scenes.BaseScene;const search = new Base("search");const { leave } = Scenes.Stage;search.enter(async (ctx) => {  const backKeyboard = getBackKeyboard(ctx);  await ctx.replyWithHTML("scenes.search.welcome_to_search",    backKeyboard  );});search.hears("Back"), leave());search.on("text", async (ctx) => {  const user = await User.findById(ctx.from.id);  const movies = getMoviesBySearch(user.language, ctx.message.text);  const movieKeyboard = getMovieKeyboard(ctx);  ctx.session.movies = movies; // Set session field  ctx.session.index = 0; // Set session field  ctx.replyWithHTML(``, movieKeyboard);});search.leave(async (ctx) => {  const { mainKeyboard } = getMainKeyboard(ctx);  await ctx.reply("shared.what_next", mainKeyboard);  delete ctx.session.index; // Delete session field  delete ctx.session.movies; // Delete session field  await ctx.scene.leave();});module.exports = search;

Conclusions

In this post I explained how to deal with the most popular js telegram libraries step by step. As I said, I prefer Telegraf to Node-Telegram-Bot-Api because it is more interesting and readable. If you have any thoughts about it, write at the comments below and correct me if I made some mistakes in this post, cause I don't speak English fluently

In addition

Today in my country, in Ukraine, is a war, which caused by Russia's aggression. I want to have a peace in my country, our army does their best and it would be great if you can support us writing #nowarinukraine in your dev posts. I hope that soon I will be able to write any posts here and make code projects again, cause now I am sitting in basement and just wait.


Original Link: https://dev.to/maklut/telegraf-vs-node-telegram-bot-api-36fk

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To