Building a serverless Telegram bot

With the arrival of FaaS and all the serverless infrastructure providers (AWS, Google Cloud, Azure, etc) now is easy to deploy our own Telegram bot.

A Webhook-based bot it's the perfect use case for serverless computing, using for example Google Cloud Functions we'll have all these advantages:

  • Our function will be associated to a public endpoint (IPv4 and IPv6) over HTTPS (using a valid certificate provided by Google)
  • Pay only for function invocations and its compute resources consumption, so it could be cheaper than paying for a server powered on all the time
  • No server management
  • Scales automatically

Requirements

Before start building your bot you'll need to:

  • Register a new bot following these instructions core.telegram.org/bots in order to get an API token
  • Using a Google Cloud account, register a new project, enable the Cloud Functions API and install the Cloud SDK following the official quickstart

Code

In a few lines of Python you can code a simple echo bot that will reply with the same message that it receives:

# main.py
import os
import telegram

def webhook(request):
    bot = telegram.Bot(token=os.environ["TELEGRAM_TOKEN"])
    if request.method == "POST":
        update = telegram.Update.de_json(request.get_json(force=True), bot)
        chat_id = update.message.chat.id
        # Reply with the same message
        bot.sendMessage(chat_id=chat_id, text=update.message.text)
    return "ok"

The only dependency needed is the amazing python-telegram-bot library:

# requirements.txt 
python-telegram-bot==11.1.0

So we just need these 2 files (main.py and requirements.txt) to deploy our bot. Google Cloud Functions will detect automatically your requirements file and it will install your dependencies in the environment of your function.

You can find the code and the requirements of this example in github.com/pabluk/serverless-telegram-bot.

Deploy

These are the steps to deploy the bot:

  1. Get the bot's code
  2. Create a Google Cloud Function
  3. Set a WebHook for the bot
  4. Test everything.

So for the step one you can clone this repository to get a basic example:

$ git clone https://github.com/pabluk/serverless-telegram-bot.git
$ cd serverless-telegram-bot

Step two, create a Google Cloud Function running this command in the same line:

$ gcloud beta functions deploy webhook --set-env-vars "TELEGRAM_TOKEN=000:yyy" \
  --runtime python37 --trigger-http

Some details:

  • Here webhook is the name of the function in the main.py file
  • You need to specify your Telegram token with the --set-env-vars option
  • --runtime python37 describe the environment used by our function, Python 3.7 in this case
  • --trigger-http is the type of trigger associated to this function, you can find here the complete list of triggers

The above command will return something like this:

Deploying function (may take a while - up to 2 minutes)...done.
availableMemoryMb: 128
entryPoint: webhook
environmentVariables:
  TELEGRAM_TOKEN: 000:yyyy
httpsTrigger:
  url: https://us-central1-<PROJECT_NAME>.cloudfunctions.net/webhook
labels:
  deployment-tool: cli-gcloud
name: projects/<PROJECT_NAME>/locations/us-central1/functions/webhook
runtime: python37
serviceAccountEmail: <PROJECT_NAME>@appspot.gserviceaccount.com
sourceUploadUrl: https://storage.googleapis.com/gcf-upload-us-central1-xxxxxx/...
status: ACTIVE
timeout: 3s
updateTime: '2018-09-03T16:18:32Z'
versionId: '1'

The most important thing of that output is the URL in httpsTrigger because it will be the public endpoint of your bot used by Telegram to send him updates.

Security warning: to simplify this example I set up the Telegram's token via an environment variable but the recommended way to manage secrets on Google Cloud is to use Cloud KMS because the contents of environment variables may result for example being sent to logs.

Step three, you need to set up your Webhook URL using this API call:

$ curl "https://api.telegram.org/bot<TELEGRAM_TOKEN>/setWebhook?url=https://us-central1-<PROJECT-NAME>.cloudfunctions.net/webhook"

You must replace <TELEGRAM_TOKEN> with your bot's token and <PROJECT_NAME> with the ID of your Google Cloud project that was returned by the precedent command. If everything is good you'll see this response:

{
    "description": "Webhook was set",
    "ok": true,
    "result": true
}

And finally you can test and play with your bot via curl:

$ curl "https://us-central1-<PROJECT-NAME>.cloudfunctions.net/webhook"
ok

Or via the mobile app:

Telegram mobile application screenshot

Next steps

A few considerations:

  • Always keep your bot's token safe
  • and don't share its Webhook URL to minimize the number of invocations

This a very basic example of what we can do using serverless computing to build a bot, then from here it could be easy to improve it using all the features provided by the python-telegram-bot.org library and by the Google Cloud platform (Storage, Observability, etc).