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
main
branch 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_AUTHTOKEN
variable in.env
file in the project root directory - Claim a free ngrok domain and save it to
NGROK_DOMAIN
variable in.env
file in the project root directory - Copy Telegram Bot token and save it to
TELEGRAM_BOT_TOKEN
variable in.env
file in the project root directory - Copy Telegram Payments token and save it to
TELEGRAM_PAYMENTS_TOKEN
variable in.env
file in the project root directory - Generate random string for JWT signing secret and save it to
JWT_SECRET
variable in.env
file in the project root directory - Install Docker
To start or update the environment with the latest code changes, use:
docker compose up --build -d
After 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_ID
GitHub variable - Pick a region for your app and save it to
GCP_PROJECT_REGION
GitHub 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_EMAIL
GitHub variable - Export the service account key and save it to
GCP_SA_KEY
GitHub 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_REGION
region - Copy Artifact Registry name and save it to
GCP_ARTIFACT_REGISTRY
GitHub variable - Create a PostgreSQL Cloud SQL instance in
GCP_PROJECT_REGION
region- 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_NAME
GitHub 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_REGION
region - 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_TOKEN
GitHub variable - Telegram Payments token and save the secret name to
GCP_SECRET_TG_PAYMENTS_TOKEN
GitHub variable - Random string for JWT signing secret and save the secret name to
GCP_SECRET_JWT_SECRET
GitHub variable - PostgreSQL connection string and save the secret name to
GCP_SECRET_DB_URL
GitHub 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_URL
GitHub 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_NAME
with the desired name of DB migration Cloud Run jobGCP_SERVICE_UI_NAME
with the desired name of UI Cloud Run instanceGCP_SERVICE_UI_MAX_INSTANCES
with the desired maximum number of UI service instancesGCP_SERVICE_API_NAME
with the desired name of API Cloud Run instanceGCP_SERVICE_API_MAX_INSTANCES
with 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.
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}/bot
In 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
config
table withkey
equal toTICKET_CURRENCY
andvalue
equal to the ticket price currency code - Create a row in
config
table withkey
equal toTICKET_PRICE
andvalue
equal 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
objects
table- Set
code
to the value of Code
- Set
- Create a new row in the
objects_i18n
table- For each language (at least data for
en
language must be provided):- Set
object_id
to the id of the row created in the previous step - Set
language
to language code in ISO 639-1 format - Set
title
to the value of Title in the specified language - Set
audio_path
to 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
covers
table for each uploaded file from Covers collection- Set
object_id
to the id of the row created in the previous step - Set
index
to the number indicating the order in which the picture will be displayed - Set
path
to 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.