fix(channelbridge): IM 发送过滤 action/narration + <p>拆多气泡 + 0.5-2s 间隔
把回复转发给 IM 适配器(sendReply)时剥掉 <action>/<narration> 动作/内心独白(Web 端 才渲染灰斜体,IM 只能收纯文本),并按 <p> 段落拆成多条气泡分别发送;多气泡发送间隔 随机 0.5~2s(仅 IM,Web 前端不延迟)。新增 sanitize.go stripNarration/splitBubbles/ bubbleGap + 测试。
This commit is contained in:
1 parent
dcb0b33954
commit
5a0c1e2fd1
11 files changed
+790
-12
No files matched your search
@@ -597,19 +597,38 @@ func (b *Bridge) sendReply(ctx context.Context, in adapter.UnifiedMessage, a ada
|
||||
if a == nil {
|
||||
return fmt.Errorf("channelbridge: no adapter for platform %q", in.Platform)
|
||||
}
|
||||
out := adapter.UnifiedMessage{
|
||||
Platform: in.Platform,
|
||||
ChannelType: in.ChannelType,
|
||||
ChannelID: in.ChannelID,
|
||||
GroupID: in.GroupID,
|
||||
GroupName: in.GroupName,
|
||||
SenderID: in.SenderID,
|
||||
Sender: in.Sender,
|
||||
Content: text,
|
||||
ContentType: adapter.ContentText,
|
||||
Timestamp: time.Now().UTC(),
|
||||
// IM channels receive the reply as one or more bubbles: role-play/action/narration
|
||||
// markup (rendered as muted italic on the Web) is stripped, and each <p> paragraph
|
||||
// becomes its own bubble/message (design/17 §2). A reply that was only an action is
|
||||
// dropped rather than sent empty. A multi-bubble reply spaces its sends 0.5-2s apart
|
||||
// so a burst doesn't flood the channel; the Web frontend has no such delay.
|
||||
bubbles := splitBubbles(text)
|
||||
if len(bubbles) == 0 {
|
||||
b.log.Debug("reply has no plain text, skipped", "platform", in.Platform, "channel", in.ChannelID)
|
||||
return nil
|
||||
}
|
||||
return a.SendMessage(ctx, adapter.UnifiedResponse{Messages: []adapter.UnifiedMessage{out}})
|
||||
for i, content := range bubbles {
|
||||
if i > 0 {
|
||||
time.Sleep(bubbleGap())
|
||||
}
|
||||
out := adapter.UnifiedMessage{
|
||||
Platform: in.Platform,
|
||||
ChannelType: in.ChannelType,
|
||||
ChannelID: in.ChannelID,
|
||||
GroupID: in.GroupID,
|
||||
GroupName: in.GroupName,
|
||||
SenderID: in.SenderID,
|
||||
Sender: in.Sender,
|
||||
Content: content,
|
||||
ContentType: adapter.ContentText,
|
||||
Timestamp: time.Now().UTC(),
|
||||
}
|
||||
// Each bubble is its own send so the gap lands between messages.
|
||||
if err := a.SendMessage(ctx, adapter.UnifiedResponse{Messages: []adapter.UnifiedMessage{out}}); err != nil {
|
||||
return fmt.Errorf("channelbridge: send bubble #%d of %d: %w", i+1, len(bubbles), err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// adapter returns the registered adapter for a platform name, or nil.
|
||||
|
||||
Reference in new issue
Block a user