chore(config): move admins && trustedGroups to a new config bot_user_config.json.

feat(config): add load bot_user_config endpoint
style(config): rename `LoadConfig` to `LoadGlobalConfig`.
This commit is contained in:
2026-09-02 21:19:50 +08:00
parent 0b7fcd6c48
commit bf4cdf0d88
15 changed files with 196 additions and 108 deletions
+3 -3
View File
@@ -77,7 +77,7 @@ func (m *Manager) ShowBotInitMessage() {
m.mu.RLock()
defer m.mu.RUnlock()
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildBotInitializationMsgParams()
message := template.Render(cfg.ControllerMessage.BotStarted, params)
@@ -102,7 +102,7 @@ func (m *Manager) ShowBotServerList() {
m.mu.RLock()
defer m.mu.RUnlock()
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromServerList()
message := template.Render(cfg.ControllerMessage.ServerList, params)
@@ -125,7 +125,7 @@ func (m *Manager) NotifyStatusChange(change node.StatusChange) {
m.mu.RLock()
defer m.mu.RUnlock()
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
templateStr := cfg.ControllerMessage.ServerStatusChanged
params := template.BuildParamsFromStatusChange(change)
+3 -3
View File
@@ -64,7 +64,7 @@ func (e *EmailController) SendStatusChange(change node.StatusChange) error {
return nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromStatusChange(change)
body := template.Render(cfg.ControllerMessage.ServerStatusChanged, params)
@@ -78,7 +78,7 @@ func (e *EmailController) SendServerList(onlineServers, offlineServers string) e
return nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromServerList()
body := template.Render(cfg.ControllerMessage.ServerList, params)
@@ -91,7 +91,7 @@ func (e *EmailController) SendExecuteResult(serverName, serverUUID, command, res
return nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromExecResult(serverName, serverUUID, command, result)
body := template.Render(cfg.ControllerMessage.ServerExecuteResult, params)
+3 -3
View File
@@ -58,7 +58,7 @@ func (n *NtfyController) SendStatusChange(change node.StatusChange) error {
return nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromStatusChange(change)
message := template.Render(cfg.ControllerMessage.ServerStatusChanged, params)
@@ -72,7 +72,7 @@ func (n *NtfyController) SendServerList(onlineServers, offlineServers string) er
return nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromServerList()
message := template.Render(cfg.ControllerMessage.ServerList, params)
@@ -85,7 +85,7 @@ func (n *NtfyController) SendExecuteResult(serverName, serverUUID, command, resu
return nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromExecResult(serverName, serverUUID, command, result)
message := template.Render(cfg.ControllerMessage.ServerExecuteResult, params)
@@ -155,7 +155,7 @@ func (c *Client) SendMsg(targetType string, targetID int64, msg string, hasAt bo
return nil, fmt.Errorf("failed to marshal request: %w", err)
}
if config.GetConfig().Debug.ShowNapcatAction {
if config.GetGlobalConfig().Debug.ShowNapcatAction {
postLog.Debug(fmt.Sprintf("[Napcat] SendMsg -> %s (%s): %s", endpoint, targetType, message))
}
@@ -176,7 +176,7 @@ func (c *Client) RecallMsg(msgID int64) (*APIResponse, error) {
return nil, fmt.Errorf("failed to marshal request: %w", err)
}
if config.GetConfig().Debug.ShowNapcatAction {
if config.GetGlobalConfig().Debug.ShowNapcatAction {
postLog.Debug(fmt.Sprintf("[Napcat] RecallMsg -> /delete_msg: %d", msgID))
}
@@ -190,7 +190,7 @@ func (c *Client) RecallMsg(msgID int64) (*APIResponse, error) {
// GetGroupList retrieves the list of joined groups from NapCat.
func (c *Client) GetGroupList() (*APIResponse, error) {
if config.GetConfig().Debug.ShowNapcatAction {
if config.GetGlobalConfig().Debug.ShowNapcatAction {
postLog.Debug("[Napcat] GetGroupList -> /get_group_list")
}
@@ -211,7 +211,7 @@ func (c *Client) GetGroupInfo(groupID int64) (*APIResponse, error) {
return nil, fmt.Errorf("failed to marshal request: %w", err)
}
if config.GetConfig().Debug.ShowNapcatAction {
if config.GetGlobalConfig().Debug.ShowNapcatAction {
postLog.Debug(fmt.Sprintf("[Napcat] GetGroupInfo -> /get_group_info: %d", groupID))
}
@@ -225,7 +225,7 @@ func (c *Client) GetGroupInfo(groupID int64) (*APIResponse, error) {
// GetFriendsList retrieves the friends list from NapCat.
func (c *Client) GetFriendsList() (*APIResponse, error) {
if config.GetConfig().Debug.ShowNapcatAction {
if config.GetGlobalConfig().Debug.ShowNapcatAction {
postLog.Debug("[Napcat] GetFriendsList -> /get_friend_list")
}
+45 -29
View File
@@ -15,18 +15,18 @@ import (
// oneBotEvent mirrors a OneBot 11 event pushed over the NapCat WebSocket.
// Only "message" events are handled; notice/request/meta_event are ignored.
type oneBotEvent struct {
PostType string `json:"post_type"` // Identifies "message", "notice", "request", or "meta_event"
MessageType string `json:"message_type"` // Identifies "private" or "group"
GroupID int64 `json:"group_id"` // Only present for group messages
UserID int64 `json:"user_id"` // The sender's QQ ID
RawMessage string `json:"raw_message"` // The raw message text
Message json.RawMessage `json:"message"` // The message content, which may include CQ codes
Sender struct { // The sender's information
UserID int64 `json:"user_id"` // The sender's QQ ID
Nickname string `json:"nickname"` // The sender's nickname
PostType string `json:"post_type"` // Identifies "message", "notice", "request", or "meta_event"
MessageType string `json:"message_type"` // Identifies "private" or "group"
GroupID int64 `json:"group_id"` // Only present for group messages
UserID int64 `json:"user_id"` // The sender's QQ ID
RawMessage string `json:"raw_message"` // The raw message text
Message json.RawMessage `json:"message"` // The message content, which may include CQ codes
Sender struct { // The sender's information
UserID int64 `json:"user_id"` // The sender's QQ ID
Nickname string `json:"nickname"` // The sender's nickname
} `json:"sender"`
SelfID int64 `json:"self_id"` // The bot's QQ ID
SubType string `json:"sub_type"` // The subtype of the message, e.g., "normal", "anonymous", etc.
SelfID int64 `json:"self_id"` // The bot's QQ ID
SubType string `json:"sub_type"` // The subtype of the message, e.g., "normal", "anonymous", etc.
}
// QQController handles QQ Bot interactions by connecting directly to NapCat.
@@ -94,24 +94,24 @@ func (q *QQController) handleNapcatEvent(raw []byte) {
return
}
if config.GetConfig().System.DebugMode && config.GetConfig().Debug.ShowNapcatMsg {
if config.GetGlobalConfig().System.DebugMode && config.GetGlobalConfig().Debug.ShowNapcatMsg {
postLog.Debug("Napcat WS event received: " + string(raw))
}
// Only handle message events; ignore notice/request/meta_event.
if ev.PostType != "message" {
if config.GetConfig().System.DebugMode && config.GetConfig().Debug.ShowNapcatAction {
if config.GetGlobalConfig().System.DebugMode && config.GetGlobalConfig().Debug.ShowNapcatAction {
postLog.Debug("Ignoring Napcat WS event: " + string(raw))
}
return
}
// Ignore messages the bot itself sent (echo prevention).
if q.isSelfMessage(ev) && !config.GetConfig().System.DebugMode {
if q.isSelfMessage(ev) && !config.GetGlobalConfig().System.DebugMode {
return
}
if q.isSelfMessage(ev) && config.GetConfig().System.DebugMode && config.GetConfig().Debug.NapcatIgnoreSelfMsg {
if config.GetConfig().System.DebugMode && config.GetConfig().Debug.ShowNapcatAction {
if q.isSelfMessage(ev) && config.GetGlobalConfig().System.DebugMode && config.GetGlobalConfig().Debug.NapcatIgnoreSelfMsg {
if config.GetGlobalConfig().System.DebugMode && config.GetGlobalConfig().Debug.ShowNapcatAction {
postLog.Debug("Ignoring Napcat WS self message: " + string(raw))
}
return
@@ -132,7 +132,7 @@ func (q *QQController) handleNapcatEvent(raw []byte) {
response := q.processCommand(cmd)
if response == "" {
if config.GetConfig().System.DebugMode && config.GetConfig().Debug.ShowNapcatAction {
if config.GetGlobalConfig().System.DebugMode && config.GetGlobalConfig().Debug.ShowNapcatAction {
postLog.Debug("Napcat WS command discarded: " + string(raw))
}
return
@@ -162,7 +162,7 @@ func (q *QQController) processCommand(cmd controller.Command) string {
if q.cfg.ListenMethod == "at" {
atMention := fmt.Sprintf("[CQ:at,qq=%d]", q.cfg.BotQQID)
if !strings.Contains(text, atMention) {
if config.GetConfig().System.DebugMode && config.GetConfig().Debug.ShowNapcatAction {
if config.GetGlobalConfig().System.DebugMode && config.GetGlobalConfig().Debug.ShowNapcatAction {
postLog.Debug("Napcat WS message ignored (no @mention): " + text)
}
return "" // Not mentioned, ignore.
@@ -183,8 +183,8 @@ func (q *QQController) processCommand(cmd controller.Command) string {
// Hand the complete command to the unified processor, which checks group
// vs private, trusted groups, admin permissions, and executes it.
response, err := controller.GetManager().Trigger(parsed, q.cfg.TrustedGroups, q.cfg.Admins, q.cfg.ListenMethod)
if config.GetConfig().System.DebugMode && config.GetConfig().Debug.ShowTriggerCmdEcho {
response, err := controller.GetManager().Trigger(parsed, q.trustedGroupIDs(), q.adminIDs(), q.cfg.ListenMethod)
if config.GetGlobalConfig().System.DebugMode && config.GetGlobalConfig().Debug.ShowTriggerCmdEcho {
postLog.Debug(fmt.Sprintf("[qq_napcat] triggered command: \"/%s\" with args: \"%s\" from chatID: %d and senderID: %d", parsed.Command, strings.Join(parsed.Args, ", "), cmd.ChatID, cmd.SenderID))
}
if err != nil {
@@ -205,6 +205,22 @@ func (q *QQController) isSelfMessage(ev oneBotEvent) bool {
return false
}
// adminIDs returns the QQ admin IDs from bot_user_config.json.
func (q *QQController) adminIDs() []string {
if c := config.C_botUserConfig; c != nil {
return c.QQ.Admins.IDs()
}
return nil
}
// trustedGroupIDs returns the QQ trusted group IDs from bot_user_config.json.
func (q *QQController) trustedGroupIDs() []string {
if c := config.C_botUserConfig; c != nil {
return c.QQ.TrustedGroups.IDs()
}
return nil
}
// 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 {
@@ -212,10 +228,10 @@ func (q *QQController) SendMessage(message string) error {
return nil
}
for _, groupID := range q.cfg.TrustedGroups {
for _, groupID := range q.trustedGroupIDs() {
q.sendGroupMessage(groupID, message)
}
for _, adminID := range q.cfg.Admins {
for _, adminID := range q.adminIDs() {
q.sendPrivateMessage(adminID, message)
}
return nil
@@ -227,17 +243,17 @@ func (q *QQController) SendStatusChange(change node.StatusChange) error {
return nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromStatusChange(change)
message := template.Render(cfg.ControllerMessage.ServerStatusChanged, params)
// Send to trusted groups.
for _, groupID := range q.cfg.TrustedGroups {
for _, groupID := range q.trustedGroupIDs() {
q.sendGroupMessage(groupID, message)
}
// Send to admins via private message.
for _, adminID := range q.cfg.Admins {
for _, adminID := range q.adminIDs() {
q.sendPrivateMessage(adminID, message)
}
@@ -250,11 +266,11 @@ func (q *QQController) SendServerList(onlineServers, offlineServers string) erro
return nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromServerList()
message := template.Render(cfg.ControllerMessage.ServerList, params)
for _, groupID := range q.cfg.TrustedGroups {
for _, groupID := range q.trustedGroupIDs() {
q.sendGroupMessage(groupID, message)
}
return nil
@@ -266,11 +282,11 @@ func (q *QQController) SendExecuteResult(serverName, serverUUID, command, result
return nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromExecResult(serverName, serverUUID, command, result)
message := template.Render(cfg.ControllerMessage.ServerExecuteResult, params)
for _, groupID := range q.cfg.TrustedGroups {
for _, groupID := range q.trustedGroupIDs() {
q.sendGroupMessage(groupID, message)
}
return nil
+28 -10
View File
@@ -142,7 +142,7 @@ func (t *TelegramController) handleUpdate(_ context.Context, _ *bot.Bot, update
}
msg := update.Message
if config.GetConfig().System.DebugMode && config.GetConfig().Debug.ShowTelegramMsg {
if config.GetGlobalConfig().System.DebugMode && config.GetGlobalConfig().Debug.ShowTelegramMsg {
raw, _ := json.Marshal(update)
postLog.Debug("Telegram update received: " + string(raw))
}
@@ -218,8 +218,8 @@ func (t *TelegramController) processCommand(cmd controller.Command) string {
// Hand the complete command to the unified processor, which checks group
// vs private, trusted groups, admin permissions, and executes it.
response, err := controller.GetManager().Trigger(parsed, t.cfg.TrustedGroups, t.resolvedAdminList(), t.cfg.ListenMethod)
if config.GetConfig().System.DebugMode && config.GetConfig().Debug.ShowTriggerCmdEcho {
response, err := controller.GetManager().Trigger(parsed, t.trustedGroupIDs(), t.resolvedAdminList(), t.cfg.ListenMethod)
if config.GetGlobalConfig().System.DebugMode && config.GetGlobalConfig().Debug.ShowTriggerCmdEcho {
postLog.Debug(fmt.Sprintf("[telegram] triggered command: \"/%s\" with args: \"%s\" from chatID: %d and senderID: %d", parsed.Command, strings.Join(parsed.Args, ", "), cmd.ChatID, cmd.SenderID))
}
if err != nil {
@@ -245,7 +245,7 @@ func (t *TelegramController) SendStatusChange(change node.StatusChange) error {
return nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromStatusChange(change)
message := template.Render(cfg.ControllerMessage.ServerStatusChanged, params)
@@ -259,7 +259,7 @@ func (t *TelegramController) SendServerList(onlineServers, offlineServers string
return nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromServerList()
message := template.Render(cfg.ControllerMessage.ServerList, params)
@@ -273,7 +273,7 @@ func (t *TelegramController) SendExecuteResult(serverName, serverUUID, command,
return nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromExecResult(serverName, serverUUID, command, result)
message := template.Render(cfg.ControllerMessage.ServerExecuteResult, params)
@@ -334,13 +334,31 @@ func (t *TelegramController) resolveUsername(username string) (int64, bool) {
return id, ok
}
// adminIDs returns the Telegram admin entries (numeric user ID or @username)
// from bot_user_config.json.
func (t *TelegramController) adminIDs() []string {
if c := config.C_botUserConfig; c != nil {
return c.Telegram.Admins.IDs()
}
return nil
}
// trustedGroupIDs returns the Telegram trusted group IDs from bot_user_config.json.
func (t *TelegramController) trustedGroupIDs() []string {
if c := config.C_botUserConfig; c != nil {
return c.Telegram.TrustedGroups.IDs()
}
return nil
}
// resolvedAdminList maps username-based admin entries to numeric IDs so the
// unified processor's numeric IsAdmin check works. Unresolvable entries (the
// user has not messaged the bot yet) pass through unchanged and simply never
// match.
func (t *TelegramController) resolvedAdminList() []string {
result := make([]string, 0, len(t.cfg.Admins))
for _, admin := range t.cfg.Admins {
admins := t.adminIDs()
result := make([]string, 0, len(admins))
for _, admin := range admins {
if id, ok := t.resolveUsername(admin); ok {
result = append(result, strconv.FormatInt(id, 10))
} else {
@@ -353,14 +371,14 @@ func (t *TelegramController) resolvedAdminList() []string {
// sendToGroupsAndAdmins sends a message to all trusted groups and admins.
func (t *TelegramController) sendToGroupsAndAdmins(message string) {
t.sendToGroups(message)
for _, admin := range t.cfg.Admins {
for _, admin := range t.adminIDs() {
t.sendAdminMessage(admin, message)
}
}
// sendToGroups sends a message to all trusted groups.
func (t *TelegramController) sendToGroups(message string) {
for _, groupID := range t.cfg.TrustedGroups {
for _, groupID := range t.trustedGroupIDs() {
t.sendGroupMessage(groupID, message)
}
}
+3 -3
View File
@@ -59,7 +59,7 @@ func (w *WebhookController) SendStatusChange(change node.StatusChange) error {
return nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromStatusChange(change)
message := template.Render(cfg.ControllerMessage.ServerStatusChanged, params)
@@ -80,7 +80,7 @@ func (w *WebhookController) SendServerList(onlineServers, offlineServers string)
return nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromServerList()
message := template.Render(cfg.ControllerMessage.ServerList, params)
@@ -101,7 +101,7 @@ func (w *WebhookController) SendExecuteResult(serverName, serverUUID, command, r
return nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromExecResult(serverName, serverUUID, command, result)
message := template.Render(cfg.ControllerMessage.ServerExecuteResult, params)
+4 -4
View File
@@ -11,13 +11,13 @@ import (
)
func handleHelp(cmd Command) (string, error) {
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildBotInitializationMsgParams()
return template.Render(cfg.ControllerMessage.BotHelp, params, cmd.Source), nil
}
func handleList(cmd Command) (string, error) {
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromServerList()
return template.Render(cfg.ControllerMessage.ServerList, params, cmd.Source), nil
}
@@ -128,7 +128,7 @@ func handleRun(cmd Command) (string, error) {
return fmt.Sprintf("Error getting results: %v", err), nil
}
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildParamsFromExecResult(uuidArg, uuidArg, command, formatTaskResults(results))
return template.Render(cfg.ControllerMessage.ServerExecuteResult, params, cmd.Source), nil
}
@@ -178,7 +178,7 @@ func handleInfo(cmd Command) (string, error) {
}
func telegram_handleStart() (string, error) {
cfg := config.GetConfig()
cfg := config.GetGlobalConfig()
params := template.BuildBotInitializationMsgParams()
return template.Render(cfg.ControllerMessage.Tg_BotStart, params, "telegram"), nil
}