Build a Telegram Bot in Go in 9 minutes

François Paupier
The Startup
Published in
9 min readMay 22, 2020

--

Photo by Volodymyr Hryshchenko on Unsplash

I like the Telegram messaging service; it has a beautiful interface and works on all types of devices. What I love the most about Telegram is the vibrant ecosystem of bots available there. Being for translation, to manage spam emails, or to set reminders, they come very handily, making Telegram one of those social media where I actually feel like a power user.

Telegram offers an API describing how to leverage their bot API. However, I found it hard to distinguish between the essentials to get your bot working and other niceties, resulting in lots of time skimming through the doc.

In this article, I provide you with an illustrated step by step guide on how to build your own Telegram Bot in 9 minutes.

I base my example on the RapGeniusBot I built (aka snoop). Snoop is a bot with which users can interact to generate original rap music lyrics based on the user’s input. The full code is available on my GitHub repository.

A working Bot in 6 steps

  1. Register your bot on Telegram
  2. Handle user requests
  3. Implement your handler (and add some test)
  4. Deploy your handler
  5. Set a webhook using the Telegram API
  6. Enjoy

1. Register your bot on Telegram

First, you need to tell Telegram you want to register a Bot. To do this, send the BotFather a /newbot command. You get a token back. We’ll use it in our code to authenticate our app against Telegram servers. See the screenshot below. Keep your token in a safe place — i.e., don’t commit it to your version control system.

When you create a bot, the BotFather generates and returns a token to access the HTTP Bot API.

To double-check the bot creation worked, you can query the /getMe endpoint of the Telegram API.

If Telegram registered your bot, you get a short JSON summary of its characteristics in response to your /getMe request.

You gave your bot a cool profile picture as well as an accurate description of what it does? Sweet! Now let’s zoom in on how to implement your bot behavior to interact with users.

2. Handle user requests

The next step is to implement the business logic you want to happen whenever a user interacts with your bot.

Before jumping straight into the code, let’s consider what happens when a user interacts with your bot on Telegram.

Telegram is a cloud-based messaging service. When you send someone a message on Telegram, the Telegram servers receive your message and distribute it to the appropriate chat. See my GIF below:

Simplified view of the cloud-based nature of the Telegram messaging service. Animated version.

In a nutshell: You send a message, then Telegram servers distribute it to the appropriate chat, now your friend can see it. Your friend sends back an answer, which gets processed by Telegram servers to distribute the answer to the chat.

Static version

Cloud-based messaging makes it possible for you to access your chats from different devices. Building on top of the previous concepts, let’s see what happens when you message a bot on Telegram.

Whenever you send a message to a bot, Telegram notifies the webhook URL that an update is available for your bot to handle. Then, your handler processes the user request and sends a response back to Telegram. Ultimately, Telegram delivers your bot answer to the user. Take a look at the GIF below to get the idea:

What happens when you send a message to a Telegram Bot (simplified), step by step.
User <—> bot interaction, static version.

You now get the critical concepts. Let’s dive in. We’ll set up the webhook once we’re ready to deploy our bot handler.

3. Implement your handler

The mission of the handler is to handle incoming Updates from the Telegram API. Remember, every time a user sends your bot a message, the webhook delivers your handler an Update from Telegram.

A Telegram Update can contain different kinds of information: text message, voice message, video, or a document, to name a few. In this article, we’ll see how to process text messages. Feel free to explore other options with audio, video, or a document processing bot!

Since the handler scope is mainly about handling responses and making API requests, the Go programming language is a perfect tool.

The Telegram Update can be an intimating object with all its fields. Fortunately, we can represent it with a simpler struct in Go to address our use case:

A lightweight Telegram Update structure in the Go programming language.

Similarly, we define a Message struct:

A lightweight Telegram Message struct in Go.

And finally a Chat struct:

A lightweight Telegram Chat struct in Go.

With those three structs; Update, Message, and Chat , we’ re ready to process our users’ messages.

You notice the `json:"something"` on the right to each field of the struct. This is to indicate to the JSON decoder how to parse an incoming Telegram Request into the appropriate struct. For instance, `json:"update_id"` in the Update struct tells the JSON decoder to look for a key whose name is update_id and set the matching value to the UpdateId attribute of our Go Update struct.

We can now easily decode an incoming Request containing an Update from Telegram.

Now that we parsed the request, we can access the Message.Text and do some magic. It’s your time to shine here; you can now develop the features that make your bot outstanding.

Below is an example from the RapGeniusBot, a bot that generates rap music lyrics based on the Message.Text of the incoming Update. The primary function of my handler is :

For the implementation details of each function, the complete code for RapGeniusBot is available on my repository.

Ok, now that you did some processing based on the value of the Message, you are ready to send a Message back to the Chat. Let’s zoom on the sendTextToTelegramChat function to see how we can do this:

Focus on lines 5 to 10. Here, we send our message to the chat by making a POST request to the explicit /sendMessage endpoint of the Telegram API. To do this, you need to authenticate using the bot token the BotFather gave you during your bot creation.

Let’s recap; you now have a handler function that does all the processing,

  1. Your handler decodes incoming Telegram requests,
  2. Your handler can access the fields of the Update, like the Message.Text to perform some transformation, like generating rap music lyrics in the example of the RapGeniusBot.
  3. Your handler ultimately POSTs a message back to the chat that initiated the conversation.

Now is an excellent time to add some tests to ensure your handler works as expected. For instance, we can test that our handler correctly parses incoming Telegram requests. This is fairly easy using the net/http/httpest package in Go. Let’s write our test in a separate test file, for exampleparse_update_test.go .

run go test in the test file folder to run the test

Want to write more tests to ensure everything works as expected? Telegram does an fantastic job by providing developers with sample update JSON to use for our test cases, make sure to check them out on their documentation to build a robust handler.

Nice! All this code lives beautifully on our machine. Let’s now deploy the handler and make your bot available on Telegram.
Don’t worry; you’re already 95% done by now. 😉

4. Deploy your handler

Two possibilities,

  1. You have your own server, and you know how to set up your handler to listen to a given port. You also are comfortable with setting up certificates.
  2. You’re not that much into SysAdmin.

If you recognize yourself in 1., Telegram offers detailed documentation on how to set up your webhook.

I’ll focus on option 2. We’ll use a cloud provider to deploy our handler as function-as-a-service, meaning you’re billed only when your handler actually uses resources. Given the nature of the webhook push mechanism, you’ re not charged if your bot is not used, which is nice compared to an always-on server. The disadvantage is a potential higher response time. When the handler is called for the first time in a while, the cold start can take a few seconds.

All major cloud providers provide function-as-a-service: Cloud Function on Google Cloud, AWS Lambda, and Azure Function on MS Azure.
Pick your weapon of choice. I continue with Google’s Cloud Function.

On Google Cloud console, first, select a project (create one if you’re new to Google Cloud). Then, click on the top left burger menu and find the Cloud Function.

Find the Cloud function in the compute section.

Then, click on the “Create Function” button.

Now let’s complete some config information;

  • Name — set an explicit name for your function, e.g., telegram-bot-handler.
  • Memory allocated — I advise you experiment starting from the smallest value 128 MiB should be enough. Go is not memory hungry, especially if you only make a few requests in your handler or some simple string processing. Plus, it’s likely your handler is only a middle-man passing the query to an other service. In the example of RapGeniusBot, my handler calls another API to get the music lyrics based on the text of the message to process.
  • Trigger — make sure to select HTTP.
  • Authentication — Check the “Allow unauthenticated invocations”. This will make it possible for Telegram to send Update to your handler through the webhook.

Scroll some more, and you can submit the source code to execute upon your function invocation;

  • Source code — Select “Inline editor”
  • Runtime —Select the runtime matching your Go code.
  • Function.go — Copy all your handler code (don’t forget the imports) and paste it within the Function.go text box.
  • Function to execute — Write the function that google servers should call when your cloud function is invoked. Here it is your handler, e.g., HandleTelegramWebHook.

Now click on “Environment variables, networking, timeouts and more”.

A bunch of options appears, adjust Region and Timeout to match any requirements you may have.

  • Ingress settings — Make sure to check “Allow all traffic” so that Telegram servers can access your handler.

Last but not least, set the environment variable your code needs. You need, at least, to set the TELEGRAM_BOT_TOKEN the BotFather gave you in part 1.

Click “create”. Your cloud function is ready in a few seconds.

Now navigate to the “Trigger” tab of your newly created Cloud function and copy the URL for your function invocation. We will tell Telegram to send Updates to this URL when defining the webhook in the next step.

That’s it; you’re done with your cloud provider! The only thing left to do is to set up the webhook URL of your Telegram Bot.

5. Set a webhook using the Telegram API

Final step!

Now that we created our cloud function, we need to register its URL as the webhook URL to Telegram. Like this, Telegram can push Updates for our bot to the URL on which our handler is listening.

That’s 3 lines in your shell.

You get a nice {“ok”:true,”result”:true,”description”:”Webhook was set”} as response from the Telegram API.

6. Enjoy

Congrats, your bot is now live! 🔥👏

Chat with it in Telegram and share it with your friends. By this point, you built an amazing Telegram Bot. Drop a comment about your bot; I can’t wait to see the exciting stuff you developed!

Resources

Tools I used to write this post:

  • carbon.now.sh for the code snippet
  • MS Powerpoint for the animated GIF creation

--

--

François Paupier
The Startup

Machine Learning — Data pipeline — Software Engineering