fix: TLS连接池复用 + 禁言检测 + 降级回复静默
- llm/openai.go: 移除DisableKeepAlives,启用连接池(100idle/20perhost/90s) 修复频繁TLS握手超时问题 - qq/adapter.go: 监听group_ban通知,发送前检查禁言状态 防止向被禁言群发消息导致风控 - cmd/main.go: 降级回复仅管理员私聊,群聊静默失败避免怪话 - protocol.go: OBv11Message新增Duration字段 - bridge/router.go: 处理noticeToUnified返回nil(内部消费的通知)
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -46,6 +47,9 @@ type Adapter struct {
|
||||
groupNames map[int64]string // group ID → group name cache
|
||||
groupNamesMu sync.RWMutex
|
||||
|
||||
mutedGroups map[int64]time.Time // group ID → mute expiry (zero = indefinitely muted)
|
||||
mutedGroupsMu sync.RWMutex
|
||||
|
||||
pendingResponses map[string]chan *OBv11APIResponse
|
||||
respMu sync.Mutex
|
||||
}
|
||||
@@ -64,9 +68,42 @@ func NewAdapter(configID, configName, mode, port, accessToken, remoteURL string,
|
||||
sendIntervalMs: sendIntervalMs,
|
||||
pendingResponses: make(map[string]chan *OBv11APIResponse),
|
||||
groupNames: make(map[int64]string),
|
||||
mutedGroups: make(map[int64]time.Time),
|
||||
}
|
||||
}
|
||||
|
||||
// IsGroupMuted returns true if the bot is currently muted in the given group.
|
||||
func (a *Adapter) IsGroupMuted(groupID int64) bool {
|
||||
a.mutedGroupsMu.RLock()
|
||||
expiry, ok := a.mutedGroups[groupID]
|
||||
a.mutedGroupsMu.RUnlock()
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if expiry.IsZero() {
|
||||
return true
|
||||
}
|
||||
return time.Now().Before(expiry)
|
||||
}
|
||||
|
||||
// setGroupMuted marks the bot as muted in a group.
|
||||
func (a *Adapter) setGroupMuted(groupID int64, duration int64) {
|
||||
a.mutedGroupsMu.Lock()
|
||||
defer a.mutedGroupsMu.Unlock()
|
||||
if duration <= 0 {
|
||||
a.mutedGroups[groupID] = time.Time{}
|
||||
} else {
|
||||
a.mutedGroups[groupID] = time.Now().Add(time.Duration(duration) * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
// clearGroupMuted removes the mute status for a group.
|
||||
func (a *Adapter) clearGroupMuted(groupID int64) {
|
||||
a.mutedGroupsMu.Lock()
|
||||
delete(a.mutedGroups, groupID)
|
||||
a.mutedGroupsMu.Unlock()
|
||||
}
|
||||
|
||||
// SetHTTPConfig sets the optional HTTP API configuration.
|
||||
func (a *Adapter) SetHTTPConfig(url, token string) {
|
||||
a.httpURL = url
|
||||
@@ -463,7 +500,23 @@ func (a *Adapter) ToUnified(rawMessage interface{}) (*bridge.UnifiedMessage, err
|
||||
}
|
||||
|
||||
// noticeToUnified converts an OBv11 notice event (poke/戳一戳 etc.) to a UnifiedMessage.
|
||||
// Returns nil when the notice is handled internally (e.g., mute tracking).
|
||||
func (a *Adapter) noticeToUnified(msg *OBv11Message) (*bridge.UnifiedMessage, error) {
|
||||
// Handle group mute/ban notices — track mute state internally.
|
||||
if msg.NoticeType == "group_ban" && msg.GroupID != 0 {
|
||||
botUID, _ := strconv.ParseInt(a.selfID, 10, 64)
|
||||
if msg.UserID == botUID {
|
||||
if msg.SubType == "ban" {
|
||||
a.setGroupMuted(msg.GroupID, msg.Duration)
|
||||
log.Printf("[qq] 群 %d 被禁言 (时长=%ds)", msg.GroupID, msg.Duration)
|
||||
} else if msg.SubType == "lift_ban" {
|
||||
a.clearGroupMuted(msg.GroupID)
|
||||
log.Printf("[qq] 群 %d 解除禁言", msg.GroupID)
|
||||
}
|
||||
}
|
||||
return nil, nil // internally handled, no chat message to dispatch
|
||||
}
|
||||
|
||||
senderID := fmt.Sprintf("%d", msg.UserID)
|
||||
senderName := senderID
|
||||
|
||||
@@ -623,8 +676,8 @@ func (a *Adapter) ReadMessages(ctx context.Context, msgCh chan<- *OBv11Message)
|
||||
fmt.Printf("[qq:%s] self ID captured: %s\n", a.configName, a.selfID)
|
||||
}
|
||||
|
||||
// Dispatch message and notice (poke, etc.) events.
|
||||
if msg.PostType == "message" || (msg.PostType == "notice" && msg.NoticeType == "notify" && msg.SubType == "poke") {
|
||||
// Dispatch message and notice events (poke, group_ban for mute tracking).
|
||||
if msg.PostType == "message" || (msg.PostType == "notice" && (msg.NoticeType == "notify" || msg.NoticeType == "group_ban")) {
|
||||
select {
|
||||
case msgCh <- &msg:
|
||||
case <-ctx.Done():
|
||||
|
||||
Reference in New Issue
Block a user