MessageChain
消息链, List<SingleMessage>
, 即 单个消息元素 的有序集合.
MessageChain 代表一条完整的聊天中的消息, 可包含 带内容的消息 MessageContent
和 不带内容的元数据 MessageMetadata
.
元素类型
MessageContent 如 纯文字, 图片, 语音, 是能被用户看到的内容.
MessageMetadata 是用来形容这条消息的状态的数据, 因此称为 元数据 (metadata). 元数据目前只分为 消息来源 MessageSource
和 引用回复 QuoteReply
.
MessageSource 存储这条消息的发送人, 接收人, 识别 ID (服务器提供), 发送时间等信息. MessageSource 是精确的. 凭 MessageSource 就可以在服务器上定位一条消息, 因此可以用来 撤回消息.
QuoteReply 是一个标记, 表示这条消息引用了另一条消息 (在官方客户端中可通过 "回复" 功能发起引用). QuoteReply.source 则指代那条被引用的消息. 由于 MessageSource 是精确的, 如果对 QuoteReply.source 使用 MessageSource.recall, 则可以撤回那条被引用的消息.
获得消息链
在消息事件中可以获得消息内容作为 MessageChain: MessageEvent.message
在主动发送消息时, 可使用如下方案.
在 Kotlin 构造消息链
获取不包含任何元素的消息链: EmptyMessageChain
messageChainOf: 类似 listOf, 将多个 Message 构造为 MessageChain:
val chain = messageChainOf(PlainText("..."), Image("..."), ...)
buildMessageChain: 使用 DSL 构建器.
val chain = buildMessageChain {
+"你想要的图片是:"
+Image("...")
}
Message.plus: 将两个消息相连成为一个消息链:
val chain = PlainText("Hello ") + PlainText("Mirai!") // chain: MessageChain
toMessageChain 将 Iterable, Array, Sequence, Iterator, Flow, Stream 转换为 MessageChain. 相关定义为:
public fun Sequence<Message>.toMessageChain(): MessageChain
public fun Iterable<Message>.toMessageChain(): MessageChain
public fun Iterator<Message>.toMessageChain(): MessageChain
public fun Stream<Message>.toMessageChain(): MessageChain
public fun Flow<Message>.toMessageChain(): MessageChain
public fun Array<Message>.toMessageChain(): MessageChain
Message.toMessageChain 将单个 Message 包装成一个单元素的 MessageChain
在 Java 构造消息链
MessageUtils.newChain
: 有多个重载, 相关定义如下:
public static MessageChain newChain(Message messages...)
public static MessageChain newChain(Iterable<Message> iterable)
public static MessageChain newChain(Iterator<Message> iterator)
public static MessageChain newChain(Stream<Message> stream)
public static MessageChain newChain(Message[] array)
Message.plus: 将两个消息相连成为一个消息链:
MessageChain chain = new PlainText("Hello ").plus(new PlainText("Mirai!"))
MessageChainBuilder builder = MessageChainBuilder.create();
builder.append(new PlainText("Hello "));
builder.append(new PlainText(" Mirai!"));
MessageChain chain = builder.build();
元素唯一性
部分消息类型如 语音, 小程序 在官方客户端限制中只允许单独存在于一条消息. 在创建 MessageChain 时这种限制会被体现.
当添加只允许单独存在的消息元素到一个消息链时, 已有的元素可能会被删除或替换. 详见 AbstractPolymorphicMessageKey 和 ConstrainSingle.
操作消息链
MessageChain 继承 List<SingleMessage>
. 可以以 List 的方式处理 MessageChain.
额外地, 若要获取一个 ConstrainSingle 的元素, 可以通过 ConstrainSingle.key:
val quote = chain[QuoteReply] // Kotlin
QuoteReply quote = chain.get(QuoteReply.Key) // Java
相关地还可以使用 MessageChain.contains 和 MessageChain.getOrFail
直接索引访问
MessageChain 实现接口 List, 可以通过索引 get(index)
来访问. 由于 MessageChain 是稳定的, 这种访问操作也是稳定的.
但在处理来自服务器的 MessageChain 时, 请尽量避免这种直接索引访问. 来自服务器的消息的组成有可能会变化, 可能会有新的 MessageMetadata 加入. 例如用户发送了两条内容相同的消息, 但其中一条带有引用回复而另一条没有, 则两条消息的索引可能有变化 (当然内容顺序不会改变, 只是 QuoteReply 的位置有可能会变化). 因此在使用直接索引访问时要格外注意兼容性, 故不推荐这种访问方案.
避免索引访问以提高性能
自 2.12 起, MessageChain 内部结构有性能优化. 该优化大幅降低元素数量多的 MessageChain 的连接的时间复杂度. 性能优化默认生效, 但若使用 get, subList 等 List 于 Collection 之外的方法时则会让该优化失效 (相比 2.12 以前不会丢失性能, 只是没有优化).
撤回和引用
要撤回消息, 查看 MessageSource
MessageChain.quote
MessageChain.recall
MessageChain.recallIn
Kotlin 扩展
属性委托
val at: At? by chain.orNull()
val at: At by chain.orElse { /* 返回一个 At */}
val at: At by chain
筛选得到 Sequence 与 List
序列化
kotlinx-serialization 序列化
使用 MessageChain.serializeToJsonString 将 MessageChain 序列化为 JSON String.
使用 MessageChain.deserializeFromJsonString 将 JSON String 反序列化为 MessageChain.
Mirai Code 序列化
详见 MiraiCode
使用 MessageChain.serializeToMiraiCode 将 MessageChain 序列化为 Mirai Code String.
使用 MessageChain.deserializeFromMiraiCode 将 Mirai Code String 反序列化为 MessageChain.
Inheritors
Types
Functions
当存在 ConstrainSingle.key 为 key 的 SingleMessage 实例时返回 true
.
判断内容是否与 another 相等.
判断内容是否与 another 相等即 this
与 another 的 contentToString 相等.
判断内容是否与 another 相等即 this
与 another 的 contentToString 相等.
获取 Sequence<MessageContent>
相当于 this.asSequence().filterIsInstance<MessageContent>()
转为接近官方格式的字符串, 即 "内容". 如 At(member) + "test"
将转为 "@QQ test"
.
解析形如 "mirai:" 的 mirai 码, 即 CodableMessage.serializeToMiraiCode 返回的内容.
获取第一个 M 实例. 在不存在时返回 null
.
获取第一个 M 实例. 在不存在时抛出 NoSuchElementException.
获取第一个 M 实例. 在不存在时返回 null
.
将 this
和 tail 连接.
获取第一个类型为 key 的 Message 实例, 在找不到此类型的元素时抛出 NoSuchElementException
提供一个类型的值的委托. 若不存在则会抛出异常 NoSuchElementException
当消息内容为空白时返回 true
.
当消息内容为空时返回 true
.
获取 Sequence<MessageMetadata>
相当于 this.asSequence().filterIsInstance<MessageMetadata>()
创建一个消息链, 将 another 连接到这个消息的尾部. 这不会改变本 Message, 而是会创建新的 MessageChain 实例. 返回的 MessageChain 实例的第一个元素为本 Message, 随后为按顺序的 another 中的元素.
创建一个消息链, 将 another 连接到这个消息的尾部. 这不会改变本 Message, 而是会创建新的 MessageChain 实例. 返回的 MessageChain 实例的第一个元素为本 Message, 随后为按顺序的 another 中的元素.
创建一个消息链, 将 another 连接到这个消息的尾部. 这不会改变本 Message, 而是会创建新的 MessageChain 实例. 返回的 MessageChain 实例的第一个元素为本 Message, 随后为按顺序的 another 中的元素.
创建一个消息链, 将 another 连接到这个消息的尾部. 这不会改变本 Message, 而是会创建新的 MessageChain 实例. 返回的 MessageChain 实例的第一个元素为本 Message, 随后为按顺序的 another 中的元素.
创建一个消息链, 将 another 连接到这个消息的尾部. 这不会改变本 Message, 而是会创建新的 MessageChain 实例. 返回的 MessageChain 实例的第一个元素为本 Message, 随后为按顺序的 another 中的元素.
创建一个消息链, 将 another 连接到这个消息的尾部. 这不会改变本 Message, 而是会创建新的 MessageChain 实例. 返回的 MessageChain 实例的第一个元素为本 Message, 随后为按顺序的 another 中的元素.
创建一个消息链, 将 another 连接到这个消息的尾部. 这不会改变本 Message, 而是会创建新的 MessageChain 实例. 返回的 MessageChain 实例的第一个元素为本 Message, 随后为按顺序的 another 中的元素.
创建一个消息链, 将 another 连接到这个消息的尾部. 这不会改变本 Message, 而是会创建新的 MessageChain 实例. 返回的 MessageChain 实例的第一个元素为本 Message, 随后为按顺序的 another 中的元素.
创建一个消息链, 将 another 连接到这个消息的尾部. 这不会改变本 Message, 而是会创建新的 MessageChain 实例. 返回的 MessageChain 实例的第一个元素为本 Message, 随后为按顺序的 another 中的元素.
引用这条消息. 仅从服务器接收的消息 (即来自 MessageEvent) 才可以通过这个方式被引用.
在一段时间后撤回这条消息.
将 MessageChain 序列化为 JSON 字符串.
转换为 mirai 码.
转换得到 mirai 码.
将 MessageChain 序列化为指定格式的字符串.
转换为 ForwardMessage
扁平化 this 并创建一个 MessageChain.