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 构造消息链

val chain = messageChainOf(PlainText("..."), Image("..."), ...)
val chain = buildMessageChain {
+"你想要的图片是:"
+Image("...")
}
val chain = PlainText("Hello ") + PlainText("Mirai!") // chain: 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

在 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)
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 时这种限制会被体现.

当添加只允许单独存在的消息元素到一个消息链时, 已有的元素可能会被删除或替换. 详见 AbstractPolymorphicMessageKeyConstrainSingle.

操作消息链

MessageChain 继承 List<SingleMessage>. 可以以 List 的方式处理 MessageChain.

额外地, 若要获取一个 ConstrainSingle 的元素, 可以通过 ConstrainSingle.key:

val quote = chain[QuoteReply] // Kotlin

QuoteReply quote = chain.get(QuoteReply.Key) // Java

相关地还可以使用 MessageChain.containsMessageChain.getOrFail

直接索引访问

MessageChain 实现接口 List, 可以通过索引 get(index) 来访问. 由于 MessageChain 是稳定的, 这种访问操作也是稳定的.

但在处理来自服务器的 MessageChain 时, 请尽量避免这种直接索引访问. 来自服务器的消息的组成有可能会变化, 可能会有新的 MessageMetadata 加入. 例如用户发送了两条内容相同的消息, 但其中一条带有引用回复而另一条没有, 则两条消息的索引可能有变化 (当然内容顺序不会改变, 只是 QuoteReply 的位置有可能会变化). 因此在使用直接索引访问时要格外注意兼容性, 故不推荐这种访问方案.

撤回和引用

要撤回消息, 查看 MessageSource

Kotlin 扩展

属性委托

val at: At? by chain.orNull()
val at: At by chain.orElse { /* 返回一个 At */}
val at: At by chain

筛选得到 SequenceList

序列化

kotlinx-serialization 序列化

Mirai Code 序列化

详见 MiraiCode

Types

Companion
Link copied to clipboard
object Companion
Serializer
Link copied to clipboard
object Serializer : KSerializer<MessageChain>

MessageChain 作为 List<SingleMessage> 序列化. 使用 多态序列化.

Functions

appendMiraiCodeTo
Link copied to clipboard
open override fun appendMiraiCodeTo(builder: StringBuilder)
contains
Link copied to clipboard
abstract operator override fun contains(element: SingleMessage): Boolean

open operator fun <M : SingleMessage> contains(key: MessageKey<M>): Boolean

当存在 ConstrainSingle.keykeySingleMessage 实例时返回 true.

containsAll
Link copied to clipboard
abstract override fun containsAll(elements: Collection<SingleMessage>): Boolean
contentEquals
Link copied to clipboard
open fun contentEquals(another: String, ignoreCase: Boolean = false): Boolean

判断内容是否与 another 相等.

open fun contentEquals(another: Message, ignoreCase: Boolean = false): Boolean

判断内容是否与 another 相等即 thisanothercontentToString 相等.

open fun contentEquals(another: Message, ignoreCase: Boolean = false, strict: Boolean = false): Boolean

判断内容是否与 another 相等即 thisanothercontentToString 相等. stricttrue 时, 还会额外判断每个消息元素的类型, 顺序和属性. 如 Image 会判断 Image.imageId

contentToString
Link copied to clipboard
abstract fun contentToString(): String

转为最接近官方格式的字符串. 如 At(member) + "test" 将转为 "@群名片 test".

followedBy
Link copied to clipboard
open fun followedBy(tail: Message): MessageChain

thistail 连接.

get
Link copied to clipboard
abstract operator fun get(index: Int): SingleMessage

open operator fun <M : SingleMessage> get(key: MessageKey<M>): M?

获取第一个类型为 keyMessage 实例. 若不存在此实例, 返回 null.

indexOf
Link copied to clipboard
abstract fun indexOf(element: SingleMessage): Int
isEmpty
Link copied to clipboard
abstract override fun isEmpty(): Boolean
iterator
Link copied to clipboard
abstract operator override fun iterator(): Iterator<SingleMessage>
lastIndexOf
Link copied to clipboard
abstract fun lastIndexOf(element: SingleMessage): Int
listIterator
Link copied to clipboard
abstract fun listIterator(): ListIterator<SingleMessage>
abstract fun listIterator(index: Int): ListIterator<SingleMessage>
plus
Link copied to clipboard
open operator fun plus(another: Array<out Message>): MessageChain

another 按顺序连接到这个消息的尾部.

open operator fun plus(another: CharSequence): MessageChain

another 作为 PlainText 连接到这个消息的尾部.

open operator fun plus(another: String): MessageChain

another 作为 PlainText 连接到这个消息的尾部.

open operator fun plus(another: Iterable<String>): MessageChain

another 按顺序连接到这个消息的尾部.

open operator fun plus(another: Iterable<Message>): MessageChain

another 按顺序连接到这个消息的尾部.

open operator fun plus(another: Sequence<Message>): MessageChain

another 按顺序连接到这个消息的尾部.

open operator fun plus(another: Message): MessageChain

another 按顺序连接到这个消息的尾部.

open operator fun plus(another: MessageChain): MessageChain

another 按顺序连接到这个消息的尾部.

open operator fun plus(another: SingleMessage): MessageChain

another 连接到这个消息的尾部.

serializeToMiraiCode
Link copied to clipboard
open fun serializeToMiraiCode(): String

转换为 mirai 码.

subList
Link copied to clipboard
abstract fun subList(fromIndex: Int, toIndex: Int): List<SingleMessage>
toString
Link copied to clipboard
abstract override fun toString(): String

得到包含 mirai 消息元素代码的, 易读的字符串. 如 At(member) + "test" 将转为 "[mirai:at:qqId]test".

Properties

size
Link copied to clipboard
abstract override val size: Int

Inheritors

EmptyMessageChain
Link copied to clipboard

Extensions

anyIsInstance
Link copied to clipboard
inline fun <M : SingleMessage> MessageChain.anyIsInstance(): Boolean

this 中存在 M 的实例时返回 true.

bot
Link copied to clipboard
val MessageChain.bot: Bot

消息内部 ids.

contentsList
Link copied to clipboard
fun MessageChain.contentsList(): List<MessageContent>
contentsSequence
Link copied to clipboard
fun MessageChain.contentsSequence(): Sequence<MessageContent>

获取 Sequence<MessageContent> 相当于 this.asSequence().filterIsInstance<MessageContent>()

deserializeFromMiraiCode
Link copied to clipboard
fun MessageChain.deserializeFromMiraiCode(miraiCode: String, contact: Contact? = null): MessageChain

解析形如 "mirai:" 的 mirai 码, 即 CodableMessage.serializeToMiraiCode 返回的内容.

findIsInstance
Link copied to clipboard
inline fun <M : SingleMessage?> MessageChain.findIsInstance(): M?

获取第一个 M 实例. 在不存在时返回 null.

firstIsInstance
Link copied to clipboard
inline fun <M : SingleMessage> MessageChain.firstIsInstance(): M

获取第一个 M 实例. 在不存在时抛出 NoSuchElementException.

firstIsInstanceOrNull
Link copied to clipboard
inline fun <M : SingleMessage?> MessageChain.firstIsInstanceOrNull(): M?

获取第一个 M 实例. 在不存在时返回 null.

getOrFail
Link copied to clipboard
inline fun <M : SingleMessage> MessageChain.getOrFail(key: MessageKey<M>, crossinline lazyMessage: (key: MessageKey<M>) -> String = { key.toString() }): M

获取第一个类型为 keyMessage 实例, 在找不到此类型的元素时抛出 NoSuchElementException

getValue
Link copied to clipboard
inline operator fun <T : SingleMessage> MessageChain.getValue(thisRef: Any?, property: KProperty<*>): T

提供一个类型的值的委托. 若不存在则会抛出异常 NoSuchElementException

ids
Link copied to clipboard
val MessageChain.ids: IntArray

消息 ids.

internalId
Link copied to clipboard
val MessageChain.internalId: IntArray

消息内部 ids.

metadataList
Link copied to clipboard
fun MessageChain.metadataList(): List<MessageMetadata>
metadataSequence
Link copied to clipboard
fun MessageChain.metadataSequence(): Sequence<MessageMetadata>

获取 Sequence<MessageMetadata> 相当于 this.asSequence().filterIsInstance<MessageMetadata>()

orElse
Link copied to clipboard
inline fun <T : R, R : SingleMessage?> MessageChain.orElse(lazyDefault: () -> R): OrNullDelegate<R>

提供一个类型的 Message 的委托, 若不存在这个类型的 Message 则委托会提供 null

orNull
Link copied to clipboard
inline fun <T : SingleMessage> MessageChain.orNull(): OrNullDelegate<T?>

提供一个类型的 Message 的委托, 若不存在这个类型的 Message 则委托会提供 null

quote
Link copied to clipboard
fun MessageChain.quote(): QuoteReply

引用这条消息. 仅从服务器接收的消息 (即来自 MessageEvent) 才可以通过这个方式被引用.

recall
Link copied to clipboard
suspend fun MessageChain.recall()

撤回这条消息. 可撤回自己 2 分钟内发出的消息, 和任意时间的群成员的消息.

recallIn
Link copied to clipboard
fun MessageChain.recallIn(millis: Long): AsyncRecallResult

在一段时间后撤回这条消息.

serializeToJsonString
Link copied to clipboard
fun MessageChain.serializeToJsonString(json: <ERROR CLASS> = getDefaultJson()): String

MessageChain 序列化为 JSON 字符串.

serializeToString
Link copied to clipboard
fun MessageChain.serializeToString(format: StringFormat): String

MessageChain 序列化为指定格式的字符串.

source
Link copied to clipboard
val MessageChain.source: MessageSource

获取这条消息的 消息源.

sourceOrNull
Link copied to clipboard
val MessageChain.sourceOrNull: MessageSource?

获取这条消息的 消息源.

time
Link copied to clipboard
val MessageChain.time: Int

消息时间.