René van Mil

A Telegram Weather Bot With Node.js and Express

Telegram is an amazing messaging service which I’ve been using for more than a year now (I switched when WhatsApp sold its soul). Recently the service introduced a major new feature for third-party developers: the Telegram Bot Platform.

In this post I’ll show you how I built my first Telegram bot: @WeatherDemoBot. It’s a simple bot which responds to you with a message if you ask it about the weather in a location you specify.

Summary

  • Create a new bot with the @BotFather
  • Build and host an Express application which will serve as the backend for the bot

The Server

To build a Telegram bot you’ll need a webserver which can handle HTTPS connections. This guide assumes you are running an Ubuntu server.

Note that self-signed certificates do not work, and you have to use the ports 443, 80, 88 or 8443

If you don’t have a server yet, I can recommend Digital Ocean (please use this referral link, thanks :)) because it’s really easy to get started. Select the smallest droplet and pick the Ubuntu distribution to get started quickly. There are a lot of really great tutorials for setting up Digital Ocean droplets, so I won’t explain how to do that here.

The Telegram Bot

Step 1 - Create the bot

Open your Telegram client and start a chat with the @BotFather. Then send the following commands:

New bot commands
1
2
3
4
5
6
/newbot
WeatherDemo
WeatherDemoBot
/setcommands
@WeatherDemoBot
weather - Returns a forecast e.g. /weather New York
  1. The /newbot command creates a new bot.
  2. The name for your bot.
  3. The username for your bot. This must be a unique name and will be used to start a chat with your bot.
  4. The /setcommands command lets you specify a list of commands which your bot will respond to.
  5. Select the bot you just created by typing its username.
  6. Register the /weather command which your bot will respond to.

Step 2 - Connect the bot

Check if your bot is active with the getMe API call.

Get the bot info
1
2
3
4
GET /bot12345678:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/getMe HTTP/1.1
Host: api.telegram.org
Connection: close
User-Agent: Paw/2.2.2 (Macintosh; OS X/10.10.3) GCDHTTPRequest
getMe response
1
2
3
4
5
6
7
8
{
  "ok": true,
  "result": {
    "id": 12345678,
    "first_name": "WeatherDemo",
    "username": "WeatherDemoBot"
  }
}

Telegram needs to know where to send the messages which are sent to the bot. This is done by setting a webhook for your bot.

The request below sets the webhook to https://yourweatherbot.yourserver.com/telegram/. Change this to the address of your own server where the Express app will be running.

Set the bot webhook
1
2
3
4
GET /bot12345678:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/setWebhook?url=https%3A%2F%2Fyourweatherbot.yourserver.com%2Ftelegram%2F HTTP/1.1
Host: api.telegram.org
Connection: close
User-Agent: Paw/2.2.2 (Macintosh; OS X/10.10.3) GCDHTTPRequest
setWebhook response
1
2
3
4
5
{
  "ok": true,
  "result": true,
  "description": "Webhook was set"
}

The Express App

Step 1 - Installation

Install nginx, Node.js and npm.

Installation
1
2
3
4
sudo apt-get update
sudo apt-get install nginx
sudo apt-get install nodejs
sudo apt-get install npm

Create a user which will be used to run the Express app.

Create user
1
adduser --disabled-login weatherdemobot

Step 2 - Configure Nginx

Configure a new server in nginx for the Express app. Create a new site file…

Create nginx site configuration
1
sudo nano /etc/nginx/sites-available/yourweatherbot.yourserver.com

…and enter the following configuration:

Nginx site configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
       listen         80;
       server_name    yourweatherbot.yourserver.com;
       return         301 https://$server_name$request_uri;
}

server {
        listen        443 ssl;
        server_name   yourweatherbot.yourserver.com;

        ssl_certificate /path/to/your/ssl/certificate.crt;
        ssl_certificate_key /path/to/your/ssl/certificate.key;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

        location / {
                proxy_pass http://127.0.0.1:3000;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade; # allow websockets
                proxy_set_header Connection $connection_upgrade;
                proxy_set_header X-Forwarded-For $remote_addr; # preserve client IP
                if ($uri != '/') {
                    expires 30d;
                }
        }
}

Enable the configuration and restart nginx.

Enable nginx site configuration
1
2
sudo ln -s /etc/nginx/sites-available/yourweatherbot.yourserver.com /etc/nginx/sites-enabled/yourweatherbot.yourserver.com
sudo service nginx restart

If everything is working correctly you should see a 502 Bad Gateway message when you open your bot url https://yourweatherbot.yourserver.com in the browser.

Step 3 - Create the Express app

The fastest way to get started with Express is to use the application generator. Install it globally:

Install Express application generator
1
sudo npm install express-generator -g

We can now use the generator to create a new app inside the home directory of the user we created to run the app with.

Generate Express app
1
2
3
4
cd /home/weatherdemobot
sudo -u weatherdemobot express weatherdemobot
cd weatherdemobot
sudo -u weatherdemobot HOME=/home/weatherdemobot npm install

Add two dependencies which we’ll be using.

Add dependencies
1
2
sudo -u weatherdemobot HOME=/home/weatherdemobot npm install striptags --save
sudo -u weatherdemobot HOME=/home/weatherdemobot npm install underscore --save

Check if the app works after generating:

Start the new Express app
1
sudo -u weatherdemobot DEBUG=weatherdemobot:* npm start

If everything is working correctly you should no longer see a 502 Bad Gateway message when you open your bot url https://yourweatherbot.yourserver.com in the browser, but instead you should see a Welcome to Express message.

And if you already tried sending the /weather command to your bot, you should see lots of POST /telegram/ 404 6.906 ms - 1206 debug messages appear. This is Telegram trying to deliver the commands to your bot, but since you haven’t implemented the /telegram endpoint yet, the Express app is sending 404 responses.

Step 4 - Implement the Express app

You can find the source for the Express app over here. You can use this repo to copy/paste the code into your own app.

We’ll start with two helpers: one to get the weather data from the Yahoo Weather API and another one to communicate with the Telegram API.

  1. Create a helpers folder inside the express app root folder.
  2. Create the telegram.js file.
  3. Create the yahoo.js file.

Communicating with the Telegram API is done with the token you received when creating your bot. It should remain a secret, so I’ve stored it inside a config file.

  1. Create a config folder inside the express app root folder.
  2. Create a config.js file (copy the sample-config.js file).
  3. Change the file so that it contains your Telegram bot token.

We have told the BotFather to set the webhook to the /telegram path, so we need to create a router for that path.

  1. Open the routes folder.
  2. Create the telegram.js file.

To activate this route, edit the app.js file and add the route and router by adding these two lines (check the github repo to see where to place them).

Edit app.js
1
2
var telegram = require('./routes/telegram');
app.use('/telegram', telegram);

That’s all, your Telegram bot is now ready to run!

Step 5 - Run the Express app

You can manually start the Express app with this command:

Start Express app
1
2
cd /home/weatherdemobot/weatherdemobot
sudo -u weatherdemobot npm start

But if you’re going to want to keep your bot running as a service, it’s better to create an Upstart script for it. The easiest way to do this is to use upstarter for this.

Create a service for the bot
1
2
3
sudo npm install -g upstarter
cd /home/weatherdemobot/weatherdemobot
sudo upstarter

You will be asked a couple of questions:

  1. Upstart service name (weatherdemobot): <ENTER, use default>
  2. Command(s) to run: npm start
  3. Upstart service description: WeatherDemoBot
  4. Log output to /var/log/upstart? (y/n): y
  5. System user to run under (root): weatherdemobot
  6. Set max file descriptors (1000000): <ENTER, use default>
  7. Working directory for process (/home/weatherdemobot/weatherdemobot): <ENTER, use default>
  8. Respawn automatically? (y/n): y
  9. about to write this to /etc/init/weatherdemobot.conf. is this ok? (y/n): y

You can now start/restart/stop your bot with the following commands:

Bot service
1
2
3
sudo service weatherdemobot start
sudo service weatherdemobot restart
sudo service weatherdemobot stop

And see what happens in the Telegram client :)

Where to go from here

Congratulations on building your first Telegram bot :)

If you’re considering building a more advanced bot, I can recommend checking out this Telegram Bot project made by a colleague of mine. The goal is to build a more generic implementation, so you can use it as a library to quickly build your own Telegram bot.

Comments

Real Time Web Analytics