Cloud Connections

Cloud Connections

cloud engineering, automation, devops, systems architecture and more…

21 Jun 2020

Building a Serverless Telegram Bot on AWS

Nowadays, chat bots are frequently used on instance messaging platforms to send notifications, host/play games, moderate groups, check for services etc. I’ve always wanted to try out to build a small notification bot myself. So, I decided to take a serverless approach to it.

I chose Telegram for this project as their Bot API was quite easy to understand. There are also very useful bot frameworks built around the API, so I could get started quickly.

cover_image

Features Included

The goal of this project is to get the basics working and build more features as we go.

  • Automatically setup an API endpoint (called a webhook) for Telegram to send updates (ie. whenever any message is sent to the bot).
  • Have the bot respond to a few commands.

general diagram

The project is available on Github if you wish you try it out yourself.

Create the Bot

Check out the guide from Telegram to create your bot. The instructions are straighforward. The important piece here is to get the token which is used to make authorized requests to the Bot API.

tg_botfather

Lambda Code Walkthrough

I’m using NodeJS for the the Lambda code here. I’m not going to dive in too much into the code detail, but I’ll highlight some of the important parts in this code.

The structure of the code is made up of 2 functions, that are triggered based on which API endpoint is called.

// handler.js

// setup the bot

// hello function handles updates(messages) sent from Telegram to the webhook API
module.exports.hello = async event => {
    // using a try/catch block
    try {
      // process event data
      const body = JSON.parse(event.body);

      // bot handles processed data from the event body
      await bot.handleUpdates(body);

      // return an Ok response
    } catch (err) {
      // handle any errors

      // return any Err responses
    }
}

// setWebhook function handles initial webhook setup for Telegram
module.exports.setWebhook = async event => {
    // using a try/catch block
    try {
      // process webhook url based on event data
      let url = 'https://' + event.headers.Host + '/' + event.requestContext.stage
        + '/webhook';

      // use bot methods to set the webhook url
      await bot.telegram.setWebhook(url);

      // return an Ok response
    } catch (err) {
      // handle any errors

      // return any Err responses
    }
}

Telegraf Bot Framework

Telegraf is a Telegram Bot Framework for NodeJS which has a good set of features and is easy to use. In this example I’m implementing a few commands that the bot will respond to using this framework.

// setup the bot
const { Telegraf } = require('telegraf');
const bot = new Telegraf(process.env.BOT_TOKEN);

// set a start command
bot.start((ctx) => {
      return ctx.reply('Hello from Lambda! Use /help to view available commands.');
});

// bot handles processed data from the event body
await bot.handleUpdates(body);

Deploy using Serverless Framework

Using the Serverless Framework, we can define all the resources required in a .yml file and it will go deploy the application on AWS.

I already talked about how I used it in an earlier post. But there are some important things to note in this setup highlighted below.

# set the BOT_TOKEN as an environment variable so that it 
# is accessible to the function

# define env variables under provider section
provider:
  name: aws
  runtime: nodejs12.x
  environment:
    BOT_TOKEN: ${file(./serverless.env.yml):TELEGRAM_TOKEN, ''}

# define functions and their API endpoints
functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: webhook
          method: post
          cors: true

  set-webhook:
    handler: handler.setWebhook
    events:
      - http:
          path: setWebhook
          method: post
          cors: true

Deploy by running serverless deploy on the terminal and that’s it. After a few minutes your application will be setup on AWS.

It’ll show the output of the configuration once completed.

sls_output

Get Updates from Telegram via Webhook

There are 2 ways of getting updates from Telegram; polling and webhook. Since this is a serverless application and functions are triggered on events, we’ll be using the webhook method.

So, as the final step, register the bot’s webhook URL with Telegram by calling the setWebhook API endpoint.

curl -X POST https://<api_gateway_url>/prod/setWebhook

And that’s about it!

Test the Bot

Send a few commands and check out the replies.

tg_botchat

Final Thoughts

  • Most of the time for this project was spent on figuring out how to use the bot framework and NodeJS as this is my first time using the language.
  • I think I should have a separate file to implement the bot functionality and have the handler refer to it. That way it would be more modular and I can update parts of the application easily.

References