Files
Cyrene_v2/plugins/channels/qq_obv11/addressed.go
T
AskaEth b26bc55a15 feat(channel): 消息契约加「她自己账号 id / 是否在叫她」结构化判据并接线 qq_obv11
契约(internal/channel/adapter):UnifiedMessage 新增三个字段 —— SelfID(她自己在该
平台的账号 id)、MentionAll(是否 @全体,design/26 §2.4 的 mention_all)、AddressedToMe
(本条是否指向她本人);判据的唯一出处是新增的 MentionedSelf(结构化 id 精确比对,
空 selfID 一律 false)与 AddressedToSelf(私聊恒 true;群聊 = 点名她或 @全体;
平台未给 SelfID ⇒ fail-closed)。全程不匹配正文文本。

接线(plugins/channels/qq_obv11):新增 addressed.go,把事件里早已解出、此前只用于
debug 日志与 notice 判定的 self_id 接进 toUnified,并从 at 段解出 @全体(qq=all),
在 ChannelType 判定之后统一回写三个字段。

design/18 §2 触发① 的旧口径「Mentions 非空」= @谁不论(实测群 672432767 里 @别人两次
被回);本片让消费侧(light.go:142,归 M12)能改用 AddressedToMe || MentionAll。
既有字段 Mentions/ReplyToID/ReplyToText 语义与形状不变。

测试:qq_obv11 十种帧形态(私聊/@她/@别人/@全体/无@/CQ 形态/fail-closed/纯回复)
逐条断言;adapter 侧覆盖 MentionedSelf 与 AddressedToSelf。变异自证:判据改回
「Mentions 非空」⇒ group_mention_other 红;摘掉 selfId 接线 ⇒ group_mention_me 红。
2026-10-13 20:17:56 +08:00

47 lines
2.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package qq_obv11
// 本文件承载「这条消息是不是在叫她」的**结构化接线**:把 OneBot 事件里已有的
// self_id(她自己在该平台的账号 id)与 at 段(点名 / @全体)写进统一契约
// adapter.UnifiedMessage,让下游不必再靠「Mentions 非空」这种 **@ 谁不论**的判据
// (design/18 §2 触发① 的 2026-10-13 修订;主人裁决「甲 = 要」)。
//
// 红线:判据**全部来自平台元数据**(self_id + at 段的 qq),绝不匹配正文里的
// "@<数字>" —— 正文里恰好只有这种文本,而它正是不可靠的原因(@ 她与 @ 别人长得一模一样)。
//
// 只覆盖**真消息**那条路径(toUnified)。debug 帧日志(inbound_debug.go)与 notice 的
// self 命中(notice.go / event.go)各有各的语义,本片不动它们。
import (
"git.yeij.top/AskaEth/Cyrene_v2/internal/channel/adapter"
)
// mentionAllQQ 是 OneBot v11 at 段里 **@全体成员** 的 qq 取值
// (数组段 `{"type":"at","data":{"qq":"all"}}`,CQ 码形态 `[CQ:at,qq=all]`)。
// design/26 §2.4 把它登记为随消息到达的**结构化标志**(mention_all),不另立一类事件。
// 该字面量是 OneBot 协议约定,所以落在平台侧(这里),不污染平台中立的 adapter 包。
const mentionAllQQ = "all"
// mentionsContainAll 报告 mentions 里是否含 @全体。只比对结构化的 UserID 字段,
// 不看正文;判据是精确相等(QQ 号是纯数字,与 "all" 不可能撞号)。
func mentionsContainAll(mentions []adapter.Mention) bool {
for _, m := range mentions {
if m.UserID == mentionAllQQ {
return true
}
}
return false
}
// applyAddressing 把平台元数据写成统一契约里的结构化字段:SelfID(她自己在该平台的
// 账号 id)、MentionAll(是否 @全体)、AddressedToMe(本条是否指向她本人,推导见
// adapter.UnifiedMessage.AddressedToSelf)。三个字段同源同步,下游读哪个都不会自相矛盾。
//
// 调用点必须在 ChannelType 判定**之后**:私聊与群聊的 AddressedToMe 取值不同。
// self_id 取不到(字段缺失 / 为 0)时 SelfID 如实留空、AddressedToMe 随之 false ——
// fail-closed,绝不退回正文匹配(见 adapter.MentionedSelf)。
func applyAddressing(msg *adapter.UnifiedMessage, selfID string, mentions []adapter.Mention) {
msg.SelfID = selfID
msg.MentionAll = mentionsContainAll(mentions)
msg.AddressedToMe = msg.AddressedToSelf()
}