Build telegram bot with node

Table of tutorials contents

  1. Setting up the project - Tutorial part 1
  2. Working with messages
  3. Adding commands to the bot, working with the special messages and keyboards - WIP
  4. Persisting state between sessions - WIP
  5. Using telegraf middleware - WIP

Our project is set up and our bot is listening for its start but that’s not that useful if you ask me. Let’s see options do we have to make it smarter. If you have not been following the previous part of the tutorial and would like to get up and running to have the same project structure you are most welcome to go to the starting point of the series. Otherwise let’s learn how to work with messages!

Working with messages

For handling messages telegraph uses hears() method and we can write our first message handler straight ahead. Note that it listens for strings or more complicated patterns, so you are totally free to intercept the messages vie regex.

To make our app cleaner we can code split our dedicated handlers as separate functions that just receive bot instance.

responses/onmessage.js
js
1const
Copy
Copy
onMessage
Copy
Copy
=
Copy
Copy
bot
Copy
Copy
=>
Copy
Copy
{
Copy
Copy
2 bot.hears('hello', ctx => {
3 ctx.reply('Wondeful I can listen to `hello` message now!😎')
4 })
5}
6
7module.exports = { onMessage }
bot.js
js
1const
Copy
Copy
{
Copy
onMessage
Copy
}
Copy
Copy
=
Copy
Copy
require
Copy
(
Copy
"./responses/onMessage"
Copy
)
Copy
;
Copy
Copy
2...
3
4bot.start(async ctx => {
5 const name = ctx.from.first_name;
6 ctx.reply(
7 `Hello ${
8 name ? name : "friend"
9 }! You managed to run me!`
10 );
11});
12
13onMessage(bot);

The main thing to know about messages and any other interactions that you do with the bots within telegraf is that they have context object which carries all the useful information about the user, message and gives you the access to telegram native functions like reply() which we have used now or others like sendMessage() or deleteMessage() and more. Let’s have a closer look inside context.

If you examine the ctx object you will see that it has plenty of methods and data. For example you can already identify the user by his telegram id using ctx.from or getting access to message that has been sent with ctx.message. Let’s make our response more elaborate using this new knowledge!

responses/onmessage.js
js
1const
Copy
Copy
onMessage
Copy
Copy
=
Copy
Copy
bot
Copy
Copy
=>
Copy
Copy
{
Copy
Copy
2 bot.hears(/^(hello|hey|heya)$/, ctx => {
3 console.log(ctx.match)
4 ctx.reply(
5 `Hello <b>${ctx.from.first_name ||
6 'friend'}</b>! Your telegram id is <i>${
7 ctx.from.id
8 }</i>\n\nYour have sent me the following message: <code>${
9 ctx.match[0]
10 }</code>`,
11 {
12 parse_mode: 'Html',
13 }
14 )
15 })
16}
17
18module.exports = { onMessage }

Let me go trough the main points that you need to learn from the above code:

  1. As I’ve mentioned earlier, you can not only pass string to hears() but also regex patterns, which we are utilising right now to make our bot more lively and understanding natural speech. This regex /^(hello|hey|heya)$/ will match one of the three words and if one of them is our message will trigger reply.

  2. You might have noticed that there is additional object added as second parameter of the reply method. It tells telegram that this message can contain some formatting, and specifies in which format it shall parse the message. This HTML implies that we can use some of the valid html formatting tags like b, i or code which we are now using to make message not a plain wall of text. Note: this is quite limited now, as you get access only to some of the formatting tags in both HTML and markdown formatting modes.

  3. Note that \n is used to add breaks and spaces to the lines. This is a line break.

Deleting messages

Let’s move even further and access some other method inside our response handle. For example consider situation in which you want to delete the messages send by bot or the user as they are not important to keep in the chat history anymore. We can achieve this with native telegram functions provided to us by the context object.

responses/onmessage.js
js
1const
Copy
Copy
onMessage
Copy
Copy
=
Copy
Copy
bot
Copy
Copy
=>
Copy
Copy
{
Copy
Copy
2
3 const {
4 message_id: messageId,
5 chat: { id: chatId }
6 } = ctx.message;
7
8 ctx.reply(
9 `Hello <b>${ctx.from.first_name ||
10 "friend"}</b>! Your telegram id is <i>${
11 ctx.from.id
12 }</i>\n\nYour have sent me the following message: <code>${
13 ctx.match[0]
14 }</code>`,
15 {
16 parse_mode: "Html"
17 }
18 );
19
20 setTimeout(() => {
21 ctx.telegram.deleteMessage(chatId, messageId);
22 ctx.telegram.deleteMessage(chatId, messageId + 1);
23 ctx.telegram.sendMessage(
24 chatId,
25 "Cool, I managed to delete both messages!"
26 );
27 }, 2500);
28 });
29};
30
31module.exports = { onMessage };

As telegram allows you to easily delete messages by their chat id and message id, and send messages by chat id we just need to use the correct methods of telegram and you should see your message and the response to it disappear while success message appear in the chat!

Notice that sending five ‘Hey’ messages consecutively before setTimeout kick in won’t break our bot as the context works with isolated messages, namely the function will be called for each message and its reply separately.

Thanks for learning with me!

Thanks for reading and congrats on finishing another part of the series! In the next part you will learn how to add commands to your bot, how to show them in the nice list of native commands provided by telegram app. Apart from that you will be able to use inline menus and buttons to answer the questions of the bot, which is one of the most exciting things about telegram!

In the next part of the series you will learn how to add commands to the bot, work with the special messages and keyboards, to give your users the best possible interaction experience

I have worked hard on the newsletter to make sure you are always getting updates when my new content is out, so if you don’t want to miss the next part of the series hit the form down below to subscribe to my newsletter. 👇👇👇


Comments section

Dimitri Ivashchuk

Written by Dimitri who lives and works in Vienna building useful things. He is passionate about modern web technologies and enjoys learning something new everyday as well as sharing his knowledge with others.

Front-end engineer @CubeTech
Instructor @egghead.io