llms.txt: machine-readable documentation index. Markdown version of this page is also available.

Simple Robot 5.x Help

消息元素

消息元素实现

所有的 Message.Element 特殊实现类型均定义在包 love.forte.simbot.component.qguild.message 中。

它们都继承了 love.forte.simbot.component.qguild.message.QGMessageElement。

QGArk

对 API 模块中 Ark 消息的包装体,可用来发送 Ark 消息。

QGContentText
QGMarkdown
QGAttachmentMessage

接收到的附件消息,字段说明见下文的附件章节。

QGEmbed

对 API 模块中 Embed 消息的包装体,可用来发送 Embed 消息。

QGReference

发送消息时,QQ频道的消息引用。与官方发送消息API中的 reference 对应。

QGReplyTo

发送消息时,指定一个需要回复的目标消息ID。

QGMedia
QGKeyboards

对 API 模块中 MessageKeyboards 的包装体,可用来发送包含多行、多按钮的 Markdown 消息按钮。 旧的 QGKeyboard 只包装单个 MessageKeyboard ,自 4.4.0 起应改用 QGKeyboards。

QGKeyboard

旧的单按钮包装体,只能包装单个 MessageKeyboard ,无法完整表达官方 keyboard.content.rows[].buttons[] 结构。 请使用 QGKeyboards 替代。

附件

QGAttachmentMessage 用于接收附件,暂不支持直接发送。 url 为下载地址,缺少协议前缀时会补充 https://。

附件信息通过以下类型化字段提供。

字段

类型与含义

filename

String? ,文件名

width/height

Int? ,图片宽高,单位为像素

size

Long? ,文件大小,单位为字节

contentType

String? ,附件内容类型

voiceWavUrl

String? ,语音转换后的 WAV 地址

asrReferText

String? ,语音识别参考结果

attachmentId

String? ,QQ 附件 ID,需要选择加入 QGUnstableProperty

source 提供原始的 Message.Attachment 。其中的 url 可能没有协议前缀。 未由平台提供的可选属性为 null。

旧的 properties 字符串属性表、构造函数、 copy() 和解构方法已废弃。 旧 id 也已废弃,其值仍为下载 URL 的 ID 包装;需要下载地址时使用 url ,需要平台附件 ID 时使用 attachmentId。

序列化仍使用 qg.attachment 类型名,新格式输出类型化字段,反序列化兼容旧 properties 中的字段。 历史自定义字符串属性仍会保留。

发送消息

在simbot中,使用组件的消息元素与使用其他消息元素别无二致, 通常使用 SendSupport 和 ReplySupport 的实现类中提供的 send(...) 和 reply(..) API 发送消息。

前者多由 行为对象 中的一些类型实现(例如QGMember、 QGTextChannel), 而后者则通常由与消息相关的事件实现(例如 QGAtMessageCreateEvent)。

此处以 QGTextChannel 为例, send 可以使用拼接后的消息链、字符串或单独的消息元素作为参数。

val channel: QGTextChannel = ... channel.send("消息内容") channel.send("消息内容".toText() + At("user id".ID))
QGTextChannel channel = ... var sendTask1 = channel.sendAsync("消息内容"); var sendTask2 = channel.sendAsync(Messages.of( Text.of("文本消息"), At.of(Identifies.of("user id")) ));
QGTextChannel channel = ...; channel.sendBlocking("消息内容"); channel.sendBlocking(Messages.of( Text.of("文本消息"), At.of(Identifies.of("user id")) ));
QGTextChannel channel = ...; channel.sendReserve("消息内容") .transform(SuspendReserves.mono()) .subscribe(receipt -> { ... }); channel.sendReserve(Messages.of( Text.of("文本消息"), At.of(Identifies.of("user id")) )) .transform(SuspendReserves.mono()) .subscribe(receipt -> { ... });

消息撤回

自 5.0 起,QQ 群消息事件的 messageContent 也支持撤回当前收到的群消息:

process<QGGroupMessageCreateEvent> { event -> event.messageContent.delete() }

QGGroupAtMessageCreateEvent 的 messageContent 也具有相同能力。 C2C 单聊消息虽然同样提供 messageContent ,但其中没有可用于撤回的目标消息上下文, 因此调用 delete() 时仍不支持撤回。频道消息使用频道消息撤回接口,具体参见 DeleteChannelMessageApi; 旧的 DeleteMessageApi 仅为兼容保留。

从 QGGroup 或 QGFriend 发送、回复消息得到的 QGMessageReceipt 会保留目标 OpenID, 因此可以撤回机器人刚发送的消息。消息链被拆分为多条消息时,聚合回执的 delete() 会依次撤回其中的消息:

val groupReceipt = group.send("临时提示") groupReceipt.delete() val friendReceipt = friend.send("C2C 临时消息") friendReceipt.delete()

群消息与 C2C 单聊消息通常只能撤回发送时间不超过两分钟的消息。 群管理员可以撤回机器人自身和普通成员的消息,普通成员只能撤回机器人自身发送的消息; C2C 单聊撤回接口只能撤回机器人发送给用户的消息。

如果当前实现没有撤回上下文,默认会抛出 UnsupportedOperationException; 可以传入 StandardDeleteOption.IGNORE_ON_UNSUPPORTED 忽略不支持的场景。 QQ 服务端拒绝撤回时默认继续抛出异常,也可以使用 StandardDeleteOption.IGNORE_ON_FAILURE 忽略失败。

按目的地将普通文本作为 Markdown 发送

自 4.5.0 起,可以通过 Bot 配置文件 的 contentAsMarkdownAll 和 contentAsMarkdown ,分别为 CHANNEL、 DMS、 GROUP、 USER 四种目的地控制普通文本的发送载荷。

启用后,普通 Text 、文本消息链以及其中的 @、表情等文本内容会写入 Markdown 的 content 。这不会替代显式构造 QGMarkdown :当你需要发送模板 Markdown 或自行指定 Markdown 内容时,仍应使用 QGMarkdown。

Markdown 消息按钮

自 4.4.0 起,群聊和单聊 Markdown 消息按钮使用 QGKeyboards/MessageKeyboards 表示。 它支持按行组织多个按钮,并在发送体中仍序列化为官方 API 的 keyboard 字段。

val keyboards = QGKeyboards { content { row { button { renderData("确认", visitedLabel = "已确认", style = 1) action { type = 1 data = "confirm" unsupportTips = "当前客户端暂不支持" permissionAllAccessible() } } } row { addButton(MessageKeyboard.create("template-id")) } } } group.send(QGMarkdown.create("请选择") + keyboards) // 只有一行按钮时,也可以直接包装 MessageKeyboards。 val singleRow = MessageKeyboards.create( listOf( MessageKeyboard.create("template-a"), MessageKeyboard.create("template-b") ) ) group.send(QGMarkdown.create("请选择") + QGKeyboards.create(singleRow))
var keyboards = MessageKeyboards.create(List.of( MessageKeyboard.create("template-a"), MessageKeyboard.create("template-b") )); var sendTask = group.sendAsync(Messages.of( QGMarkdown.create("请选择"), QGKeyboards.create(keyboards) ));
var keyboards = MessageKeyboards.create(List.of( MessageKeyboard.create("template-a"), MessageKeyboard.create("template-b") )); group.sendBlocking(Messages.of( QGMarkdown.create("请选择"), QGKeyboards.create(keyboards) ));
var keyboards = MessageKeyboards.create(List.of( MessageKeyboard.create("template-a"), MessageKeyboard.create("template-b") )); group.sendReserve(Messages.of( QGMarkdown.create("请选择"), QGKeyboards.create(keyboards) )).transform(SuspendReserves.mono()).subscribe(receipt -> { ... });
29 October 2026