feat: 频道自动发现 — platform-bridge定时刷新频道路由 + ai-core周期同步

platform-bridge:
- QQ adapter: FetchGroups/FetchFriends 从NapCat API获取
- ChannelLister接口 + ChannelInfo结构体
- GET /api/v1/channels 端点 + cachedChannels缓存
- StartChannelRefresh 每10分钟自动刷新

ai-core:
- channel_sync.go: 每5分钟从platform-bridge拉取频道
- 自动更新thinker的platformChannels + botUIDs
- 不再依赖PLATFORM_CHANNELS环境变量手动配置

修复:
- SendMessage显式设AutoEscape:false
- PLATFORM_BRIDGE_URL默认端口8082→8095
- OBv11Params.AutoEscape去掉omitempty

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-06-23 13:12:54 +08:00
parent c9bf839945
commit 6bf59f7eee
9 changed files with 316 additions and 11 deletions
@@ -0,0 +1,59 @@
package handler
import (
"log"
"net/http"
"time"
"git.yeij.top/AskaEth/Cyrene/platform-bridge/internal/bridge"
)
// listChannels returns cached channels from all adapters (groups + friends).
// GET /api/v1/channels
func (h *BridgeHandler) listChannels(w http.ResponseWriter, r *http.Request) {
h.channelsMu.RLock()
channels := h.cachedChannels
h.channelsMu.RUnlock()
if channels == nil {
channels = []bridge.ChannelInfo{}
}
writeJSON(w, http.StatusOK, map[string]interface{}{
"channels": channels,
"total": len(channels),
})
}
// StartChannelRefresh periodically queries all adapters for their channel lists.
func (h *BridgeHandler) StartChannelRefresh(interval time.Duration) {
if interval <= 0 {
interval = 10 * time.Minute
}
go func() {
ticker := time.NewTicker(interval)
defer ticker.Stop()
log.Printf("[channel-refresh] 频道缓存刷新已启动 (间隔=%v)", interval)
h.refreshChannels()
for range ticker.C {
h.refreshChannels()
}
}()
}
// refreshChannels queries all ChannelLister adapters and updates the cache.
func (h *BridgeHandler) refreshChannels() {
var all []bridge.ChannelInfo
for _, name := range h.router.ListAdapters() {
a, err := h.router.GetAdapter(name)
if err != nil {
continue
}
if lister, ok := a.(bridge.ChannelLister); ok {
channels := lister.ListChannels()
all = append(all, channels...)
}
}
h.channelsMu.Lock()
h.cachedChannels = all
h.channelsMu.Unlock()
log.Printf("[channel-refresh] 频道缓存已更新: %d 个频道", len(all))
}