refactor: 彻底消除硬编码 qq — 平台标识统一为 obv11
- PlatformName() 返回 "obv11" - platformFormats key: "obv11" - 所有 platform == "qq" 检查 → "obv11" - session prefix: platform_qq_ → platform_obv11_ - env var PLATFORM_CHANNELS: obv11:group:xxx - ethend 平台标识同步更新 - 注释和测试用例同步 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -37,7 +37,7 @@ PROACTIVE_MSG_MIN_GAP_SEC=1800
|
|||||||
|
|
||||||
# ========== 平台接入 ==========
|
# ========== 平台接入 ==========
|
||||||
# --- 平台观察 ---
|
# --- 平台观察 ---
|
||||||
PLATFORM_CHANNELS=qq:group:群号
|
PLATFORM_CHANNELS=obv11:group:群号
|
||||||
PLATFORM_THINK_INTERVAL_SEC=600
|
PLATFORM_THINK_INTERVAL_SEC=600
|
||||||
# --- 平台桥接 ---
|
# --- 平台桥接 ---
|
||||||
PLATFORM_BRIDGE_URL=http://localhost:8095
|
PLATFORM_BRIDGE_URL=http://localhost:8095
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ type PendingThought struct {
|
|||||||
// ProactiveTarget describes the target for proactive platform messages (OBv11, etc.).
|
// ProactiveTarget describes the target for proactive platform messages (OBv11, etc.).
|
||||||
// When nil, the message goes through the existing Web push path.
|
// When nil, the message goes through the existing Web push path.
|
||||||
type ProactiveTarget struct {
|
type ProactiveTarget struct {
|
||||||
Platform string // "qq"
|
Platform string // "obv11"
|
||||||
ChatType string // "private" or "group"
|
ChatType string // "private" or "group"
|
||||||
UserID string // OBv11 user number
|
UserID string // OBv11 user number
|
||||||
GroupID string // OBv11 group number (group chat)
|
GroupID string // OBv11 group number (group chat)
|
||||||
@@ -71,7 +71,7 @@ type PlatformFormat struct {
|
|||||||
// defaultPlatformFormats returns the built-in platform format registry.
|
// defaultPlatformFormats returns the built-in platform format registry.
|
||||||
func defaultPlatformFormats() map[string]*PlatformFormat {
|
func defaultPlatformFormats() map[string]*PlatformFormat {
|
||||||
formats := make(map[string]*PlatformFormat)
|
formats := make(map[string]*PlatformFormat)
|
||||||
qq := &PlatformFormat{
|
obv11 := &PlatformFormat{
|
||||||
Label: "OBv11",
|
Label: "OBv11",
|
||||||
TargetRegex: `【OBv11(私聊|群聊):(\d+)(?:@(\d+))?】`,
|
TargetRegex: `【OBv11(私聊|群聊):(\d+)(?:@(\d+))?】`,
|
||||||
GroupMarkerFmt: "【OBv11群聊:%s】",
|
GroupMarkerFmt: "【OBv11群聊:%s】",
|
||||||
@@ -80,14 +80,14 @@ func defaultPlatformFormats() map[string]*PlatformFormat {
|
|||||||
GroupKeyword: "群聊",
|
GroupKeyword: "群聊",
|
||||||
PrivateKeyword: "私聊",
|
PrivateKeyword: "私聊",
|
||||||
}
|
}
|
||||||
qq.compiled = regexp.MustCompile(qq.TargetRegex)
|
obv11.compiled = regexp.MustCompile(obv11.TargetRegex)
|
||||||
formats["qq"] = qq
|
formats["obv11"] = obv11
|
||||||
return formats
|
return formats
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParsePlatformChannels parses PLATFORM_CHANNELS env var.
|
// ParsePlatformChannels parses PLATFORM_CHANNELS env var.
|
||||||
// Format: "qq:group:123456,telegram:group:789012"
|
// Format: "obv11:group:123456,telegram:group:789012"
|
||||||
// Optional 4th field for display name: "qq:group:123456:群名称"
|
// Optional 4th field for display name: "obv11:group:123456:群名称"
|
||||||
func ParsePlatformChannels(raw string) []PlatformChannel {
|
func ParsePlatformChannels(raw string) []PlatformChannel {
|
||||||
if raw == "" {
|
if raw == "" {
|
||||||
return nil
|
return nil
|
||||||
@@ -228,7 +228,7 @@ type Thinker struct {
|
|||||||
platformChannels []PlatformChannel
|
platformChannels []PlatformChannel
|
||||||
platformThinkInterval time.Duration
|
platformThinkInterval time.Duration
|
||||||
|
|
||||||
// 平台 Bot UID (platform -> bot's own UID, e.g. "qq" -> "123456789")
|
// 平台 Bot UID (platform -> bot's own UID, e.g. "obv11" -> "123456789")
|
||||||
botUIDs map[string]string
|
botUIDs map[string]string
|
||||||
|
|
||||||
// 平台格式注册表 (platform -> format)
|
// 平台格式注册表 (platform -> format)
|
||||||
@@ -1609,15 +1609,15 @@ func (t *Thinker) buildThinkingUserPrompt(
|
|||||||
sb.WriteString("\n\n【你的平台身份与可用频道】\n")
|
sb.WriteString("\n\n【你的平台身份与可用频道】\n")
|
||||||
|
|
||||||
// Bot's own identity.
|
// Bot's own identity.
|
||||||
if qqBotUID, ok := botUIDs["qq"]; ok && qqBotUID != "" {
|
if qqBotUID, ok := botUIDs["obv11"]; ok && qqBotUID != "" {
|
||||||
sb.WriteString(fmt.Sprintf("你在OBv11上的账号是: %s(昔涟),这就是你。\n", qqBotUID))
|
sb.WriteString(fmt.Sprintf("你在OBv11上的账号是: %s(昔涟),这就是你。\n", qqBotUID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Active session context with time, group name, and trigger-aware guidance.
|
// Active session context with time, group name, and trigger-aware guidance.
|
||||||
if strings.HasPrefix(activeSID, "platform_qq_") {
|
if strings.HasPrefix(activeSID, "platform_obv11_") {
|
||||||
activeChID := strings.TrimPrefix(activeSID, "platform_qq_")
|
activeChID := strings.TrimPrefix(activeSID, "platform_obv11_")
|
||||||
for _, ch := range qqChannels {
|
for _, ch := range qqChannels {
|
||||||
if ch.Platform == "qq" && ch.ChannelID == activeChID {
|
if ch.Platform == "obv11" && ch.ChannelID == activeChID {
|
||||||
chLabel := activeChID
|
chLabel := activeChID
|
||||||
if ch.ChannelName != "" {
|
if ch.ChannelName != "" {
|
||||||
chLabel = fmt.Sprintf("%s(%s)", ch.ChannelName, activeChID)
|
chLabel = fmt.Sprintf("%s(%s)", ch.ChannelName, activeChID)
|
||||||
@@ -1665,7 +1665,7 @@ func (t *Thinker) buildThinkingUserPrompt(
|
|||||||
sb.WriteString("- OBv11群聊@某人: 【主动消息】【OBv11群聊:群号@账号】消息内容\n")
|
sb.WriteString("- OBv11群聊@某人: 【主动消息】【OBv11群聊:群号@账号】消息内容\n")
|
||||||
sb.WriteString("\n可用的平台频道列表:\n")
|
sb.WriteString("\n可用的平台频道列表:\n")
|
||||||
for _, ch := range qqChannels {
|
for _, ch := range qqChannels {
|
||||||
if ch.Platform != "qq" {
|
if ch.Platform != "obv11" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
label := ch.ChannelID
|
label := ch.ChannelID
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ func TestExtractProactiveMessage_OBv11Group(t *testing.T) {
|
|||||||
if target == nil {
|
if target == nil {
|
||||||
t.Fatal("expected target, got nil")
|
t.Fatal("expected target, got nil")
|
||||||
}
|
}
|
||||||
if target.Platform != "qq" {
|
if target.Platform != "obv11" {
|
||||||
t.Errorf("expected platform 'qq', got %q", target.Platform)
|
t.Errorf("expected platform 'obv11', got %q", target.Platform)
|
||||||
}
|
}
|
||||||
if target.ChatType != "group" {
|
if target.ChatType != "group" {
|
||||||
t.Errorf("expected chatType 'group', got %q", target.ChatType)
|
t.Errorf("expected chatType 'group', got %q", target.ChatType)
|
||||||
|
|||||||
@@ -300,14 +300,14 @@ func main() {
|
|||||||
// Sync admin identities from config fields.
|
// Sync admin identities from config fields.
|
||||||
syncAdminUIDs(mapper, platform, fields, cfg.AdminNickname)
|
syncAdminUIDs(mapper, platform, fields, cfg.AdminNickname)
|
||||||
// Restart OBv11 reader when OBv11 config changes.
|
// Restart OBv11 reader when OBv11 config changes.
|
||||||
if platform == "qq" {
|
if platform == "obv11" {
|
||||||
startOBv11Readers(router)
|
startOBv11Readers(router)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
router.RemoveAdapter(name)
|
router.RemoveAdapter(name)
|
||||||
fmt.Printf("Platform adapter removed: %s\n", name)
|
fmt.Printf("Platform adapter removed: %s\n", name)
|
||||||
// Cancel reader goroutines for removed adapter.
|
// Cancel reader goroutines for removed adapter.
|
||||||
if platform == "qq" {
|
if platform == "obv11" {
|
||||||
startOBv11Readers(router)
|
startOBv11Readers(router)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -366,7 +366,7 @@ func startOBv11Readers(router *bridge.PlatformRouter) {
|
|||||||
qqReaderCancels = make(map[string]context.CancelFunc)
|
qqReaderCancels = make(map[string]context.CancelFunc)
|
||||||
qqReaderCancelsMu.Unlock()
|
qqReaderCancelsMu.Unlock()
|
||||||
|
|
||||||
for _, qqa := range router.GetAdaptersByPlatform("qq") {
|
for _, qqa := range router.GetAdaptersByPlatform("obv11") {
|
||||||
qqAdapter, ok := qqa.(*qqadapter.Adapter)
|
qqAdapter, ok := qqa.(*qqadapter.Adapter)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
@@ -485,7 +485,7 @@ func createAdapters(cfg *config.Config, store *config.Store) []bridge.PlatformAd
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Seed default adapters for platforms that have no stored config.
|
// Seed default adapters for platforms that have no stored config.
|
||||||
defaultPlatforms := []string{"qq", "telegram", "webhook", "wechat", "feishu", "discord"}
|
defaultPlatforms := []string{"obv11", "telegram", "webhook", "wechat", "feishu", "discord"}
|
||||||
for _, name := range defaultPlatforms {
|
for _, name := range defaultPlatforms {
|
||||||
if seen[name] {
|
if seen[name] {
|
||||||
continue
|
continue
|
||||||
@@ -500,10 +500,10 @@ func createAdapters(cfg *config.Config, store *config.Store) []bridge.PlatformAd
|
|||||||
}
|
}
|
||||||
|
|
||||||
// createSingleAdapter creates one platform adapter from config fields.
|
// createSingleAdapter creates one platform adapter from config fields.
|
||||||
// platform is the base platform type ("qq", "telegram", etc.), configName is the instance key.
|
// platform is the base platform type ("obv11", "telegram", etc.), configName is the instance key.
|
||||||
func createSingleAdapter(cfg *config.Config, platform, configName, configID string, fields map[string]string) bridge.PlatformAdapter {
|
func createSingleAdapter(cfg *config.Config, platform, configName, configID string, fields map[string]string) bridge.PlatformAdapter {
|
||||||
switch platform {
|
switch platform {
|
||||||
case "qq":
|
case "obv11":
|
||||||
port := cfg.OBv11BotPort
|
port := cfg.OBv11BotPort
|
||||||
if p, ok := fields["bot_port"]; ok && p != "" {
|
if p, ok := fields["bot_port"]; ok && p != "" {
|
||||||
port = p
|
port = p
|
||||||
@@ -565,7 +565,7 @@ func mergeFields(cfg *config.Config, platform string, stored *config.PlatformCon
|
|||||||
if fields["webhook_url"] == "" && cfg.TelegramWebhookURL != "" && platform == "telegram" {
|
if fields["webhook_url"] == "" && cfg.TelegramWebhookURL != "" && platform == "telegram" {
|
||||||
fields["webhook_url"] = cfg.TelegramWebhookURL
|
fields["webhook_url"] = cfg.TelegramWebhookURL
|
||||||
}
|
}
|
||||||
if fields["bot_port"] == "" && cfg.OBv11BotPort != "" && platform == "qq" {
|
if fields["bot_port"] == "" && cfg.OBv11BotPort != "" && platform == "obv11" {
|
||||||
fields["bot_port"] = cfg.OBv11BotPort
|
fields["bot_port"] = cfg.OBv11BotPort
|
||||||
}
|
}
|
||||||
return fields
|
return fields
|
||||||
@@ -989,7 +989,7 @@ func seedIdentities(m *bridge.IdentityMapper, store *config.Store, adminNickname
|
|||||||
}
|
}
|
||||||
|
|
||||||
// From stored platform configs (admin_uids field).
|
// From stored platform configs (admin_uids field).
|
||||||
for _, name := range []string{"qq", "telegram", "webhook", "wechat", "feishu", "discord"} {
|
for _, name := range []string{"obv11", "telegram", "webhook", "wechat", "feishu", "discord"} {
|
||||||
stored, _ := store.Get(name)
|
stored, _ := store.Get(name)
|
||||||
if stored == nil {
|
if stored == nil {
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ func NewAdapter(configID, configName, mode, port, accessToken, remoteURL string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Adapter) PlatformName() string { return "qq" }
|
func (a *Adapter) PlatformName() string { return "obv11" }
|
||||||
func (a *Adapter) ConfigID() string { return a.configID }
|
func (a *Adapter) ConfigID() string { return a.configID }
|
||||||
func (a *Adapter) ConfigName() string { return a.configName }
|
func (a *Adapter) ConfigName() string { return a.configName }
|
||||||
func (a *Adapter) SendIntervalMs() int { return a.sendIntervalMs }
|
func (a *Adapter) SendIntervalMs() int { return a.sendIntervalMs }
|
||||||
@@ -391,7 +391,7 @@ func (a *Adapter) ToUnified(rawMessage interface{}) (*bridge.UnifiedMessage, err
|
|||||||
return &bridge.UnifiedMessage{
|
return &bridge.UnifiedMessage{
|
||||||
SenderID: senderID,
|
SenderID: senderID,
|
||||||
SenderName: senderName,
|
SenderName: senderName,
|
||||||
Platform: "qq",
|
Platform: "obv11",
|
||||||
ChannelID: channelID,
|
ChannelID: channelID,
|
||||||
ChannelType: channelType,
|
ChannelType: channelType,
|
||||||
Content: content,
|
Content: content,
|
||||||
@@ -442,7 +442,7 @@ func (a *Adapter) noticeToUnified(msg *OBv11Message) (*bridge.UnifiedMessage, er
|
|||||||
return &bridge.UnifiedMessage{
|
return &bridge.UnifiedMessage{
|
||||||
SenderID: senderID,
|
SenderID: senderID,
|
||||||
SenderName: senderName,
|
SenderName: senderName,
|
||||||
Platform: "qq",
|
Platform: "obv11",
|
||||||
ChannelID: channelID,
|
ChannelID: channelID,
|
||||||
ChannelType: channelType,
|
ChannelType: channelType,
|
||||||
Content: content,
|
Content: content,
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ func (a *Adapter) FetchGroups() []bridge.ChannelInfo {
|
|||||||
a.SetGroupName(g.GroupID, g.GroupName)
|
a.SetGroupName(g.GroupID, g.GroupName)
|
||||||
}
|
}
|
||||||
channels = append(channels, bridge.ChannelInfo{
|
channels = append(channels, bridge.ChannelInfo{
|
||||||
Platform: "qq",
|
Platform: "obv11",
|
||||||
ChannelType: "group",
|
ChannelType: "group",
|
||||||
ChannelID: fmt.Sprintf("%d", g.GroupID),
|
ChannelID: fmt.Sprintf("%d", g.GroupID),
|
||||||
ChannelName: g.GroupName,
|
ChannelName: g.GroupName,
|
||||||
@@ -124,7 +124,7 @@ func (a *Adapter) FetchFriends() []bridge.ChannelInfo {
|
|||||||
name = f.Nickname
|
name = f.Nickname
|
||||||
}
|
}
|
||||||
channels = append(channels, bridge.ChannelInfo{
|
channels = append(channels, bridge.ChannelInfo{
|
||||||
Platform: "qq",
|
Platform: "obv11",
|
||||||
ChannelType: "private",
|
ChannelType: "private",
|
||||||
ChannelID: fmt.Sprintf("%d", f.UserID),
|
ChannelID: fmt.Sprintf("%d", f.UserID),
|
||||||
ChannelName: name,
|
ChannelName: name,
|
||||||
|
|||||||
Reference in New Issue
Block a user