常见问题
stream 为什么有时候是布尔值,有时候是对象?
这是当前适配器的兼容设计。
stream: true
表示使用适配器内部的快捷流式首包写法,也就是自动附加:
state = 1
stream: { ... }
表示你自己直接传 QQ 官方原始流式对象。
例如:
ts
stream: {
state: 10,
id: streamId,
index: 1,
reset: true,
}也就是说,stream 现在统一只有一个名字,只是支持两种值类型。
stream: true 为什么不会自动结束?
这是当前刻意保留的行为。 适配器只负责帮你进入流式状态,不自动决定何时结束。
原因是不同消息的结束时机很难统一,而且自动补 state = 10 容易导致:
- 重复消息
- 空消息
- 主动消息权限错误
- 不同客户端表现不一致
所以现在如果你要结束流式,请自己传原始 stream 对象。
为什么 Windows QQ 和手机 QQ 的 Markdown 显示不一样?
这是 QQ 客户端本身的差异。 同一条原生 Markdown 消息,在不同端的渲染和复制结果可能不同,尤其是下面这些内容:
- 方括号链接
- 分隔线
- 代码块
- 蓝字按钮
如果某类消息需要跨端显示尽量一致,建议:
- 保持 Markdown 简单
- 少用复杂链接语法
- 必要时关闭
autoStreamText
autoStreamText 开了以后,为什么普通文本看起来像 Markdown?
因为这个开关的实现方式就是:
- 检测到纯文本
- 改成 QQ 原生 Markdown 消息发送
- 再附加流式首包
所以开启后,本质上已经不是“普通文本消息”了。
私聊 channelId 为什么是 private:xxxx?
这是适配器内部约定的私聊频道 ID 格式:
text
private:{userId}这样可以明确区分:
- 群聊
channelId - 私聊
channelId
并且你可以统一调用:
sendMessage(channelId, ...)deleteMessage(channelId, messageId)
适配器会在内部自动还原真实 QQ 用户 ID。
qq zombied connection 是什么?
这是心跳检测发现连接已经僵死。 适配器现在会在这种情况下立即重连,而不是完全依赖默认的重试间隔。
所以看到这条日志不一定代表插件出故障,更像是一次主动的快速自恢复。
为什么群里能拿到用户名,私聊里却拿不到?
这是 QQ 官方事件内容本身的差异。 有些 WebSocket 事件会带 author.username,有些不会。
适配器现在会:
- 优先使用事件里带来的用户名
- 写入数据库
- 后续再从缓存或数据库回填到
session.username
所以第一次可能拿不到,后面同一用户就更稳定了。