How to build and monitor a Telegram bot with AWS Lambda & SNS – A comprehensive guide

There was a time only a tech-savvy person could understand and build a bot, now bots are everywhere. Building a bot is no longer a complex process, and a Telegram Bot is the easiest one. At the core, Bots are third party applications that run in Telegram and help publish messages to the Telegram group.

Telegram bots can be used to enrich chats by integrating content from external services. They can also be used for sending you customized notifications/news, alerts, weather forecasts and so on.  Telegram bots can also be used to accept payment from other Telegram users. 

This blog explains the complete process of how to build a Telegram bot and monitor using AWS services. Here, the AWS Services used are AWS Cloudwatch, SNS, and Lambda. The messaging service used is Telegram. The Cloudwatch alerts are notified on the Telegram group, where everyone who has a Telegram account can join and receive the alerts. The functional specification flow is as given below:

Amazon Simple Notification Service (SNS) is a web service which allows you to publish messages from Cloudwatch logs and immediately deliver them to the subscribers(Lambda function, which gets triggered and pushes the messages on the Telegram Bot).

To deliver your notification to a Telegram chat, you will not be able to simply integrate the SNS topic with Telegram Bot API through an HTTP/S endpoint. Instead, you will have to create a simple Lambda function which calls the Bot API and forwards the notifications to a Telegram chat. The procedure is as detailed below.

Forwarding SNS Notifications to Telegram Chat

To kickstart this procedure, you need to first create a Telegram bot. These are nothing but Telegram accounts that are operated by software instead of people. Here in our case, the Telegram bot will be operated by a Lambda function which sends a notification to Telegram chat on behalf of the bot. This communication is unidirectional, which means that although the bot sends a message to you, it does not process any messages that it receives from you.

The SNS notifications can be forwarded to a Telegram chat by following the below steps:

  1. Create a new Telegram bot.
    • In the Telegram app, type and search for @BotFather. Next, press the Start button (alternatively, you may send the /start command). Once this is done, send the /newbot command and follow the few easy steps to create a new Telegram bot. The BotFather will generate an authorization token for the new bot. This token is a string which resembles something like 123456789:ABCD1234efgh5678-IJKLM. This is required for sending requests to the Telegram Bot API.
    • In the Telegram app, search the name of the bot that you had created. Then, press the Start button (you may also send the /start command). Write down any text message to chat with your bot. For, e.g., write ‘Hello’.
    • Now, execute the Bot API call to retrieve the ID of your chat with the bot. In the given command, replace <token> with the value of the authorization token that you had received from the BotFather.
      curl ‘https://api.telegram.org/bot<token>/getUpdates’ | python -m json.tool
      The output of this will give your chat id.
  2. Go to https://console.aws.amazon.com/sns/home to open Amazon SNS Console. Create a new SNS topic at the AWS region of your choice.
  3. Go to https://console.aws.amazon.com/lambda/home and open the Lambda Management Console. Now, switch to the same AWS region where you had created your SNS topic. Create a new Lambda function with the IAM role as “Executing the basic Lamda function reading the Cloudwatch logs”. 
  4. The following function will execute the sendMessage method of Telegram Bot API and help forward the SNS messages (notifications) to a Telegram chat.

Sample code in python

import json

import os

import logging

from botocore.vendored import requests

# Initializing a logger and settign it to INFO

logger = logging.getLogger()

logger.setLevel(logging.INFO)

# Reading environment variables and generating a Telegram Bot API URL

TOKEN = os.environ[‘TOKEN’]

USER_ID = os.environ[‘USER_ID’]

TELEGRAM_URL = “https://api.telegram.org/bot{}/sendMessage”.format(TOKEN)

# Helper function to prettify the message if it’s in JSON

def process_message(input):

    try:

        # Loading JSON into a string

        raw_json = json.loads(input)

        # Outputing as JSON with indents

        output = json.dumps(raw_json, indent=4)

    except:

        output = input

    return output

# Main Lambda handler

def lambda_handler(event, context):

    # logging the event for debugging

    logger.info(“event=”)

    logger.info(json.dumps(event))

    # Basic exception handling. If anything goes wrong, logging the exception    

    try:

        # Reading the message “Message” field from the SNS message

        message = process_message(event[‘Records’][0][‘Sns’][‘Message’])

        # Payload to be set via POST method to Telegram Bot API

        payload = {

            “text”: message.encode(“utf8”),

            “chat_id”: USER_ID

        }

        # Posting the payload to Telegram Bot API

        requests.post(TELEGRAM_URL, payload)

    except Exception as e:

        raise e

5. Memory (MB): 128 MB
Timeout: 5 sec
Environment variables: set the CHAT_ID and TOKEN environment variables of your Lambda function (use the values from Step 1).
For example:

6. Publish the new version of your Lambda function. Copy the function ARN (along with the version suffix) from the top of the page.

7. Open the SNS topic in Amazon SNS Console. With the ARN in the previous step, create a new subscription for the AWS Lambda protocol.

8. Open your SNS topic in the Amazon SNS Console and publish a test message.
The message will be delivered to your Telegram chat with your bot.

Once the above configuration is done, set the Event Metrics and create the Alarm associated with the Metric. Henceforth, if a similar situation occurs, an alert notification will be sent to the Telegram Bot, which in turn gets cascaded to the group.

Here’s a sample notification for reference:

{

    “AlarmName”: “High CPU on Test Server”,

    “AlarmDescription”: “Created from EC2 Console”,

    “AWSAccountId”: “525477889965”,

    “NewStateValue”: “ALARM”,

    “NewStateReason”: “Threshold Crossed: 1 datapoint [99.6666666666667 (15/02/20 09:21:00)] was greater than or equal to the threshold (80.0).”,

    “StateChangeTime”: “2020-02-15T09:22:34.928+0000”,

    “Region”: “US East (Ohio)”,

    “OldStateValue”: “OK”,

    “Trigger”: {

        “MetricName”: “CPUUtilization”,

        “Namespace”: “AWS/EC2”,

        “StatisticType”: “Statistic”,

        “Statistic”: “AVERAGE”,

        “Unit”: null,

        “Dimensions”: [

            {

                “value”: “i-0e8f79e0801648253”,

                “name”: “InstanceId”

            }

        ],

        “Period”: 60,

        “EvaluationPeriods”: 1,

        “ComparisonOperator”: “GreaterThanOrEqualToThreshold”,

        “Threshold”: 80.0,

        “TreatMissingData”: “”,

        “EvaluateLowSampleCountPercentile”: “”

    }

}

Note: Ensure that the Lambda function is provided with proper permissions to pick the message from the SNS topic.

This concludes the case of notifying the Cloudwatch logs monitoring. The same arrangement can be used for the Cloudtrail logs monitoring the API calls, as well.