diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsAndroid.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsAndroid.kt index eafc5cfb9..ae344886e 100644 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsAndroid.kt +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsAndroid.kt @@ -25,7 +25,7 @@ actual val deviceName: String get() = InetAddress.getLocalHost().hostName * Ktor HttpClient. 不同平台使用不同引擎. */ @KtorExperimentalAPI -internal actual val httpClient: HttpClient +internal actual val Http: HttpClient get() = HttpClient(CIO) /** diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt index d69d2e7a0..2b7997125 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt @@ -226,6 +226,7 @@ Mirai 22:04:48 : Packet received: UnknownEventPacket(id=00 D6, identity=(2092749 * 添加一个好友 * * @param lazyMessage 若需要验证请求时的验证消息. + * @param lazyRemark 好友备注 */ suspend fun ContactSystem.addFriend(id: UInt, lazyMessage: () -> String = { "" }, lazyRemark: () -> String = { "" }): AddFriendResult = bot.withSession { when (CanAddFriendPacket(bot.qqAccount, id, bot.sessionKey).sendAndExpect()) { diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt index 9d9e78cbe..abe4f0714 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt @@ -5,7 +5,9 @@ package net.mamoe.mirai.message import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.QQ import net.mamoe.mirai.network.protocol.tim.packet.action.FriendImageIdRequestPacket +import net.mamoe.mirai.network.protocol.tim.packet.action.download import net.mamoe.mirai.utils.ExternalImage +import net.mamoe.mirai.utils.Http import kotlin.js.JsName import kotlin.jvm.Volatile @@ -154,17 +156,6 @@ inline class Image(inline val id: ImageId) : Message { override val stringValue: String get() = "[${id.value}]" override fun toString(): String = stringValue - /** - * 下载这个图片 - */ - suspend fun download(): ExternalImage { - // http://101.89.39.21/offpic_new/892185277C8A24AB9BB91AE888A6BC910C4D48CBA84BBB2F0D800761F1DD2F71F205364442C451A82D2F6FAD38CF71A9D65B6873409BD10CCF22BBF7DFA73DD7DA06FBB7386E31E4/0?vuin=1040400290&term=255&srvver=26933&rf=naio - // http://61.151.234.54/offpic_new/A47CAC5D3C5EF955A77ECE13DA969A69238167886464C00FD75FFC49A76EF15A1F05ED04BC2DE91190A40048AAF97BB6DFDB25BFB0EFE6A9516DC3BE0532A9A93A87A4C8D2E9729C/0?vuin=1040400290&term=255&srvver=26933&rf=naio - - - TODO() - } - companion object Key : Message.Key } @@ -181,7 +172,11 @@ inline class ImageId(inline val value: String) /** * 图片数据地址. */ -inline class ImageLink(inline val value: String) +inline class ImageLink(inline val value: String) { + + // TODO: 2019/11/15 应添加更多方法. 避免使用 byte[] + suspend fun downloadAsByteArray(): ByteArray = Http.download(value) +} fun ImageId.checkLength() = check(value.length == 37 || value.length == 42) { "Illegal ImageId length" } fun ImageId.requireLength() = require(value.length == 37 || value.length == 42) { "Illegal ImageId length" } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotSession.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotSession.kt index 0527cee9e..3b5f0c27d 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotSession.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotSession.kt @@ -31,7 +31,6 @@ import kotlin.coroutines.coroutineContext */ @Suppress("FunctionName", "NOTHING_TO_INLINE") internal inline fun TIMBotNetworkHandler.BotSession( - bot: Bot, sessionKey: SessionKey, socket: DataPacketSocketAdapter ): BotSession = BotSession(bot, sessionKey, socket, this) @@ -42,7 +41,7 @@ internal inline fun TIMBotNetworkHandler.BotSession( * * @author Him188moe */ -class BotSession( +data class BotSession( val bot: Bot, val sessionKey: SessionKey, val socket: DataPacketSocketAdapter, @@ -105,39 +104,11 @@ class BotSession( return deferred } - /** - * 发送一个数据包, 并期待接受一个特定的 [ServerPacket][P]. - * 将能从本函数的返回值 [CompletableDeferred] 接收到所期待的 [P] - * 本函数将能帮助实现清晰的包处理逻辑 - * - * 实现方法: - * ```kotlin - * with(session){ - * val deferred = ClientPacketXXX(...).sendAndExpectAsync() - * // do something - * - * deferred.await() // or deferred.join() - * } - * ``` - */ suspend inline fun OutgoingPacket.sendAndExpectAsync(checkSequence: Boolean = true): Deferred

= sendAndExpectAsync(checkSequence) { it } - /** - * 发送一个数据包, 并期待接受一个特定的 [ServerPacket][P]. - * 将调用 [CompletableDeferred.await], 挂起等待接收到指定的包后才返回. - * 本函数将能帮助实现清晰的包处理逻辑 - * - * 实现方法: - * ```kotlin - * with(session){ - * val packet:AddFriendPacket.Response = AddFriendPacket(...).sendAndExpect() - * } - * ``` - * @sample Bot.addFriend 添加好友 - */ - suspend inline fun OutgoingPacket.sendAndExpect(checkSequence: Boolean = true, crossinline block: (P) -> R): R = - sendAndExpectAsync(checkSequence) { block(it) }.await() + suspend inline fun OutgoingPacket.sendAndExpect(checkSequence: Boolean = true, crossinline mapper: (P) -> R): R = + sendAndExpectAsync(checkSequence) { mapper(it) }.await() suspend inline fun OutgoingPacket.sendAndExpect(checkSequence: Boolean = true): P = sendAndExpectAsync(checkSequence) { it }.await() diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/TIMBotNetworkHandler.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/TIMBotNetworkHandler.kt index 0d0756dba..fef5a2e5d 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/TIMBotNetworkHandler.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/TIMBotNetworkHandler.kt @@ -62,7 +62,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou handlersLock.withLock { temporaryPacketHandlers.add(temporaryPacketHandler) } - temporaryPacketHandler.send(this[ActionPacketHandler].session) + temporaryPacketHandler.send(this.session) } override suspend fun login(configuration: BotConfiguration): LoginResult { @@ -90,7 +90,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou //private | internal private fun onLoggedIn() { require(size == 0) { "Already logged in" } - val session = BotSession(bot, sessionKey, socket) + val session = BotSession(sessionKey, socket) add(ActionPacketHandler(session).asNode(ActionPacketHandler)) bot.logger.info("Successfully logged in") diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/PacketHandler.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/PacketHandler.kt index 4fa20c391..b5b37004a 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/PacketHandler.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/PacketHandler.kt @@ -36,5 +36,5 @@ internal fun T.asNode(key: PacketHandler.Key): PacketHand internal open class PacketHandlerList : MutableList> by mutableListOf() { @Suppress("UNCHECKED_CAST") - operator fun get(key: PacketHandler.Key): T = this.first { it.key === key }.instance as T + operator fun get(key: PacketHandler.Key): T = this.first { it.key == key }.instance as T } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/Annotations.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/Annotations.kt index 9a0d23602..3c3564375 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/Annotations.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/Annotations.kt @@ -9,11 +9,10 @@ import kotlin.reflect.KClass /** * 包 ID. 除特殊外, [PacketFactory] 都需要这个注解来指定包 ID. */ -@Deprecated("Reflection is not supported in JS. Consider to remove") @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.CLASS) -annotation class AnnotatedId( +annotation class AnnotatedId( // 注解无法在 JS 平台使用, 但现在暂不需要考虑 JS val id: KnownPacketId ) @@ -40,7 +39,7 @@ annotation class CorrespondingEvent( internal annotation class PacketVersion(val date: String, val timVersion: String) /** - * 带有这个注解的 [Packet], 将不会被记录在 log 中. + * 带有这个注解的 [Packet] 将不会被记录在 log 中. */ @Target(AnnotationTarget.CLASS) @Retention(AnnotationRetention.RUNTIME) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/PacketFactory.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/PacketFactory.kt index 891a49fe2..5a1eee4ef 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/PacketFactory.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/PacketFactory.kt @@ -26,7 +26,7 @@ abstract class PacketFactory(val d */ private val annotatedId: AnnotatedId get() = (this::class.annotations.firstOrNull { it is AnnotatedId } as? AnnotatedId) - ?: error("Annotation AnnotatedId not found") + ?: error("Annotation AnnotatedId not found for class ${this::class.simpleName}") /** * 包 ID. diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/AddContact.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/AddContact.kt index bb34812fb..43e57bdf6 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/AddContact.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/AddContact.kt @@ -205,7 +205,7 @@ object AddFriendPacket : SessionPacketFactory() { /** * 备注名 */ - remark: String, + remark: String, //// TODO: 2019/11/15 无备注的情况 key: FriendAdditionKey ): OutgoingPacket = buildSessionPacket(bot, sessionKey) { diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/DownloadImage.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/DownloadImage.kt new file mode 100644 index 000000000..1d4b2e77e --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/DownloadImage.kt @@ -0,0 +1,16 @@ +package net.mamoe.mirai.network.protocol.tim.packet.action + +import net.mamoe.mirai.contact.QQ +import net.mamoe.mirai.contact.withSession +import net.mamoe.mirai.message.Image +import net.mamoe.mirai.message.ImageLink +import net.mamoe.mirai.network.protocol.tim.packet.action.FriendImageIdDownloadLinkRequestPacket.ImageLinkResponse +import net.mamoe.mirai.network.sessionKey +import net.mamoe.mirai.qqAccount + + +suspend fun QQ.getLink(image: Image): ImageLink = withSession { + FriendImageIdDownloadLinkRequestPacket(bot.qqAccount, bot.sessionKey, id, image.id).sendAndExpect().link +} + +suspend inline fun QQ.downloadAsByteArray(image: Image): ByteArray = this.getLink(image).downloadAsByteArray() \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/SendGroupMessagePacket.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/SendGroupMessagePacket.kt index 965a3d675..179a50ec8 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/SendGroupMessagePacket.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/SendGroupMessagePacket.kt @@ -12,6 +12,8 @@ import net.mamoe.mirai.network.protocol.tim.TIMProtocol import net.mamoe.mirai.network.protocol.tim.packet.* import net.mamoe.mirai.utils.io.* +@AnnotatedId(KnownPacketId.SEND_GROUP_MESSAGE) +@PacketVersion(date = "2019.10.19", timVersion = "2.3.2 (21173)") object SendGroupMessagePacket : SessionPacketFactory() { operator fun invoke( botQQ: UInt, diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/UploadImage.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/UploadImage.kt index 331a6c3c0..d28c8d339 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/UploadImage.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/UploadImage.kt @@ -14,6 +14,7 @@ import kotlinx.coroutines.withContext import kotlinx.io.core.* import net.mamoe.mirai.contact.* import net.mamoe.mirai.message.ImageId +import net.mamoe.mirai.message.ImageLink import net.mamoe.mirai.message.requireLength import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.network.protocol.tim.TIMProtocol @@ -22,8 +23,8 @@ import net.mamoe.mirai.network.protocol.tim.packet.event.EventPacket import net.mamoe.mirai.network.qqAccount import net.mamoe.mirai.qqAccount import net.mamoe.mirai.utils.ExternalImage +import net.mamoe.mirai.utils.Http import net.mamoe.mirai.utils.configureBody -import net.mamoe.mirai.utils.httpClient import net.mamoe.mirai.utils.io.* import net.mamoe.mirai.withSession import kotlin.coroutines.coroutineContext @@ -47,7 +48,7 @@ suspend fun Group.uploadImage(image: ExternalImage): ImageId = withSession { withContext(userContext) { when (response) { - is GroupImageIdRequestPacket.Response.RequireUpload -> httpClient.postImage( + is GroupImageIdRequestPacket.Response.RequireUpload -> Http.postImage( htcmd = "0x6ff0071", uin = bot.qqAccount, groupId = GroupId(id), @@ -79,7 +80,7 @@ suspend fun QQ.uploadImage(image: ExternalImage): ImageId = bot.withSession { .sendAndExpectAsync { return@sendAndExpectAsync when (it) { is FriendImageIdRequestPacket.Response.RequireUpload -> { - httpClient.postImage( + Http.postImage( htcmd = "0x6ff0070", uin = bot.qqAccount, groupId = null, @@ -132,11 +133,11 @@ internal suspend inline fun HttpClient.postImage( imageInput.close() } - internal suspend inline fun HttpClient.download( url: String ): ByteArray = get(url).readBytes() // TODO 不知道为什么找不到 `ByteReadChannel`. + /* /** * 似乎没有必要. 服务器的返回永远都是 01 00 00 00 02 00 00 @@ -195,7 +196,7 @@ object SubmitImageFilenamePacket : PacketFactory { */ @AnnotatedId(KnownPacketId.FRIEND_IMAGE_ID) @PacketVersion(date = "2019.11.14", timVersion = "2.3.2 (21173)") -object FriendImageIdDownloadLinkRequestPacket : SessionPacketFactory() { +object FriendImageIdDownloadLinkRequestPacket : SessionPacketFactory() { operator fun invoke( bot: UInt, sessionKey: SessionKey, @@ -239,14 +240,14 @@ object FriendImageIdDownloadLinkRequestPacket : SessionPacketFactory): DownloadLink { + override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): ImageLinkResponse { //00 00 00 08 00 00 // [02 2B] // 12 [06] 98 01 02 A0 01 00 @@ -282,7 +283,7 @@ object FriendImageIdDownloadLinkRequestPacket : SessionPacketFactory): LoginResponse { val size = remaining.toInt() return when { - size == 229 || size == 271 || size == 207 -> { + size == 229 || size == 271 || size == 207 || size == 165 /* TODO CHECK 165 */ -> { discardExact(5)//01 00 1E 00 10 val privateKeyUpdate = PrivateKey(readBytes(0x10)) discardExact(4)//00 06 00 78 @@ -243,6 +243,8 @@ object SubmitPasswordPacket : PacketFactory LoginResult.DEVICE_LOCK 343, 359 -> LoginResult.TAKEN_BACK + // 165: 01 00 1E 00 10 72 36 7B 6B 6D 78 3A 4B 63 7B 47 5B 68 3E 21 59 00 06 00 78 34 F6 F9 49 AA 13 F5 F5 01 36 13 E1 4C F7 0F 25 C1 2C 10 75 CA 69 E9 12 B3 6D F4 A7 59 60 FF 01 03 73 28 47 A3 2A B8 46 C3 92 24 D5 8A AE 8B C2 45 0C 31 27 B5 17 9E 22 13 59 AF B4 CC F6 E3 3A 91 60 13 21 11 3C 25 D9 50 F4 23 C6 06 1D F4 15 41 BA 5D 7B 66 26 96 EB 0E 04 14 8E 5B D4 33 6E B8 5D E7 10 3A 0E EF 96 B1 D4 22 E4 74 48 A7 1D 3A 46 7D E6 EF 1F 6B 69 01 15 00 10 6F 99 48 5E 98 AE D3 4B F8 35 63 1D 70 EE 6D 82 + else -> { MiraiLogger.error("login response packet size = $size, data=${this.readRemainingBytes().toUHexString()}") LoginResult.UNKNOWN diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt index 5334b9aaa..ef3591002 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt @@ -43,7 +43,7 @@ expect fun localIpAddress(): String /** * Ktor HttpClient. 不同平台使用不同引擎. */ -internal expect val httpClient: HttpClient +internal expect val Http: HttpClient // FIXME: 2019/10/28 这个方法不是很好的实现 diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt index 42663feb2..47c084df2 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt @@ -55,7 +55,7 @@ actual fun solveIpAddress(hostname: String): String = InetAddress.getByName(host actual fun localIpAddress(): String = InetAddress.getLocalHost().hostAddress -internal actual val httpClient: HttpClient = HttpClient(CIO) +internal actual val Http: HttpClient = HttpClient(CIO) internal actual fun HttpRequestBuilder.configureBody( inputSize: Long, diff --git a/mirai-demos/mirai-demo-gentleman/build.gradle b/mirai-demos/mirai-demo-gentleman/build.gradle index d1158c62c..7d64528bc 100644 --- a/mirai-demos/mirai-demo-gentleman/build.gradle +++ b/mirai-demos/mirai-demo-gentleman/build.gradle @@ -9,6 +9,8 @@ dependencies { api group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: kotlin_version api group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: coroutines_version + implementation("org.jetbrains.kotlinx:kotlinx-io:$kotlinxio_version") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-io:$coroutinesio_version") compile group: 'com.alibaba', name: 'fastjson', version: '1.2.62' implementation 'org.jsoup:jsoup:1.12.1' } diff --git a/mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/Main.kt b/mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/Main.kt index 12236a96f..372bf871d 100644 --- a/mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/Main.kt +++ b/mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/Main.kt @@ -2,9 +2,11 @@ package demo.gentleman +import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import net.mamoe.mirai.Bot import net.mamoe.mirai.BotAccount import net.mamoe.mirai.addFriend @@ -12,7 +14,11 @@ import net.mamoe.mirai.event.Subscribable import net.mamoe.mirai.event.subscribeAlways import net.mamoe.mirai.event.subscribeMessages import net.mamoe.mirai.login +import net.mamoe.mirai.message.Image +import net.mamoe.mirai.network.protocol.tim.packet.action.downloadAsByteArray +import net.mamoe.mirai.network.protocol.tim.packet.event.FriendMessage import net.mamoe.mirai.network.protocol.tim.packet.login.requireSuccess +import net.mamoe.mirai.utils.currentTime import java.io.File import kotlin.random.Random @@ -52,21 +58,23 @@ suspend fun main() { sender.profile.await().toString() } - /* has { - reply(message) - }*/ + if (this is FriendMessage) { + withContext(IO) { + reply(message[Image] + " downloading") + sender.downloadAsByteArray(message[Image]).inputStream() + .transferTo(File(System.getProperty("user.dir", "testDownloadedImage${currentTime}.png")).outputStream()) + reply(message[Image] + " downloaded") + } + } + } startsWith("随机图片", removePrefix = true) { - try { - repeat(it.toIntOrNull() ?: 1) { - GlobalScope.launch { - delay(Random.Default.nextLong(100, 1000)) - Gentlemen.provide(subject).receive().image.await().send() - } + repeat(it.toIntOrNull() ?: 1) { + GlobalScope.launch { + delay(Random.Default.nextLong(100, 1000)) + Gentlemen.provide(subject).receive().image.await().send() } - } catch (e: Exception) { - reply(e.message ?: "exception: null") } }