mirror of
https://github.com/mamoe/mirai.git
synced 2025-04-01 04:10:12 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
1956a587f2
149
README.md
149
README.md
@ -1,8 +1,12 @@
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<img width="160" src="http://img.mamoe.net/2020/02/16/a759783b42f72.png" alt="logo"></br>
|
<img width="160" src="http://img.mamoe.net/2020/02/16/a759783b42f72.png" alt="logo"></br>
|
||||||
|
|
||||||
<img width="95" src="http://img.mamoe.net/2020/02/16/c4aece361224d.png" alt="title">
|
<img width="95" src="http://img.mamoe.net/2020/02/16/c4aece361224d.png" alt="title">
|
||||||
----
|
----
|
||||||
|
|
||||||
[](https://gitter.im/mamoe/mirai?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
[](https://gitter.im/mamoe/mirai?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||||
[](https://github.com/mamoe/mirai/actions)
|
[](https://github.com/mamoe/mirai/actions)
|
||||||
[](https://bintray.com/him188moe/mirai/mirai-core/)
|
[](https://bintray.com/him188moe/mirai/mirai-core/)
|
||||||
@ -16,6 +20,7 @@ Mirai 是一个在全平台下运行,提供 QQ Android 和 TIM PC 协议支持
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
## Mirai
|
## Mirai
|
||||||
|
|
||||||
**[English](README-eng.md)**
|
**[English](README-eng.md)**
|
||||||
|
|
||||||
多平台 **QQ Android 和 TimPC** 协议支持库与高效率的机器人框架.
|
多平台 **QQ Android 和 TimPC** 协议支持库与高效率的机器人框架.
|
||||||
@ -27,94 +32,59 @@ Mirai既可以作为你项目中的QQ协议支持Lib, 也可以作为单独的Ap
|
|||||||
|
|
||||||
加入 Gitter, 或加入 QQ 群: 655057127
|
加入 Gitter, 或加入 QQ 群: 655057127
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 开始使用Mirai
|
||||||
|
|
||||||
|
Mirai支持以多种方式进行部署,但是目前,我们在集中对mirai-core,mirai-japt以及mirai-api-http等核心模块进行特性的开发,对于非开发者的使用暂时不做过多支持,仅展示开发计划。
|
||||||
|
|
||||||
|
### 开发者
|
||||||
|
|
||||||
|
- 假如你熟悉Kotlin及包管理工具,请参阅[Mirai Guide - Quick Start](/docs/guide_quick_start.md)
|
||||||
|
- 假如你不熟悉Kotlin,希望一份较详细的起步教程,请参阅[Mirai Guide - Getting Started](/docs/guide_getting_started.md)
|
||||||
|
- 假如你使用Java作为开发语言,请参阅[mirai-japt](/mirai-japt/README.md)
|
||||||
|
- 假如你是其他平台开发者,可以通过了解 [mirai-api-http](https://github.com/mamoe/mirai/tree/master/mirai-api-http) 进行接入,欢迎开发不同平台的mirai-sdk
|
||||||
|
- 此外,你还可以在 [Wiki](https://github.com/mamoe/mirai/wiki/Home) 中查看各类帮助,**如 API 示例**。
|
||||||
|
|
||||||
|
### 使用者
|
||||||
|
|
||||||
|
- [mirai-console](https://github.com/mamoe/mirai/tree/master/mirai-console) 支持插件, 在终端中启动 Mirai 并获得机器人服务,**本模块还未完善**,请耐心等待开发完成。
|
||||||
|
- mirai-webpanel Mirai的Web控制台,支持在网页中管理机器人与插件。本模块目前在计划中。在其他模块稳定后,将开始进行开发。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## CHANGELOG
|
## CHANGELOG
|
||||||
|
|
||||||
在 [Project](https://github.com/mamoe/mirai/projects/3) 查看已支持功能和计划
|
在 [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) 查看版本更新记录 (仅发布的版本)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
### mirai-core
|
### mirai-core
|
||||||
|
|
||||||
通用 API 模块,一套 API 适配两套协议。
|
通用 API 模块,一套 API 适配两套协议。
|
||||||
**请参考此模块的 API**
|
**请参考此模块的 API**
|
||||||
|
|
||||||
### mirai-core-qqandroid
|
### mirai-core-qqandroid
|
||||||
|
|
||||||
QQ for Android (8.2.0 版本,2019 年 12 月)协议的实现,目前完成大部分。
|
QQ for Android (8.2.0 版本,2019 年 12 月)协议的实现,目前完成大部分。
|
||||||
|
|
||||||
- 高兼容性:协议仅含极少部分为硬编码,其余全部随官方方式动态生成
|
- 高兼容性:协议仅含极少部分为硬编码,其余全部随官方方式动态生成
|
||||||
- 高安全性:密匙随机,ECDH 动态计算
|
- 高安全性:密匙随机,ECDH 动态计算
|
||||||
- 已支持大部分使用场景, 详情请在[Project](https://github.com/mamoe/mirai/projects/3)查看
|
- 已支持大部分使用场景, 详情请在[Project](https://github.com/mamoe/mirai/projects/3)查看
|
||||||
|
|
||||||
### mirai-core-timpc
|
### mirai-core-timpc
|
||||||
|
|
||||||
TIM PC (2.3.2 版本,2019 年 8 月)协议的实现
|
TIM PC (2.3.2 版本,2019 年 8 月)协议的实现
|
||||||
支持的功能:
|
支持的功能:
|
||||||
|
|
||||||
- 消息收发:图片文字复合消息,图片消息
|
- 消息收发:图片文字复合消息,图片消息
|
||||||
- 群管功能:群员列表,禁言
|
- 群管功能:群员列表,禁言
|
||||||
(目前不再更新此协议,请关注上文的安卓协议)
|
(目前不再更新此协议,请关注上文的安卓协议)
|
||||||
|
|
||||||
## Use directly
|
|
||||||
**直接使用 Mirai(终端环境/网页面板(将来)).**
|
|
||||||
[Mirai-Console](https://github.com/mamoe/mirai/tree/master/mirai-console) 插件支持, 在终端中启动 Mirai 并获得机器人服务
|
|
||||||
本模块还未完善。
|
|
||||||
|
|
||||||
## Use as a library
|
|
||||||
**mirai-core 为独立设计, 可以作为库内置于任意 Java(JVM)/Android 项目中使用.**
|
|
||||||
|
|
||||||
请将 `VERSION` 替换为最新的版本(如 `0.15.0`):
|
|
||||||
[](https://bintray.com/him188moe/mirai/mirai-core/)
|
|
||||||
**Mirai 目前还处于实验性阶段, 我们无法保证任何稳定性, API 也可能会随时修改.**
|
|
||||||
|
|
||||||
### Maven
|
|
||||||
Kotlin 在 Maven 上只支持 JVM 平台.
|
|
||||||
```xml
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>jcenter</id>
|
|
||||||
<url>https://jcenter.bintray.com/</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
```
|
|
||||||
```xml
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.mamoe</groupId>
|
|
||||||
<artifactId>mirai-core-qqandroid-jvm</artifactId>
|
|
||||||
<version>0.15.1</version> <!-- 替换版本为最新版本 -->
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Gradle
|
|
||||||
Mirai 只发布在 `jcenter`, 因此请确保添加 `jcenter()` 仓库:
|
|
||||||
```kotlin
|
|
||||||
repositories{
|
|
||||||
jcenter()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
若您需要使用在跨平台项目, 则要对各个目标平台添加不同的依赖,这与 kotlin 相关多平台库的依赖是类似的。
|
|
||||||
**若您只需要使用在单一平台, 则只需要添加一项该平台的依赖.**
|
|
||||||
|
|
||||||
**注意:**
|
|
||||||
Mirai 核心由 API 模块(`mirai-core`)和协议模块组成。
|
|
||||||
只添加 API 模块将无法正常工作。
|
|
||||||
现在只推荐使用 QQAndroid 协议,请参照下文选择对应目标平台的依赖添加。
|
|
||||||
|
|
||||||
**jvm** (JVM 平台)
|
|
||||||
```kotlin
|
|
||||||
implementation("net.mamoe:mirai-core-qqandroid-jvm:VERSION")
|
|
||||||
```
|
|
||||||
**common** (通用平台)
|
|
||||||
```kotlin
|
|
||||||
implementation("net.mamoe:mirai-core-qqandroid-common:VERSION")
|
|
||||||
```
|
|
||||||
**android** (Android 平台)
|
|
||||||
```kotlin
|
|
||||||
implementation("net.mamoe:mirai-core-qqandroid-android:VERSION")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Java Compatibility
|
|
||||||
**若你希望使用 Java 开发**, 请查看: [mirai-japt](mirai-japt/README.md)
|
|
||||||
|
|
||||||
### Performance
|
|
||||||
Android 上, Mirai 运行需使用 80M 内存.
|
|
||||||
JVM 上启动需 80M 内存, 每多一个机器人实例需要 30M 内存.
|
|
||||||
|
|
||||||
## Contribution
|
## Contribution
|
||||||
|
|
||||||
@ -125,41 +95,12 @@ JVM 上启动需 80M 内存, 每多一个机器人实例需要 30M 内存.
|
|||||||
|
|
||||||
您的 star 是对我们最大的鼓励(点击项目右上角)
|
您的 star 是对我们最大的鼓励(点击项目右上角)
|
||||||
|
|
||||||
## Wiki
|
|
||||||
在 [Wiki](https://github.com/mamoe/mirai/wiki/Home) 中查看各类帮助,**如 API 示例**。
|
|
||||||
|
|
||||||
## Try
|
|
||||||
|
|
||||||
### On JVM or Android
|
|
||||||
现在体验低付出高效率的 Mirai
|
|
||||||
|
|
||||||
```kotlin
|
|
||||||
val bot = Bot(qqId, password).alsoLogin()
|
|
||||||
bot.subscribeMessages {
|
|
||||||
"你好" reply "你好!"
|
|
||||||
"profile" reply { sender.queryProfile() }
|
|
||||||
contains("图片"){ File(imagePath).send() }
|
|
||||||
}
|
|
||||||
bot.subscribeAlways<MemberPermissionChangedEvent> {
|
|
||||||
if (it.kind == BECOME_OPERATOR)
|
|
||||||
reply("${it.member.id} 成为了管理员")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Clone
|
|
||||||
2. Import as Gradle project
|
|
||||||
3. 运行 Demo 程序: [mirai-demo](#mirai-demo) 示例和演示程序
|
|
||||||
|
|
||||||
|
|
||||||
## Build Requirements
|
## Libraries used
|
||||||
|
|
||||||
- Kotlin 1.3.61
|
|
||||||
- JDK 8 (required)
|
|
||||||
- JDK 11(for protocol tools, optional)
|
|
||||||
- Android SDK 29 (for Android target, optional)
|
|
||||||
|
|
||||||
#### Libraries used
|
|
||||||
感谢:
|
感谢:
|
||||||
|
|
||||||
- [kotlin-stdlib](https://github.com/JetBrains/kotlin)
|
- [kotlin-stdlib](https://github.com/JetBrains/kotlin)
|
||||||
- [kotlinx-coroutines](https://github.com/Kotlin/kotlinx.coroutines)
|
- [kotlinx-coroutines](https://github.com/Kotlin/kotlinx.coroutines)
|
||||||
- [kotlinx-io](https://github.com/Kotlin/kotlinx-io)
|
- [kotlinx-io](https://github.com/Kotlin/kotlinx-io)
|
||||||
@ -176,15 +117,21 @@ bot.subscribeAlways<MemberPermissionChangedEvent> {
|
|||||||
- [toml4j](https://github.com/mwanji/toml4j)
|
- [toml4j](https://github.com/mwanji/toml4j)
|
||||||
- [snakeyaml](https://mvnrepository.com/artifact/org.yaml/snakeyaml)
|
- [snakeyaml](https://mvnrepository.com/artifact/org.yaml/snakeyaml)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
协议原版权归属腾讯科技股份有限公司所有,本项目其他代码遵守:
|
协议原版权归属腾讯科技股份有限公司所有,本项目其他代码遵守:
|
||||||
**GNU AFFERO GENERAL PUBLIC LICENSE version 3**
|
**GNU AFFERO GENERAL PUBLIC LICENSE version 3**
|
||||||
|
|
||||||
其中部分要求:
|
其中部分要求:
|
||||||
|
|
||||||
- (见 LICENSE 第 13 节) 尽管本许可协议有其他规定,但如果您修改本程序,则修改后的版本必须显着地为所有通过计算机网络与它进行远程交互的用户(如果您的版本支持这种交互)提供从网络服务器通过一些标准或惯用的软件复制方法**免费**访问相应的**源代码**的机会
|
- (见 LICENSE 第 13 节) 尽管本许可协议有其他规定,但如果您修改本程序,则修改后的版本必须显着地为所有通过计算机网络与它进行远程交互的用户(如果您的版本支持这种交互)提供从网络服务器通过一些标准或惯用的软件复制方法**免费**访问相应的**源代码**的机会
|
||||||
- (见 LICENSE 第 4 节) 您可以免费或收费地传递这个项目的源代码或目标代码(即编译结果), **但前提是提供明显的版权声明** (您需要标注本 `GitHub` 项目地址)
|
- (见 LICENSE 第 4 节) 您可以免费或收费地传递这个项目的源代码或目标代码(即编译结果), **但前提是提供明显的版权声明** (您需要标注本 `GitHub` 项目地址)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Acknowledgement
|
## Acknowledgement
|
||||||
|
|
||||||
特别感谢 [JetBrains](https://www.jetbrains.com/?from=mirai) 为开源项目提供免费的 [IntelliJ IDEA](https://www.jetbrains.com/idea/?from=mirai) 等 IDE 的授权
|
特别感谢 [JetBrains](https://www.jetbrains.com/?from=mirai) 为开源项目提供免费的 [IntelliJ IDEA](https://www.jetbrains.com/idea/?from=mirai) 等 IDE 的授权
|
||||||
[<img src=".github/jetbrains-variant-3.png" width="200"/>](https://www.jetbrains.com/?from=mirai)
|
[<img src=".github/jetbrains-variant-3.png" width="200"/>](https://www.jetbrains.com/?from=mirai)
|
||||||
|
|
@ -1,18 +1,20 @@
|
|||||||
# Mirai Guide - Getting Started
|
# Mirai Guide - Getting Started
|
||||||
|
|
||||||
由于Mirai项目在快速推进中,因此内容时有变动,本文档的最后更新日期为```2020-02-20```,对应版本```0.16.0```
|
由于Mirai项目在快速推进中,因此内容时有变动,本文档的最后更新日期为```2020-02-20```,对应版本```0.17.0```
|
||||||
|
|
||||||
假如仅仅使用Mirai,不需要对整个项目进行Clone,只需在项目内添加Gradle Dependency或使用即可。
|
假如仅仅使用Mirai,不需要对整个项目进行Clone,只需在项目内添加Gradle Dependency或使用即可。
|
||||||
|
|
||||||
下面介绍详细的入门步骤。
|
下面介绍详细的入门步骤。
|
||||||
|
|
||||||
## With Console
|
本页采用Kotlin作为开发语言,**若你希望使用 Java 开发**, 请参阅: [mirai-japt](mirai-japt/README.md)
|
||||||
|
|
||||||
|
## Use Console
|
||||||
|
|
||||||
使用mirai-console,以插件形式对服务器功能进行管理,启动无需任何IDE。
|
使用mirai-console,以插件形式对服务器功能进行管理,启动无需任何IDE。
|
||||||
|
|
||||||
**由于mirai-console还没有开发完成,暂时不提供入门**
|
**由于mirai-console还没有开发完成,暂时不提供入门**
|
||||||
|
|
||||||
## With Loader
|
## Use Loader
|
||||||
|
|
||||||
通过编写Kotlin程序启动mirai-core,并定义你的Mirai Bot行为。
|
通过编写Kotlin程序启动mirai-core,并定义你的Mirai Bot行为。
|
||||||
|
|
||||||
@ -20,7 +22,7 @@
|
|||||||
|
|
||||||
### 1 安装IDEA与JDK
|
### 1 安装IDEA与JDK
|
||||||
|
|
||||||
JDK要求8以上
|
JDK要求6以上
|
||||||
|
|
||||||
### 2 新建Gradle项目
|
### 2 新建Gradle项目
|
||||||
|
|
||||||
@ -51,12 +53,11 @@ JDK要求8以上
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- 添加依赖,将dependencies部分覆盖为
|
- 添加依赖,将dependencies部分覆盖。 `mirai-core` 的最新版本为: [](https://bintray.com/him188moe/mirai/mirai-core/)
|
||||||
|
|
||||||
```groovy
|
```groovy
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'net.mamoe:mirai-core:0.16.0'
|
implementation 'net.mamoe:mirai-core-qqandroid-jvm:0.17.0'//此处版本应替换为当前最新
|
||||||
implementation 'net.mamoe:mirai-core-qqandroid-jvm:0.16.0'
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
|
||||||
testCompile group: 'junit', name: 'junit', version: '4.12'
|
testCompile group: 'junit', name: 'junit', version: '4.12'
|
||||||
}
|
}
|
||||||
@ -83,7 +84,7 @@ import net.mamoe.mirai.event.subscribeMessages
|
|||||||
suspend fun main() {
|
suspend fun main() {
|
||||||
val qqId = 10000L//Bot的QQ号,需为Long类型,在结尾处添加大写L
|
val qqId = 10000L//Bot的QQ号,需为Long类型,在结尾处添加大写L
|
||||||
val password = "your_password"//Bot的密码
|
val password = "your_password"//Bot的密码
|
||||||
val miraiBot = Bot(qqId, password).alsoLogin()//新建Bot并登陆
|
val miraiBot = Bot(qqId, password).alsoLogin()//新建Bot并登录
|
||||||
miraiBot.subscribeMessages {
|
miraiBot.subscribeMessages {
|
||||||
"你好" reply "你好!"
|
"你好" reply "你好!"
|
||||||
case("at me") {
|
case("at me") {
|
||||||
@ -94,7 +95,7 @@ suspend fun main() {
|
|||||||
"刘老板太强了".reply()
|
"刘老板太强了".reply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
miraiBot.join()
|
miraiBot.join() // 等待 Bot 离线, 避免主线程退出
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -104,3 +105,25 @@ suspend fun main() {
|
|||||||
|
|
||||||
|
|
||||||
至此,简单的入门已经结束,下面可根据不同的需求参阅wiki进行功能的添加。
|
至此,简单的入门已经结束,下面可根据不同的需求参阅wiki进行功能的添加。
|
||||||
|
|
||||||
|
|
||||||
|
### 此外,还可以使用Maven作为包管理工具
|
||||||
|
本项目推荐使用gradle,因此不提供详细入门指导
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>jcenter</id>
|
||||||
|
<url>https://jcenter.bintray.com/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
```
|
||||||
|
```xml
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.mamoe</groupId>
|
||||||
|
<artifactId>mirai-core-qqandroid-jvm</artifactId>
|
||||||
|
<version>0.17.0</version> <!-- 替换版本为最新版本 -->
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
```
|
||||||
|
114
docs/guide_quick_start.md
Normal file
114
docs/guide_quick_start.md
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
# Mirai Guide - Quick Start
|
||||||
|
|
||||||
|
由于Mirai项目在快速推进中,因此内容时有变动,本文档的最后更新日期为```2020-02-20```,对应版本```0.17.0```
|
||||||
|
|
||||||
|
本文适用于对kotlin较熟悉的开发者
|
||||||
|
|
||||||
|
**若你希望一份更为基础且详细的guide**, 请参阅: [mirai-guide-getting-started](guide_getting_started.md)
|
||||||
|
|
||||||
|
**若你希望使用 Java 开发**, 请参阅: [mirai-japt](/mirai-japt/README.md)
|
||||||
|
|
||||||
|
## Build Requirements
|
||||||
|
|
||||||
|
- Kotlin 1.3.61
|
||||||
|
- JDK 6 (required)
|
||||||
|
- JDK 11(for protocol tools, optional)
|
||||||
|
- Android SDK 29 (for Android target, optional)
|
||||||
|
|
||||||
|
## Use directly
|
||||||
|
|
||||||
|
**直接使用 Mirai(终端环境/网页面板(将来)).**
|
||||||
|
[Mirai-Console](https://github.com/mamoe/mirai/tree/master/mirai-console) 插件支持, 在终端中启动 Mirai 并获得机器人服务
|
||||||
|
本模块还未完善。
|
||||||
|
|
||||||
|
## Use as a library
|
||||||
|
|
||||||
|
**mirai-core 为独立设计, 可以作为库内置于任意 Java(JVM)/Android 项目中使用.**
|
||||||
|
|
||||||
|
请将 `VERSION` 替换为最新的版本(如 `0.15.0`):
|
||||||
|
[](https://bintray.com/him188moe/mirai/mirai-core/)
|
||||||
|
**Mirai 目前还处于实验性阶段, 我们无法保证任何稳定性, API 也可能会随时修改.**
|
||||||
|
|
||||||
|
### Maven
|
||||||
|
|
||||||
|
Kotlin 在 Maven 上只支持 JVM 平台.
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>jcenter</id>
|
||||||
|
<url>https://jcenter.bintray.com/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
```
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.mamoe</groupId>
|
||||||
|
<artifactId>mirai-core-qqandroid-jvm</artifactId>
|
||||||
|
<version>0.15.1</version> <!-- 替换版本为最新版本 -->
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Gradle
|
||||||
|
|
||||||
|
Mirai 只发布在 `jcenter`, 因此请确保添加 `jcenter()` 仓库:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
repositories{
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
若您需要使用在跨平台项目, 则要对各个目标平台添加不同的依赖,这与 kotlin 相关多平台库的依赖是类似的。
|
||||||
|
**若您只需要使用在单一平台, 则只需要添加一项该平台的依赖.**
|
||||||
|
|
||||||
|
**注意:**
|
||||||
|
Mirai 核心由 API 模块(`mirai-core`)和协议模块组成。
|
||||||
|
只添加 API 模块将无法正常工作。
|
||||||
|
现在只推荐使用 QQAndroid 协议,请参照下文选择对应目标平台的依赖添加。
|
||||||
|
|
||||||
|
**jvm** (JVM 平台)
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
implementation("net.mamoe:mirai-core-qqandroid-jvm:VERSION")
|
||||||
|
```
|
||||||
|
|
||||||
|
**common** (通用平台)
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
implementation("net.mamoe:mirai-core-qqandroid-common:VERSION")
|
||||||
|
```
|
||||||
|
|
||||||
|
**android** (Android 平台)
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
implementation("net.mamoe:mirai-core-qqandroid-android:VERSION")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Try
|
||||||
|
|
||||||
|
### On JVM or Android
|
||||||
|
|
||||||
|
现在体验低付出高效率的 Mirai
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val bot = Bot(qqId, password).alsoLogin()
|
||||||
|
bot.subscribeMessages {
|
||||||
|
"你好" reply "你好!"
|
||||||
|
"profile" reply { sender.queryProfile() }
|
||||||
|
contains("图片"){ File(imagePath).send() }
|
||||||
|
}
|
||||||
|
bot.subscribeAlways<MemberPermissionChangedEvent> {
|
||||||
|
if (it.kind == BECOME_OPERATOR)
|
||||||
|
reply("${it.member.id} 成为了管理员")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
|
||||||
|
Android 上, Mirai 运行需使用 80M 内存.
|
||||||
|
JVM 上启动需 80M 内存, 每多一个机器人实例需要 30M 内存.
|
||||||
|
|
@ -13,6 +13,8 @@ import kotlinx.coroutines.*
|
|||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.api.http.queue.MessageQueue
|
import net.mamoe.mirai.api.http.queue.MessageQueue
|
||||||
import net.mamoe.mirai.event.Listener
|
import net.mamoe.mirai.event.Listener
|
||||||
|
import net.mamoe.mirai.event.events.BotEvent
|
||||||
|
import net.mamoe.mirai.event.subscribeAlways
|
||||||
import net.mamoe.mirai.event.subscribeMessages
|
import net.mamoe.mirai.event.subscribeMessages
|
||||||
import net.mamoe.mirai.message.MessagePacket
|
import net.mamoe.mirai.message.MessagePacket
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
@ -102,12 +104,10 @@ class TempSession internal constructor(coroutineContext: CoroutineContext) : Ses
|
|||||||
class AuthedSession internal constructor(val bot: Bot, coroutineContext: CoroutineContext) : Session(coroutineContext) {
|
class AuthedSession internal constructor(val bot: Bot, coroutineContext: CoroutineContext) : Session(coroutineContext) {
|
||||||
|
|
||||||
val messageQueue = MessageQueue()
|
val messageQueue = MessageQueue()
|
||||||
private val _listener: Listener<MessagePacket<*, *>>
|
private val _listener: Listener<BotEvent>
|
||||||
|
|
||||||
init {
|
init {
|
||||||
bot.subscribeMessages {
|
_listener = bot.subscribeAlways{ this.run(messageQueue::add) }
|
||||||
_listener = always { this.run(messageQueue::add) } // this aka messagePacket
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
|
@ -9,7 +9,7 @@ import net.mamoe.mirai.message.MessagePacket
|
|||||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
open class BotEventDTO : EventDTO()
|
sealed class BotEventDTO : EventDTO()
|
||||||
|
|
||||||
@UseExperimental(MiraiExperimentalAPI::class)
|
@UseExperimental(MiraiExperimentalAPI::class)
|
||||||
fun BotEvent.toDTO() = when(this) {
|
fun BotEvent.toDTO() = when(this) {
|
@ -17,6 +17,6 @@ abstract class VerifyDTO : DTO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
open class EventDTO : DTO
|
abstract class EventDTO : DTO
|
||||||
|
|
||||||
object IgnoreEventDTO : EventDTO()
|
object IgnoreEventDTO : EventDTO()
|
@ -32,32 +32,36 @@ data class FriendMessagePacketDTO(val sender: QQDTO) : MessagePacketDTO()
|
|||||||
@SerialName("GroupMessage")
|
@SerialName("GroupMessage")
|
||||||
data class GroupMessagePacketDTO(val sender: MemberDTO) : MessagePacketDTO()
|
data class GroupMessagePacketDTO(val sender: MemberDTO) : MessagePacketDTO()
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@SerialName("UnKnownMessage")
|
|
||||||
data class UnKnownMessagePacketDTO(val msg: String) : MessagePacketDTO()
|
|
||||||
|
|
||||||
// Message
|
// Message
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("Source")
|
@SerialName("Source")
|
||||||
data class MessageSourceDTO(val uid: Long) : MessageDTO()
|
data class MessageSourceDTO(val uid: Long) : MessageDTO()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("At")
|
@SerialName("At")
|
||||||
data class AtDTO(val target: Long, val display: String = "") : MessageDTO()
|
data class AtDTO(val target: Long, val display: String = "") : MessageDTO()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("AtAll")
|
@SerialName("AtAll")
|
||||||
data class AtAllDTO(val target: Long = 0) : MessageDTO() // target为保留字段
|
data class AtAllDTO(val target: Long = 0) : MessageDTO() // target为保留字段
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("Face")
|
@SerialName("Face")
|
||||||
data class FaceDTO(val faceId: Int) : MessageDTO()
|
data class FaceDTO(val faceId: Int) : MessageDTO()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("Plain")
|
@SerialName("Plain")
|
||||||
data class PlainDTO(val text: String) : MessageDTO()
|
data class PlainDTO(val text: String) : MessageDTO()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("Image")
|
@SerialName("Image")
|
||||||
data class ImageDTO(val imageId: String) : MessageDTO()
|
data class ImageDTO(val imageId: String) : MessageDTO()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("Xml")
|
@SerialName("Xml")
|
||||||
data class XmlDTO(val xml: String) : MessageDTO()
|
data class XmlDTO(val xml: String) : MessageDTO()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("Unknown")
|
@SerialName("Unknown")
|
||||||
data class UnknownMessageDTO(val text: String) : MessageDTO()
|
data class UnknownMessageDTO(val text: String) : MessageDTO()
|
||||||
@ -66,8 +70,8 @@ data class UnknownMessageDTO(val text: String) : MessageDTO()
|
|||||||
* Abstract Class
|
* Abstract Class
|
||||||
* */
|
* */
|
||||||
@Serializable
|
@Serializable
|
||||||
sealed class MessagePacketDTO : DTO {
|
sealed class MessagePacketDTO : EventDTO() {
|
||||||
lateinit var messageChain : MessageChainDTO
|
lateinit var messageChain: MessageChainDTO
|
||||||
}
|
}
|
||||||
|
|
||||||
typealias MessageChainDTO = List<MessageDTO>
|
typealias MessageChainDTO = List<MessageDTO>
|
||||||
@ -79,11 +83,15 @@ sealed class MessageDTO : DTO
|
|||||||
/*
|
/*
|
||||||
Extend function
|
Extend function
|
||||||
*/
|
*/
|
||||||
fun MessagePacket<*, *>.toDTO(): MessagePacketDTO = when (this) {
|
fun MessagePacket<*, *>.toDTO() = when (this) {
|
||||||
is FriendMessage -> FriendMessagePacketDTO(QQDTO(sender))
|
is FriendMessage -> FriendMessagePacketDTO(QQDTO(sender))
|
||||||
is GroupMessage -> GroupMessagePacketDTO(MemberDTO(sender))
|
is GroupMessage -> GroupMessagePacketDTO(MemberDTO(sender))
|
||||||
else -> UnKnownMessagePacketDTO("UnKnown Message Packet")
|
else -> IgnoreEventDTO
|
||||||
}.apply { messageChain = mutableListOf<MessageDTO>().also{ ls -> message.foreachContent { ls.add(it.toDTO()) }}}
|
}.apply {
|
||||||
|
if (this is MessagePacketDTO) {
|
||||||
|
messageChain = mutableListOf<MessageDTO>().also { ls -> message.foreachContent { ls.add(it.toDTO()) } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun MessageChainDTO.toMessageChain(contact: Contact) =
|
fun MessageChainDTO.toMessageChain(contact: Contact) =
|
||||||
MessageChain().apply { this@toMessageChain.forEach { add(it.toMessage(contact)) } }
|
MessageChain().apply { this@toMessageChain.forEach { add(it.toMessage(contact)) } }
|
||||||
@ -111,5 +119,3 @@ fun MessageDTO.toMessage(contact: Contact) = when (this) {
|
|||||||
is MessageSourceDTO, is UnknownMessageDTO -> PlainText("assert cannot reach")
|
is MessageSourceDTO, is UnknownMessageDTO -> PlainText("assert cannot reach")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,26 +9,35 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.api.http.queue
|
package net.mamoe.mirai.api.http.queue
|
||||||
|
|
||||||
|
import net.mamoe.mirai.api.http.data.common.EventDTO
|
||||||
|
import net.mamoe.mirai.api.http.data.common.IgnoreEventDTO
|
||||||
|
import net.mamoe.mirai.api.http.data.common.toDTO
|
||||||
|
import net.mamoe.mirai.event.events.BotEvent
|
||||||
import net.mamoe.mirai.message.GroupMessage
|
import net.mamoe.mirai.message.GroupMessage
|
||||||
import net.mamoe.mirai.message.MessagePacket
|
|
||||||
import net.mamoe.mirai.message.data.MessageSource
|
import net.mamoe.mirai.message.data.MessageSource
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.util.concurrent.ConcurrentLinkedDeque
|
import java.util.concurrent.ConcurrentLinkedDeque
|
||||||
|
|
||||||
class MessageQueue : ConcurrentLinkedDeque<MessagePacket<*, *>>() {
|
class MessageQueue : ConcurrentLinkedDeque<BotEvent>() {
|
||||||
|
|
||||||
val quoteCache = ConcurrentHashMap<Long, GroupMessage>()
|
val quoteCache = ConcurrentHashMap<Long, GroupMessage>()
|
||||||
|
|
||||||
fun fetch(size: Int): List<MessagePacket<*, *>> {
|
fun fetch(size: Int): List<EventDTO> {
|
||||||
var count = size
|
var count = size
|
||||||
quoteCache.clear()
|
quoteCache.clear()
|
||||||
val ret = ArrayList<MessagePacket<*, *>>(count)
|
val ret = ArrayList<EventDTO>(count)
|
||||||
while (!this.isEmpty() && count-- > 0) {
|
while (!this.isEmpty() && count > 0) {
|
||||||
val packet = pop()
|
val event = pop()
|
||||||
ret.add(packet)
|
|
||||||
|
|
||||||
if (packet is GroupMessage) {
|
event.toDTO().also {
|
||||||
addCache(packet)
|
if (it != IgnoreEventDTO) {
|
||||||
|
ret.add(it)
|
||||||
|
count--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event is GroupMessage) {
|
||||||
|
addCache(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
|
@ -37,9 +37,8 @@ fun Application.messageModule() {
|
|||||||
miraiGet("/fetchMessage") {
|
miraiGet("/fetchMessage") {
|
||||||
val count: Int = paramOrNull("count")
|
val count: Int = paramOrNull("count")
|
||||||
val fetch = it.messageQueue.fetch(count)
|
val fetch = it.messageQueue.fetch(count)
|
||||||
val ls = Array(fetch.size) { index -> fetch[index].toDTO() }
|
|
||||||
|
|
||||||
call.respondJson(ls.toList().toJson())
|
call.respondJson(fetch.toJson())
|
||||||
}
|
}
|
||||||
|
|
||||||
miraiVerify<SendDTO>("/sendFriendMessage") {
|
miraiVerify<SendDTO>("/sendFriendMessage") {
|
||||||
|
@ -13,7 +13,6 @@ import kotlinx.serialization.*
|
|||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.modules.SerializersModule
|
import kotlinx.serialization.modules.SerializersModule
|
||||||
import net.mamoe.mirai.api.http.data.common.*
|
import net.mamoe.mirai.api.http.data.common.*
|
||||||
import net.mamoe.mirai.message.data.MessageSource
|
|
||||||
|
|
||||||
// 解析失败时直接返回null,由路由判断响应400状态
|
// 解析失败时直接返回null,由路由判断响应400状态
|
||||||
@UseExperimental(ImplicitReflectionSerializer::class)
|
@UseExperimental(ImplicitReflectionSerializer::class)
|
||||||
@ -45,20 +44,46 @@ else MiraiJson.json.stringify(serializer, this)
|
|||||||
*/
|
*/
|
||||||
object MiraiJson {
|
object MiraiJson {
|
||||||
val json = Json(context = SerializersModule {
|
val json = Json(context = SerializersModule {
|
||||||
polymorphic(MessagePacketDTO.serializer()) {
|
|
||||||
|
polymorphic(EventDTO.serializer()) {
|
||||||
GroupMessagePacketDTO::class with GroupMessagePacketDTO.serializer()
|
GroupMessagePacketDTO::class with GroupMessagePacketDTO.serializer()
|
||||||
FriendMessagePacketDTO::class with FriendMessagePacketDTO.serializer()
|
FriendMessagePacketDTO::class with FriendMessagePacketDTO.serializer()
|
||||||
UnKnownMessagePacketDTO::class with UnKnownMessagePacketDTO.serializer()
|
|
||||||
}
|
BotOnlineEventDTO::class with BotOnlineEventDTO.serializer()
|
||||||
polymorphic(MessageDTO.serializer()) {
|
BotOfflineEventActiveDTO::class with BotOfflineEventActiveDTO.serializer()
|
||||||
MessageSourceDTO::class with MessageSourceDTO.serializer()
|
BotOfflineEventForceDTO::class with BotOfflineEventForceDTO.serializer()
|
||||||
AtDTO::class with AtDTO.serializer()
|
BotOfflineEventDroppedDTO::class with BotOfflineEventDroppedDTO.serializer()
|
||||||
AtAllDTO::class with AtAllDTO.serializer()
|
BotReloginEventDTO::class with BotReloginEventDTO.serializer()
|
||||||
FaceDTO::class with FaceDTO.serializer()
|
BotGroupPermissionChangeEventDTO::class with BotGroupPermissionChangeEventDTO.serializer()
|
||||||
PlainDTO::class with PlainDTO.serializer()
|
BotMuteEventDTO::class with BotMuteEventDTO.serializer()
|
||||||
ImageDTO::class with ImageDTO.serializer()
|
BotUnmuteEventDTO::class with BotUnmuteEventDTO.serializer()
|
||||||
XmlDTO::class with XmlDTO.serializer()
|
BotJoinGroupEventDTO::class with BotJoinGroupEventDTO.serializer()
|
||||||
UnknownMessageDTO::class with UnknownMessageDTO.serializer()
|
GroupNameChangeEventDTO::class with GroupNameChangeEventDTO.serializer()
|
||||||
|
GroupEntranceAnnouncementChangeEventDTO::class with GroupEntranceAnnouncementChangeEventDTO.serializer()
|
||||||
|
GroupMuteAllEventDTO::class with GroupMuteAllEventDTO.serializer()
|
||||||
|
GroupAllowAnonymousChatEventDTO::class with GroupAllowAnonymousChatEventDTO.serializer()
|
||||||
|
GroupAllowConfessTalkEventDTO::class with GroupAllowConfessTalkEventDTO.serializer()
|
||||||
|
GroupAllowMemberInviteEventDTO::class with GroupAllowMemberInviteEventDTO.serializer()
|
||||||
|
MemberJoinEventDTO::class with MemberJoinEventDTO.serializer()
|
||||||
|
MemberLeaveEventKickDTO::class with MemberLeaveEventKickDTO.serializer()
|
||||||
|
MemberLeaveEventQuitDTO::class with MemberLeaveEventQuitDTO.serializer()
|
||||||
|
MemberCardChangeEventDTO::class with MemberCardChangeEventDTO.serializer()
|
||||||
|
MemberSpecialTitleChangeEventDTO::class with MemberSpecialTitleChangeEventDTO.serializer()
|
||||||
|
MemberPermissionChangeEventDTO::class with MemberPermissionChangeEventDTO.serializer()
|
||||||
|
MemberMuteEventDTO::class with MemberMuteEventDTO.serializer()
|
||||||
|
MemberUnmuteEventDTO::class with MemberUnmuteEventDTO.serializer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Message Polymorphic
|
||||||
|
// polymorphic(MessageDTO.serializer()) {
|
||||||
|
// MessageSourceDTO::class with MessageSourceDTO.serializer()
|
||||||
|
// AtDTO::class with AtDTO.serializer()
|
||||||
|
// AtAllDTO::class with AtAllDTO.serializer()
|
||||||
|
// FaceDTO::class with FaceDTO.serializer()
|
||||||
|
// PlainDTO::class with PlainDTO.serializer()
|
||||||
|
// ImageDTO::class with ImageDTO.serializer()
|
||||||
|
// XmlDTO::class with XmlDTO.serializer()
|
||||||
|
// UnknownMessageDTO::class with UnknownMessageDTO.serializer()
|
||||||
|
// }
|
||||||
})
|
})
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user