Merge pull request #320 from mamoe/doc

Add docs
This commit is contained in:
Him188 2020-05-11 16:07:03 +08:00 committed by GitHub
commit cac46f5e30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 161 additions and 39 deletions

BIN
.github/机器人和联系人架构.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -6,6 +6,8 @@ mirai 欢迎一切形式的代码贡献。你可以通过以下几种途径向 m
## 主仓库 `mirai-core` ## 主仓库 `mirai-core`
**阅读文档** [docs/mirai.md](docs/mirai.md)
### 代码优化 ### 代码优化
优化功能设计或实现, 或是引入一个新的设计(建议先通过 issue 与我们达成共识) 优化功能设计或实现, 或是引入一个新的设计(建议先通过 issue 与我们达成共识)
@ -13,15 +15,10 @@ mirai 欢迎一切形式的代码贡献。你可以通过以下几种途径向 m
为 mirai 添加更广泛的协议支持。 为 mirai 添加更广泛的协议支持。
### 注意事项 ### 注意事项
- mirai 框架已经把实现协议需要做的工作最小化. 为避免工作重复, 请务必熟悉 `net.mamoe.mirai.utils``net.mamoe.mirai.qqandroid.utils` 中工具类
- mirai 使用 [`kotlinx.io`](https://github.com/Kotlin/kotlinx-io) IO 库 - mirai 使用 [`kotlinx.io`](https://github.com/Kotlin/kotlinx-io) IO 库
- mirai 为多平台项目, 请务必考虑多平台兼容性
- mirai 为全协程实现, 请在有必要的时候考虑并发安全性
- 尽量不要引用新的库 - 尽量不要引用新的库
- 遵守 Kotlin 代码规范(提交前使用 IDE 格式化代码 (commit 时勾选 'Reformat code') - 遵守 Kotlin 代码规范(提交前使用 IDE 格式化代码 (commit 时勾选 'Reformat code')
- 熟悉 [`PacketFactory`](https://github.com/mamoe/mirai/blob/master/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt) 架构
- 不要手动拆解数据包. 请一定使用 `kotlinx.serialization` 拆解 ProtoBuf, 使用 mirai 的 `Jce` 序列化器拆解 Jce 数据包, 使用 `kotlinx.serialization` 拆解 Json 数据. - 不要手动拆解数据包. 请一定使用 `kotlinx.serialization` 拆解 ProtoBuf, 使用 mirai 的 `Jce` 序列化器拆解 Jce 数据包, 使用 `kotlinx.serialization` 拆解 Json 数据.
- 必须保证高代码效率(使用 `ByteArrayPool``WeakRef` 等)
## 社区 ## 社区

View File

@ -84,7 +84,7 @@ mirai 既可以作为项目中的 QQ 协议支持库, 也可以作为单独的
### 开发者 ### 开发者
**了解 mirai 架构** [Wiki](https://github.com/mamoe/mirai/wiki/Home) **阅读文档** [docs/mirai.md](docs/mirai.md)
#### 使用 mirai 作为服务器,为 mirai 开发插件 #### 使用 mirai 作为服务器,为 mirai 开发插件
@ -130,10 +130,9 @@ Demos: [mirai-demos](https://github.com/mamoe/mirai-demos)
## 更新日志 ## 更新日志
* 在 [Project](https://github.com/mamoe/mirai/projects/3) 查看已支持功能和计划
* 在 [CHANGELOG](https://github.com/mamoe/mirai/blob/master/CHANGELOG.md) 查看版本更新记录 (仅发布的版本) * 在 [CHANGELOG](https://github.com/mamoe/mirai/blob/master/CHANGELOG.md) 查看版本更新记录 (仅发布的版本)
## [贡献](https://github.com/mamoe/mirai/blob/master/CONTRIBUTING.md) ## [贡献](CONTRIBUTING.md)
我们欢迎一切形式的贡献。 我们欢迎一切形式的贡献。
我们也期待有更多人能加入 mirai 的开发。 我们也期待有更多人能加入 mirai 的开发。

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -1,14 +1,12 @@
# Mirai Guide - Quick Start # Mirai Guide - Quick Start
由于 mirai 项目在快速推进中,因此内容时有变动,本文档的最后更新日期为```2020/3/26```,对应版本```0.30.1``` 由于 mirai 项目在快速推进中,因此内容时有变动,本文档的最后更新日期为```2020/5/11```,对应版本```1.0-RC2-1```
本文适用于对 Kotlin 较熟悉的开发者, 本文适用于对 Kotlin 较熟悉的开发者,
使用 mirai 作为第三方依赖库引用任意一个 Kotlin, Java 或其他 JVM 平台的项目 使用 mirai 作为第三方依赖库引用任意一个 Kotlin, Java 或其他 JVM 平台的项目
**若你希望一份更基础的教程**, 请参阅: [mirai-guide-getting-started](guide_getting_started.md) **若你希望一份更基础的教程**, 请参阅: [mirai-guide-getting-started](guide_getting_started.md)
**若你希望使用 Java 开发**, 请参阅: [mirai-japt](https://github.com/mamoe/mirai-japt)
## 构建需求 ## 构建需求
- Kotlin 1.3.71 (必须) - Kotlin 1.3.71 (必须)
@ -76,7 +74,6 @@ implementation("net.mamoe:mirai-core-qqandroid-common:VERSION")
**android** (Android 平台源集) **android** (Android 平台源集)
**注意**: 在 [KT-37152](https://youtrack.jetbrains.com/issue/KT-37152) 修复前, mirai 无法支持 Android 平台目标. **注意**: 在 [KT-37152](https://youtrack.jetbrains.com/issue/KT-37152) 修复前, mirai 无法支持 Android 平台目标.
```kotlin ```kotlin
implementation("net.mamoe:mirai-core-qqandroid-android:VERSION") implementation("net.mamoe:mirai-core-qqandroid-android:VERSION")
``` ```
@ -85,12 +82,16 @@ implementation("net.mamoe:mirai-core-qqandroid-android:VERSION")
```kotlin ```kotlin
val bot = Bot(qqId, password).alsoLogin() val bot = Bot(qqId, password).alsoLogin()
bot.subscribeMessages { bot.subscribeAlways<GroupMessageEvent> { event ->
"你好" reply "你好!" if (event.message.content.contains("你好")) {
contains("图片"){ File("C:\\image.png").sendAsImage() } reply("你好!")
} else if (event.message.content.contains("你好")) {
File("C:\\image.png").uploadAsImage()
}
} }
bot.subscribeAlways<MemberPermissionChangedEvent> {
if (it.kind == BECOME_OPERATOR) bot.subscribeAlways<MemberPermissionChangedEvent> { event ->
reply("${it.member.id} 成为了管理员") if (event.kind == BECOME_OPERATOR)
reply("${event.member.id} 成为了管理员")
} }
``` ```

112
docs/mirai.md Normal file
View File

@ -0,0 +1,112 @@
# mirai
欢迎来到 mirai 文档.
本文档基于 mirai 1.0.0, 最后修改时间为 2020/5/11
## 声明
1. mirai 为完全免费的开源项目. mirai 项目维护者和贡献者 (下文简称 '我们') 不通过任何方式收取任何费用, 也不提供任何稳定性保障.
2. mirai 不允许被用于任何违反相关法律法规的工作, 包括但不限于: 盗取账号密码, 盗窃用户资金, 群发违禁内容. 因此我们没有支持设备锁验证, 也没有支持免密登录 (在非常用地点登录会频繁要求输入验证码).
3. mirai 不提供任何可能促进上述违法行为的功能, 包括但不限于: 收发红包, 收发转账, 主动添加好友.
4. mirai 不公开任何协议接口. 不支持任何协议扩展.
## 项目整体架构
mirai 项目整体由 核心 (`mirai-core`) 与 控制台(`mirai-console`) 组成.
- [`mirai-core`](../mirai-core) 是机器人服务支持**库**. 提供所有机器人相关 API. **本身只包含抽象类和接口, 具体由协议模块实现**.
可用的协议模块:
- [`mirai-core-qqandroid`](../mirai-core-qqandroid): Android QQ 8.3.0 版本协议实现.
`mirai-core` 设计为一个 **`支持库`**, 意味着它可以被独立依赖, 在任意项目中使用. 详见下文.
- `mirai-core-qqandroid` 继承 `mirai-core`, 是 Android QQ 协议的实现. 在使用时只需参考 `mirai-core` 的 API.
- [`mirai-console`](https://github.com/mamoe/mirai-console) 是基于 `mirai-core` 的, 支持插件加载, 指令系统, 和配置等的**控制台框架**.
console 由 '后端' 和 '前端' 组成.
`mirai-console` 即为后端, 包含所有开发时需要用到的功能.
可用的前端:
- 命令行: `mirai-console` 内置命令行后端.
- 基于 JavaFX 的图形端: [`mirai-console-graphical`](https://github.com/mamoe/mirai-console/tree/master/mirai-console-graphical)
- Unix 友好的终端: [`mirai-console-terminal`](https://github.com/mamoe/mirai-console/tree/master/mirai-console-terminal)
**注意**: `mirai-core` 于 2020 年 6 月发布的 `1.0.0` 版本正式进入稳定更新阶段,
**而 `mirai-console` 仍处于快速迭代阶段, 任何 API 都有可能在不经过警告的情况下改动, 任何 API 都不具有任何稳定性.**
## `mirai-core`
`mirai-core` 仅包含抽象类和接口和一些扩展方法, 且拥有非常完整的 KDoc (源码内文档). 此处没有必要过多赘述.
你可以在这里快速地大致了解 mirai 的全部 API.
要能看懂下文, 建议至少学习 Java, Kotlin 或 C# 其中一门语言.
### 准备
mirai 全部使用 Kotlin, 若你无法理解部分 API, 可先简略阅读 Kotlin 参考: [kotlincn.net](https://www.kotlincn.net/docs/reference/)
有关协程 (`suspend`)部分, mirai 做了大量的兼容性转换以让 Java 使用相同的 API 阻塞地调用一个协程函数.
因此, 对于函数如 `suspend fun sendMessage(Message)`, Java 使用者也可以直接调用它.
### 开始
1. [实验性 API 注解 MiraiExperimentalAPI](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/Annotations.kt#L41-L54)
2. '机器人' 和 '联系人'
1. [ContactOrBot](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/ContactOrBot.kt)
2. [机器人对象 Bot](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt)
3. [Contact](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt)
4. [用户对象 User](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/User.kt)
5. [好友对象 Friend](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Friend.kt)
6. [群对象 Group](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt)
7. [群成员对象 Member](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt)
总结: [机器人和联系人架构](../.github/机器人和联系人架构.png). 其中 `CoroutineScope` 为 Kotlin 协程作用域, Java 使用者可忽略.
3. '消息'
1. [消息对象 Message](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt)
特别注意, `Message` 分为 单个消息(`SingleMessage`) 和 多个消息, 即消息链(`MessageChain` ).
// TODO 此处还有更详细的扩展 API 解释, 待更新
2. [消息链 MessageChain](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt)
// TODO 此处还有更详细的扩展 API 解释, 待更新
3. 接下来可按需阅读各类型消息 [各类型消息](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/). 一个文件包含一种消息.
4. '事件'
mirai 支持异步的事件系统.
1. [事件接口 Event](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/Event.kt)
2. [广播事件 Event.broadcast](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/Event.kt)
3. - Kotlin: [函数式监听事件 subscribe](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/subscriber.kt)
- Kotlin & Java: [方法反射监听事件 JvmMethodListeners](../mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/event/JvmMethodListeners.kt)
4. 内建事件列表 [README](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/README.md).
注意: mirai 将接收到的消息事件独立放置在 `net.mamoe.mirai.message` 下, 并命名为 `MessageEvent`. 并为他们实现了一些扩展. 详见 [MessageEvent.kt](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageEvent.kt)
5. 事件工具类和工具函数 (仅 Kotlin) (可以跳过本节):
标注 (*) 的几种处理方式可能需要比较好的 Kotlin 技能才能理解并正确使用. 建议在不熟悉时不要使用它们.
- 挂起当前协程, 直到返回下一个事件实例: [nextEvent](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/nextEvent.kt)
- 挂起当前协程, 并从一个事件中同步一个值: [syncFromEvent](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/linear.kt)
- (*) 消息事件监听 DSL: [subscribeMessages](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/subscribeMessages.kt)
- (*) 协程 `select` 语法的监听方式: [selectMessages](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/select.kt)
- (*) 挂起协程并等待下一个与 `this` 语境相同的事件 [MessageEvent.nextMessage](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/utils.kt#L50)
一切准备就绪. 现在开始构造 `Bot` 实例:
1. `Bot` 的配置: [BotConfiguration](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt)
可大致了解或跳过. 一般使用默认属性即可.
2. 构造 `Bot` 实例: [BotFactory](../mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/BotFactory.kt#L23), [newBot](../mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/BotFactory.kt#L53)
另外地, 你还可以了解 mirai 提供的多平台日志系统 (为了同时支持控制台和独立依赖): [MiraiLogger](../mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/MiraiLogger.kt), 也可以跳过这个内容
### 使用
使用 mirai 作为一个依赖库: 阅读 [Quick Start](../docs/guide_quick_start.md) 配置依赖.
使用 mirai 作为控制台框架: 使用 [mirai-console](https://github.com/mamoe/mirai-console) 开发插件
## `mirai-core-qqandroid`
`mirai-core` 的实现部分. 不提供任何说明. 使用者无需考虑任何协议实现过程.
## `mirai-console`
此模块处于实验性阶段, 可能没有很好地文档支持, 详见 [mirai-console](https://github.com/mamoe/mirai-console)

View File

@ -9,6 +9,7 @@
package net.mamoe.mirai.contact package net.mamoe.mirai.contact
import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
/** /**
@ -18,7 +19,7 @@ import net.mamoe.mirai.Bot
* @see Contact * @see Contact
* @see Bot * @see Bot
*/ */
interface ContactOrBot { interface ContactOrBot : CoroutineScope {
/** /**
* QQ 号或群号. * QQ 号或群号.
*/ */

View File

@ -12,9 +12,12 @@
package net.mamoe.mirai.event package net.mamoe.mirai.event
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.JavaFriendlyAPI
import net.mamoe.mirai.event.internal.broadcastInternal import net.mamoe.mirai.event.internal.broadcastInternal
import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.SinceMirai import net.mamoe.mirai.utils.SinceMirai
import net.mamoe.mirai.utils.internal.runBlocking
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic import kotlin.jvm.JvmSynthetic
import kotlin.jvm.Volatile import kotlin.jvm.Volatile
@ -32,6 +35,8 @@ import kotlin.jvm.Volatile
* *
* @see [broadcast] 广播事件 * @see [broadcast] 广播事件
* @see [CoroutineScope.subscribe] 监听事件 * @see [CoroutineScope.subscribe] 监听事件
*
* @see CancellableEvent 可被取消的事件
*/ */
interface Event { interface Event {
/** /**
@ -140,7 +145,9 @@ interface CancellableEvent : Event {
/** /**
* 广播一个事件的唯一途径. * 广播一个事件的唯一途径.
* @see __broadcastJava
*/ */
@JvmSynthetic
suspend fun <E : Event> E.broadcast(): E = apply { suspend fun <E : Event> E.broadcast(): E = apply {
if (this is BroadcastControllable && !this.shouldBroadcast) { if (this is BroadcastControllable && !this.shouldBroadcast) {
return@apply return@apply
@ -148,6 +155,21 @@ suspend fun <E : Event> E.broadcast(): E = apply {
this@broadcast.broadcastInternal() // inline, no extra cost this@broadcast.broadcastInternal() // inline, no extra cost
} }
/**
* Java 广播一个事件的唯一途径.
*
* 调用方法: `EventKt.broadcast(event)`
*/
@Suppress("FunctionName")
@JvmName("broadcast")
@JavaFriendlyAPI
fun <E : Event> E.__broadcastJava(): E = apply {
if (this is BroadcastControllable && !this.shouldBroadcast) {
return@apply
}
runBlocking { this@__broadcastJava.broadcastInternal() }
}
/** /**
* 设置为 `true` 以关闭事件. * 设置为 `true` 以关闭事件.
* 所有的 `subscribe` 都能正常添加到监听器列表, 但所有的广播都会直接返回. * 所有的 `subscribe` 都能正常添加到监听器列表, 但所有的广播都会直接返回.

View File

@ -28,6 +28,8 @@ import kotlin.jvm.JvmOverloads
* **注意:** 请为日志做好分类, 即不同的模块使用不同的 [MiraiLogger]. * **注意:** 请为日志做好分类, 即不同的模块使用不同的 [MiraiLogger].
* , [Bot] 中使用 identity "Bot(qqId)" [MiraiLogger] * , [Bot] 中使用 identity "Bot(qqId)" [MiraiLogger]
* [Bot] 的网络处理中使用 identity "BotNetworkHandler" . * [Bot] 的网络处理中使用 identity "BotNetworkHandler" .
*
* Java 调用: `Utils.getDefaultLogger().invoke(identity)`
*/ */
var DefaultLogger: (identity: String?) -> MiraiLogger = { PlatformLogger(it) } var DefaultLogger: (identity: String?) -> MiraiLogger = { PlatformLogger(it) }

View File

@ -47,6 +47,8 @@ actual interface BotFactory {
/** /**
* 自动加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例 * 自动加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*
* Java 调用方式: `BotFactoryJvm.newBot(...)`
*/ */
@JvmName("newBot") @JvmName("newBot")
@JvmOverloads @JvmOverloads
@ -63,6 +65,8 @@ inline fun Bot(context: Context, qq: Long, password: String, configuration: (Bot
/** /**
* 自动加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例 * 自动加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*
* Java 调用方式: `BotFactoryJvm.newBot(...)`
*/ */
@JvmName("newBot") @JvmName("newBot")
@JvmOverloads @JvmOverloads
@ -79,6 +83,8 @@ inline fun Bot(qq: Long, password: String, configuration: (BotConfiguration.() -
/** /**
* 自动加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例 * 自动加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*
* Java 调用方式: `BotFactoryJvm.newBot(...)`
*/ */
@JvmName("newBot") @JvmName("newBot")
@JvmOverloads @JvmOverloads
@ -100,6 +106,8 @@ inline fun Bot(context: Context, qq: Long, passwordMd5: ByteArray, configuration
/** /**
* 自动加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例 * 自动加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*
* Java 调用方式: `BotFactoryJvm.newBot(...)`
*/ */
@JvmName("newBot") @JvmName("newBot")
@JvmOverloads @JvmOverloads
@ -114,9 +122,6 @@ inline fun Bot(qq: Long, passwordMd5: ByteArray, configuration: (BotConfiguratio
factory.Bot(ContextImpl(), qq, passwordMd5, BotConfiguration().apply(configuration)) factory.Bot(ContextImpl(), qq, passwordMd5, BotConfiguration().apply(configuration))
// Do not use ServiceLoader. Probably not working on MPP // Do not use ServiceLoader. Probably not working on MPP
@PublishedApi @PublishedApi
internal val factory: BotFactory = run { internal val factory: BotFactory = run {

View File

@ -1,17 +0,0 @@
/*
* 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
*/
@file:JvmName("BotFactoryJvm")
@file:Suppress("FunctionName", "unused")
package net.mamoe.mirai
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.Context
import net.mamoe.mirai.utils.ContextImpl