Bot Service
Bingo Bot is a multi-platform bot service supporting Telegram and Discord, providing service management, notification delivery, and channel subscription features.
Core Features
- Multi-Platform Support - Telegram and Discord
- Service Management - Health checks, version queries, maintenance mode
- Notification Subscription - Channel subscription management and system notifications
- Unified Interface - Shared business logic and data storage across platforms
Supported Platforms
Telegram
Built on telebot.v3:
- Bot command interactions
- Channel message broadcasting
- Group management
Discord
Built on discordgo:
- Slash Commands
- Channel message broadcasting
- Server management
Quick Start
1. Create Bot
Telegram Bot
- Find @BotFather in Telegram
- Send
/newbotto create a new bot - Follow prompts to set bot name and username
- Get Bot Token (keep it secure and never expose it publicly)
Discord Bot
- Visit Discord Developer Portal
- Click "New Application"
- Go to "Bot" tab, click "Add Bot"
- Get Bot Token from "TOKEN" section
- Enable necessary Intents (e.g., Message Content Intent)
2. Configuration
Create bingo-bot.yaml:
yaml
# Bot server
server:
name: bingo-bot
mode: release
addr: :18080
timezone: Asia/Shanghai
key: your-secret-key
# Bot configuration
bot:
telegram: "YOUR_TELEGRAM_BOT_TOKEN"
discord: "YOUR_DISCORD_BOT_TOKEN"
# MySQL configuration
mysql:
host: mysql:3306
username: root
password: root
database: bingo
maxIdleConnections: 100
maxOpenConnections: 100
maxConnectionLifeTime: 10s
logLevel: 4
# Redis configuration
redis:
host: redis:6379
password: ""
database: 1
# JWT configuration
jwt:
secretKey: your-jwt-secret-key
ttl: 1440 # Token expiration (minutes)
# Logging
log:
level: info
days: 7
format: console
console: true
maxSize: 100
compress: true
path: storage/log/bot.log
feature:
profiling: true
# Mail service
mail:
host: "smtp.example.com"
port: 465
username: "[email protected]"
password: "your-password"
fromAddr: "[email protected]"
fromName: "Bingo Bot"
# Verification code
code:
length: 6
ttl: 5 # Expiration (minutes)
waiting: 1 # Resend wait time (minutes)⚠️ Security Warning:
- Replace
YOUR_TELEGRAM_BOT_TOKENandYOUR_DISCORD_BOT_TOKENwith your actual tokens from BotFather and Discord Developer Portal - Never commit configuration files containing real tokens to Git repositories or share them publicly
- Consider using environment variables or secret management services to store tokens
- If a token is leaked, regenerate it immediately on the respective platform
3. Start Service
bash
# Use default configuration
./bingo-bot
# Specify configuration file
./bingo-bot -c /path/to/bingo-bot.yaml4. Add Bot to Channel
Telegram
- Add bot to group or channel
- Grant necessary permissions (send messages, manage messages, etc.)
Discord
- In Developer Portal, go to "OAuth2" > "URL Generator":
- Scopes:
bot,applications.commands - Select required Bot Permissions
- Scopes:
- Copy generated URL and open in browser
- Select server and authorize
Available Commands
Service Management
| Command | Description | Example |
|---|---|---|
/ping or /pong | Health check | /ping → pong |
/healthz | Service status | /healthz → ok |
/version | View version | /version → v1.0.0 |
/maintenance | Toggle maintenance | /maintenance → Operation success |
Subscription Management
| Command | Description | Example |
|---|---|---|
/subscribe | Subscribe to notifications | /subscribe → Successfully subscribe |
/unsubscribe | Unsubscribe | /unsubscribe → Successfully unsubscribe |
Usage Examples
Telegram Bot
User: /ping
Bot: pong
User: /subscribe
Bot: Successfully subscribe, enjoy it!Discord Bot (Slash Commands)
/ping
Bot: pong
/subscribe
Bot: Successfully subscribe, enjoy it!Notification System
Bot service supports pushing system notifications to subscribed channels.
Database Schema
Subscription data is stored in bot_channels table:
sql
CREATE TABLE `bot_channels` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`source` varchar(20) NOT NULL COMMENT 'Platform: telegram, discord',
`channel_id` varchar(100) NOT NULL COMMENT 'Channel ID',
`author` text COMMENT 'Subscriber info (JSON)',
`status` tinyint NOT NULL DEFAULT '1' COMMENT 'Status: 1-enabled, 0-disabled',
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_source_channel` (`source`, `channel_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;Send Notifications
Trigger notifications from other services:
go
import (
"bingo/internal/pkg/store"
"bingo/internal/pkg/model/bot"
)
// Get all subscribed channels
channels, err := store.S.Channels().List(ctx, &bot.ListChannelsOptions{
Status: bot.StatusEnabled,
})
// Send message to each channel
for _, channel := range channels {
sendMessage(channel.Source, channel.ChannelID, "System notification: Service updated")
}Architecture
Layered Design
┌─────────────────────────────────────┐
│ Platform Layer (Telegram/Discord) │ ← Platform adapters
├─────────────────────────────────────┤
│ Controller Layer │ ← Controllers
├─────────────────────────────────────┤
│ Business Logic (Biz) │ ← Business logic
├─────────────────────────────────────┤
│ Data Access (Store) │ ← Data access
└─────────────────────────────────────┘Code Structure
internal/bot/
├── biz/ # Business logic
│ ├── bot/
│ └── syscfg/
├── telegram/ # Telegram platform
│ ├── controller/
│ ├── middleware/
│ ├── router.go
│ └── run.go
├── discord/ # Discord platform
│ ├── controller/
│ ├── middleware/
│ ├── client/
│ ├── router.go
│ └── run.go
├── app.go
└── run.goAdvanced Features
Custom Commands
1. Add Command Handler
go
// internal/bot/telegram/controller/v1/custom/custom.go
package custom
import "gopkg.in/telebot.v3"
type CustomController struct {
// ...
}
func (ctrl *CustomController) Hello(c telebot.Context) error {
return c.Send("Hello, " + c.Sender().FirstName + "!")
}2. Register Route
go
// internal/bot/telegram/router.go
func RegisterRouter(b *telebot.Bot) {
customCtrl := custom.New(store.S)
b.Handle("/hello", customCtrl.Hello)
}Middleware
go
// Logging middleware
func Logger(next telebot.HandlerFunc) telebot.HandlerFunc {
return func(c telebot.Context) error {
start := time.Now()
err := next(c)
log.Infof("Command: %s, User: %s, Duration: %v",
c.Text(), c.Sender().Username, time.Since(start))
return err
}
}
// Register middleware
b.Use(Logger)Permission Control
go
// Admin-only middleware
func AdminOnly(next telebot.HandlerFunc) telebot.HandlerFunc {
return func(c telebot.Context) error {
if !isAdmin(c.Sender().ID) {
return c.Send("Admin only")
}
return next(c)
}
}
// Use permission middleware
b.Handle("/maintenance", ctrl.ToggleMaintenance, AdminOnly)Operations & Monitoring
View Logs
bash
# Real-time logs
tail -f storage/log/bot.log
# Error logs
grep "ERROR" storage/log/bot.logPerformance Profiling
If profiling is enabled:
bash
# Heap memory
curl http://localhost:18080/debug/pprof/heap
# Goroutines
curl http://localhost:18080/debug/pprof/goroutine
# CPU profile (30s)
curl http://localhost:18080/debug/pprof/profile?seconds=30 > cpu.profCommon Issues
1. Bot Not Responding
Check:
- Bot Token correctness
- Network connectivity
- Bot added to channel
- Sufficient permissions
2. Subscription Failed
Possible Causes:
- Database connection failure
- Duplicate channel ID
- Insufficient permissions
3. Message Send Failed
Check:
- Bot in channel
- Sufficient permissions
- Correct channel ID
- Rate limits (Telegram: 30 msg/sec, Discord: 5 req/sec)
Best Practices
1. Error Handling
go
func (ctrl *ServerController) SomeCommand(c telebot.Context) error {
result, err := ctrl.b.DoSomething(ctx)
if err != nil {
log.Errorf("Operation failed: %v", err)
return c.Send("Operation failed, please try again")
}
return c.Send(fmt.Sprintf("Success: %s", result))
}2. Message Formatting
go
// Telegram supports Markdown and HTML
func (ctrl *ServerController) Status(c telebot.Context) error {
message := `
*Service Status*
━━━━━━━━━━━━
🟢 API Server: Running
🟢 Scheduler: Running
🟡 Bot: Maintenance
━━━━━━━━━━━━
Updated: %s
`
return c.Send(fmt.Sprintf(message, time.Now().Format("15:04:05")),
&telebot.SendOptions{ParseMode: telebot.ModeMarkdown})
}3. Rate Limiting
go
// Prevent abuse
var limiter = rate.NewLimiter(rate.Every(time.Second), 10)
func (ctrl *ServerController) RateLimitedCommand(c telebot.Context) error {
if !limiter.Allow() {
return c.Send("Too many requests, please try again later")
}
// Process command
return nil
}4. Scheduler Integration
Send scheduled notifications:
go
// Define task in Scheduler
func SendDailyReport(ctx context.Context, t *asynq.Task) error {
report := generateReport()
channels, _ := store.S.Channels().List(ctx, nil)
for _, ch := range channels {
sendNotification(ch, report)
}
return nil
}Security
1. Token Protection
yaml
# Don't hardcode tokens
# Use environment variables or config files
bot:
telegram: ${TELEGRAM_BOT_TOKEN}
discord: ${DISCORD_BOT_TOKEN}2. Minimal Permissions
- Grant only necessary permissions
- Regular permission audits
- Use admin whitelist
3. Input Validation
go
func (ctrl *ServerController) ProcessInput(c telebot.Context) error {
input := c.Text()
if len(input) > 1000 {
return c.Send("Input too long")
}
input = sanitize(input)
// Process input
return nil
}Integration with Other Services
Call API Server
go
import "bingo/internal/apiserver/biz"
func (ctrl *ServerController) GetUserInfo(c telebot.Context) error {
user, err := store.S.Users().Get(ctx, userID)
if err != nil {
return c.Send("User not found")
}
return c.Send(fmt.Sprintf("User: %s", user.Username))
}Send Email
go
import "bingo/internal/pkg/mail"
func (ctrl *ServerController) SendReport(c telebot.Context) error {
report := generateReport()
err := mail.Send(mail.Message{
To: []string{"[email protected]"},
Subject: "Bot Report",
Body: report,
})
if err != nil {
return c.Send("Failed to send")
}
return c.Send("Report sent")
}Related Resources
Next Step
- Core Components Overview - Learn about the framework's core components