Telegram Bots - From Idea To Production

Published on Feb. 6, 2022 | Tags: python telegram heroku bots

Recently, I've had a surge of ideas, silly ideas that is, for telegram bots, and I ended up streamlining the process of creating them and deploying them to Heroku within a few minutes. In this post, I will detail my process and show how can a telegram bot be quickly developed and deployed.


Requirements


In order to create a fully deployed telegram bot, we will need a few things:
1. A Telegram Account
2. A Heroku Account
3. A GitLab account (Or GitHub, but you will need to adapt the CI/CD job).
4. Development tools: Git, python (with poetry installed) and a text editor.


What are telegram bots?


Simply put, a bot is a user that is run by a program instead of a human. It is a great way for automating things, integrating with other services or do a lot of memeing. Some bots that you might have already found when talking in telegram are @pic or @gif.


Telegram API


In order for your program to receive and send messages on telegram, telegram offers an API for doing so. Among the variety of APIs that are offered, the bot API is the one we are interested about.


Sending requests to APIs is generally not a difficult thing, but in this case doing so from scratch would be quite a lot of work. Instead, we are going to look into a python library that does all the work for us: Python Telegram Bot.


Bot commands


As a (human) user, you can interact with bots in different ways. The most common one is through commands. A command, in bot terms is, a special word which will instruct the bot what to do. Commands are usually prefixed with a backslack \ and then the name of the command.


To send a command to a bot is just sending a message to the bot like \commandname. This will instruct the bot to run a function which will do something.


Another way of interacting with bots, is through queries. These look like this: First @ then the name of the bot and after, a query. A great example of this are the @pic and @gif bots. These are available everywhere, so in any conversation you could start writing a message with @pic kitty and the bot will look for images with kitties in them.


There are other ways to interact with bots, for example, when a bot is added to a group you can decide whether it can read messages sent. And so you can make it do an action when a certain message is sent. For more information on bots, check out the official documentation.


Creating a bot


In order to create a new bot, we need to talk to the bot father. Immediately, it will allow us to create a bot, give it a name, a username, and it will give us the API Key we'll need later.


The Bot Father in action


This bot also allows you to change your bot description, about section, picture, list of commands, and more.


Minimal working example


In the library's documentation, we can find a small hello world example, but in bot.


Python Telegram Bot in Heroku Template


In order to make the process of creating a new bot from scratch easier, I put all my changes along with other necessary files and configurations into a template repository. This allows anyone to fork the repo and have everything setup for starting working on the bot without all the hassle of setting and figuring everything out.


The template is available over in GitLab: https://gitlab.com/mrswats/python-telegram-bot-heroku-template.


What does this template includes? Well, besides the bot's code is shown below, it includes dependencies through poetry, GitLab's CI/CD configuration, gitignore, an example for the dotenv file, LICENCE, Procfile, and a README with all the necessary steps to get it up and running. Feel free to open any issues you encounter with the template or open any merge requests! It also includes configuration for black and isort along with flake8, but it is not enforced in the CI. In the future I want to add some tests, but that's not ready yet.


Let's have a look at bot.py and go over the new setup:


First, we use python-dotenv to load environment variables for local development from a .env file. Then, we set up the logging, which the library also provides a lot of useful information in the logs if configured. Then, we have some variables for our bot. The WEBHOOK_URL is for telling telegram where our bot is, that is what the start_webhook function does, in a nutshell. The port, in Heroku, will be given to us, but we can use 8443 for local development.


The first function hello is a handler. When a command is issued, this function will be called and will perform whatever action we program, here. Once this function is defined, we have to register it with the Updater.


On Heroku, we are not interested in polling the API for new messages, as it would take up a lot of resources and not be very efficient. While excellent for local development, it's not suitable for production. Therefore, another environment variable is fetched from the environment. So, in Heroku will define an ENV variable such that is not empty.


After all that, it's time to idle and wait for messages to arrive. As you can see, it's a very bare-bones template, but that allows us to get up and running in no time. With time, this bot can be as complicated as wanted or kept as simple as possible.


Running the bot locally


Before we can run any code, we need to install the dependencies. This template uses poetry to manage the dependencies and virtual environment so first, we need to install the dependencies like:


poetry install

Once that's done, the next step should be to create a .env file from the example in the template repository with the appropriate variables. Now, we are ready to run


poetry run python ./bot.py

And we should see some logging happening in the terminal. Now, you can try sending commands, messages and whatnot to your bot over on https://t.me/<name-of-your-bot>/ and you will see the bot receive and process the messages. Now, it's time to put your ideas into play. I would also recommend having a look at the library documentation to see what is capable of. There are also a bunch of examples to look at for different patterns and recipes.


Heroku


Heroku is a Platform as a Service (PaaS) which allows you to push your git repo directly in order to deploy your code. All you need is to define a buildstack and a way to run your application with a Procfile and you are basically set.


First, we can create the Heroku app from the terminal with:


heroku apps:create <name-of-your-app>

This will output the URL of the app when it is finally deployed and the git URL. We want to annotate the first one for the deployment.


Then, we add the buildpacks:


heroku buildpacks:add https://github.com/moneymeets/python-poetry-buildpack.git
heroku buildpacks:add heroku/python

This will allow us to run python applications and to install poetry dependencies directly instead of having to export a requirements file.


And we can finally set up the environment variables:


heroku config:set TELEGRAM_API_TOKEN=<your token from the bot father here>
heroku config:set WEBHOOK_URL=<the url heroku showed you after creating the app>
heroku config:set ENV="production" # This value doesn't matter, it has to be set to some non-empty string

Once everything is set up, it's time to deploy! The easiest way to deploy on Heroku is to add a remote and push to that remote.


heroku git:remote
git push heroku

And you should see the build logs in the terminal before the push command exits. Any errors will pop up and will usually tell you what's wrong. And assuming there are no more errors and everything is working as intended you are done, you deployed your telegram bot into herokU!


Automatic deploys


However, having to syncronize the GitLab repo with the Heroku repo is a bit not ideal, so I came up with a solution for managing this easily. GitLab offers a very nice and simple CI solution (and free!) and we can leverage that to our advantage here.


So the idea is that every time a commit is pushed into GitLab, GitLab CI will automatically push to Heroku. For that we use a tool named dpl which will do exactly that.


For that, we'll need to set up the Heroku app name and Heroku API key in the CI (both as non-masked and non-protected). And that's basically it, the configuration in the template will take care of installing the tool.


Conclusions


After developing several silly telegram bots, I came up with a nice template to develop them faster and get up and running in no time. This was a very instructive exercise and a way to learn and hopefully open the door for you to create your own telegram bots! I have a short list of some of my favourite bots I've made so far over at jovell.dev/bots.


Ferran Jovell