Update docs and improve source code readability

This commit is contained in:
Him188 2021-05-09 15:31:50 +08:00
parent 2e1ec03daa
commit d43a77b590
11 changed files with 231 additions and 29 deletions

View File

@ -89,7 +89,8 @@ Mirai 支持多种消息类型。
[`Voice`]: ../mirai-core-api/src/commonMain/kotlin/message/data/Voice.kt
[`ForwardMessage`]: ../mirai-core-api/src/commonMain/kotlin/message/data/ForwardMessage.kt
[`ShowImageFlag`]: ../mirai-core-api/src/commonMain/kotlin/message/data/ShowImageFlag.kt
[`RichMessageOrigin`]: ../mirai-core-api/src/commonMain/kotlin/message/data/RichMessageOrigin.kt
[`RichMessageOrigin`]: ../mirai-core-api/src/commonMain/kotlin/message/data/MessageOrigin.kt
[`MessageOrigin`]: ../mirai-core-api/src/commonMain/kotlin/message/data/MessageOrigin.kt
| [`MessageContent`] 类型 | 解释 | `contentToString()` | 最低支持的版本 |
@ -112,16 +113,18 @@ Mirai 支持多种消息类型。
| [`FileMessage`] | 文件消息 | `[文件]文件名称` | 2.5 |
> *(1)*: [`ForwardMessage`] 在 2.0 支持发送, 在 2.3 支持接收
| [`MessageMetadata`] 类型 | 解释 | 最低支持的版本 |
|:-----------------------:|:------------|:------------:|
|:-----------------------:|:------------|:-------------------:|
| [`MessageSource`] | 消息来源元数据 | 2.0 |
| [`QuoteReply`] | 引用回复 | 2.0 |
| [`ShowImageFlag`] | 秀图标识 | 2.2 |
| [`RichMessageOrigin`] | 富文本消息源 | 2.3 |
| [`RichMessageOrigin`] | 富文本消息源 | 2.3*<sup>(2)</sup>* |
| [`MessageOrigin`] | 富文本消息源 | 2.6 |
> *(1):* [`ForwardMessage`] 在 2.0 支持发送, 在 2.3 支持接收
> *(2):* [`RichMessageOrigin`] 在 2.3 增加, 在 2.6 弃用并以 [`MessageOrigin`] 替换
### 用法

89
mirai-core-api/README.md Normal file
View File

@ -0,0 +1,89 @@
# mirai-core-api
mirai 核心 API 模块。本文档帮助读者了解该模块的主要架构。
> mirai 为多平台设计。支持 Android 和 JVM 双平台,拥有多个源集。
>
> - `commonMain`:平台无关的通用代码。绝大部分代码都存在与这个源集。
> - `jvmMain`:桌面 JVM 平台的特别实现。
> - `androidMain`Android 平台的特别实现。
>
> 阅读源码通常阅读 `src/commonMain`
## 架构
| 包名 | 描述 |
|:------------------|:----------------------------------------------------|
| `net.mamoe.mirai` | mirai 核心 API |
| `.contact` | 联系人类型。如群 `Group`,好友 `Friend` |
| `.event` | 事件框架。提供事件对象的基类以及监听事件的方法 |
| `.event.events` | 事件的定义。包含许多事件的具体类, 如消息事件 `MessageEvent` |
| `.message` | 消息系统 |
| `.message.data` | 提供对富文本聊天消息及其元素多样性的抽象 |
| `.message.code` | 提供一个易于阅读的消息字符串表示方式 |
| `.message.action` | 提供与消息有关的动作的抽象,如戳一戳 |
| `.utils` | 一些工具类 |
| `.internal` | 内部实现 |
| `.internal.event` | 事件框架的实现 |
## `net.mamoe.mirai`
### `IMirai`
[IMirai.kt](src/commonMain/kotlin/IMirai.kt#L33)
**API 模块与协议实现模块的对接接口。**
- 单例
- 通过 `ServiceLoader` 寻找[协议实现](../mirai-core/README.md)。
- 若 `ServiceLoader` 在特定环境下不可用,外部可在 Kotlin **在调用任何 Mirai API 之前**覆盖实例:
```kotlin
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // 必要
net.mamoe.mirai._MiraiInstance.set(net.mamoe.mirai.internal.MiraiImpl())
```
### `Bot`
[BotFactory]: src/commonMain/kotlin/BotFactory.kt
[Bot.kt](src/commonMain/kotlin/IMirai.kt#L29)
表示一个机器人对象(账户)。
- 通过 [BotFactory] 构造
- 是功能的入口点----大部分操作都直接或间接经过 `Bot`
- 持有联系人(好友和群)对象列表
- 可获得事件通道
## `net.mamoe.mirai.contact`
联系人系统。[docs/Contacts](../docs/Contacts.md)
## `net.mamoe.mirai.event`
事件系统。[docs/Contacts](../docs/Contacts.md)
## `net.mamoe.mirai.event.events`
事件列表。[README](src/commonMain/kotlin/event/events/README.md#事件)
## `net.mamoe.mirai.message`
消息系统。
### `MessageReceipt`
[MessageReceipt.kt](src/commonMain/kotlin/message/MessageReceipt.kt#L25)
在发送消息(`Contact.sendMessage`)后收到的回执。
### `MessageSerializers`
[MessageSerializers.kt](src/commonMain/kotlin/message/MessageSerializers.kt#L27)
[kotlinx.serialization](https://github.com/kotlin/kotlinx.serialization) 序列化支持。
## `net.mamoe.mirai.message.data`
对富文本聊天消息及其元素多样性的抽象。
一个消息元素最基本的接口为 [Message](src/commonMain/kotlin/message/data/Message.kt#L30).

View File

@ -6,11 +6,9 @@
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:Suppress(
"EXPERIMENTAL_API_USAGE", "unused", "FunctionName", "NOTHING_TO_INLINE", "UnusedImport",
"EXPERIMENTAL_OVERRIDE", "CanBeParameter", "MemberVisibilityCanBePrivate", "INAPPLICABLE_JVM_NAME",
"EXPOSED_SUPER_CLASS"
)
@file:Suppress("NOTHING_TO_INLINE")
@file:JvmBlockingBridge
package net.mamoe.mirai
@ -43,7 +41,6 @@ public suspend inline fun <B : Bot> B.alsoLogin(): B = also { login() }
*
* @see BotFactory 构造 [Bot] 的工厂, [Bot] 唯一的构造方式.
*/
@JvmBlockingBridge
public interface Bot : CoroutineScope, ContactOrBot, UserOrBot {
/**
* Bot 配置

View File

@ -10,6 +10,7 @@
@file:Suppress("INTERFACE_NOT_SUPPORTED", "PropertyName")
@file:JvmName("Mirai")
@file:OptIn(LowLevelApi::class, MiraiExperimentalApi::class, MiraiInternalApi::class)
@file:JvmBlockingBridge
package net.mamoe.mirai
@ -31,18 +32,46 @@ import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.MiraiInternalApi
/**
* [IMirai] 实例
* [IMirai] 实例.
*/
@get:JvmName("getInstance") // Java 调用: Mirai.getInstance()
public val Mirai: IMirai
get() = _MiraiInstance.get()
/**
* Mirai API 接口.
* Mirai API 接口. Mirai API Mirai 协议实现对接的接口.
*
* ## 获取实例
*
* 通常在引用 `net.mamoe:mirai-core` 模块后就可以通过 [Mirai] 获取到 [IMirai] 实例.
* Kotlin 调用顶层定义 `Mirai`, Java 调用 `Mirai.getInstance()`.
*
* ### 使用 [IMirai] 的接口
*
* [IMirai] 中的接口通常是稳定
*
* ### 手动提供实例
*
* 默认通过 [_MiraiInstance.get] 使用 [java.util.ServiceLoader] 寻找实例. 若某些环境下 [java.util.ServiceLoader] 不可用, 可在 Kotlin 手动设置实例:
* ```
* @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // 必要
* net.mamoe.mirai._MiraiInstance.set(net.mamoe.mirai.internal.MiraiImpl())
* ```
*
* 但通常都可用自动获取而不需要手动设置.
*
* ## 稳定性
*
* ### 使用稳定
*
* 所有接口默认是可以稳定使用的. [LowLevelApiAccessor] 中的方法默认是非常不稳定的.
*
* ### 继承不稳定
*
* **[IMirai] 可能会增加新的抽象属性或函数. 因此不适合被继承或实现.**
*
* @see Mirai 获取实例
*/
@JvmBlockingBridge
public interface IMirai : LowLevelApiAccessor {
/**
* 请优先使用 [BotFactory.INSTANCE]
@ -298,6 +327,9 @@ internal object _MiraiInstance {
this.instance = instance
}
/**
* 获取通过 [set] 设置的实例, 或使用 [findMiraiInstance] 寻找一个实例.
*/
@JvmStatic
fun get(): IMirai {
return instance ?: findMiraiInstance().also { instance = it }

View File

@ -7,6 +7,8 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:JvmBlockingBridge
package net.mamoe.mirai
import kotlinx.coroutines.Job
@ -36,7 +38,6 @@ public annotation class LowLevelApi
* **警告**: 所有的低级 API 都可能在任意时刻不经过任何警告和迭代就被修改. 因此非常不建议在任何情况下使用这些 API.
*/
@LowLevelApi
@JvmBlockingBridge
public interface LowLevelApiAccessor {
/**
* 主动刷新 keys, SKey, PSKey .

View File

@ -110,7 +110,7 @@ import kotlin.internal.LowPriorityInOverloadResolution
* if (!content.equals("#") && content.startsWith("#")) {
* String name = content.substring(content.indexOf('#') + 1); // `#` 之后的内容
* switch(name) {
* "mute": event.sender.mute(60000) // 发 #mute 就把自己禁言 1 分钟
* case "mute": event.sender.mute(60000) // 发 #mute 就把自己禁言 1 分钟
* }
* }
* ```
@ -139,8 +139,7 @@ public interface Message { // TODO: 2021/1/10 Make sealed interface in Kotlin 1.
*
* 各个消息类型的转换示例:
* - [PlainText] : `"Hello"`
* - [GroupImage] : `"[mirai:image:{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.mirai]"`
* - [FriendImage] : `"[mirai:image:/f8f1ab55-bf8e-4236-b55e-955848d7069f]"`
* - [Image] : `"[mirai:image:{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.mirai]"`
* - [PokeMessage] : `"[mirai:poke:1,-1]"`
* - [MessageChain] : 无间隔地连接所有元素 (`joinToString("")`)
* - ...

View File

@ -45,6 +45,15 @@ public inline fun buildMessageChain(initialSize: Int, block: MessageChainBuilder
*
* 多个连续的 [String] 会被连接为单个 [PlainText] 以优化性能
*
* ```java
* MessageChain chain = new MessageChainBuilder()
* .append("Hello ")
* .append("mirai!")
* .build();
*
* // chain 将会只包含一个 [PlainText], 其内容为 "Hello mirai!".
* ```
*
* ## Kotlin 示例
*
* ```

View File

@ -0,0 +1,3 @@
# mirai-core-utils
内部工具类模块。提供二进制兼容而不提供源码兼容,但也不保证破坏性变更不会发生,因此若要使用该工具模块,请自行承担兼容后果。

View File

@ -1,5 +1,62 @@
# mirai-core-qqandroid
# mirai-core
mirai 核心实现模块。首先阅读 [mirai-core-api/README.md](../mirai-core-api/README.md)。
本文仅介绍重要部分。
## 架构
| 包名 | 描述 |
|:---------------------------|:--------------------|
| `net.mamoe.mirai.internal` | mirai 核心 API 的实现 |
| `.contact` | 联系人实现 |
| `.message` | 消息系统的实现 |
| `.network` | 网络层实现 |
| `.utils` | 工具类 |
## `net.mamoe.mirai.internal.contact`
### `AbstractContact`
[AbstractContact.kt](src/commonMain/kotlin/contact/AbstractContact.kt#L22)
所有 `Contact` 实现的基类. 实现生命周期等.
### `SendMessageHandler`
[SendMessageHandler.kt](src/commonMain/kotlin/contact/SendMessageHandler.kt#L35)
处理 mirai 消息系统 `Message` 到协议数据结构的转换, 并处理长消息上传, 音乐转发上传等.
QQ for Android 8.2.7 协议实现.
相较于 `mirai-core`, 此模块仅提供协议和功能的实现, 不提供额外的公开的 API.
## `net.mamoe.mirai.internal.message`
### `ReceiveMessageTransformer`
[ReceiveMessageHandler.kt](src/commonMain/kotlin/message/ReceiveMessageHandler.kt#L29)
处理协议数据结构到 `Message` 的转换. 设有 `RefinableMessage` 处理长消息下载, 合并转发下载并展开等.
### `RefinableMessage`
[RefinableMessage.kt](src/commonMain/kotlin/message/RefinableMessage.kt#L17)
支持处理长消息下载, 合并转发下载并展开等.
### `Image` 实现
[imagesImpl.kt](src/commonMain/kotlin/message/imagesImpl.kt#L30)
图片的实现的基类为 `AbstractImage`.
在底层协议, 群图片与私聊图片很不同. 因此图片实现可以是 `GroupImage``FriendImage`.
图片又细分了 `OnlineImage``OfflineImage`. 故有 `OnlineGroupImage` 等四个类型, 及他们分别的 `Impl`.
`OnlineImage` 为通过 `Contact.uploadImage` 上传得到的, 或刚刚从服务器接收的图片对象. `OfflineImage` 则为反序列化得到的对象.
### `MessageSource` 实现
[MessageSourceInternal.kt](src/commonMain/kotlin/message/MessageSourceInternal.kt#L20)
`MessageSource` 在协议底层十分复杂,

View File

@ -33,7 +33,9 @@ import net.mamoe.mirai.utils.castOrNull
import net.mamoe.mirai.utils.currentTimeSeconds
/**
* 通用处理器
* 处理 mirai 消息系统 `Message` 到协议数据结构的转换.
*
* 外部调用 [sendMessageImpl]
*/
internal abstract class SendMessageHandler<C : Contact> {
abstract val contact: C
@ -109,7 +111,7 @@ internal abstract class SendMessageHandler<C : Contact> {
}
/**
* Final process
* Final process. Convert transformed message to protocol internals and transfer to server
*/
suspend fun sendMessagePacket(
originalMessage: Message,
@ -311,7 +313,7 @@ internal suspend fun <C : Contact> SendMessageHandler<C>.sendMessage(
/**
* Might be recalled with [transformedMessage] `is` [LongMessageInternal] if length estimation failed (sendMessagePacket)
*/
internal suspend fun <C : Contact> SendMessageHandler<C>.sendMessageImpl(
private suspend fun <C : Contact> SendMessageHandler<C>.sendMessageImpl(
originalMessage: Message,
transformedMessage: MessageChain,
step: SendMessageStep,

View File

@ -10,11 +10,15 @@
package net.mamoe.mirai.internal.message
import net.mamoe.mirai.Bot
import net.mamoe.mirai.internal.message.DeepMessageRefiner.refineDeep
import net.mamoe.mirai.internal.message.LightMessageRefiner.refineLight
import net.mamoe.mirai.message.data.*
/**
* 在接收解析消息后会经过一层转换的消息.
* @see MessageChain.refineLight
*
* @see DeepMessageRefiner.refineDeep
* @see LightMessageRefiner.refineLight
*/
internal interface RefinableMessage : SingleMessage {
@ -134,6 +138,9 @@ internal class SimpleRefineContext(
}
}
/**
* 执行不需要 `suspend` refine. 用于 [MessageSource.originalMessage].
*/
internal object LightMessageRefiner : MessageRefiner() {
fun MessageChain.refineLight(
bot: Bot,
@ -143,6 +150,9 @@ internal object LightMessageRefiner : MessageRefiner() {
}
}
/**
* 执行需要 `suspend` refine. 用于解析到的消息.
*/
internal object DeepMessageRefiner : MessageRefiner() {
suspend fun MessageChain.refineDeep(
bot: Bot,