20. June 2016

Building a Telegram Bot using express.js

The Telegram messaging app has an extensive Bot API that is available to the public. I published a Node.js client library to npm. The library explicitly lacks a hook for setting up long polling as it is actually quite easy to build a simple express app that handles incoming messages for you.


Assuming you are familiar with express.js let’s look at what needs to be done:

Creating the client

Creating the client is pretty straightforward: call the constructor using your API token and export it for use throughout your application:

const TelegramBotClient = require('telegram-bot-client');
const client = new TelegramBotClient('<YOUR_BOTS_API_TOKEN>');

module.exports = client;

Setting the webhook URL

When your application starts up use #setWebhook to notify Telegram about your URL

// in app.js
const app = express();
// later...
const client = require('./client');
client.setWebhook('<YOUR_WEBHOOK_URL>');
app.use('/', require('./routes/message'));

Telegram advises you to use a secret token in the URL so no third party is able to send messages to your bot. To do so simply generate a randomstring at startup:

// in app.js
const app = express();
const randomstring = require('randomstring');
const WEBHOOK_TOKEN = randomstring.generate(16);
// later...
const client = require('./client');
client.setWebhook(`<YOUR_WEBHOOK_URL>/${WEBHOOK_TOKEN}`);
app.use(`/${WEBHOOK_TOKEN}`, require('./routes/message'));

Handling messages in the router

When Telegram sends a message to your bot it will now simply be part of the request body, so we can simply reply with a friendly nonsensical message:

// routes/message.js
const express = require('express');
const bodyParser  require('body-parser');
const client  require('./../client');
const router = express.Router();

router.use(bodyParser.json());

router.post('/', (req, res, next) => {
    client
        .sendMessage(req.body.message.chat.id, 'I\'m a bot, so what?')
        .promise()
        // replying succeeded, so we can send a 200 response to Telegram
        // the actual payload does not matter
        .then(() => res.json({ ok: true }))
        // something above failed, we will use express' default error handling
        .catch(next);
});

For help on how to use the client you can have a look at the GitHub repository.

Done

With a simple setup like this and a mature framework like express at hand I feel this is definitely an alternative to having your Telegram client library acting as “your bot’s server”.


If you are interested this demo application is also available on GitHub for you to fork / clone / look at / have fun with.