Telegram bot for taking audio tours, built on top of Telegram Mini App Template.
Guide is available at @audio_guide_bot.
Bot supports only mobile Telegram clients with Telegram Bot API version of at least 6.9.
Payments are working in test mode. Transactions must be made using test cards like 4242 4242 4242 4242, other cards can be found in payments provider docs.
QR codes for the bot can be found in /admin/test-data.
- Integration with Telegram Payments - Guide Bot tickets can be bought directly in Telegram
- Integration with Telegram CloudStorage - after activation, the user's ticket is available to all user devices
- UI delivered as Telegram Mini App - no need for a standalone application, Guide Bot is available as a part of Telegram bot
- Adaptive UI - Guide Bot will automatically pick up the user's color theme and adapt the size to both expanded and minimized modes
- Local environment with docker-compose- spin-up bot environment locally in one command
- Continious deliviery to Google Cloud Platform - all changes to the
mainbranch are automatically delivered to the production
- Complete setup prerequisites
- Start the bot locally or deploy it to the production
- Configure bot and enter data about your objects
- Message your bot, buy a ticket, scan the code, and start listening
Telegram Bot token is required to interact with Telegram Bot API. To get one, сreate a bot using @BotFather or follow Telegram bot instructions.
Telegram Payments token is required to start accepting payments for tickets. To get one, request it from @BotFather or follow Telegram payments instructions.
This repository provides an easy-to-use local development environment. Using it you can start writing your bot business logic without spending time on the environment.
Local environment includes:
- ngrok reverse proxy to server local mini-app and bot deployment over HTTPS
- nginx reverse proxy to host both API and UI on one ngrok domain and thus fit into the free plan
- React fast refresh to avoid rebuilding docker container on each change of the UI code
- PostgreSQL database instance and pgAdmin instance to manage it
- s3gw S3 instance and s3gw-ui instance to manage it
Local environment setup:
- Create an account on ngrok
- Get a ngrok auth token and save it to
NGROK_AUTHTOKENvariable in.envfile in the project root directory - Claim a free ngrok domain and save it to
NGROK_DOMAINvariable in.envfile in the project root directory - Copy Telegram Bot token and save it to
TELEGRAM_BOT_TOKENvariable in.envfile in the project root directory - Copy Telegram Payments token and save it to
TELEGRAM_PAYMENTS_TOKENvariable in.envfile in the project root directory - Generate random string for JWT signing secret and save it to
JWT_SECRETvariable in.envfile in the project root directory - Install Docker
To start or update the environment with the latest code changes, use:
docker compose up --build -dAfter successful deployment, your local bot API will be available at https://ngrok-domain/api. Use this URL to set the bot webhook as described switching bot environment.
This repository provides a workflow to automatically deploy the code to Google Cloud Platform. The deploy job is triggered on each push to the main branch.
GCP services used for deployment:
- Cloud Run to host dockerized API and UI code
- Artifact Registry to store docker images
- Secret Manager to store sensitive data
- Cloud SQL to host a relational database
- Cloud Storage to store binary data
Deployment setup:
- Create a project in GCP
- Copy project ID and save it to
GCP_PROJECT_IDGitHub variable - Pick a region for your app and save it to
GCP_PROJECT_REGIONGitHub variable - Create a service account with the following rights:
- Service Account User (to create resources by the name of this account)
- Cloud Run Admin (to create Cloud Run instances)
- Artifact Registry Administrator (to manage images in the registry)
- Secret Manager Secret Accessor (to access GCP secrets)
- Cloud SQL Client (to connect to the Cloud SQL instance)
- Storage Object User (to access objects in Cloud Storage bucket)
- Copy the service account email and save it to
GCP_SA_EMAILGitHub variable - Export the service account key and save it to
GCP_SA_KEYGitHub secret - Enable the following GCP APIs:
- Cloud Run Admin API (to create Cloud Run instances)
- Secret Manager API (to securely store secrets)
- Compute Engine API (to create Cloud SQL instances)
- Cloud SQL Admin API (to connect Cloud Run to Cloud SQL)
- Create Artifact Registry for Docker images in
GCP_PROJECT_REGIONregion - Copy Artifact Registry name and save it to
GCP_ARTIFACT_REGISTRYGitHub variable - Create a PostgreSQL Cloud SQL instance in
GCP_PROJECT_REGIONregion- If you want to reduce the cost of the instance:
- You can implement instance scheduler
- You can set "Zonal availability" to "Single zone" instead of "Multiple zones (Highly available)"
- You can set the machine configuration to the minimal one (1 shared vCPU, 0.614 GB RAM)
- You can set the storage type to HDD
- You can reduce storage size to 10 GB
- If you want to reduce the cost of the instance:
- Copy Cloud SQL instance connection name, that can be found on the Overview page for your instance, and save it to
GCP_SQL_INSTANCE_CONNECTION_NAMEGitHub variable - Create a user for your Cloud SQL instance
- Create a database for your Cloud SQL instance
- Create a Cloud Storage bucket in
GCP_PROJECT_REGIONregion - Create an HMAC key for your service account
- Create the following secrets in Secret Manager:
- Telegram Bot token and save the secret name to
GCP_SECRET_TG_BOT_TOKENGitHub variable - Telegram Payments token and save the secret name to
GCP_SECRET_TG_PAYMENTS_TOKENGitHub variable - Random string for JWT signing secret and save the secret name to
GCP_SECRET_JWT_SECRETGitHub variable - PostgreSQL connection string and save the secret name to
GCP_SECRET_DB_URLGitHub variable- Connection string format is
postgres://{USER}:{PASSWORD}@/{DATABASE}?host={HOST}, where:{USER}is the name of the user created for Cloud SQL instance above{PASSWORD}is the password of the user created for Cloud SQL instance above{HOST}is the/cloudsql/{INSTANCE_CONNECTION_NAME}, where{INSTANCE_CONNECTION_NAME}is the Cloud SQL instance connection name, that is equal toGCP_SQL_INSTANCE_CONNECTION_NAME{DATABASE}is the name of the database created for Cloud SQL instance above
- Connection string format is
- Cloud Storage connection string and save the secret name to
GCP_SECRET_S3_URLGitHub variable- Connection string format is
https://{KEY}:{SECRET}@storage.googleapis.com/{BUCKET}, where:{KEY}is the key of the service account HMAC key created above{SECRET}is the secret of the service account HMAC key created above{BUCKET}is the name of the bucket created in the Cloud Storage above
- Connection string format is
- Telegram Bot token and save the secret name to
- Define the following GitHub variables:
GCP_SERVICE_MIGRATOR_NAMEwith the desired name of DB migration Cloud Run jobGCP_SERVICE_UI_NAMEwith the desired name of UI Cloud Run instanceGCP_SERVICE_UI_MAX_INSTANCESwith the desired maximum number of UI service instancesGCP_SERVICE_API_NAMEwith the desired name of API Cloud Run instanceGCP_SERVICE_API_MAX_INSTANCESwith the desired maximum number of API service instances
After successful deployment, obtain the bot API URL from either deploy-services job results or from GCP Project Console and proceed to switching bot environment.
Alternatively, to fit within the GCP free tier, you can deploy PostgreSQL on an e2-micro Compute Engine VM and connect Cloud Run services using Direct VPC. However, because a self-managed PostgreSQL instance requires additional configuration and operational oversight, this approach is not covered in this instruction.
After the bot is either launched locally or deployed in GCP, Telegram needs to be configured with a proper webhook URL. To set it, use:
curl https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/setWebhook?url=${BOT_API_URL}/botIn the case of local environment, pgAdmin for DB management and s3gw-ui for S3 management are already running as containers. Discover their addresses in your docker daemon.
In case of production deployment, S3 management is available from GCP Project Console, but for DB management you need to setup an instance of pgAdmin with cloud-sql-proxy to connect to your Cloud SQL instance. Instructions are available in /admin.
To configure the Guide Bot you need:
- Connect to the DB using DB management tool
- Create a row in
configtable withkeyequal toTICKET_CURRENCYandvalueequal to the ticket price currency code - Create a row in
configtable withkeyequal toTICKET_PRICEandvalueequal to the ticket price in the smallest units of the currency
To create an object in the Guide Bot you need:
- Prepare the data
- Title: string that will be displayed as a title of the object. It must not exceed 64 characters. Title string can be added in different languanges to provide translations for users.
- Code: string that will be encoded in a QR code to access your object
- Covers: collection of image files that will be displayed while listening to the Guide. Amount of covers is not limited. Cover image can be any size but will be cropped to 1:1 proportions to fit in the UI. Also, keep in mind that a large size slows down the loading of the object.
- Audio: audio file that will be played when viewing the object. It can be any size, but keep in mind that a large size slows down the loading of the object. Audio file can be added in different languanges to provide translations for users.
- Connect to the S3 bucket using S3 management tool
- Upload Covers and Audio to the bucket and save paths to the uploaded files. Make sure to include the original file extension in the file name otherwise, some clients will not be able to play audio tracks.
- Connect to the DB using DB management tool
- Create a new row in the
objectstable- Set
codeto the value of Code
- Set
- Create a new row in the
objects_i18ntable- For each language (at least data for
enlanguage must be provided):- Set
object_idto the id of the row created in the previous step - Set
languageto language code in ISO 639-1 format - Set
titleto the value of Title in the specified language - Set
audio_pathto the path of the uploaded file Audio in the specified language
- Set
- For each language (at least data for
- Create a new row in the
coverstable for each uploaded file from Covers collection- Set
object_idto the id of the row created in the previous step - Set
indexto the number indicating the order in which the picture will be displayed - Set
pathto the path of the uploaded file from Covers collection
- Set
- Encode Code to the QR Code to access your object from the Guide Bot
For testing purposes you also can use files from /admin/test-data.
Project is built of 4 parts:
- API Service - implements integration with Telegram API and Guide business logic
- UI Service - user interface in the format of Telegram MiniApp
- Database - stores entity data such as tickets or objects
- Blob storage - stores binary files such as object images or audio tracks
Project design:
- Base project entity is called Object - any point of interest that will be available in the system
- All objects include:
- Title - name of the object
- Code - unique text data that is used for object identification
- Covers - array of images associated with the object
- Audio - audio track associated with the object
- Access to the objects is provided by scanning QR codes with encoded object code
- Access to the objects is limited by token-based authorization
- Token validity is limited by the expiration date
- Token must be persisted until it becomes invalid
- Token can be acquired by activating a separate entity - Ticket
- Ticket includes:
- Code - unique text data that is used for ticket identification
- Activation flag - once set to true, cannot be activated anymore
- Ticket can be bought via Telegram Payments
- Project root directory - contains files for local environment
- docker-compose.yml - docker-compose file to setup local environment
- proxy.template - nginx config template to route ngrok domain to API and UI containers
- api - contains files for the bot backend written in Go, check the README file for details
- ui - contains files for the mini app UI written in JS with React, check the README file for details
- admin - contains files for production administration environment, check the README file for details
- Docker
- Go
- React
- Vite
- PostgreSQL
- Fiber
- gotgbot
- minio-go
- migrate
- jwt-go
- go-i18n
- axios
- i18n-js
- s3gw
- s3gw-ui
- pgAdmin
- nginx
- ngrok
Distributed under the MIT License. See LICENSE for more information.
Want a new feature added? Found a bug? Go ahead and open a new issue or feel free to submit a pull request.


