Host Telegram bot in Node.js in Google Cloud Run

Nick Filat
4 min readJun 7, 2023

--

I was thinking of automating some routine tasks using a Telegram bot. For those, who are not familiar, it is kind of one more messenger, but with some additional features like bot functionality.

It is possible to create a bot to resolve some tasks in a chat manner.

So, the task itself was quite simple; I needed to create a payment link in Venmo (a payment system), based on a message in a group chat from a specific user who requests money after some event (in our case, it was for volleyball field rent payment).

I won’t describe how to register new Telegram bot using BotFather and get bot token for it, there are a lot of resources provided to do that.

So, as I said, the bot just checks if the message is forwarded from a specific user, and, if so, create Venmo link to pay this user amount of money extracted from the message and a comment containing current user name/username.

I used node-telegram-bot-api to create the bot itself and use Telegram API. It is quite straightforward, how to do that and explained very well on its GitHub page. My code with the bot is here:

The problem I want to explain in this post is the hosting of this bot.

Host locally

For the purposes of testing and debugging you can host on your local machine. To do that just launch node application and all the rest will do Telegram API:

nodemon node index.js

At the beginning, when I just started to develop it, I thought that hosting wasn’t a developer’s problem. I mistakenly considered that it uploads a build somewhere to Telegram environment and hosts there without any cost and efforts from my side. I was wrong and each time my laptop has gone to sleep, the bot lied down.

So, the problem of hosting arose unexpectedly. I decided to use Cloud Run service of Google Cloud Platform as it gives some free quota.

Create Cloud Run project

I won’t describe how to create GCP account, there are enough resources about that too. After the GCP account is created, new Cloud Run project for the bot should be created:

  • in GCP dashboard go to Cloud Run
  • Click on ‘Create Service’
  • Set the next values:

1. Deploy one revision from an existing container image

2. Service name and Region

3. CPU is only allocated during request processing

4. Autoscaling — 1 container as minimum and 1 as a maximum

5. Allow direct access to your service from the internet

6. Allow unauthenticated invocations for Authentification

7. Create

It’s worth explaining why both the minimum and maximum containers are set to 1. The minimum is 1 is because the the problem of “Scaling to Zero”. It means, that Google Cloud Run automatically scales down to zero instances when there is no incoming traffic. This is a cost-saving feature, but it could cause issues for applications that are supposed to be long-running, like a Telegram bot. Our bot is designed to constantly listen for new updates, but there are no instances running, then it would be unable to receive those updates.

The maximum is set to 1 because the Telegram API can’t use concurrent apps to process bot requests.

Dockerize

To host our bot in Cloud Run we have to containerize our app, so let’s create simple Dockerfile for that:

FROM node:14
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD [ "node", "index.js" ]

Pass Google Cloud Run Health Checks

There is a standard procedure that Google Cloud Run services are pinged by health checks after they launched. We don’t have any public endpoint to be called by them, so the service will be considered unhealthy and shut down by GCP runtime in a while. To avoid this problem, we need to add “fake” express 8080 port listener just to respond on health check calls.

import express from 'express'
const app = express()
const port = 8080

app.listen(port, () => {
console.log(`Server started on port ${port}`);
})

Telegram anti-spam requirements

You have to consider that there is a requirement in Telegram that your bot can’t initiate any messages to any user till this user starts a conversation with this bot. Likely, this was done to avoid bots spamming all users in Telegram. So, remember, user has to write something to the bot (even something not meaningful) first and later bot can send messages to this user without any barriers. It is necessary to initiate this conversation just once to receive all subsequent messages from the bot.

Deploy bot to Cloud Run

Just run ‘gcloud run deploy’ (make sure to install it first) to deploy the container to Cloud Run:

gcloud run deploy --max-instances 1 --min-instances 1 --set-env-vars BOT_TOKEN=*****

It is more secure to store the BOT_TOKEN in Secret Manager, but for our purposes, it will be an environment variable.

And the bot works.

Resources

Code — https://github.com/GydroCasper/voleyballHelperBot

--

--