Ver Fonte

Update docs and improve source code readability

Him188 há 4 anos atrás
pai
commit
d43a77b590

+ 11 - 8
docs/Messages.md

@@ -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*<sup>(2)</sup>* |
+|    [`MessageOrigin`]    | 富文本消息源   |         2.6         |
 
-| [`MessageMetadata`] 类型 | 解释         | 最低支持的版本 |
-|:-----------------------:|:------------|:------------:|
-|    [`MessageSource`]    | 消息来源元数据 |     2.0     |
-|     [`QuoteReply`]      | 引用回复      |     2.0     |
-|    [`ShowImageFlag`]    | 秀图标识      |     2.2     |
-|  [`RichMessageOrigin`]  | 富文本消息源   |     2.3     |
+> *(1):* [`ForwardMessage`] 在 2.0 支持发送, 在 2.3 支持接收  
+> *(2):* [`RichMessageOrigin`] 在 2.3 增加, 在 2.6 弃用并以 [`MessageOrigin`] 替换
 
 
 ### 用法

+ 89 - 0
mirai-core-api/README.md

@@ -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).

+ 3 - 6
mirai-core-api/src/commonMain/kotlin/Bot.kt

@@ -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 配置

+ 35 - 3
mirai-core-api/src/commonMain/kotlin/IMirai.kt

@@ -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 }

+ 2 - 1
mirai-core-api/src/commonMain/kotlin/LowLevelApiAccessor.kt

@@ -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 等.

+ 2 - 3
mirai-core-api/src/commonMain/kotlin/message/data/Message.kt

@@ -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("")`)
      * - ...

+ 9 - 0
mirai-core-api/src/commonMain/kotlin/message/data/MessageChainBuilder.kt

@@ -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 示例
  *
  * ```

+ 3 - 0
mirai-core-utils/README.md

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

+ 60 - 3
mirai-core/README.md

@@ -1,5 +1,62 @@
-# mirai-core-qqandroid
+# mirai-core
 
+mirai 核心实现模块。首先阅读 [mirai-core-api/README.md](../mirai-core-api/README.md)。
 
-QQ for Android 8.2.7 协议实现.
-相较于 `mirai-core`, 此模块仅提供协议和功能的实现, 不提供额外的公开的 API.
+本文仅介绍重要部分。
+
+## 架构
+
+| 包名                        | 描述                 |
+|:---------------------------|:--------------------|
+| `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` 到协议数据结构的转换, 并处理长消息上传, 音乐转发上传等.
+
+
+## `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` 在协议底层十分复杂,

+ 5 - 3
mirai-core/src/commonMain/kotlin/contact/SendMessageHandler.kt

@@ -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,

+ 12 - 2
mirai-core/src/commonMain/kotlin/message/RefinableMessage.kt

@@ -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 {
 
@@ -47,7 +51,7 @@ internal sealed class MessageRefiner {
 
         if (none {
                 it is RefinableMessage
-                    || (it is PlainText && convertLineSeparator && it.content.contains('\r'))
+                        || (it is PlainText && convertLineSeparator && it.content.contains('\r'))
             }
         ) return this
 
@@ -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,