mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-05 07:30:09 +08:00
Add docs
This commit is contained in:
parent
ed11f38b3f
commit
9733490266
@ -26,13 +26,15 @@ import kotlin.jvm.JvmName
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
|
||||
/**
|
||||
* 发送消息后得到的回执. 可用于撤回.
|
||||
*
|
||||
* 此对象持有 [Contact] 的弱引用, [Bot] 离线后将会释放引用, 届时 [target] 将无法访问.
|
||||
* 发送消息后得到的回执. 可用于撤回, 引用回复等.
|
||||
*
|
||||
* @param source 指代发送出去的消息
|
||||
* @param target 消息发送对象
|
||||
*
|
||||
* @see quote 引用这条消息. 即引用机器人自己发出去的消息
|
||||
* @see quoteReply 引用并回复这条消息.
|
||||
* @see recall 撤回这条消息
|
||||
*
|
||||
* @see Group.sendMessage 发送群消息, 返回回执(此对象)
|
||||
* @see User.sendMessage 发送群消息, 返回回执(此对象)
|
||||
* @see Member.sendMessage 发送临时消息, 返回回执(此对象)
|
||||
@ -148,6 +150,16 @@ suspend inline fun <C : Contact> MessageReceipt<C>.quoteReply(message: String):
|
||||
inline val MessageReceipt<*>.sourceId: Int
|
||||
get() = this.source.id
|
||||
|
||||
|
||||
/**
|
||||
* 获取源消息 [MessageSource.internalId]
|
||||
*
|
||||
* @see MessageSource.id
|
||||
*/
|
||||
@get:JvmSynthetic
|
||||
inline val MessageReceipt<*>.sourceInternalId: Int
|
||||
get() = this.source.internalId
|
||||
|
||||
/**
|
||||
* 获取源消息 [MessageSource.time]
|
||||
*
|
||||
|
@ -19,7 +19,8 @@ import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.message.data.Message.Key
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
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.JvmName
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
@ -29,7 +30,7 @@ import kotlin.jvm.JvmSynthetic
|
||||
*
|
||||
* [消息][Message] 分为
|
||||
* - [SingleMessage]:
|
||||
* - [MessageMetadata] 消息元数据, 包括: [消息来源][MessageSource], [引用回复][QuoteReply].
|
||||
* - [MessageMetadata] 消息元数据, 即消息的属性. 包括: [消息来源][MessageSource], [引用回复][QuoteReply].
|
||||
* - [MessageContent] 含内容的消息, 包括: [纯文本][PlainText], [@群员][At], [@全体成员][AtAll] 等.
|
||||
* - [MessageChain]: 不可变消息链, 链表形式链接的多个 [SingleMessage] 实例.
|
||||
*
|
||||
@ -57,11 +58,6 @@ import kotlin.jvm.JvmSynthetic
|
||||
* #### 实现规范
|
||||
* 除 [MessageChain] 外, 所有 [Message] 的实现类都有伴生对象实现 [Key] 接口.
|
||||
*
|
||||
* #### [CharSequence] 继承
|
||||
* 所有 [CharSequence] 的行为均由 [toString] 委托.
|
||||
*
|
||||
* 即, `appendable.append(message)` 相当于 `appendable.append(message.toString())`
|
||||
*
|
||||
* #### 发送消息
|
||||
* - 通过 [Contact] 中的成员函数: [Contact.sendMessage]
|
||||
* - 通过 [Message] 的扩展函数: [Message.sendTo]
|
||||
@ -186,13 +182,8 @@ interface Message { // must be interface. Don't consider any changes.
|
||||
}
|
||||
|
||||
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: 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())
|
||||
}
|
||||
|
||||
@ -200,7 +191,9 @@ interface Message { // must be interface. Don't consider any changes.
|
||||
/**
|
||||
* [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()
|
||||
* - [PlainText] 长度为 0
|
||||
* - [MessageChain] 所有元素都满足 [isContentEmpty]
|
||||
*/
|
||||
fun Message.isContentEmpty(): Boolean = 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
|
||||
|
||||
inline fun Message.isNotPlain(): Boolean = this !is PlainText
|
||||
|
||||
@JvmSynthetic
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
suspend inline fun <C : Contact> Message.sendTo(contact: C): MessageReceipt<C> {
|
||||
return contact.sendMessage(this) as MessageReceipt<C>
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Message.isContentEmpty(): Boolean {
|
||||
contract {
|
||||
returns(false) implies (this@isContentEmpty is MessageContent)
|
||||
}
|
||||
return when (this) {
|
||||
is MessageMetadata -> true
|
||||
is PlainText -> this.content.isEmpty()
|
||||
is MessageChain -> this.all { it.isContentEmpty() }
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
inline fun Message.isContentNotEmpty(): Boolean {
|
||||
contract {
|
||||
returns(true) implies (this@isContentNotEmpty is MessageContent)
|
||||
}
|
||||
return !this.isContentEmpty()
|
||||
}
|
||||
|
||||
@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
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
inline fun Message.isNotPlain(): Boolean {
|
||||
contract {
|
||||
returns(false) implies (this@isNotPlain is PlainText)
|
||||
returns(true) implies (this@isNotPlain !is PlainText)
|
||||
}
|
||||
return this !is PlainText
|
||||
}
|
||||
|
||||
/**
|
||||
* 将此消息元素按顺序重复 [count] 次.
|
||||
*/
|
||||
// inline: for future removal
|
||||
inline fun Message.repeat(count: Int): MessageChain {
|
||||
if (this is ConstrainSingle<*>) {
|
||||
@ -241,26 +258,28 @@ inline fun Message.repeat(count: Int): MessageChain {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将此消息元素按顺序重复 [count] 次.
|
||||
*/
|
||||
@JvmSynthetic
|
||||
inline operator fun Message.times(count: Int): MessageChain = this.repeat(count)
|
||||
|
||||
@Suppress("OverridingDeprecatedMember")
|
||||
/**
|
||||
* 单个消息元素. 与之相对的是 [MessageChain], 是多个 [SingleMessage] 的集合.
|
||||
*/
|
||||
interface SingleMessage : Message {
|
||||
@PlannedRemoval("1.2.0")
|
||||
@JvmSynthetic
|
||||
@SinceMirai("1.0.0")
|
||||
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
|
||||
fun length(): Int = this.toString().length
|
||||
|
||||
@PlannedRemoval("1.2.0")
|
||||
@JvmSynthetic
|
||||
@SinceMirai("1.0.0")
|
||||
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
|
||||
fun charAt(index: Int): Char = this.toString()[index]
|
||||
|
||||
@PlannedRemoval("1.2.0")
|
||||
@JvmSynthetic
|
||||
@SinceMirai("1.0.0")
|
||||
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
|
||||
fun subSequence(start: Int, end: Int): CharSequence = this.toString().subSequence(start, end)
|
||||
}
|
||||
@ -268,6 +287,8 @@ interface SingleMessage : Message {
|
||||
/**
|
||||
* 消息元数据, 即不含内容的元素.
|
||||
*
|
||||
* 这种类型的 [Message] 只表示一条消息的属性. 其子类为 [MessageSource], [QuoteReply]
|
||||
*
|
||||
* 所有子类的 [contentToString] 都应该返回空字符串.
|
||||
*
|
||||
* @see MessageSource 消息源
|
||||
@ -284,6 +305,10 @@ interface MessageMetadata : SingleMessage
|
||||
* 实现此接口的元素将会在连接时自动处理替换.
|
||||
*/
|
||||
interface ConstrainSingle<out M : Message> : MessageMetadata {
|
||||
/**
|
||||
* 用于判断是否为同一种元素的 [Key]
|
||||
* @see Key 查看更多信息
|
||||
*/
|
||||
val key: Key<M>
|
||||
}
|
||||
|
||||
@ -296,8 +321,10 @@ interface ConstrainSingle<out M : Message> : MessageMetadata {
|
||||
* @see HummerMessage 一些特殊消息: [戳一戳][PokeMessage], [闪照][FlashImage]
|
||||
* @see Image 图片
|
||||
* @see RichMessage 富文本
|
||||
* @see ServiceMessage 服务消息, 如 JSON/XML
|
||||
* @see Face 原生表情
|
||||
* @see ForwardMessage 合并转发
|
||||
* @see Voice 语音
|
||||
*/
|
||||
interface MessageContent : SingleMessage
|
||||
|
||||
@ -307,4 +334,9 @@ interface MessageContent : SingleMessage
|
||||
@JvmSynthetic
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
suspend inline fun <C : Contact> MessageChain.sendTo(contact: C): MessageReceipt<C> =
|
||||
contact.sendMessage(this) as MessageReceipt<C>
|
||||
contact.sendMessage(this) as MessageReceipt<C>
|
||||
|
||||
@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
|
||||
/**
|
||||
* 消息链. 空的实现为 [EmptyMessageChain]
|
||||
*
|
||||
* 要获取更多信息, 请查看 [Message]
|
||||
* 在发送消息时必须构造一个消息链, 可通过一系列扩展函数 [asMessageChain] 转换.
|
||||
*
|
||||
* 要获取更多消息相关的信息, 查看 [Message]
|
||||
*
|
||||
* ### 构造消息链
|
||||
*
|
||||
* ### 消息链如何工作
|
||||
* - [SingleMessageChainImpl] 将 [单个消息][SingleMessage] 委托为一个 [MessageChain]
|
||||
*
|
||||
* @see get 获取消息链中一个类型的元素, 不存在时返回 `null`
|
||||
* @see getOrFail 获取消息链中一个类型的元素, 不存在时抛出异常 [NoSuchElementException]
|
||||
* @see quote 引用这条消息.
|
||||
*
|
||||
* @see buildMessageChain 构造一个 [MessageChain]
|
||||
* @see asMessageChain 将单个 [Message] 转换为 [MessageChain]
|
||||
* @see asMessageChain 将 [Iterable] 或 [Sequence] 委托为 [MessageChain]
|
||||
*
|
||||
* @see forEachContent 遍历内容
|
||||
* @see allContent 判断是否每一个 [MessageContent] 都满足条件
|
||||
* @see noneContent 判断是否每一个 [MessageContent] 都不满足条件
|
||||
*
|
||||
* @see orNull 属性委托扩展
|
||||
* @see orElse 属性委托扩展
|
||||
@ -45,7 +58,7 @@ interface MessageChain : Message, Iterable<SingleMessage> {
|
||||
/**
|
||||
* 元素数量. [EmptyMessageChain] 不参加计数.
|
||||
*/
|
||||
val size: Int
|
||||
override val size: Int
|
||||
|
||||
/**
|
||||
* 获取第一个类型为 [key] 的 [Message] 实例. 若不存在此实例, 返回 `null`
|
||||
@ -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
|
||||
|
||||
/**
|
||||
* 获取第一个 [M] 类型的 [Message] 实例
|
||||
* 判断 [this] 中是否存在 [Message] 的实例
|
||||
*/
|
||||
@JvmSynthetic
|
||||
inline fun <reified M : Message> MessageChain.anyIsInstance(): Boolean = this.any { it is M }
|
||||
@ -257,7 +270,7 @@ inline fun <reified T : Message?> MessageChain.orElse(
|
||||
// endregion delegate
|
||||
|
||||
|
||||
// region converters
|
||||
// region asMessageChain
|
||||
/**
|
||||
* 得到包含 [this] 的 [MessageChain].
|
||||
*
|
||||
@ -409,7 +422,7 @@ inline fun MessageChain.flatten(): Sequence<SingleMessage> = this.asSequence() /
|
||||
/**
|
||||
* 不含任何元素的 [MessageChain].
|
||||
*/
|
||||
object EmptyMessageChain : MessageChain, Iterator<SingleMessage> {
|
||||
object EmptyMessageChain : MessageChain, Iterator<SingleMessage>, List<SingleMessage> by emptyList() {
|
||||
|
||||
override val size: Int get() = 0
|
||||
override fun toString(): String = ""
|
||||
|
@ -79,16 +79,15 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSo
|
||||
*
|
||||
* #### 顺序
|
||||
* 群消息的 id 由服务器维护. 好友消息的 id 由 mirai 维护.
|
||||
* 此 id 不一定从 0 开始.
|
||||
*
|
||||
* - 在同一个群的消息中此值随每条消息递增 1.
|
||||
* - 在同一个群的消息中此值随每条消息递增 1, 但此行为由服务器决定, mirai 不保证自增顺序.
|
||||
* - 在好友消息中无法保证每次都递增 1. 也可能会产生大幅跳过的情况.
|
||||
*/
|
||||
abstract val id: Int
|
||||
|
||||
/**
|
||||
* 内部 id. 仅用于协议模块使用.
|
||||
*
|
||||
* 在撤回消息和引用回复时均需使用此 id.
|
||||
* 内部 id. **仅用于协议模块使用**
|
||||
*
|
||||
* 值没有顺序, 也可能为 0, 取决于服务器是否提供.
|
||||
*
|
||||
@ -100,8 +99,6 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSo
|
||||
* 发送时间时间戳, 单位为秒.
|
||||
*
|
||||
* 时间戳可能来自服务器, 也可能来自 mirai, 且无法保证两者时间同步.
|
||||
*
|
||||
* 撤回消息时需要此值.
|
||||
*/
|
||||
abstract val time: Int
|
||||
|
||||
@ -188,6 +185,10 @@ sealed class OnlineMessageSource : MessageSource() {
|
||||
*/
|
||||
abstract val subject: Contact
|
||||
|
||||
/*
|
||||
* 以下子类型仅是覆盖了 [target], [subject], [sender] 等的类型
|
||||
*/
|
||||
|
||||
/**
|
||||
* 由 [机器人主动发送消息][Contact.sendMessage] 产生的 [MessageSource], 可通过 [MessageReceipt] 获得.
|
||||
*/
|
||||
@ -229,7 +230,6 @@ sealed class OnlineMessageSource : MessageSource() {
|
||||
|
||||
abstract override val target: Group
|
||||
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() {
|
||||
*/
|
||||
abstract class OfflineMessageSource : MessageSource() {
|
||||
companion object Key : Message.Key<OfflineMessageSource> {
|
||||
override val typeName: String
|
||||
get() = "OfflineMessageSource"
|
||||
override val typeName: String get() = "OfflineMessageSource"
|
||||
}
|
||||
|
||||
enum class Kind {
|
||||
@ -303,8 +302,6 @@ abstract class OfflineMessageSource : MessageSource() {
|
||||
* 消息种类
|
||||
*/
|
||||
abstract val kind: Kind
|
||||
|
||||
// final override fun toString(): String = "OfflineMessageSource(sender=$senderId, target=$targetId)"
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,6 +29,9 @@ import kotlin.jvm.JvmSynthetic
|
||||
*
|
||||
* 支持引用任何一条消息发送给任何人.
|
||||
*
|
||||
* #### 元数据
|
||||
* [QuoteReply] 被作为 [MessageMetadata], 因为它不包含实际的消息内容, 且只能在消息中单独存在.
|
||||
*
|
||||
* #### [source] 的类型:
|
||||
* - 在发送引用回复时, [source] 类型为 [OnlineMessageSource] 或 [OfflineMessageSource]
|
||||
* - 在接收引用回复时, [source] 类型一定为 [OfflineMessageSource]
|
||||
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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() {
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user