feat(controller): add init message for bot pipes

chore: move softwareInfo from main package to a individual global package
This commit is contained in:
2026-08-07 22:13:15 +08:00
parent d8a192e4e5
commit 56ed32ac0c
9 changed files with 345 additions and 151 deletions
+59
View File
@@ -31,6 +31,15 @@ type Controller interface {
SendExecuteResult(serverName, serverUUID, command, result string) error
}
// BotController is implemented by controllers that act as chat bots and can
// deliver arbitrary messages, such as the bot initialization message on startup.
// Only bot-type pipes (QQ/NapCat, Telegram) implement it; notification-only
// pipes (email, ntfy, webhook) do not.
type BotController interface {
Controller
SendMessage(message string) error
}
// Manager manages all controller instances and routes events.
type Manager struct {
mu sync.RWMutex
@@ -60,6 +69,56 @@ func (m *Manager) Register(c Controller) {
postLog.Info("Controller registered: " + c.Name())
}
// ShowBotInitMessage sends the bot initialization message to all enabled
// bot controllers (QQ/NapCat and Telegram). Notification-only pipes that do
// not implement BotController are skipped.
func (m *Manager) ShowBotInitMessage() {
m.mu.RLock()
defer m.mu.RUnlock()
cfg := config.GetConfig()
params := template.BuildBotInitializationMsgParams()
message := template.Render(cfg.ControllerMessage.BotStarted, params)
for _, ctrl := range m.controllers {
if !ctrl.IsEnabled() {
continue
}
bot, ok := ctrl.(BotController)
if !ok {
continue // Notification-only pipe (email/ntfy/webhook), not a bot.
}
if err := bot.SendMessage(message); err != nil {
postLog.Warning(fmt.Sprintf("Controller %s failed to send init message: %v", bot.Name(), err))
}
}
}
// ShowBotServerList sends the server list to all enabled bot controllers. The
// message content is identical to the /list command (same template and
// parameters).
func (m *Manager) ShowBotServerList() {
m.mu.RLock()
defer m.mu.RUnlock()
cfg := config.GetConfig()
params := template.BuildParamsFromServerList()
message := template.Render(cfg.ControllerMessage.ServerList, params)
for _, ctrl := range m.controllers {
if !ctrl.IsEnabled() {
continue
}
bot, ok := ctrl.(BotController)
if !ok {
continue // Notification-only pipe (email/ntfy/webhook), not a bot.
}
if err := bot.SendMessage(message); err != nil {
postLog.Warning(fmt.Sprintf("Controller %s failed to send server list: %v", bot.Name(), err))
}
}
}
// NotifyStatusChange sends a status change notification to all enabled controllers.
func (m *Manager) NotifyStatusChange(change node.StatusChange) {
m.mu.RLock()
+16
View File
@@ -201,6 +201,22 @@ func (q *QQController) isSelfMessage(ev oneBotEvent) bool {
return false
}
// SendMessage sends an arbitrary message (e.g. the bot initialization message)
// to all QQ trusted groups and admins.
func (q *QQController) SendMessage(message string) error {
if !q.cfg.Enabled {
return nil
}
for _, groupID := range q.cfg.TrustedGroups {
q.sendGroupMessage(groupID, message)
}
for _, adminID := range q.cfg.Admins {
q.sendPrivateMessage(adminID, message)
}
return nil
}
// SendStatusChange sends a status change notification via QQ.
func (q *QQController) SendStatusChange(change node.StatusChange) error {
if !q.cfg.Enabled {
+11
View File
@@ -92,6 +92,17 @@ func (t *TelegramController) processCommand(cmd controller.Command) string {
return response
}
// SendMessage sends an arbitrary message (e.g. the bot initialization message)
// via Telegram. The Telegram Bot API integration is currently a stub, so this
// only logs the message for now.
func (t *TelegramController) SendMessage(message string) error {
if !t.cfg.Enabled || t.cfg.BotToken == "" {
return nil
}
postLog.Debug("Telegram init message: " + message)
return nil
}
// SendStatusChange sends a status change notification via Telegram.
func (t *TelegramController) SendStatusChange(change node.StatusChange) error {
if !t.cfg.Enabled || t.cfg.BotToken == "" {