mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-28 13:10:13 +08:00
Fixed image
This commit is contained in:
parent
3f56faae75
commit
b6f54dbb7b
309
README.md
309
README.md
@ -1,64 +1,287 @@
|
||||
# Mirai
|
||||
[](http://hits.dwyl.io/him188/mamoe/mirai) [](https://www.codacy.com/manual/Him188/mirai?utm_source=github.com&utm_medium=referral&utm_content=mamoe/mirai&utm_campaign=Badge_Grade)
|
||||
|
||||
一个以 **TIM PC协议(非web)** 驱动的跨平台QQ机器人服务端核心, 虽然目前仅支持 JVM
|
||||
采用服务端-插件模式运行,同时提供独立的跨平台核心库.
|
||||
Mirai 的所有模块均开源
|
||||
一个以 **TIM PC协议(非web)** 驱动的跨平台开源 QQ 机器人服务端核心, 目前仅支持 JVM
|
||||
Mirai 在 JVM 平台采用插件模式运行,同时提供独立的跨平台核心库.
|
||||
未来会在 Native(Win32) 平台提供目前比较流行的几种机器人软件的 API 转接
|
||||
|
||||
项目处于开发阶段, 还有很多未完善的地方. 欢迎任何的代码贡献, 或是 issue.
|
||||
若您有任何意见或建议, 欢迎提交 issue.
|
||||
|
||||
部分协议来自网络上开源项目
|
||||
|
||||
**一切开发旨在学习,请勿用于非法用途**
|
||||
|
||||
## 抢先体验
|
||||
核心框架结构已经开发完毕,一些核心功能也测试完成。
|
||||
仅需几分钟就可以测试 Mirai.
|
||||
## Try
|
||||
|
||||
现在您可以开始体验低付出高效率的 Mirai
|
||||
|
||||
目前还没有写构建,请使用 IDE 运行单个 main 函数。
|
||||
1. Clone
|
||||
2. Import as Gradle project
|
||||
3. Run demo main [Demo 1 Main](mirai-demos/mirai-demo-1/src/main/java/demo1/Main.kt#L22)
|
||||
3. Run demo main [Demo 1 Main](mirai-demos/mirai-demo-1/src/main/java/demo/subscribe/SubscribeSamples.kt)
|
||||
|
||||
### 事件
|
||||
**转到[开发文档](#Development-Guide---Kotlin)**
|
||||
|
||||
#### 使用 Kotlin
|
||||
这里只演示进行不终止地监听。
|
||||
##### Top-level reified
|
||||
多数情况下这是最好的方式。
|
||||
## Update log
|
||||
|
||||
- 发送好友/群消息(10/14)
|
||||
- 接受解析好友消息(10/14)
|
||||
- 接收解析群消息(10/14)
|
||||
- 成员昵称(10/18)
|
||||
- 成员权限(10/18, 计划优化)
|
||||
- 好友在线状态改变(10/14)
|
||||
- Android客户端上线/下线(10/18)
|
||||
- 上传并发送好友/群图片(10/21, 10/26)
|
||||
|
||||
计划中: 添加好友
|
||||
|
||||
## Requirements
|
||||
|
||||
所有平台:
|
||||
- Kotlin 1.3.50
|
||||
|
||||
JVM 平台:
|
||||
- Java 8
|
||||
|
||||
#### Libraries used
|
||||
Mirai 使用以下开源库:
|
||||
- kotlin-stdlib
|
||||
- kotlinx-coroutines
|
||||
- kotlinx-io
|
||||
- kotlin-reflect
|
||||
- pcap4j
|
||||
- atomicfu
|
||||
- ktor
|
||||
- klock
|
||||
- tornadofx
|
||||
- javafx
|
||||
|
||||
## Development Guide - Kotlin
|
||||
|
||||
平台通用开发帮助(不含协议层).
|
||||
|
||||
您需要有一定 Kotlin 基础才能读懂以下内容.
|
||||
若您对本文档有建议, 请告诉我们
|
||||
|
||||
目录:
|
||||
- [Introduction](#Introduction) Mirai 介绍
|
||||
- [Modules](#Modules) 模块介绍
|
||||
- [mirai-core](#mirai-core) 核心模块
|
||||
- [mirai-console](#mirai-console) JVM 控制台
|
||||
- [mirai-demo](#mirai-demo) 示例和演示程序
|
||||
- [mirai-debug](#mirai-debug) 抓包工具和分析工具\
|
||||
- [Logger](#Logger) 日志系统
|
||||
- [Bot](#Bot) 机器人类
|
||||
- [Contact](#Contact) 联系人
|
||||
- [Message](#Message) 消息
|
||||
- [MessageChain](#MessageChain) `MessageChain`
|
||||
- [Types](#Types) 消息类型
|
||||
- [Operators](#Operators) `Message` 一般用法
|
||||
- [Extensions](#Extensions) `Message` 的常用扩展方法
|
||||
- [Image](#Image) 图片
|
||||
- [Image JVM](#Image-JVM) JVM 平台扩展实现
|
||||
- [Event](#Event) 事件
|
||||
- [Subscription](#Subscription) 事件监听(订阅)
|
||||
- [Message Event](#Message-Event) 针对消息事件的订阅实现
|
||||
|
||||
### Introduction
|
||||
|
||||
Mirai 目前为快速流转(Moving fast)状态, 增量版本之间可能不具有兼容性,任何功能都可能在没有警告的情况下添加、删除或者更改。
|
||||
|
||||
### Modules
|
||||
Mirai 的模块组成
|
||||
|
||||
#### mirai-core
|
||||
Mirai 的核心部分.
|
||||
|
||||
- 独立的跨平台设计, 可以被以库的形式内置在任意项目内.
|
||||
- 现有 JVM 支持
|
||||
- 未来计划 Android, Native 支持
|
||||
|
||||
#### mirai-console
|
||||
- 仅 JVM 平台
|
||||
- 仅命令行
|
||||
- Jar 插件支持
|
||||
|
||||
#### mirai-demo
|
||||
Samples and demos.
|
||||
目前仅有 [SubscribeSamples](mirai-demos/mirai-demo-1/src/main/java/demo/subscribe/SubscribeSamples.kt)
|
||||
|
||||
#### mirai-debug
|
||||
抓包工具和分析工具. 不会进行稳定性维护.
|
||||
|
||||
- 抓包自动解密和分析
|
||||
- Hex 着色比较器
|
||||
- GUI Hex 调试器(值转换)
|
||||
|
||||
### Logger
|
||||
[Contact](mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/MiraiLogger.kt)
|
||||
Mirai 维护跨平台日志系统, 针对平台的实现为 `expect class PlatformLogger`,
|
||||
一般推荐使用顶层的 `var DefaultLogger: (identity: String?) -> PlatformLogger` 通过 `DefaultLogger( ... )` 来创建日志记录器.
|
||||
每个 `Bot` 都拥有一个日志记录器, 可通过 `Bot.logger` 获取
|
||||
|
||||
-日志记录尚不完善, 以后可能会修改-
|
||||
|
||||
### Bot
|
||||
[Bot](mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt) 为机器人
|
||||
一个机器人实例只有一个账号.
|
||||
一个机器人实例由多个模块构成.
|
||||
- `BotNetworkHandler` (管理所有网络方面事务, 本文不介绍)
|
||||
- `ContactSystem` (管理联系人, 维护一个 `QQ` 列表和一个 `Group` 列表)
|
||||
|
||||
Mirai 能同时维护多个机器人账号.
|
||||
|
||||
[BotHelper](mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotHelper.kt) 中存在一些快捷方法
|
||||
|
||||
### Contact
|
||||
[Contact](mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt) 为联系人.
|
||||
虽是联系人, 但它包含 `QQ` 和 `Group`.
|
||||
联系人并不是独立的, 它必须隶属于某个 `Bot`
|
||||
|
||||
**共有方法**:
|
||||
- `sendMessage`(`String`|`Message`|`MessageChain`)
|
||||
|
||||
**共有属性**:
|
||||
- id (即 QQ 号和群号)
|
||||
|
||||
注: 为减少出错概率, 联系人的 `id` 均使用无符号整型 `UInt`, 这是 Kotlin 1.3 的一个实验性类型
|
||||
我们建议您在开发中也使用 `UInt`, 以避免产生一些难以发现的问题
|
||||
|
||||
### Message
|
||||
Mirai 中所有的消息均为对象化的 [Message](mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt)
|
||||
实际上, 所有的 `Message` 都是 `inline class`, 保证无性能损失的前提下又不失使用的严谨性和便捷性.
|
||||
`Message` 有大量扩展和相关函数. 本文只介绍使用较多的一部分. 其他函数您也将会在实际开发中通过注释指引了解到.
|
||||
|
||||
#### MessageChain
|
||||
|
||||
一条消息为一个 `MessageChain` 对象.
|
||||
`MessageChain` 也是 `Message` 的一种
|
||||
`MessageChain` 实现 `MutableList` 接口.
|
||||
它有多种实现:
|
||||
- `inline class MessageChainImpl` 通常的 `MutableList<Message>` 实现
|
||||
- `inline class SingleMessageChain` 单个消息的不可变代表包装
|
||||
- `object NullMessageChain` 空的不可变实现. 用于替代 `null` 情况
|
||||
|
||||
仅 `NullMessageChain` 是公开(public)的. 在开发中无需考虑另外两个的存在, 他们将会在 Mirai 内部合适地使用.
|
||||
|
||||
#### Types
|
||||
现支持的消息类型:
|
||||
- `PlainText` 纯文本
|
||||
- `Image` 图片 (将会有独立章节来说明图片的上传等)
|
||||
- `Face` 表情 (QQ 自带表情)
|
||||
|
||||
计划中:
|
||||
- `At` (仅限群, 将会被 QQ 显示为蓝色的连接)
|
||||
- `XML`
|
||||
- `File` (文件上传)
|
||||
|
||||
#### Operators
|
||||
|
||||
| 操作表示 | 说明 |
|
||||
|---| ---|
|
||||
| Message + Message | 连接 `Message`, 得到 `MessageChain` |
|
||||
| Message + String | 连接 `Message` 与 `String`(`PlainText`) 为 `MessageChain` |
|
||||
| Message eq String | 可读字符串如 "\[@10000\]" 判断 |
|
||||
| String in Message | 内容包含判断 |
|
||||
|
||||
#### Extensions
|
||||
|
||||
| 扩展方法 | 说明 |
|
||||
|---| ---|
|
||||
|String.toChain():MessageChain| PlainText(this) |
|
||||
|Message.toChain():MessageChain| 构造上文提到的 SingleMessageChain |
|
||||
|suspend Message.sendTo(Contact)| 发送给联系人 |
|
||||
|
||||
### Image
|
||||
考虑到协议需求和内存消耗, Mirai 的所有 API 均使用 [ExternalImage](mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt)
|
||||
`ExternalImage` 包含图片长宽、大小、格式、文件数据
|
||||
您只需通过扩展函数处理图片.
|
||||
|
||||
| 扩展函数 | 说明 |
|
||||
|---| ---|
|
||||
|suspend ExternalImage.sendTo(Contact)| 上传图片并以纯图片消息发送给联系人 |
|
||||
|suspend ExternalImage.upload():Image | 上传图片并得到 [Image] 消息 |
|
||||
|suspend Contact.sendImage(ExternalImage) | 上传图片并发送给指定联系人 |
|
||||
|
||||
注: 使用 `upload` 而不是 `toMessage` 作为函数名是为了强调它是一个耗时的过程.
|
||||
|
||||
#### Image JVM
|
||||
|
||||
对于 JVM 平台, Mirai 提供额外的足以应对大多数情况的扩展函数:
|
||||
[ExternalImageJvm](mirai-core/src/jvmMain/kotlin/net.mamoe.mirai/utils/ExternalImageJvm.kt)
|
||||
若有必要, 这些函数将会创建临时文件以避免使用内存缓存图片
|
||||
一下内容中, `IMAGE` 可替换为 `ExternalImage`, `BufferedImage`, `File`, `InputStream`, `URL` 或 `Input` (来自 `kotlinx.io`)
|
||||
|
||||
转为 `ExternalImage`
|
||||
- `suspend IMAGE.toExternalImage():ExternalImage`
|
||||
|
||||
直接发送
|
||||
- `suspend IMAGE.sendTo(Contact)`
|
||||
- `suspend Contact.sendImage(IMAGE)`
|
||||
|
||||
转为 Message
|
||||
- `suspend IMAGE.upload(Contact)`
|
||||
- `suspend Contact.upload(IMAGE)`
|
||||
|
||||
只要语义上正确的函数, 在 Mirai 都是可行的.
|
||||
|
||||
### Event
|
||||
|
||||
#### Subscription
|
||||
|
||||
[查看相关监听代码](mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/Subscribers.kt)
|
||||
|
||||
您可以通过顶层 (top-level) 方法 `subscribeXXX` 对某个事件进行监听, 其中 `XXX` 可以是
|
||||
- Always (不断监听)
|
||||
- Once (一次监听)
|
||||
- Until / While (条件监听)
|
||||
|
||||
例:
|
||||
```kotlin
|
||||
inline fun <reified E: Event> subscribeAlways(handler: (E) -> Unit)
|
||||
|
||||
subscribeAlways<FriendMessageEvent>{
|
||||
//it: FriendMessageEvent
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
#### Message Event
|
||||
|
||||
### 图片测试
|
||||
现在可以接收图片消息(并解析为消息链):
|
||||

|
||||

|
||||
对于消息事件, Mirai 还提供了更强大的 DSL 监听方式.
|
||||
[MessageSubscribersBuilder](mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/MessageSubscribers.kt#L140)
|
||||
可用条件方法为:
|
||||
- case (内容相等)
|
||||
- contains
|
||||
- startsWith
|
||||
- endsWith
|
||||
- sentBy (特定发送者)
|
||||
|
||||
上传发送图片已经完成, 您可以在 Demo 中找到发送方式.
|
||||
机器人可以转发图片消息.详情查看 [Image.kt](mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt#L81)
|
||||
|
||||
## 现已支持
|
||||
|
||||
- 发送好友/群消息(10/14)
|
||||
- 接受解析好友消息(10/14)
|
||||
- 接收解析群消息(10/14)
|
||||
- 成员权限, 昵称(10/18)
|
||||
- 好友在线状态改变(10/14)
|
||||
- Android客户端上线/下线(10/18)
|
||||
- 上传并发送图片(10/21)
|
||||
|
||||
## 使用方法
|
||||
### 要求
|
||||
- Kotlin 1.3+
|
||||
#### 用于 JVM 平台
|
||||
- Java 8
|
||||
## 插件开发
|
||||
``` text
|
||||
to be continued
|
||||
...
|
||||
```kotlin
|
||||
// 监听所有群和好友消息
|
||||
subscribeMessages {// this: MessageSubscribersBuilder
|
||||
case("你好"){
|
||||
// this: SenderAndMessage
|
||||
// message: MessageChain
|
||||
// sender: QQ
|
||||
// it: String (来自 MessageChain.toString)
|
||||
// group: Group (如果是群消息)
|
||||
reply("你好!")// reply将发送给这个事件的主体(群消息的群, 好友消息的好友)
|
||||
}
|
||||
|
||||
replyCase("你好"){ "你好!" } // lambda 的返回值将会作为回复消息
|
||||
|
||||
"Hello" reply "World" // 收到 "Hello" 回复 "World"
|
||||
}
|
||||
```
|
||||
|
||||
当然, 您也可以仅监听来自群或好友的消息
|
||||
```kotlin
|
||||
// 监听所有好友消息
|
||||
subscribeFriendMessages { }
|
||||
//监听所有群消息
|
||||
subscribeGroupMessages { }
|
||||
```
|
||||
|
||||
另外, 由于 Mirai 可同时维护多个机器人账号, Mirai 也提供了对单个机器人的事件的监听.
|
||||
为了限制只监听来自某个机器人账号的事件, 您只需要在 `subscribeMessages` 前添加 `bot.` 将其修改为调用扩展方法.
|
||||
例:
|
||||
```kotlin
|
||||
bot.subscribeMessages { }
|
||||
```
|
@ -27,8 +27,9 @@ internal fun IoBuffer.parseLongText0x19(): PlainText {
|
||||
//01 00 59 AA 02 56 30 01 3A 40 6E 35 46 4F 62 68 75 4B 6F 65 31 4E 63 45 41 6B 77 4B 51 5A 5A 4C 47 54 57 43 68 30 4B 56 7A 57 44 38 67 58 70 37 62 77 6A 67 51 69 66 66 53 4A 63 4F 69 78 4F 75 37 36 49 49 4F 37 48 32 55 63 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 14 01 75 01 01 6B 01 78 9C CD 92 BB 4E C3 30 14 86 77 9E C2 32 73 DA A4 21 24 48 4E AA F4 06 A5 B4 51 55 A0 A8 0B 4A 5D 27 35 E4 82 72 69 4B B7 6E 08 06 C4 C0 06 42 48 30 20 21 60 62 EB E3 34 F4 31 70 4A 11 23 23 FC 96 2C F9 D8 BF CF F1 77 8C F2 23 D7 01 03 12 84 D4 F7 54 28 64 78 08 88 87 FD 1E F5 6C 15 C6 91 C5 29 30 AF AD 00 26 E4 86 36 E8 06 94 58 2A CC FC 73 41 E0 1E 5A D4 21 0D D3 25 2A 2C 55 0A 1B D2 BA 5E E0 24 91 D7 B9 B5 72 41 E1 74 B9 5C E0 78 25 27 8B 92 28 14 45 45 FF 76 B4 E8 98 39 18 05 13 47 0B 24 03 4A 86 F5 D8 89 68 3D B4 21 B0 1C 93 71 11 21 08 49 30 A0 98 54 4B 6C 25 A5 E6 80 84 B4 A7 42 4F AA 18 DD 7E 5C F3 89 D0 C0 65 FD 78 58 6B 76 3A 3B 9B BB ED 62 9F AF ED 8F DB 25 C5 3E 38 91 BB C3 23 BB 49 2D AB B5 8D 0D 3A 32 62 79 BD 5A 35 E4 AD DC 1E 86 40 03 88 46 C4 05 8E 79 EA C7 11 EB 09 64 91 88 46 0E D1 C0 5F 73 FD 4D 00 65 97 95 02 D4 0F 34 94 65 D3 B2 78 80 7D C7 0F 54 B8 AA F0 E9 60 8F 4A EE 1E 3F 6E 2E 84 E4 F6 7E 3E 7D 9E 5D 5E 25 EF 67 C9 E4 15 FC DC 81 B2 29 08 0D 85 7E 1C 60 02 BC 45 33 E7 93 F3 D9 C3 D3 FC E5 6D 36 BD 86 2C C3 D7 66 7A 98 FD 4F ED 13 9B C7 C1 78 02 00 04 00 00 00 23 0E 00 07 01 00 04 00 00 00 09
|
||||
discardExact(1)//0x01
|
||||
val raw = readLVByteArray()
|
||||
//TODO 这应该是手机发送时的字体或气泡之类的
|
||||
println("parseLongText0x19.raw=${raw.toUHexString()}")
|
||||
return PlainText(raw.toUHexString())
|
||||
return PlainText("")
|
||||
}
|
||||
|
||||
internal fun IoBuffer.parseMessageImage0x06(): Image {
|
||||
@ -100,6 +101,8 @@ internal fun ByteReadPacket.readMessage(): Message? {
|
||||
println("0x14的未知压缩的data=" + value.toUHexString())
|
||||
//todo 未知压缩算法
|
||||
|
||||
return PlainText("")
|
||||
|
||||
//后面似乎还有一节?
|
||||
//discardExact(7)//02 00 04 00 00 00 23
|
||||
return PlainText(value.toUHexString())
|
||||
|
@ -8,4 +8,6 @@ dependencies {
|
||||
|
||||
compile group: 'com.alibaba', name: 'fastjson', version: '1.2.62'
|
||||
implementation 'org.jsoup:jsoup:1.12.1'
|
||||
|
||||
implementation files('./lib/ExImageGallery.jar')
|
||||
}
|
||||
|
BIN
mirai-demos/mirai-demo-gentleman/lib/ExImageGallery.jar
Normal file
BIN
mirai-demos/mirai-demo-gentleman/lib/ExImageGallery.jar
Normal file
Binary file not shown.
@ -1,10 +1,23 @@
|
||||
package demo.gentleman
|
||||
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.launch
|
||||
import net.mamoe.ex.content.RandomAccessHDImage
|
||||
import net.mamoe.ex.network.ExNetwork
|
||||
import net.mamoe.ex.network.connections.defaults.DownloadHDImageStreamSpider
|
||||
import net.mamoe.ex.network.connections.defaults.ExIPWhiteListSpider
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.message.sendTo
|
||||
import net.mamoe.mirai.message.uploadImage
|
||||
import net.mamoe.robot.AsyncTaskPool
|
||||
import java.io.Closeable
|
||||
import java.io.InputStream
|
||||
import java.util.*
|
||||
import java.util.concurrent.ExecutionException
|
||||
import java.util.concurrent.Future
|
||||
|
||||
|
||||
/**
|
||||
@ -23,6 +36,104 @@ object Gentlemen : MutableMap<UInt, Gentleman> by mutableMapOf() {
|
||||
fun getOrPut(key: Contact): Gentleman = this.getOrPut(key.id) { Gentleman(key) }
|
||||
}
|
||||
|
||||
|
||||
private val sessionMap = LinkedHashMap<Long, HPictureSession>()
|
||||
|
||||
val ERROR_LINK = "https://i.loli.net/2019/08/05/usINjXSiZxrQJkT.jpg"
|
||||
val TITLE_PICTURE_LINK = "https://i.loli.net/2019/08/04/B5ZMw1rdzVQI7Yv.jpg"
|
||||
|
||||
var minstar = 100
|
||||
|
||||
class HPictureSession constructor(private val group: Group, private val sender: QQ, val keyword: String) : Closeable {
|
||||
|
||||
private var hdImage: RandomAccessHDImage? = null
|
||||
var sentCount: Int = 0
|
||||
set(sentCount) {
|
||||
field = this.sentCount
|
||||
}//已经发送了几个 ImageSet
|
||||
|
||||
private var fetchTask: Future<RandomAccessHDImage>? = null
|
||||
|
||||
init {
|
||||
AsyncTaskPool.submit {
|
||||
try {
|
||||
Thread.sleep((1000 * 60 * 10).toLong())//10min
|
||||
} catch (ignored: InterruptedException) {
|
||||
}
|
||||
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
GlobalScope.launch { reloadImage() }
|
||||
}
|
||||
|
||||
private suspend fun reloadImage() {
|
||||
if (keyword.isEmpty()) {
|
||||
group.sendMessage("正在搜寻随机色图")
|
||||
} else {
|
||||
group.sendMessage("正在搜寻有关 $keyword 的色图")
|
||||
}
|
||||
try {
|
||||
withContext(IO) {
|
||||
if (!ExNetwork.doSpider(ExIPWhiteListSpider()).get()) {
|
||||
group.sendMessage("无法连接EX")
|
||||
close()
|
||||
return@withContext
|
||||
}
|
||||
}
|
||||
} catch (e: InterruptedException) {
|
||||
e.printStackTrace()
|
||||
close()
|
||||
return
|
||||
} catch (e: ExecutionException) {
|
||||
e.printStackTrace()
|
||||
close()
|
||||
return
|
||||
}
|
||||
|
||||
this.fetchTask = ExNetwork.getRandomImage(keyword, minstar) { value ->
|
||||
this.hdImage = value
|
||||
if (this.hdImage == null) {
|
||||
runBlocking { group.sendMessage("没找到") }
|
||||
close()
|
||||
} else {
|
||||
with(this.hdImage!!) {
|
||||
if (this.picId != null) {
|
||||
runBlocking {
|
||||
group.sendMessage(picId)
|
||||
}
|
||||
} else {
|
||||
AsyncTaskPool.submit {
|
||||
try {
|
||||
runBlocking {
|
||||
group.uploadImage(ExNetwork.doSpider(DownloadHDImageStreamSpider(this@with)).get() as InputStream).sendTo(group)
|
||||
}
|
||||
} catch (var7: Exception) {
|
||||
var7.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
this.hdImage = null
|
||||
if (this.fetchTask != null) {
|
||||
if (!this.fetchTask!!.isCancelled && !this.fetchTask!!.isDone) {
|
||||
this.fetchTask!!.cancel(true)
|
||||
}
|
||||
}
|
||||
this.fetchTask = null
|
||||
sessionMap.entries.removeIf { longHPictureSessionEntry -> longHPictureSessionEntry.value === this }
|
||||
}
|
||||
}
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
class Gentleman(private val contact: Contact) : Channel<GentleImage> by Channel(IMAGE_BUFFER_CAPACITY) {
|
||||
init {
|
||||
@ -30,7 +141,7 @@ class Gentleman(private val contact: Contact) : Channel<GentleImage> by Channel(
|
||||
GlobalScope.launch {
|
||||
while (!isClosedForSend) {
|
||||
send(GentleImage().apply {
|
||||
sample_url = "http://dev.itxtech.org:10322/randomImg.uue?tdsourcetag=s_pctim_aiomsg"
|
||||
sample_url = "http://dev.itxtech.org:10322/randomImg.uue?tdsourcetag=s_pctim_aiomsg&size=large"
|
||||
contact = this@Gentleman.contact
|
||||
|
||||
image.await()
|
||||
|
@ -2,12 +2,14 @@
|
||||
|
||||
package demo.gentleman
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.BotAccount
|
||||
import net.mamoe.mirai.event.subscribeGroupMessages
|
||||
import net.mamoe.mirai.event.subscribeMessages
|
||||
import net.mamoe.mirai.login
|
||||
import net.mamoe.mirai.message.Image
|
||||
import net.mamoe.mirai.message.ImageId
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.login.requireSuccess
|
||||
import java.io.File
|
||||
|
||||
@ -37,17 +39,30 @@ suspend fun main() {
|
||||
bot.subscribeMessages {
|
||||
"你好" reply "你好!"
|
||||
|
||||
startsWith("发送图片", removePrefix = true) {
|
||||
reply(Image(ImageId(it)))
|
||||
startsWith("随机色图", removePrefix = true) {
|
||||
withContext(Dispatchers.Default) {
|
||||
try {
|
||||
repeat(it.toIntOrNull() ?: 1) {
|
||||
launch {
|
||||
Gentlemen.getOrPut(subject).receive().image.await().send()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
reply(e.message ?: "exception: null")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case("随机色图") {
|
||||
Gentlemen.getOrPut(subject).receive().image.await().send()
|
||||
}
|
||||
|
||||
bot.subscribeGroupMessages {
|
||||
startsWith("色图", removePrefix = true) {
|
||||
HPictureSession(group, sender, it)
|
||||
}
|
||||
|
||||
"色图" caseReply {
|
||||
|
||||
""
|
||||
startsWith("minstar=", removePrefix = true) {
|
||||
minstar = it.toInt()
|
||||
reply("minStar set to $minstar")
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user