Writing Telegram bots from command line
Tags: telegram, bot, curl, shel
Published: 2022-09-13 15:49:05

Telegram is a fantastic messaging service. It suits social communications well, but it can also be used nicely in different automation scenarios, for example, in DevOps.

Enter Telegram bots. These are special Telegram accounts, which are usually used programmatically. Software controls the behaviour of such accounts, allowing them to communicate with other Telegram accounts (individuals, groups or channels).

The article below will show how to start using Telegram bots programmatically. To begin with, you need only one tool from your command line environment. It is [curl](https://curl.se/).

Other tools are available for similar purposes, for example, [HTTPie](https://httpie.io/cli). Technically, you can match `curl` syntax to `HTTPie` almost one-to-one. Still, I will be using `curl`, because it is standard and available by default in the majority and UNIX-based environments and macOS. On Windows, you may need to install it separately. It would be best if you also were careful with double quotes and the syntax of the environment variables substitution in the commands below because `cmd` or `PowerShell` interpret them differently.

First, you must create a Telegram if you don't have one. It takes less than a minute. Go to your Telegram client on any platform, find the [@BotFather](https://t.me/BotFather) and open the chat with it. `@BotFather` is the bot provided by Telegram, and it is used to create and manage all other bots.

Type `/newbots`, follow simple steps and create a bot.

![Create bot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7isbux0ezksnsb81zlhw.png)

In the example above, I have created a new bot called `my_supercool_shiny_bot`. By the Telegram rules, the bot names must always end with `bot`. Pick the name accordingly.

Telegram generated the unique token of this bot `5387301065:AAEWZqC49ilJ9Xds93sP7gU_70OdAfIiTSA`.

IMPORTANT NOTE: Please, keep the token of your bot secret. **Never** commit it to public repos, and always pass it as the parameter to your code, for example, via an environment variable. 

If someone knows your bot's token, they can communicate with Telegram on behalf of your bot, and you will have to revoke the token and regenerate it.

Don't worry. It is impossible to hack into your main Telegram account via a leaked bot token, but the bot itself will be compromised.

I am using the bot token openly in this article for demonstration purposes, but by the time the article will be published, the bot will be removed, and the token will no longer be valid.

Ok, let's set an environment variable with the bot token first:
```shell
export BOT_TOKEN="5387301065:AAEWZqC49ilJ9Xds93sP7gU_70OdAfIiTSA"
```

Let's start talking to the bot by requesting its details via the `getMe` command:
```shell
curl https://api.telegram.org/bot$BOT_TOKEN/getMe
```
It will respond with:
```json
{
   "ok":true,
   "result":{
      "id":5387301065,
      "is_bot":true,
      "first_name":"my_supercool_shiny_bot",
      "username":"my_supercool_shiny_bot",
      "can_join_groups":true,
      "can_read_all_group_messages":false,
      "supports_inline_queries":false
   }
}
```
We see that the bot responds with details about itself. The main thing here is its Telegram id `5387301065`. This number represents the bot within Telegram API. Also, we see the bot username - `my_supercool_shiny_bot`.

Now let's send a message from the bot to a Telegram user, for example, you. To do that, we need to know your Telegram id (it's not your Telegram username). We can find it out if you don't remember it.

In your Telegram GUI client find our new bot via search by its name.

![Search](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/odgp3dn4mhtdoubuz5uh.png)

In my case, it is `my_supercool_shiny_bot`. Initiate the chat with the bot by pressing the `Start` button.

![Start](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t17wt88r1j65qt6kx3r0.png)

Let's now send a message from you to the bot. Type, for example, "TEST" in the chat and send it.

![Send](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ssg3s0nuphrdpkjwtd4m.png)

Now, let's receive that message in the bot via the `getUpdates` command:

```shell
curl "https://api.telegram.org/bot$BOT_TOKEN/getUpdates"
```
The response would be:
```json
{
   "ok":true,
   "result":[
      {
         "update_id":754613580,
         "message":{
            "message_id":1,
            "from":{
               "id":123456789,
               "is_bot":false,
               "first_name":"FIRSTNAME",
               "last_name":"LASTNAME",
               "username":"USERNAME",
               "language_code":"en"
            },
            "chat":{
               "id":123456789,
               "first_name":"FIRSTNAME",
               "last_name":"LASTNAME",
               "username":"vegoon",
               "type":"private"
            },
            "date":1663079584,
            "text":"/start",
            "entities":[
               {
                  "offset":0,
                  "length":6,
                  "type":"bot_command"
               }
            ]
         }
      },
      {
         "update_id":754613581,
         "message":{
            "message_id":2,
            "from":{
               "id":123456789,
               "is_bot":false,
               "first_name":"FIRSTNAME",
               "last_name":"LASTNAME",
               "username":"USERNAME",
               "language_code":"en"
            },
            "chat":{
               "id":123456789,
               "first_name":"FIRSTNAME",
               "last_name":"LASTNAME",
               "username":"USERNAME",
               "type":"private"
            },
            "date":1663079706,
            "text":"TEST"
         }
      }
   ]
}
```

There two updates from Telegram to the bot. The first message is `/start`. It happened when we initiated the chat with the bot. The second message with `"text":"TEST"` is the text we sent in the GUI client. 

Now the bot sees your message!

Also, there is another essential value in this response - your Telegram user id. It is the `id` field in JSON. In this example - `123456789`. Let's remember it.

Let's send the response back from the bot to you via the `sendMessage` command (replace `123456789` with your Telegram user id):

```shell
curl -X POST \
-H 'Content-Type: application/json' \
-d '{"chat_id": "123456789", "text": "Reply from the bot to your TEST sent via curl"}' \
https://api.telegram.org/bot$BOT_TOKEN/sendMessage
```
The response would be:
```json
{
   "ok":true,
   "result":{
      "message_id":3,
      "from":{
         "id":5387301065,
         "is_bot":true,
         "first_name":"my_supercool_shiny_bot",
         "username":"my_supercool_shiny_bot"
      },
      "chat":{
         "id":123456789,
         "first_name":"FIRSTNAME",
         "last_name":"LASTNAME",
         "username":"USERNAME",
         "type":"private"
      },
      "date":1663080612,
      "text":"Reply from the bot to your TEST sent via curl"
   }
}
```
In the Telegram GUI client, you will see the response:

![Response](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcju3xgdv0kub0u6l8eh.png)

The bot has responded to you!

Reflect on what we have just done for a second. Just in the few commands, we communicated between the bot and you. Now imagine, you can programmatically send updates from your DevOps pipelines or other running services to operators via Telegram! There are lots of different possible use cases.

That's it. 

We only scratched the surface of Telegram bots. For further details, consider the [official Telegram Bot API documentation](https://core.telegram.org/bots/api).

But on the fundamental level, the techniques we looked at in this article can be used for all other functions from the Telegram Bot API.

Final notes.

In this article, we created a bot from scratch. You could also use an existing bot if you know its token.

In this case, when you issued the `getUpdates` command, you might receive an error like:
```json
{
   "ok":false,
   "error_code":409,
   "description":"Conflict: can't use getUpdates method while webhook is active; use deleteWebhook to delete the webhook first"
}
```
It means that some software is already operating the bot via the webhook. You need to delete the webhook first to be able to retrieve the bot updates via the `getUpdates` command directly. I would recommend the check with the bot's owner first that the bot is not used in essential operations, and you can remove the webhook temporarily.

To remove the webhook, use the `deleteWebhook` command.
```shell
curl "https://api.telegram.org/bot$BOT_ID/deleteWebhook"
```
The response for the removal would be:
```json
{
   "ok":true,
   "result":true,
   "description":"Webhook was deleted"
}
```
After that, you can use the `getUpdates` command directly.