Telegram bot for organizing customer support via topic threads. Add it to a group with Topics mode enabled — each user gets a dedicated thread for a two-way dialogue.
- One thread per user — first message creates a forum topic, all subsequent messages go to the same thread
- Bidirectional relay — messages from users are forwarded to the thread, replies from agents are sent back to the user
- Anonymous agents — uses
CopyMessageso users only see messages from the bot, not the agent's profile - Full media support — text, photos, videos, documents, stickers, voice, video notes, animations, audio, contacts, locations
- Thread lifecycle — auto-reopen closed threads when user or agent writes, detect deleted threads and recreate
- Multilingual messages — all bot messages configured in
messages.ymlwith language resolution based on user's Telegram language - Quick replies — canned response templates for agents via inline mode (
@botnamein a thread) - User blocked detection — notifies agents when a user has blocked the bot
- Info cards — configurable pinned user info card in each thread with template macros
- SQLite storage — persists users and relayed messages for audit and continuity
- Go 1.21+
- A Telegram bot token from @BotFather
- A Telegram group with Topics (Forum) mode enabled
- The bot added to the group as an administrator with "Manage Topics" permission
To enable quick replies for agents, turn on Inline Mode in @BotFather:
- Open @BotFather →
/setinline - Select your bot
- Set a placeholder (e.g.
Quick reply...)
git clone https://github.com/dortanes/tg-support-bot.git
cd tg-support-bot
go mod tidyCopy the example env file and fill in the values:
cp .env.example .env| Variable | Description |
|---|---|
BOT_TOKEN |
Bot token from @BotFather |
CHAT_ID |
ID of the support group chat (with topics) |
make runOr build and run the binary:
make build
./bin/botcp .env.example .env # fill in BOT_TOKEN and CHAT_ID
docker compose up -dAll bot messages are configured in messages.yml. Each message supports multiple languages, resolved by the user's Telegram language_code. If not found, falls back to en, then to the first available language.
HTML parse mode is enabled — you can use <b>, <i>, <code>, <tg-emoji>, etc.
| Key | Description |
|---|---|
welcome_message |
Sent when user sends /start |
wait_message |
Sent when user writes to a reopened (closed) thread |
close_message |
Sent when support agent closes the thread |
user_blocked_message |
Posted in thread when user has blocked the bot |
info_card |
Pinned user info card (supports macros) |
quick_replies |
Canned responses for agents via inline mode |
The info_card template supports these placeholders:
| Macro | Value |
|---|---|
{{id}} |
Telegram user ID |
{{username}} |
Username (no @) |
{{first_name}} |
First name |
{{language}} |
Language code |
quick_replies:
- title: "👋 Greeting"
text: "Hello! How can I help you?"
- title: "⏳ Please wait"
text: "Please wait, we are checking the information."Agents type @botname in a thread to see the list. Only members of the support group can access quick replies.
.
├── cmd/bot/main.go # Entrypoint
├── internal/
│ ├── config/config.go # Env loading
│ ├── database/database.go # GORM + SQLite init
│ ├── models/ # User, Message models
│ ├── bot/bot.go # Bot setup
│ ├── handler/handler.go # Message routing & relay
│ └── messages/messages.go # YAML message loader
├── messages.yml # Message templates
├── .env.example
├── Makefile
└── README.md
MIT