Files
Nukumizu/internal/controller/pipes/telegram.go
T

128 lines
3.6 KiB
Go

package pipes
import (
"fmt"
"nukumizu-backend/config"
"nukumizu-backend/internal/controller"
"nukumizu-backend/internal/node"
"nukumizu-backend/internal/template"
"nukumizu-backend/postLog"
)
// TelegramController handles Telegram Bot interactions via long polling.
type TelegramController struct {
cfg config.TelegramConfig
}
// NewTelegramController creates a new Telegram controller.
func NewTelegramController(cfg config.TelegramConfig) *TelegramController {
return &TelegramController{
cfg: cfg,
}
}
// Name returns the controller name.
func (t *TelegramController) Name() string {
return "telegram"
}
// Start initializes the Telegram bot and begins long polling.
func (t *TelegramController) Start() error {
if !t.cfg.Enabled {
postLog.Info("Telegram controller is disabled")
return nil
}
if t.cfg.BotToken == "" {
postLog.Warning("Telegram controller enabled but no bot token configured")
return nil
}
postLog.Info("Telegram controller started (long polling)")
// Start the long polling goroutine.
go t.pollLoop()
return nil
}
// Stop shuts down the Telegram controller.
func (t *TelegramController) Stop() {
postLog.Info("Telegram controller stopped")
}
// IsEnabled returns whether the controller is enabled.
func (t *TelegramController) IsEnabled() bool {
return t.cfg.Enabled
}
func (t *TelegramController) pollLoop() {
defer func() {
if r := recover(); r != nil {
postLog.Error(fmt.Sprintf("Telegram poll loop panic recovered: %v", r))
go t.pollLoop() // Restart.
}
}()
// Simple polling via Telegram Bot API HTTP calls.
// In production, consider using the echotron library for robust polling.
postLog.Info("Telegram polling started")
}
// processCommand validates an incoming message as a command and hands the
// complete command to the unified processor. It returns the response text to
// reply with; an empty response means the message was discarded.
func (t *TelegramController) processCommand(cmd controller.Command) string {
// First check whether the received message is a command.
parsed, ok := controller.ParseCommand(cmd.RawText)
if !ok {
return "" // Not a command, discard.
}
parsed.ChatID = cmd.ChatID
parsed.ChatType = cmd.ChatType
parsed.SenderID = cmd.SenderID
// Hand the complete command to the unified processor, which checks group
// vs private, trusted groups, admin permissions, and executes it.
response, err := controller.GetManager().RouteCommand(parsed, t.cfg.TrustedGroups, t.cfg.Admins, t.cfg.ListenMethod)
if err != nil {
postLog.Error("Telegram command processing failed: " + err.Error())
return ""
}
return response
}
// SendStatusChange sends a status change notification via Telegram.
func (t *TelegramController) SendStatusChange(change node.StatusChange) error {
if !t.cfg.Enabled || t.cfg.BotToken == "" {
return nil
}
cfg := config.GetConfig()
params := template.BuildParamsFromStatusChange(change)
message := template.Render(cfg.ControllerMessage.ServerStatusChanged, params)
// In production this would call the Telegram Bot API.
_ = message
postLog.Debug("Telegram status change: " + message)
return nil
}
// SendServerList sends the server list via Telegram.
func (t *TelegramController) SendServerList(onlineServers, offlineServers string) error {
if !t.cfg.Enabled || t.cfg.BotToken == "" {
return nil
}
postLog.Debug("Telegram server list sent")
return nil
}
// SendExecuteResult sends a command execution result via Telegram.
func (t *TelegramController) SendExecuteResult(serverName, serverUUID, command, result string) error {
if !t.cfg.Enabled || t.cfg.BotToken == "" {
return nil
}
postLog.Debug("Telegram execute result sent")
return nil
}