Commit 97334902 authored by Him188's avatar Him188

Add docs

parent ed11f38b
...@@ -26,13 +26,15 @@ import kotlin.jvm.JvmName ...@@ -26,13 +26,15 @@ import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic import kotlin.jvm.JvmSynthetic
/** /**
* 发送消息后得到的回执. 可用于撤回. * 发送消息后得到的回执. 可用于撤回, 引用回复等.
*
* 此对象持有 [Contact] 的弱引用, [Bot] 离线后将会释放引用, 届时 [target] 将无法访问.
* *
* @param source 指代发送出去的消息 * @param source 指代发送出去的消息
* @param target 消息发送对象 * @param target 消息发送对象
* *
* @see quote 引用这条消息. 即引用机器人自己发出去的消息
* @see quoteReply 引用并回复这条消息.
* @see recall 撤回这条消息
*
* @see Group.sendMessage 发送群消息, 返回回执(此对象) * @see Group.sendMessage 发送群消息, 返回回执(此对象)
* @see User.sendMessage 发送群消息, 返回回执(此对象) * @see User.sendMessage 发送群消息, 返回回执(此对象)
* @see Member.sendMessage 发送临时消息, 返回回执(此对象) * @see Member.sendMessage 发送临时消息, 返回回执(此对象)
...@@ -148,6 +150,16 @@ suspend inline fun <C : Contact> MessageReceipt<C>.quoteReply(message: String): ...@@ -148,6 +150,16 @@ suspend inline fun <C : Contact> MessageReceipt<C>.quoteReply(message: String):
inline val MessageReceipt<*>.sourceId: Int inline val MessageReceipt<*>.sourceId: Int
get() = this.source.id get() = this.source.id
/**
* 获取源消息 [MessageSource.internalId]
*
* @see MessageSource.id
*/
@get:JvmSynthetic
inline val MessageReceipt<*>.sourceInternalId: Int
get() = this.source.internalId
/** /**
* 获取源消息 [MessageSource.time] * 获取源消息 [MessageSource.time]
* *
......
...@@ -19,7 +19,8 @@ import net.mamoe.mirai.message.MessageReceipt ...@@ -19,7 +19,8 @@ import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.Message.Key import net.mamoe.mirai.message.data.Message.Key
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.PlannedRemoval import net.mamoe.mirai.utils.PlannedRemoval
import net.mamoe.mirai.utils.SinceMirai import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic import kotlin.jvm.JvmSynthetic
...@@ -29,7 +30,7 @@ import kotlin.jvm.JvmSynthetic ...@@ -29,7 +30,7 @@ import kotlin.jvm.JvmSynthetic
* *
* [消息][Message] 分为 * [消息][Message] 分为
* - [SingleMessage]: * - [SingleMessage]:
* - [MessageMetadata] 消息元数据, 包括: [消息来源][MessageSource], [引用回复][QuoteReply]. * - [MessageMetadata] 消息元数据, 即消息的属性. 包括: [消息来源][MessageSource], [引用回复][QuoteReply].
* - [MessageContent] 含内容的消息, 包括: [纯文本][PlainText], [@群员][At], [@全体成员][AtAll] 等. * - [MessageContent] 含内容的消息, 包括: [纯文本][PlainText], [@群员][At], [@全体成员][AtAll] 等.
* - [MessageChain]: 不可变消息链, 链表形式链接的多个 [SingleMessage] 实例. * - [MessageChain]: 不可变消息链, 链表形式链接的多个 [SingleMessage] 实例.
* *
...@@ -57,11 +58,6 @@ import kotlin.jvm.JvmSynthetic ...@@ -57,11 +58,6 @@ import kotlin.jvm.JvmSynthetic
* #### 实现规范 * #### 实现规范
* 除 [MessageChain] 外, 所有 [Message] 的实现类都有伴生对象实现 [Key] 接口. * 除 [MessageChain] 外, 所有 [Message] 的实现类都有伴生对象实现 [Key] 接口.
* *
* #### [CharSequence] 继承
* 所有 [CharSequence] 的行为均由 [toString] 委托.
*
* 即, `appendable.append(message)` 相当于 `appendable.append(message.toString())`
*
* #### 发送消息 * #### 发送消息
* - 通过 [Contact] 中的成员函数: [Contact.sendMessage] * - 通过 [Contact] 中的成员函数: [Contact.sendMessage]
* - 通过 [Message] 的扩展函数: [Message.sendTo] * - 通过 [Message] 的扩展函数: [Message.sendTo]
...@@ -186,13 +182,8 @@ interface Message { // must be interface. Don't consider any changes. ...@@ -186,13 +182,8 @@ interface Message { // must be interface. Don't consider any changes.
} }
operator fun plus(another: Message): MessageChain = this.followedBy(another) operator fun plus(another: Message): MessageChain = this.followedBy(another)
// don't remove! avoid resolution ambiguity between `CharSequence` and `Message`
operator fun plus(another: SingleMessage): MessageChain = this.followedBy(another) operator fun plus(another: SingleMessage): MessageChain = this.followedBy(another)
operator fun plus(another: String): MessageChain = this.followedBy(another.toMessage()) operator fun plus(another: String): MessageChain = this.followedBy(another.toMessage())
// `+ ""` will be resolved to `plus(String)` instead of `plus(CharSeq)`
operator fun plus(another: CharSequence): MessageChain = this.followedBy(another.toString().toMessage()) operator fun plus(another: CharSequence): MessageChain = this.followedBy(another.toString().toMessage())
} }
...@@ -200,7 +191,9 @@ interface Message { // must be interface. Don't consider any changes. ...@@ -200,7 +191,9 @@ interface Message { // must be interface. Don't consider any changes.
/** /**
* [Message.contentToString] 的捷径 * [Message.contentToString] 的捷径
*/ */
inline val Message.content: String get() = contentToString() @get:JvmSynthetic
inline val Message.content: String
get() = contentToString()
/** /**
...@@ -212,24 +205,48 @@ inline val Message.content: String get() = contentToString() ...@@ -212,24 +205,48 @@ inline val Message.content: String get() = contentToString()
* - [PlainText] 长度为 0 * - [PlainText] 长度为 0
* - [MessageChain] 所有元素都满足 [isContentEmpty] * - [MessageChain] 所有元素都满足 [isContentEmpty]
*/ */
fun Message.isContentEmpty(): Boolean = when (this) { @OptIn(ExperimentalContracts::class)
is MessageMetadata -> true fun Message.isContentEmpty(): Boolean {
is PlainText -> this.content.isEmpty() contract {
is MessageChain -> this.all { it.isContentEmpty() } returns(false) implies (this@isContentEmpty is MessageContent)
else -> false }
return when (this) {
is MessageMetadata -> true
is PlainText -> this.content.isEmpty()
is MessageChain -> this.all { it.isContentEmpty() }
else -> false
}
} }
inline fun Message.isContentNotEmpty(): Boolean = !this.isContentEmpty()
inline fun Message.isPlain(): Boolean = this is PlainText @OptIn(ExperimentalContracts::class)
inline fun Message.isContentNotEmpty(): Boolean {
contract {
returns(true) implies (this@isContentNotEmpty is MessageContent)
}
return !this.isContentEmpty()
}
inline fun Message.isNotPlain(): Boolean = this !is PlainText @OptIn(ExperimentalContracts::class)
inline fun Message.isPlain(): Boolean {
contract {
returns(true) implies (this@isPlain is PlainText)
returns(false) implies (this@isPlain !is PlainText)
}
return this is PlainText
}
@JvmSynthetic @OptIn(ExperimentalContracts::class)
@Suppress("UNCHECKED_CAST") inline fun Message.isNotPlain(): Boolean {
suspend inline fun <C : Contact> Message.sendTo(contact: C): MessageReceipt<C> { contract {
return contact.sendMessage(this) as MessageReceipt<C> returns(false) implies (this@isNotPlain is PlainText)
returns(true) implies (this@isNotPlain !is PlainText)
}
return this !is PlainText
} }
/**
* 将此消息元素按顺序重复 [count] 次.
*/
// inline: for future removal // inline: for future removal
inline fun Message.repeat(count: Int): MessageChain { inline fun Message.repeat(count: Int): MessageChain {
if (this is ConstrainSingle<*>) { if (this is ConstrainSingle<*>) {
...@@ -241,26 +258,28 @@ inline fun Message.repeat(count: Int): MessageChain { ...@@ -241,26 +258,28 @@ inline fun Message.repeat(count: Int): MessageChain {
} }
} }
/**
* 将此消息元素按顺序重复 [count] 次.
*/
@JvmSynthetic @JvmSynthetic
inline operator fun Message.times(count: Int): MessageChain = this.repeat(count) inline operator fun Message.times(count: Int): MessageChain = this.repeat(count)
@Suppress("OverridingDeprecatedMember") /**
* 单个消息元素. 与之相对的是 [MessageChain], 是多个 [SingleMessage] 的集合.
*/
interface SingleMessage : Message { interface SingleMessage : Message {
@PlannedRemoval("1.2.0") @PlannedRemoval("1.2.0")
@JvmSynthetic @JvmSynthetic
@SinceMirai("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) @Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun length(): Int = this.toString().length fun length(): Int = this.toString().length
@PlannedRemoval("1.2.0") @PlannedRemoval("1.2.0")
@JvmSynthetic @JvmSynthetic
@SinceMirai("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) @Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun charAt(index: Int): Char = this.toString()[index] fun charAt(index: Int): Char = this.toString()[index]
@PlannedRemoval("1.2.0") @PlannedRemoval("1.2.0")
@JvmSynthetic @JvmSynthetic
@SinceMirai("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) @Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun subSequence(start: Int, end: Int): CharSequence = this.toString().subSequence(start, end) fun subSequence(start: Int, end: Int): CharSequence = this.toString().subSequence(start, end)
} }
...@@ -268,6 +287,8 @@ interface SingleMessage : Message { ...@@ -268,6 +287,8 @@ interface SingleMessage : Message {
/** /**
* 消息元数据, 即不含内容的元素. * 消息元数据, 即不含内容的元素.
* *
* 这种类型的 [Message] 只表示一条消息的属性. 其子类为 [MessageSource], [QuoteReply]
*
* 所有子类的 [contentToString] 都应该返回空字符串. * 所有子类的 [contentToString] 都应该返回空字符串.
* *
* @see MessageSource 消息源 * @see MessageSource 消息源
...@@ -284,6 +305,10 @@ interface MessageMetadata : SingleMessage ...@@ -284,6 +305,10 @@ interface MessageMetadata : SingleMessage
* 实现此接口的元素将会在连接时自动处理替换. * 实现此接口的元素将会在连接时自动处理替换.
*/ */
interface ConstrainSingle<out M : Message> : MessageMetadata { interface ConstrainSingle<out M : Message> : MessageMetadata {
/**
* 用于判断是否为同一种元素的 [Key]
* @see Key 查看更多信息
*/
val key: Key<M> val key: Key<M>
} }
...@@ -296,8 +321,10 @@ interface ConstrainSingle<out M : Message> : MessageMetadata { ...@@ -296,8 +321,10 @@ interface ConstrainSingle<out M : Message> : MessageMetadata {
* @see HummerMessage 一些特殊消息: [戳一戳][PokeMessage], [闪照][FlashImage] * @see HummerMessage 一些特殊消息: [戳一戳][PokeMessage], [闪照][FlashImage]
* @see Image 图片 * @see Image 图片
* @see RichMessage 富文本 * @see RichMessage 富文本
* @see ServiceMessage 服务消息, 如 JSON/XML
* @see Face 原生表情 * @see Face 原生表情
* @see ForwardMessage 合并转发 * @see ForwardMessage 合并转发
* @see Voice 语音
*/ */
interface MessageContent : SingleMessage interface MessageContent : SingleMessage
...@@ -307,4 +334,9 @@ interface MessageContent : SingleMessage ...@@ -307,4 +334,9 @@ interface MessageContent : SingleMessage
@JvmSynthetic @JvmSynthetic
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
suspend inline fun <C : Contact> MessageChain.sendTo(contact: C): MessageReceipt<C> = suspend inline fun <C : Contact> MessageChain.sendTo(contact: C): MessageReceipt<C> =
contact.sendMessage(this) as MessageReceipt<C> contact.sendMessage(this) as MessageReceipt<C>
\ No newline at end of file
@JvmSynthetic
@Suppress("UNCHECKED_CAST")
suspend inline fun <C : Contact> Message.sendTo(contact: C): MessageReceipt<C> =
contact.sendMessage(this) as MessageReceipt<C>
...@@ -28,13 +28,26 @@ import kotlin.reflect.KProperty ...@@ -28,13 +28,26 @@ import kotlin.reflect.KProperty
/** /**
* 消息链. 空的实现为 [EmptyMessageChain] * 消息链. 空的实现为 [EmptyMessageChain]
* *
* 要获取更多信息, 请查看 [Message] * 在发送消息时必须构造一个消息链, 可通过一系列扩展函数 [asMessageChain] 转换.
*
* 要获取更多消息相关的信息, 查看 [Message]
*
* ### 构造消息链
*
* ### 消息链如何工作
* - [SingleMessageChainImpl] 将 [单个消息][SingleMessage] 委托为一个 [MessageChain]
*
* @see get 获取消息链中一个类型的元素, 不存在时返回 `null`
* @see getOrFail 获取消息链中一个类型的元素, 不存在时抛出异常 [NoSuchElementException]
* @see quote 引用这条消息.
* *
* @see buildMessageChain 构造一个 [MessageChain] * @see buildMessageChain 构造一个 [MessageChain]
* @see asMessageChain 将单个 [Message] 转换为 [MessageChain] * @see asMessageChain 将单个 [Message] 转换为 [MessageChain]
* @see asMessageChain 将 [Iterable] 或 [Sequence] 委托为 [MessageChain] * @see asMessageChain 将 [Iterable] 或 [Sequence] 委托为 [MessageChain]
* *
* @see forEachContent 遍历内容 * @see forEachContent 遍历内容
* @see allContent 判断是否每一个 [MessageContent] 都满足条件
* @see noneContent 判断是否每一个 [MessageContent] 都不满足条件
* *
* @see orNull 属性委托扩展 * @see orNull 属性委托扩展
* @see orElse 属性委托扩展 * @see orElse 属性委托扩展
...@@ -45,7 +58,7 @@ interface MessageChain : Message, Iterable<SingleMessage> { ...@@ -45,7 +58,7 @@ interface MessageChain : Message, Iterable<SingleMessage> {
/** /**
* 元素数量. [EmptyMessageChain] 不参加计数. * 元素数量. [EmptyMessageChain] 不参加计数.
*/ */
val size: Int override val size: Int
/** /**
* 获取第一个类型为 [key] 的 [Message] 实例. 若不存在此实例, 返回 `null` * 获取第一个类型为 [key] 的 [Message] 实例. 若不存在此实例, 返回 `null`
...@@ -161,7 +174,7 @@ inline fun <reified M : Message?> MessageChain.firstIsInstanceOrNull(): M? = thi ...@@ -161,7 +174,7 @@ inline fun <reified M : Message?> MessageChain.firstIsInstanceOrNull(): M? = thi
inline fun <reified M : Message> MessageChain.firstIsInstance(): M = this.first { it is M } as M inline fun <reified M : Message> MessageChain.firstIsInstance(): M = this.first { it is M } as M
/** /**
* 获取第一个 [M] 类型的 [Message] 实例 * 判断 [this] 中是否存在 [Message] 的实例
*/ */
@JvmSynthetic @JvmSynthetic
inline fun <reified M : Message> MessageChain.anyIsInstance(): Boolean = this.any { it is M } inline fun <reified M : Message> MessageChain.anyIsInstance(): Boolean = this.any { it is M }
...@@ -257,7 +270,7 @@ inline fun <reified T : Message?> MessageChain.orElse( ...@@ -257,7 +270,7 @@ inline fun <reified T : Message?> MessageChain.orElse(
// endregion delegate // endregion delegate
// region converters // region asMessageChain
/** /**
* 得到包含 [this] 的 [MessageChain]. * 得到包含 [this] 的 [MessageChain].
* *
...@@ -409,7 +422,7 @@ inline fun MessageChain.flatten(): Sequence<SingleMessage> = this.asSequence() / ...@@ -409,7 +422,7 @@ inline fun MessageChain.flatten(): Sequence<SingleMessage> = this.asSequence() /
/** /**
* 不含任何元素的 [MessageChain]. * 不含任何元素的 [MessageChain].
*/ */
object EmptyMessageChain : MessageChain, Iterator<SingleMessage> { object EmptyMessageChain : MessageChain, Iterator<SingleMessage>, List<SingleMessage> by emptyList() {
override val size: Int get() = 0 override val size: Int get() = 0
override fun toString(): String = "" override fun toString(): String = ""
......
...@@ -79,16 +79,15 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSo ...@@ -79,16 +79,15 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSo
* *
* #### 顺序 * #### 顺序
* 群消息的 id 由服务器维护. 好友消息的 id 由 mirai 维护. * 群消息的 id 由服务器维护. 好友消息的 id 由 mirai 维护.
* 此 id 不一定从 0 开始.
* *
* - 在同一个群的消息中此值随每条消息递增 1. * - 在同一个群的消息中此值随每条消息递增 1, 但此行为由服务器决定, mirai 不保证自增顺序.
* - 在好友消息中无法保证每次都递增 1. 也可能会产生大幅跳过的情况. * - 在好友消息中无法保证每次都递增 1. 也可能会产生大幅跳过的情况.
*/ */
abstract val id: Int abstract val id: Int
/** /**
* 内部 id. 仅用于协议模块使用. * 内部 id. **仅用于协议模块使用**
*
* 在撤回消息和引用回复时均需使用此 id.
* *
* 值没有顺序, 也可能为 0, 取决于服务器是否提供. * 值没有顺序, 也可能为 0, 取决于服务器是否提供.
* *
...@@ -100,8 +99,6 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSo ...@@ -100,8 +99,6 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSo
* 发送时间时间戳, 单位为秒. * 发送时间时间戳, 单位为秒.
* *
* 时间戳可能来自服务器, 也可能来自 mirai, 且无法保证两者时间同步. * 时间戳可能来自服务器, 也可能来自 mirai, 且无法保证两者时间同步.
*
* 撤回消息时需要此值.
*/ */
abstract val time: Int abstract val time: Int
...@@ -188,6 +185,10 @@ sealed class OnlineMessageSource : MessageSource() { ...@@ -188,6 +185,10 @@ sealed class OnlineMessageSource : MessageSource() {
*/ */
abstract val subject: Contact abstract val subject: Contact
/*
* 以下子类型仅是覆盖了 [target], [subject], [sender] 等的类型
*/
/** /**
* 由 [机器人主动发送消息][Contact.sendMessage] 产生的 [MessageSource], 可通过 [MessageReceipt] 获得. * 由 [机器人主动发送消息][Contact.sendMessage] 产生的 [MessageSource], 可通过 [MessageReceipt] 获得.
*/ */
...@@ -229,7 +230,6 @@ sealed class OnlineMessageSource : MessageSource() { ...@@ -229,7 +230,6 @@ sealed class OnlineMessageSource : MessageSource() {
abstract override val target: Group abstract override val target: Group
final override val subject: Group get() = target final override val subject: Group get() = target
// final override fun toString(): String = "OnlineMessageSource.ToGroup(group=${target.id})"
} }
} }
...@@ -289,8 +289,7 @@ sealed class OnlineMessageSource : MessageSource() { ...@@ -289,8 +289,7 @@ sealed class OnlineMessageSource : MessageSource() {
*/ */
abstract class OfflineMessageSource : MessageSource() { abstract class OfflineMessageSource : MessageSource() {
companion object Key : Message.Key<OfflineMessageSource> { companion object Key : Message.Key<OfflineMessageSource> {
override val typeName: String override val typeName: String get() = "OfflineMessageSource"
get() = "OfflineMessageSource"
} }
enum class Kind { enum class Kind {
...@@ -303,8 +302,6 @@ abstract class OfflineMessageSource : MessageSource() { ...@@ -303,8 +302,6 @@ abstract class OfflineMessageSource : MessageSource() {
* 消息种类 * 消息种类
*/ */
abstract val kind: Kind abstract val kind: Kind
// final override fun toString(): String = "OfflineMessageSource(sender=$senderId, target=$targetId)"
} }
/** /**
......
...@@ -29,6 +29,9 @@ import kotlin.jvm.JvmSynthetic ...@@ -29,6 +29,9 @@ import kotlin.jvm.JvmSynthetic
* *
* 支持引用任何一条消息发送给任何人. * 支持引用任何一条消息发送给任何人.
* *
* #### 元数据
* [QuoteReply] 被作为 [MessageMetadata], 因为它不包含实际的消息内容, 且只能在消息中单独存在.
*
* #### [source] 的类型: * #### [source] 的类型:
* - 在发送引用回复时, [source] 类型为 [OnlineMessageSource] 或 [OfflineMessageSource] * - 在发送引用回复时, [source] 类型为 [OnlineMessageSource] 或 [OfflineMessageSource]
* - 在接收引用回复时, [source] 类型一定为 [OfflineMessageSource] * - 在接收引用回复时, [source] 类型一定为 [OfflineMessageSource]
......
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package net.mamoe.mirai.event
/**
*
*/
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class EventHandler(
val priority: Listener.EventPriority = Listener.EventPriority.NORMAL,
val ignoreCancelled: Boolean = true
)
interface ListenerHoster
fun ListenerHoster.registerEvents() {
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment