From defe7ce05470191c529e29e490c408e1203c1618 Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Sat, 7 Mar 2020 11:19:05 +0800 Subject: [PATCH 1/9] Fix addSuppressed --- .../androidMain/kotlin/net/mamoe/mirai/utils/addSuppressed.kt | 2 +- .../src/jvmMain/kotlin/net/mamoe/mirai/utils/addSuppressed.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/addSuppressed.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/addSuppressed.kt index fb52beebe..8bf594b5a 100644 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/addSuppressed.kt +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/addSuppressed.kt @@ -6,7 +6,7 @@ private var isAddSuppressedSupported: Boolean = true @PublishedApi internal actual fun Throwable.addSuppressedMirai(e: Throwable) { - if (this === e) { + if (this == e) { return } if (!isAddSuppressedSupported) { diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/addSuppressed.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/addSuppressed.kt index 797402a7c..ab0da8e54 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/addSuppressed.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/addSuppressed.kt @@ -4,7 +4,7 @@ private var isAddSuppressedSupported: Boolean = true @PublishedApi internal actual fun Throwable.addSuppressedMirai(e: Throwable) { - if (this === e) { + if (this == e) { return } if (!isAddSuppressedSupported) { From 26210e7845d6a3287925882fb27a7228eed0cb1a Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Sat, 7 Mar 2020 11:29:04 +0800 Subject: [PATCH 2/9] Generify functions --- .../net.mamoe.mirai/utils/ExternalImage.kt | 3 +- .../kotlin/net.mamoe.mirai/utils/channels.kt | 33 ++++++++++++++ .../net/mamoe/mirai/message/MessagePacket.kt | 45 +++++++++++++------ .../net/mamoe/mirai/message/MessageReceipt.kt | 10 +---- .../mamoe/mirai/message/SendImageUtilsJvm.kt | 43 +++++++++--------- 5 files changed, 90 insertions(+), 44 deletions(-) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt index 527c76ec5..59a07668c 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt @@ -20,6 +20,7 @@ import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.QQ import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.data.Image +import net.mamoe.mirai.message.data.OfflineImage import net.mamoe.mirai.message.data.sendTo import net.mamoe.mirai.utils.io.toUHexString @@ -159,7 +160,7 @@ suspend fun <C : Contact> ExternalImage.sendTo(contact: C): MessageReceipt<C> = * * @see contact 图片上传对象. 由于好友图片与群图片不通用, 上传时必须提供目标联系人 */ -suspend fun ExternalImage.upload(contact: Contact): Image = when (contact) { +suspend fun ExternalImage.upload(contact: Contact): OfflineImage = when (contact) { is Group -> contact.uploadImage(this) is QQ -> contact.uploadImage(this) else -> error("unreachable") diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/channels.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/channels.kt index cc0bcfef3..e2c480e16 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/channels.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/channels.kt @@ -15,6 +15,8 @@ package net.mamoe.mirai.utils import io.ktor.utils.io.ByteReadChannel +import io.ktor.utils.io.ByteWriteChannel +import io.ktor.utils.io.close import io.ktor.utils.io.core.Output import io.ktor.utils.io.core.writeFully import io.ktor.utils.io.pool.useInstance @@ -52,6 +54,19 @@ suspend fun ByteReadChannel.copyTo(dst: Output) { } } +/** + * 从接收者管道读取所有数据并写入 [dst]. 不会关闭 [dst] + */ +suspend fun ByteReadChannel.copyTo(dst: ByteWriteChannel) { + @UseExperimental(MiraiInternalAPI::class) + ByteArrayPool.useInstance { buffer -> + var size: Int + while (this.readAvailable(buffer).also { size = it } > 0) { + dst.writeFully(buffer, 0, size) + } + } +} + /* // 垃圾 kotlin, Unresolved reference: ByteWriteChannel /** @@ -104,6 +119,24 @@ suspend fun ByteReadChannel.copyAndClose(dst: Output) { } } +/** + * 从接收者管道读取所有数据并写入 [dst], 最终关闭 [dst] + */ +suspend fun ByteReadChannel.copyAndClose(dst: ByteWriteChannel) { + try { + @UseExperimental(MiraiInternalAPI::class) + ByteArrayPool.useInstance { buffer -> + var size: Int + while (this.readAvailable(buffer).also { size = it } > 0) { + dst.writeFully(buffer, 0, size) + } + } + } finally { + @Suppress("DuplicatedCode") + dst.close() + } +} + /*// 垃圾 kotlin, Unresolved reference: ByteWriteChannel /** * 从接收者管道读取所有数据并写入 [dst], 最终关闭 [dst] diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessagePacket.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessagePacket.kt index 60faf7d90..e36d3bd19 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessagePacket.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessagePacket.kt @@ -11,7 +11,9 @@ package net.mamoe.mirai.message +import io.ktor.utils.io.ByteWriteChannel import io.ktor.utils.io.core.Input +import io.ktor.utils.io.core.Output import io.ktor.utils.io.core.use import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.QQ @@ -41,17 +43,15 @@ actual abstract class MessagePacket<TSender : QQ, TSubject : Contact> actual con // endregion // region 发送图片 - suspend inline fun sendImage(image: BufferedImage) = subject.sendImage(image) - - suspend inline fun sendImage(image: URL) = subject.sendImage(image) - suspend inline fun sendImage(image: Input) = subject.sendImage(image) - suspend inline fun sendImage(image: InputStream) = subject.sendImage(image) - suspend inline fun sendImage(image: File) = subject.sendImage(image) + suspend inline fun sendImage(image: BufferedImage): MessageReceipt<TSubject> = subject.sendImage(image) + suspend inline fun sendImage(image: URL): MessageReceipt<TSubject> = subject.sendImage(image) + suspend inline fun sendImage(image: Input): MessageReceipt<TSubject> = subject.sendImage(image) + suspend inline fun sendImage(image: InputStream): MessageReceipt<TSubject> = subject.sendImage(image) + suspend inline fun sendImage(image: File): MessageReceipt<TSubject> = subject.sendImage(image) // endregion // region 上传图片 (扩展) suspend inline fun BufferedImage.upload(): Image = upload(subject) - suspend inline fun URL.uploadAsImage(): Image = uploadAsImage(subject) suspend inline fun Input.uploadAsImage(): Image = uploadAsImage(subject) suspend inline fun InputStream.uploadAsImage(): Image = uploadAsImage(subject) @@ -59,12 +59,11 @@ actual abstract class MessagePacket<TSender : QQ, TSubject : Contact> actual con // endregion 上传图片 (扩展) // region 发送图片 (扩展) - suspend inline fun BufferedImage.send() = sendTo(subject) - - suspend inline fun URL.sendAsImage() = sendAsImageTo(subject) - suspend inline fun Input.sendAsImage() = sendAsImageTo(subject) - suspend inline fun InputStream.sendAsImage() = sendAsImageTo(subject) - suspend inline fun File.sendAsImage() = sendAsImageTo(subject) + suspend inline fun BufferedImage.send(): MessageReceipt<TSubject> = sendTo(subject) + suspend inline fun URL.sendAsImage(): MessageReceipt<TSubject> = sendAsImageTo(subject) + suspend inline fun Input.sendAsImage(): MessageReceipt<TSubject> = sendAsImageTo(subject) + suspend inline fun InputStream.sendAsImage(): MessageReceipt<TSubject> = sendAsImageTo(subject) + suspend inline fun File.sendAsImage(): MessageReceipt<TSubject> = sendAsImageTo(subject) // endregion 发送图片 (扩展) // region 下载图片 (扩展) @@ -80,6 +79,26 @@ actual abstract class MessagePacket<TSender : QQ, TSubject : Contact> actual con */ suspend inline fun Image.downloadAndClose(output: OutputStream) = channel().copyAndClose(output) + /** + * 下载图片到 [output] 但不关闭这个 [output] + */ + suspend inline fun Image.downloadTo(output: Output) = channel().copyTo(output) + + /** + * 下载图片到 [output] 并关闭这个 [output] + */ + suspend inline fun Image.downloadAndClose(output: Output) = channel().copyAndClose(output) + + /** + * 下载图片到 [output] 但不关闭这个 [output] + */ + suspend inline fun Image.downloadTo(output: ByteWriteChannel) = channel().copyTo(output) + + /** + * 下载图片到 [output] 并关闭这个 [output] + */ + suspend inline fun Image.downloadAndClose(output: ByteWriteChannel) = channel().copyAndClose(output) + /* suspend inline fun Image.downloadAsStream(): InputStream = channel().asInputStream() suspend inline fun Image.downloadAsExternalImage(): ExternalImage = withContext(Dispatchers.IO) { downloadAsStream().toExternalImage() } diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessageReceipt.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessageReceipt.kt index 3d708e3ed..0e07a3372 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessageReceipt.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessageReceipt.kt @@ -59,15 +59,7 @@ actual open class MessageReceipt<C : Contact> actual constructor( actual suspend fun recall() { @Suppress("BooleanLiteralArgument") if (_isRecalled.compareAndSet(false, true)) { - when (val contact = target) { - is Group -> { - contact.bot.recall(source) - } - is QQ -> { - TODO() - } - else -> error("Unknown contact type") - } + target.bot.recall(source) } else error("message is already or planned to be recalled") } diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt index 4da850fcc..63e246166 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.message.data.Image +import net.mamoe.mirai.message.data.OfflineImage import net.mamoe.mirai.utils.OverFileSizeMaxException import net.mamoe.mirai.utils.sendTo import net.mamoe.mirai.utils.toExternalImage @@ -36,37 +37,37 @@ import java.net.URL * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun BufferedImage.sendTo(contact: Contact) = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) +suspend fun <C : Contact> BufferedImage.sendTo(contact: C): MessageReceipt<C> = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) /** * 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun URL.sendAsImageTo(contact: Contact) = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) +suspend fun <C : Contact> URL.sendAsImageTo(contact: C): MessageReceipt<C> = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) /** * 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Input.sendAsImageTo(contact: Contact) = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) +suspend fun <C : Contact> Input.sendAsImageTo(contact: C): MessageReceipt<C> = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) /** * 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun InputStream.sendAsImageTo(contact: Contact) = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) +suspend fun <C : Contact> InputStream.sendAsImageTo(contact: C): MessageReceipt<C> = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) /** * 在 [Dispatchers.IO] 中将文件作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun File.sendAsImageTo(contact: Contact) { +suspend fun <C : Contact> File.sendAsImageTo(contact: C): MessageReceipt<C> { require(this.exists() && this.canRead()) - withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) + return withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) } // endregion @@ -78,35 +79,35 @@ suspend fun File.sendAsImageTo(contact: Contact) { * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun BufferedImage.upload(contact: Contact): Image = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) +suspend fun BufferedImage.upload(contact: Contact): OfflineImage = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) /** * 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片上传后构造 [Image] * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun URL.uploadAsImage(contact: Contact): Image = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) +suspend fun URL.uploadAsImage(contact: Contact): OfflineImage = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) /** * 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片上传后构造 [Image] * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Input.uploadAsImage(contact: Contact): Image = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) +suspend fun Input.uploadAsImage(contact: Contact): OfflineImage = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) /** * 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片上传后构造 [Image] * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun InputStream.uploadAsImage(contact: Contact): Image = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) +suspend fun InputStream.uploadAsImage(contact: Contact): OfflineImage = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) /** * 在 [Dispatchers.IO] 中将文件作为图片上传后构造 [Image] * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun File.uploadAsImage(contact: Contact): Image { +suspend fun File.uploadAsImage(contact: Contact): OfflineImage { require(this.exists() && this.canRead()) return withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) } @@ -120,35 +121,35 @@ suspend fun File.uploadAsImage(contact: Contact): Image { * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun Contact.sendImage(bufferedImage: BufferedImage) = bufferedImage.sendTo(this) +suspend inline fun <C : Contact> C.sendImage(bufferedImage: BufferedImage): MessageReceipt<C> = bufferedImage.sendTo(this) /** * 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun Contact.sendImage(imageUrl: URL) = imageUrl.sendAsImageTo(this) +suspend inline fun <C : Contact> C.sendImage(imageUrl: URL): MessageReceipt<C> = imageUrl.sendAsImageTo(this) /** * 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun Contact.sendImage(imageInput: Input) = imageInput.sendAsImageTo(this) +suspend inline fun <C : Contact> C.sendImage(imageInput: Input): MessageReceipt<C> = imageInput.sendAsImageTo(this) /** * 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun Contact.sendImage(imageStream: InputStream) = imageStream.sendAsImageTo(this) +suspend inline fun <C : Contact> C.sendImage(imageStream: InputStream): MessageReceipt<C> = imageStream.sendAsImageTo(this) /** * 在 [Dispatchers.IO] 中将文件作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun Contact.sendImage(file: File) = file.sendAsImageTo(this) +suspend inline fun <C : Contact> C.sendImage(file: File): MessageReceipt<C> = file.sendAsImageTo(this) // endregion @@ -159,34 +160,34 @@ suspend inline fun Contact.sendImage(file: File) = file.sendAsImageTo(this) * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun Contact.uploadImage(bufferedImage: BufferedImage): Image = bufferedImage.upload(this) +suspend inline fun Contact.uploadImage(bufferedImage: BufferedImage): OfflineImage = bufferedImage.upload(this) /** * 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片上传, 但不发送 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun Contact.uploadImage(imageUrl: URL): Image = imageUrl.uploadAsImage(this) +suspend inline fun Contact.uploadImage(imageUrl: URL): OfflineImage = imageUrl.uploadAsImage(this) /** * 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片上传, 但不发送 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun Contact.uploadImage(imageInput: Input): Image = imageInput.uploadAsImage(this) +suspend inline fun Contact.uploadImage(imageInput: Input): OfflineImage = imageInput.uploadAsImage(this) /** * 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片上传, 但不发送 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun Contact.uploadImage(imageStream: InputStream): Image = imageStream.uploadAsImage(this) +suspend inline fun Contact.uploadImage(imageStream: InputStream): OfflineImage = imageStream.uploadAsImage(this) /** * 在 [Dispatchers.IO] 中将文件作为图片上传, 但不发送 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun Contact.uploadImage(file: File): Image = file.uploadAsImage(this) +suspend inline fun Contact.uploadImage(file: File): OfflineImage = file.uploadAsImage(this) // endregion \ No newline at end of file From b3c4f24e333fe2eea6e050957109e4f8762fe5f0 Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Sat, 7 Mar 2020 18:48:07 +0800 Subject: [PATCH 3/9] Revert "Use `io.ktor.utils.io` than `kotlinx.io`" This reverts commit 6a85769e --- .../net/mamoe/mirai/qqandroid/ContactImpl.kt | 2 +- .../mirai/qqandroid/io/serialization/Jce.kt | 4 +- .../mirai/qqandroid/io/serialization/utils.kt | 5 +- .../mamoe/mirai/qqandroid/message/messages.kt | 5 +- .../qqandroid/network/QQAndroidClient.kt | 4 +- .../network/highway/HighwayHelper.kt | 10 +- .../qqandroid/network/highway/highway.kt | 5 +- .../network/protocol/data/proto/Cmd0x857.kt | 408 ------------------ .../network/protocol/packet/EncryptMethod.kt | 5 +- .../protocol/packet/OutgoingPacketAndroid.kt | 19 +- .../network/protocol/packet/PacketFactory.kt | 4 +- .../qqandroid/network/protocol/packet/Tlv.kt | 5 +- .../protocol/packet/chat/PbMessageSvc.kt | 2 +- .../protocol/packet/chat/TroopManagement.kt | 7 +- .../protocol/packet/chat/image/ImgStore.kt | 2 +- .../protocol/packet/chat/image/LongConn.kt | 2 +- .../packet/chat/receive/MessageSvc.kt | 3 +- .../protocol/packet/list/FriendList.kt | 2 +- .../protocol/packet/login/ConfigPushSvc.kt | 2 +- .../network/protocol/packet/login/StatSvc.kt | 2 +- .../network/protocol/packet/login/WtLogin.kt | 9 +- .../src/commonTest/kotlin/test/printing.kt | 10 +- .../JceDecoderTest.kt | 2 +- .../kotlin/test/ProtoBufDataClassGenerator.kt | 2 +- .../mamoe/mirai/utils/ExternalImageAndroid.kt | 1 + .../net/mamoe/mirai/utils/SystemDeviceInfo.kt | 2 +- .../io/PlatformDatagramChannelAndroid.kt | 8 +- .../mamoe/mirai/utils/io/PlatformSocket.kt | 10 +- .../net/mamoe/mirai/utils/platformAndroid.kt | 2 +- .../kotlin/net.mamoe.mirai/BotAccount.kt | 2 +- .../kotlin/net.mamoe.mirai/data/ImageLink.kt | 4 +- .../net.mamoe.mirai/event/events/BotEvents.kt | 1 - .../net.mamoe.mirai/utils/ExternalImage.kt | 4 +- .../kotlin/net.mamoe.mirai/utils/channels.kt | 7 +- .../net.mamoe.mirai/utils/cryptor/TEA.kt | 5 +- .../utils/io/PlatformDatagramChannel.kt | 4 +- .../utils/io/PlatformSocket.kt | 4 +- .../net.mamoe.mirai/utils/io/byteArrays.kt | 10 +- .../net.mamoe.mirai/utils/io/chunked.kt | 8 +- .../net.mamoe.mirai/utils/io/conversion.kt | 12 + .../kotlin/net.mamoe.mirai/utils/io/output.kt | 2 +- .../kotlin/net.mamoe.mirai/utils/platform.kt | 2 +- .../net/mamoe/mirai/message/MessagePacket.kt | 4 +- .../mamoe/mirai/message/SendImageUtilsJvm.kt | 2 +- .../mamoe/mirai/utils/BotConfigurationJvm.kt | 2 +- .../net/mamoe/mirai/utils/ExternalImageJvm.kt | 10 +- .../net/mamoe/mirai/utils/PlatformUtilsJvm.kt | 2 +- .../net/mamoe/mirai/utils/SystemDeviceInfo.kt | 2 +- .../mamoe/mirai/utils/io/PlatformSocket.kt | 10 +- .../mamoe/mirai/utils/io/PlatformSocketJvm.kt | 8 +- 50 files changed, 132 insertions(+), 517 deletions(-) delete mode 100644 mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Cmd0x857.kt diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt index b1ee9c6fd..9580ed3e0 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt @@ -9,9 +9,9 @@ package net.mamoe.mirai.qqandroid -import io.ktor.utils.io.core.Closeable import kotlinx.coroutines.launch import kotlinx.coroutines.withTimeoutOrNull +import kotlinx.io.core.Closeable import net.mamoe.mirai.LowLevelAPI import net.mamoe.mirai.contact.* import net.mamoe.mirai.data.* diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce.kt index 87ec126c1..bf381f7ea 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce.kt @@ -9,8 +9,8 @@ package net.mamoe.mirai.qqandroid.io.serialization -import io.ktor.utils.io.charsets.Charset -import io.ktor.utils.io.core.* +import kotlinx.io.charsets.Charset +import kotlinx.io.core.* import kotlinx.serialization.* import kotlinx.serialization.internal.* import kotlinx.serialization.modules.EmptyModule diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/utils.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/utils.kt index 3b3856cb7..fe8e46dd8 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/utils.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/utils.kt @@ -12,10 +12,7 @@ package net.mamoe.mirai.qqandroid.io.serialization -import io.ktor.utils.io.core.BytePacketBuilder -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.readBytes -import io.ktor.utils.io.core.writeFully +import kotlinx.io.core.* import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.SerialDescriptor import kotlinx.serialization.SerializationStrategy diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/messages.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/messages.kt index e23516c3b..bfa2ac150 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/messages.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/messages.kt @@ -9,7 +9,10 @@ package net.mamoe.mirai.qqandroid.message -import io.ktor.utils.io.core.* +import kotlinx.io.core.buildPacket +import kotlinx.io.core.discardExact +import kotlinx.io.core.readBytes +import kotlinx.io.core.readUInt import net.mamoe.mirai.LowLevelAPI import net.mamoe.mirai.contact.Member import net.mamoe.mirai.message.data.* diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt index 76df1763d..9a507ab35 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt @@ -11,9 +11,9 @@ package net.mamoe.mirai.qqandroid.network -import io.ktor.utils.io.core.* import kotlinx.atomicfu.AtomicInt import kotlinx.atomicfu.atomic +import kotlinx.io.core.* import net.mamoe.mirai.BotAccount import net.mamoe.mirai.RawAccountIdUse import net.mamoe.mirai.data.OnlineStatus @@ -315,7 +315,7 @@ internal class Pt4Token(data: ByteArray, creationTime: Long, expireTime: Long) : internal typealias PSKeyMap = MutableMap<String, PSKey> internal typealias Pt4TokenMap = MutableMap<String, Pt4Token> -internal inline fun Input.readUShortLVString(): String = io.ktor.utils.io.core.String(this.readUShortLVByteArray()) +internal inline fun Input.readUShortLVString(): String = kotlinx.io.core.String(this.readUShortLVByteArray()) internal inline fun Input.readUShortLVByteArray(): ByteArray = this.readBytes(this.readUShort().toInt()) diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/HighwayHelper.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/HighwayHelper.kt index 61dd755c2..c219a9881 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/HighwayHelper.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/HighwayHelper.kt @@ -18,14 +18,14 @@ import io.ktor.http.content.OutgoingContent import io.ktor.http.userAgent import io.ktor.utils.io.ByteReadChannel import io.ktor.utils.io.copyAndClose -import io.ktor.utils.io.core.Input -import io.ktor.utils.io.core.readAvailable -import io.ktor.utils.io.core.readInt -import io.ktor.utils.io.core.use -import io.ktor.utils.io.pool.useInstance import kotlinx.coroutines.InternalCoroutinesApi import kotlinx.coroutines.flow.collect import kotlinx.io.InputStream +import kotlinx.io.core.Input +import kotlinx.io.core.discardExact +import kotlinx.io.core.readAvailable +import kotlinx.io.core.use +import kotlinx.io.pool.useInstance import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.qqandroid.network.protocol.data.proto.CSDataHighwayHead diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/highway.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/highway.kt index cf13c882a..b84834661 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/highway.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/highway.kt @@ -12,10 +12,13 @@ package net.mamoe.mirai.qqandroid.network.highway import io.ktor.utils.io.ByteReadChannel -import io.ktor.utils.io.core.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlinx.io.InputStream +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.Input +import kotlinx.io.core.buildPacket +import kotlinx.io.core.writeFully import net.mamoe.mirai.qqandroid.io.serialization.toByteArray import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.qqandroid.network.protocol.data.proto.CSDataHighwayHead diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Cmd0x857.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Cmd0x857.kt deleted file mode 100644 index 2586189c4..000000000 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Cmd0x857.kt +++ /dev/null @@ -1,408 +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:Suppress("SpellCheckingInspection") - -package net.mamoe.mirai.qqandroid.network.protocol.data.proto - -import kotlinx.serialization.SerialId -import kotlinx.serialization.Serializable -import kotlinx.serialization.protobuf.ProtoNumberType -import kotlinx.serialization.protobuf.ProtoType -import net.mamoe.mirai.qqandroid.io.ProtoBuf -import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY - -class GroupOpenSysMsg : ProtoBuf { - @Serializable - class LightApp( - @SerialId(1) val app: String = "", - @SerialId(2) val view: String = "", - @SerialId(3) val desc: String = "", - @SerialId(4) val prompt: String = "", - @SerialId(5) val ver: String = "", - @SerialId(6) val meta: String = "", - @SerialId(7) val config: String = "", - @SerialId(8) val source: Source? = null - ) : ProtoBuf - - @Serializable - class RichMsg( - @SerialId(1) val title: String = "", - @SerialId(2) val desc: String = "", - @SerialId(3) val brief: String = "", - @SerialId(4) val cover: String = "", - @SerialId(5) val url: String = "", - @SerialId(6) val source: Source? = null - ) : ProtoBuf - - @Serializable - class Sender( - @SerialId(1) val uin: Long = 0L, - @SerialId(2) val nick: String = "", - @SerialId(3) val avatar: String = "", - @SerialId(4) val url: String = "" - ) : ProtoBuf - - @Serializable - class Source( - @SerialId(1) val name: String = "", - @SerialId(2) val icon: String = "", - @SerialId(3) val url: String = "" - ) : ProtoBuf - - @Serializable - class SysMsgBody( - @SerialId(1) val groupId: Long = 0L, - @SerialId(2) val appid: Long = 0L, - @SerialId(3) val sender: Sender? = null, - @SerialId(4) val msgType: Int = 0, - @SerialId(5) val content: String = "", - @SerialId(6) val richMsg: RichMsg? = null, - @SerialId(7) val lightApp: LightApp? = null - ) : ProtoBuf -} - -@Serializable -class TroopTips0x857 : ProtoBuf { - @Serializable - class AIOGrayTipsInfo( - @SerialId(1) val optUint32ShowLastest: Int = 0, - @SerialId(2) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(3) val optUint32Remind: Int = 0, - @SerialId(4) val optBytesBrief: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(5) val receiverUin: Long = 0L, - @SerialId(6) val reliaoAdminOpt: Int = 0, - @SerialId(7) val robotGroupOpt: Int = 0 - ) : ProtoBuf - - @Serializable - class AIOTopTipsInfo( - @SerialId(1) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(2) val optUint32Icon: Int = 0, - @SerialId(3) val optEnumAction: Int /* enum */ = 1, - @SerialId(4) val optBytesUrl: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(5) val optBytesData: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(6) val optBytesDataI: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(7) val optBytesDataA: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(8) val optBytesDataP: ByteArray = EMPTY_BYTE_ARRAY - ) : ProtoBuf - - @Serializable - class FloatedTipsInfo( - @SerialId(1) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY - ) : ProtoBuf - - @Serializable - class GeneralGrayTipInfo( - @SerialId(1) val busiType: Long = 0L, - @SerialId(2) val busiId: Long = 0L, - @SerialId(3) val ctrlFlag: Int = 0, - @SerialId(4) val c2cType: Int = 0, - @SerialId(5) val serviceType: Int = 0, - @SerialId(6) val templId: Long = 0L, - @SerialId(7) val msgTemplParam: List<TemplParam>? = null, - @SerialId(8) val content: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(10) val tipsSeqId: Long = 0L, - @SerialId(100) val pbReserv: ByteArray = EMPTY_BYTE_ARRAY - ) : ProtoBuf - - @Serializable - class GoldMsgTipsElem( - @SerialId(1) val type: Int = 0, - @SerialId(2) val billno: String = "", - @SerialId(3) val result: Int = 0, - @SerialId(4) val amount: Int = 0, - @SerialId(5) val total: Int = 0, - @SerialId(6) val interval: Int = 0, - @SerialId(7) val finish: Int = 0, - @SerialId(8) val uin: List<Long>? = null, - @SerialId(9) val action: Int = 0 - ) : ProtoBuf - - @Serializable - class GroupInfoChange( - @SerialId(1) val groupHonorSwitch: Int = 0 - ) : ProtoBuf - - @Serializable - class GroupNotifyInfo( - @SerialId(1) val optUint32AutoPullFlag: Int = 0, - @SerialId(2) val optBytesFeedsId: ByteArray = EMPTY_BYTE_ARRAY - ) : ProtoBuf - - @Serializable - class InstCtrl( - @SerialId(1) val msgSendToInst: List<InstInfo>? = null, - @SerialId(2) val msgExcludeInst: List<InstInfo>? = null, - @SerialId(3) val msgFromInst: InstInfo? = null - ) : ProtoBuf - - @Serializable - class InstInfo( - @SerialId(1) val apppid: Int = 0, - @SerialId(2) val instid: Int = 0, - @SerialId(3) val platform: Int = 0, - @SerialId(4) val openAppid: Int = 0, - @SerialId(5) val productid: Int = 0, - @SerialId(6) val ssoBid: Int = 0, - @SerialId(7) val guid: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(8) val verMin: Int = 0, - @SerialId(9) val verMax: Int = 0 - ) : ProtoBuf - - @Serializable - class LbsShareChangePushInfo( - @SerialId(1) val msgType: Int = 0, - @SerialId(2) val msgInfo: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(3) val versionCtrl: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(4) val groupId: Long = 0L, - @SerialId(5) val operUin: Long = 0L, - @SerialId(6) val grayTips: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(7) val msgSeq: Long = 0L, - @SerialId(8) val joinNums: Int = 0, - @SerialId(99) val pushType: Int = 0, - @SerialId(100) val extInfo: ByteArray = EMPTY_BYTE_ARRAY - ) : ProtoBuf - - @Serializable - class LuckyBagNotify( - @SerialId(1) val msgTips: ByteArray = EMPTY_BYTE_ARRAY - ) : ProtoBuf - - @Serializable - class MediaChangePushInfo( - @SerialId(1) val msgType: Int = 0, - @SerialId(2) val msgInfo: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(3) val versionCtrl: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(4) val groupId: Long = 0L, - @SerialId(5) val operUin: Long = 0L, - @SerialId(6) val grayTips: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(7) val msgSeq: Long = 0L, - @SerialId(8) val joinNums: Int = 0, - @SerialId(9) val msgPerSetting: PersonalSetting? = null, - @SerialId(10) val playMode: Int = 0, - @SerialId(99) val mediaType: Int = 0, - @SerialId(100) val extInfo: ByteArray = EMPTY_BYTE_ARRAY - ) : ProtoBuf { - @Serializable - class PersonalSetting( - @SerialId(1) val themeId: Int = 0, - @SerialId(2) val playerId: Int = 0, - @SerialId(3) val fontId: Int = 0 - ) : ProtoBuf - } - - @Serializable - class MessageBoxInfo( - @SerialId(1) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(2) val optBytesTitle: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(3) val optBytesButton: ByteArray = EMPTY_BYTE_ARRAY - ) : ProtoBuf - - @Serializable - class MessageRecallReminder( - @SerialId(1) val uin: Long = 0L, - @SerialId(2) val nickname: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(3) val recalledMsgList: List<MessageMeta> = listOf(), - @SerialId(4) val reminderContent: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(5) val userdef: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(6) val groupType: Int = 0, - @SerialId(7) val opType: Int = 0 - ) : ProtoBuf { - @Serializable - class MessageMeta( - @SerialId(1) val seq: Int = 0, - @SerialId(2) val time: Int = 0, - @SerialId(3) val msgRandom: Int = 0, - @SerialId(4) val msgType: Int = 0, - @SerialId(5) val msgFlag: Int = 0, - @SerialId(6) val authorUin: Long = 0L - ) : ProtoBuf - } - - @Serializable - class MiniAppNotify( - @SerialId(1) val msg: ByteArray = EMPTY_BYTE_ARRAY - ) : ProtoBuf - - @Serializable - class NotifyMsgBody( - @SerialId(1) val optEnumType: Int /* enum */ = 1, - @SerialId(2) val optUint64MsgTime: Long = 0L, - @SerialId(3) val optUint64MsgExpires: Long = 0L, - @SerialId(4) val optUint64GroupCode: Long = 0L, - @SerialId(5) val optMsgGraytips: AIOGrayTipsInfo? = null, - @SerialId(6) val optMsgMessagebox: MessageBoxInfo? = null, - @SerialId(7) val optMsgFloatedtips: FloatedTipsInfo? = null, - @SerialId(8) val optMsgToptips: AIOTopTipsInfo? = null, - @SerialId(9) val optMsgRedtips: RedGrayTipsInfo? = null, - @SerialId(10) val optMsgGroupNotify: GroupNotifyInfo? = null, - @SerialId(11) val optMsgRecall: MessageRecallReminder? = null, - @SerialId(12) val optMsgThemeNotify: ThemeStateNotify? = null, - @SerialId(13) val serviceType: Int = 0, - @SerialId(14) val optMsgObjmsgUpdate: NotifyObjmsgUpdate? = null, - @SerialId(15) val optMsgWerewolfPush: WereWolfPush? = null, - // @SerialId(16) val optStcmGameState: ApolloGameStatus.STCMGameMessage? = null, - // @SerialId(17) val aplloMsgPush: ApolloPushMsgInfo.STPushMsgElem? = null, - @SerialId(18) val optMsgGoldtips: GoldMsgTipsElem? = null, - @SerialId(20) val optMsgMiniappNotify: MiniAppNotify? = null, - @SerialId(21) val optUint64SenderUin: Long = 0L, - @SerialId(22) val optMsgLuckybagNotify: LuckyBagNotify? = null, - @SerialId(23) val optMsgTroopformtipsPush: TroopFormGrayTipsInfo? = null, - @SerialId(24) val optMsgMediaPush: MediaChangePushInfo? = null, - @SerialId(26) val optGeneralGrayTip: GeneralGrayTipInfo? = null, - @SerialId(27) val optMsgVideoPush: VideoChangePushInfo? = null, - @SerialId(28) val optLbsShareChangePlusInfo: LbsShareChangePushInfo? = null, - @SerialId(29) val optMsgSingPush: SingChangePushInfo? = null, - @SerialId(30) val optMsgGroupInfoChange: GroupInfoChange? = null - ) : ProtoBuf - - @Serializable - class NotifyObjmsgUpdate( - @SerialId(1) val objmsgId: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(2) val updateType: Int = 0, - @SerialId(3) val extMsg: ByteArray = EMPTY_BYTE_ARRAY - ) : ProtoBuf - - @Serializable - class RedGrayTipsInfo( - @SerialId(1) val optUint32ShowLastest: Int = 0, - @SerialId(2) val senderUin: Long = 0L, - @SerialId(3) val receiverUin: Long = 0L, - @SerialId(4) val senderRichContent: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(5) val receiverRichContent: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(6) val authkey: ByteArray = EMPTY_BYTE_ARRAY, - @ProtoType(ProtoNumberType.SIGNED) @SerialId(7) val sint32Msgtype: Int = 0, - @SerialId(8) val luckyFlag: Int = 0, - @SerialId(9) val hideFlag: Int = 0, - @SerialId(10) val pcBody: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(11) val icon: Int = 0, - @SerialId(12) val luckyUin: Long = 0L, - @SerialId(13) val time: Int = 0, - @SerialId(14) val random: Int = 0, - @SerialId(15) val broadcastRichContent: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(16) val idiom: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(17) val idiomSeq: Int = 0, - @SerialId(18) val idiomAlpha: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(19) val jumpurl: ByteArray = EMPTY_BYTE_ARRAY - ) : ProtoBuf - - @Serializable - class ReqBody( - @SerialId(1) val optUint64GroupCode: Long = 0L, - @SerialId(2) val uint64Memberuins: List<Long>? = null, - @SerialId(3) val optUint32Offline: Int = 0, - @SerialId(4) val msgInstCtrl: InstCtrl? = null, - @SerialId(5) val optBytesMsg: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(6) val optUint32BusiType: Int = 0 - ) : ProtoBuf - - @Serializable - class RspBody( - @SerialId(1) val optUint64GroupCode: Long = 0L - ) : ProtoBuf - - @Serializable - class SingChangePushInfo( - @SerialId(1) val seq: Long = 0L, - @SerialId(2) val actionType: Int = 0, - @SerialId(3) val groupId: Long = 0L, - @SerialId(4) val operUin: Long = 0L, - @SerialId(5) val grayTips: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(6) val joinNums: Int = 0 - ) : ProtoBuf - - @Serializable - class TemplParam( - @SerialId(1) val name: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(2) val value: ByteArray = EMPTY_BYTE_ARRAY - ) : ProtoBuf - - @Serializable - class ThemeStateNotify( - @SerialId(1) val state: Int = 0, - @SerialId(2) val feedsId: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(3) val themeName: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(4) val actionUin: Long = 0L, - @SerialId(5) val createUin: Long = 0L - ) : ProtoBuf - - @Serializable - class TroopFormGrayTipsInfo( - @SerialId(1) val writerUin: Long = 0L, - @SerialId(2) val creatorUin: Long = 0L, - @SerialId(3) val richContent: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(4) val optBytesUrl: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(5) val creatorNick: ByteArray = EMPTY_BYTE_ARRAY - ) : ProtoBuf - - @Serializable - class VideoChangePushInfo( - @SerialId(1) val seq: Long = 0L, - @SerialId(2) val actionType: Int = 0, - @SerialId(3) val groupId: Long = 0L, - @SerialId(4) val operUin: Long = 0L, - @SerialId(5) val grayTips: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(6) val joinNums: Int = 0, - @SerialId(100) val extInfo: ByteArray = EMPTY_BYTE_ARRAY - ) : ProtoBuf - - @Serializable - class WereWolfPush( - @SerialId(1) val pushType: Int = 0, - @SerialId(2) val gameRoom: Long = 0L, - @SerialId(3) val enumGameState: Int = 0, - @SerialId(4) val gameRound: Int = 0, - @SerialId(5) val roles: List<Role>? = null, - @SerialId(6) val speaker: Long = 0L, - @SerialId(7) val judgeUin: Long = 0L, - @SerialId(8) val judgeWords: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(9) val enumOperation: Int = 0, - @SerialId(10) val srcUser: Long = 0L, - @SerialId(11) val dstUser: Long = 0L, - @SerialId(12) val deadUsers: List<Long>? = null, - @SerialId(13) val gameResult: Int = 0, - @SerialId(14) val timeoutSec: Int = 0, - @SerialId(15) val killConfirmed: Int = 0, - @SerialId(16) val judgeNickname: ByteArray = EMPTY_BYTE_ARRAY, - @SerialId(17) val votedTieUsers: List<Long>? = null - ) : ProtoBuf { - @Serializable - class GameRecord( - @SerialId(1) val total: Int = 0, - @SerialId(2) val win: Int = 0, - @SerialId(3) val lose: Int = 0, - @SerialId(4) val draw: Int = 0 - ) : ProtoBuf - - @Serializable - class Role( - @SerialId(1) val uin: Long = 0L, - @SerialId(2) val enumType: Int = 0, - @SerialId(3) val enumState: Int = 0, - @SerialId(4) val canSpeak: Int = 0, - @SerialId(5) val canListen: Int = 0, - @SerialId(6) val position: Int = 0, - @SerialId(7) val canVote: Int = 0, - @SerialId(8) val canVoted: Int = 0, - @SerialId(9) val alreadyChecked: Int = 0, - @SerialId(10) val alreadySaved: Int = 0, - @SerialId(11) val alreadyPoisoned: Int = 0, - @SerialId(12) val playerState: Int = 0, - @SerialId(13) val enumDeadOp: Int = 0, - @SerialId(14) val enumOperation: Int = 0, - @SerialId(15) val dstUser: Long = 0L, - @SerialId(16) val operationRound: Int = 0, - @SerialId(17) val msgGameRecord: GameRecord? = null, - @SerialId(18) val isWerewolf: Int = 0, - @SerialId(19) val defendedUser: Long = 0L, - @SerialId(20) val isSheriff: Int = 0 - ) : ProtoBuf - } -} \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/EncryptMethod.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/EncryptMethod.kt index 697028560..80d0d6141 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/EncryptMethod.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/EncryptMethod.kt @@ -9,7 +9,10 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet -import io.ktor.utils.io.core.* +import kotlinx.io.core.BytePacketBuilder +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.buildPacket +import kotlinx.io.core.writeFully import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.utils.cryptor.ECDH import net.mamoe.mirai.utils.cryptor.ECDHKeyPair diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/OutgoingPacketAndroid.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/OutgoingPacketAndroid.kt index 45485aa7a..f13ec933d 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/OutgoingPacketAndroid.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/OutgoingPacketAndroid.kt @@ -10,7 +10,10 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet -import io.ktor.utils.io.core.* +import kotlinx.io.core.BytePacketBuilder +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.buildPacket +import kotlinx.io.core.writeFully import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.io.encryptAndWrite @@ -43,7 +46,6 @@ internal inline fun OutgoingPacketFactory<*>.buildOutgoingUniPacket( body: BytePacketBuilder.(sequenceId: Int) -> Unit ): OutgoingPacket { - @Suppress("DuplicatedCode") return OutgoingPacket(name, commandName, sequenceId, buildPacket { writeIntLVPacket(lengthOffset = { it + 4 }) { writeInt(0x0B) @@ -52,7 +54,7 @@ internal inline fun OutgoingPacketFactory<*>.buildOutgoingUniPacket( writeByte(0) client.uin.toString().let { writeInt(it.length + 4) - writeText(it) + writeStringUtf8(it) } encryptAndWrite(key) { writeUniPacket(commandName, client.outgoingPacketSessionId, extraData) { @@ -75,7 +77,6 @@ internal inline fun IncomingPacketFactory<*>.buildResponseUniPacket( sequenceId: Int = client.nextSsoSequenceId(), body: BytePacketBuilder.(sequenceId: Int) -> Unit ): OutgoingPacket { - @Suppress("DuplicatedCode") return OutgoingPacket(name, commandName, sequenceId, buildPacket { writeIntLVPacket(lengthOffset = { it + 4 }) { writeInt(0x0B) @@ -84,7 +85,7 @@ internal inline fun IncomingPacketFactory<*>.buildResponseUniPacket( writeByte(0) client.uin.toString().let { writeInt(it.length + 4) - writeText(it) + writeStringUtf8(it) } encryptAndWrite(key) { writeUniPacket(commandName, client.outgoingPacketSessionId, extraData) { @@ -105,7 +106,7 @@ internal inline fun BytePacketBuilder.writeUniPacket( writeIntLVPacket(lengthOffset = { it + 4 }) { commandName.let { writeInt(it.length + 4) - writeText(it) + writeStringUtf8(it) } writeInt(4 + 4) @@ -152,7 +153,7 @@ internal inline fun OutgoingPacketFactory<*>.buildLoginOutgoingPacket( client.uin.toString().let { writeInt(it.length + 4) - writeText(it) + writeStringUtf8(it) } if (key === NO_ENCRYPT) { @@ -207,7 +208,7 @@ internal inline fun BytePacketBuilder.writeSsoPacket( } commandName.let { writeInt(it.length + 4) - writeText(it) + writeStringUtf8(it) } writeInt(4 + 4) @@ -215,7 +216,7 @@ internal inline fun BytePacketBuilder.writeSsoPacket( client.device.imei.let { writeInt(it.length + 4) - writeText(it) + writeStringUtf8(it) } writeInt(4) diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt index 1f62d375b..020a45d2d 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt @@ -9,8 +9,8 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet -import io.ktor.utils.io.core.* -import io.ktor.utils.io.pool.useInstance +import kotlinx.io.core.* +import kotlinx.io.pool.useInstance import net.mamoe.mirai.data.Packet import net.mamoe.mirai.event.Event import net.mamoe.mirai.qqandroid.QQAndroidBot diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/Tlv.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/Tlv.kt index 0e83f4817..7f5d44ac1 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/Tlv.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/Tlv.kt @@ -9,7 +9,10 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet -import io.ktor.utils.io.core.* +import kotlinx.io.core.BytePacketBuilder +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.toByteArray +import kotlinx.io.core.writeFully import net.mamoe.mirai.qqandroid.network.protocol.LoginType import net.mamoe.mirai.qqandroid.utils.NetworkType import net.mamoe.mirai.utils.currentTimeMillis diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/PbMessageSvc.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/PbMessageSvc.kt index 7cfb9fc93..71e593cac 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/PbMessageSvc.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/PbMessageSvc.kt @@ -9,7 +9,7 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat -import io.ktor.utils.io.core.ByteReadPacket +import kotlinx.io.core.ByteReadPacket import net.mamoe.mirai.data.Packet import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/TroopManagement.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/TroopManagement.kt index 50faee7e5..b958354d7 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/TroopManagement.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/TroopManagement.kt @@ -9,7 +9,10 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat -import io.ktor.utils.io.core.* +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.buildPacket +import kotlinx.io.core.readBytes +import kotlinx.io.core.toByteArray import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Member import net.mamoe.mirai.data.Packet @@ -375,7 +378,7 @@ internal class TroopManagement { OutgoingPacketFactory<EditGroupNametag.Response>("friendlist.ModifyGroupCardReq") { object Response : Packet - override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response { + override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): EditGroupNametag.Response { return Response } diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/ImgStore.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/ImgStore.kt index 6b46fc0e2..6ac6e0b69 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/ImgStore.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/ImgStore.kt @@ -9,7 +9,7 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image -import io.ktor.utils.io.core.ByteReadPacket +import kotlinx.io.core.ByteReadPacket import net.mamoe.mirai.data.Packet import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/LongConn.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/LongConn.kt index 743f3e103..b4cf13881 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/LongConn.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/LongConn.kt @@ -9,7 +9,7 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image -import io.ktor.utils.io.core.ByteReadPacket +import kotlinx.io.core.ByteReadPacket import net.mamoe.mirai.data.Packet import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt index 38a148d35..0a83fb747 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt @@ -9,9 +9,10 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive -import io.ktor.utils.io.core.ByteReadPacket import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.* +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.discardExact import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.data.MemberInfo diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/list/FriendList.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/list/FriendList.kt index 0c218bf7c..f2ab4eef9 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/list/FriendList.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/list/FriendList.kt @@ -9,7 +9,7 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.list -import io.ktor.utils.io.core.ByteReadPacket +import kotlinx.io.core.ByteReadPacket import net.mamoe.mirai.data.Packet import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.io.serialization.decodeUniPacket diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/ConfigPushSvc.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/ConfigPushSvc.kt index 0ea8c4ec5..1341f7f7b 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/ConfigPushSvc.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/ConfigPushSvc.kt @@ -9,7 +9,7 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.login -import io.ktor.utils.io.core.ByteReadPacket +import kotlinx.io.core.ByteReadPacket import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.io.serialization.JceCharset import net.mamoe.mirai.qqandroid.io.serialization.decodeUniPacket diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/StatSvc.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/StatSvc.kt index f46297e34..c513076b4 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/StatSvc.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/StatSvc.kt @@ -9,7 +9,7 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.login -import io.ktor.utils.io.core.ByteReadPacket +import kotlinx.io.core.ByteReadPacket import net.mamoe.mirai.data.Packet import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.io.serialization.* diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt index 36d7b5857..6ee16aa42 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt @@ -11,7 +11,7 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.login import io.ktor.util.InternalAPI -import io.ktor.utils.io.core.* +import kotlinx.io.core.* import net.mamoe.mirai.data.Packet import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.network.* @@ -288,7 +288,7 @@ internal class WtLogin { } class Picture( - val data: ByteArray, + val data: IoBuffer, val sign: ByteArray ) : Captcha() { override fun toString(): String = "LoginPacketResponse.Captcha.Picture" @@ -394,8 +394,11 @@ internal class WtLogin { imageData.discardExact(2)//image Length val sign = imageData.readBytes(signInfoLength.toInt()) + + val buffer = IoBuffer.Pool.borrow() + imageData.readAvailable(buffer) return LoginPacketResponse.Captcha.Picture( - data = imageData.readBytes(), + data = buffer, sign = sign ) // } else error("UNKNOWN CAPTCHA QUESTION: ${question.toUHexString()}, tlvMap=" + tlvMap.contentToString()) diff --git a/mirai-core-qqandroid/src/commonTest/kotlin/test/printing.kt b/mirai-core-qqandroid/src/commonTest/kotlin/test/printing.kt index f2fc92dac..043d67d47 100644 --- a/mirai-core-qqandroid/src/commonTest/kotlin/test/printing.kt +++ b/mirai-core-qqandroid/src/commonTest/kotlin/test/printing.kt @@ -11,11 +11,11 @@ package test -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.Input -import io.ktor.utils.io.core.readAvailable -import io.ktor.utils.io.core.use -import io.ktor.utils.io.pool.useInstance +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.Input +import kotlinx.io.core.readAvailable +import kotlinx.io.core.use +import kotlinx.io.pool.useInstance import net.mamoe.mirai.utils.DefaultLogger import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiLoggerWithSwitch diff --git a/mirai-core-qqandroid/src/jvmTest/kotlin/net.mamoe.mirai.qqandroid.io.serialization/JceDecoderTest.kt b/mirai-core-qqandroid/src/jvmTest/kotlin/net.mamoe.mirai.qqandroid.io.serialization/JceDecoderTest.kt index 2f67a7195..a782d38f3 100644 --- a/mirai-core-qqandroid/src/jvmTest/kotlin/net.mamoe.mirai.qqandroid.io.serialization/JceDecoderTest.kt +++ b/mirai-core-qqandroid/src/jvmTest/kotlin/net.mamoe.mirai.qqandroid.io.serialization/JceDecoderTest.kt @@ -11,7 +11,7 @@ package net.mamoe.mirai.qqandroid.io.serialization /* -import io.ktor.utils.io.core.readBytes +import kotlinx.io.core.readBytes import kotlinx.serialization.SerialId import kotlinx.serialization.Serializable import net.mamoe.mirai.qqandroid.io.JceOutput diff --git a/mirai-core-qqandroid/src/jvmTest/kotlin/test/ProtoBufDataClassGenerator.kt b/mirai-core-qqandroid/src/jvmTest/kotlin/test/ProtoBufDataClassGenerator.kt index 860aa0b78..b456838cb 100644 --- a/mirai-core-qqandroid/src/jvmTest/kotlin/test/ProtoBufDataClassGenerator.kt +++ b/mirai-core-qqandroid/src/jvmTest/kotlin/test/ProtoBufDataClassGenerator.kt @@ -28,7 +28,7 @@ fun main() { println( File( """ - E:\Projects\QQAndroidFF\app\src\main\java\tencent\im\oidb\cmd0x857 + E:\Projects\QQAndroidFF\app\src\main\java\tencent\im\msgrevoke """.trimIndent() ) .generateUnarrangedClasses().toMutableList().arrangeClasses().joinToString("\n\n") diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt index 328af2a50..06eaee34e 100644 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt @@ -53,6 +53,7 @@ fun File.toExternalImage(): ExternalImage { md5 = this.inputStream().use { it.md5() }, imageFormat = this.nameWithoutExtension, input = this.inputStream(), + inputSize = this.length(), filename = this.name ) } diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt index 88b572239..11990fa36 100644 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt @@ -13,7 +13,7 @@ import android.annotation.SuppressLint import android.net.wifi.WifiManager import android.os.Build import android.telephony.TelephonyManager -import io.ktor.utils.io.core.toByteArray +import kotlinx.io.core.toByteArray import kotlinx.serialization.Serializable import kotlinx.serialization.Transient import kotlinx.serialization.UnstableDefault diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformDatagramChannelAndroid.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformDatagramChannelAndroid.kt index 801a19299..ed02843f3 100644 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformDatagramChannelAndroid.kt +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformDatagramChannelAndroid.kt @@ -9,12 +9,12 @@ package net.mamoe.mirai.utils.io -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.Closeable -import io.ktor.utils.io.nio.readPacketAtMost -import io.ktor.utils.io.nio.writePacket import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.Closeable +import kotlinx.io.nio.readPacketAtMost +import kotlinx.io.nio.writePacket import java.net.InetSocketAddress import java.nio.channels.DatagramChannel import java.nio.channels.ReadableByteChannel diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt index 063565c1d..f6c1d2513 100644 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt @@ -9,13 +9,13 @@ package net.mamoe.mirai.utils.io -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.Closeable -import io.ktor.utils.io.core.ExperimentalIoApi -import io.ktor.utils.io.streams.readPacketAtMost -import io.ktor.utils.io.streams.writePacket import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.Closeable +import kotlinx.io.core.ExperimentalIoApi +import kotlinx.io.streams.readPacketAtMost +import kotlinx.io.streams.writePacket import net.mamoe.mirai.utils.MiraiInternalAPI import java.io.BufferedInputStream import java.io.BufferedOutputStream diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/platformAndroid.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/platformAndroid.kt index 9adb9aa12..8430ce7e8 100644 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/platformAndroid.kt +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/platformAndroid.kt @@ -12,7 +12,7 @@ package net.mamoe.mirai.utils import io.ktor.client.HttpClient import io.ktor.client.engine.cio.CIO import io.ktor.util.KtorExperimentalAPI -import io.ktor.utils.io.pool.useInstance +import kotlinx.io.pool.useInstance import net.mamoe.mirai.utils.io.ByteArrayPool import java.io.ByteArrayOutputStream import java.io.DataInput diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotAccount.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotAccount.kt index b4c84333a..1f0a2ebe6 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotAccount.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotAccount.kt @@ -11,7 +11,7 @@ package net.mamoe.mirai -import io.ktor.utils.io.core.toByteArray +import kotlinx.io.core.toByteArray import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.md5 diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/data/ImageLink.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/data/ImageLink.kt index 713ff08a1..3cef0c4a3 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/data/ImageLink.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/data/ImageLink.kt @@ -10,8 +10,8 @@ package net.mamoe.mirai.data import io.ktor.client.request.get -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.readBytes +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.readBytes import net.mamoe.mirai.utils.Http interface ImageLink { diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt index 64a6b9e5e..ac2c51b43 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt @@ -21,7 +21,6 @@ import net.mamoe.mirai.event.events.ImageUploadEvent.Failed import net.mamoe.mirai.event.events.ImageUploadEvent.Succeed import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.MessageChain -import net.mamoe.mirai.message.data.MessageSource import net.mamoe.mirai.utils.ExternalImage import net.mamoe.mirai.utils.MiraiExperimentalAPI diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt index 59a07668c..b26e7163e 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt @@ -12,9 +12,9 @@ package net.mamoe.mirai.utils import io.ktor.utils.io.ByteReadChannel -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.Input import kotlinx.io.InputStream +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.Input import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.QQ diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/channels.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/channels.kt index e2c480e16..c544f09c4 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/channels.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/channels.kt @@ -15,13 +15,10 @@ package net.mamoe.mirai.utils import io.ktor.utils.io.ByteReadChannel -import io.ktor.utils.io.ByteWriteChannel -import io.ktor.utils.io.close -import io.ktor.utils.io.core.Output -import io.ktor.utils.io.core.writeFully -import io.ktor.utils.io.pool.useInstance import io.ktor.utils.io.readAvailable import kotlinx.io.OutputStream +import kotlinx.io.core.Output +import kotlinx.io.pool.useInstance import net.mamoe.mirai.utils.io.ByteArrayPool import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/TEA.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/TEA.kt index 4a98d4441..3e43b3fde 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/TEA.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/TEA.kt @@ -9,9 +9,8 @@ package net.mamoe.mirai.utils.cryptor -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.readFully -import io.ktor.utils.io.pool.useInstance +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.pool.useInstance import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.io.ByteArrayPool import net.mamoe.mirai.utils.io.toByteArray diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/PlatformDatagramChannel.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/PlatformDatagramChannel.kt index 057670f01..9e4b98f1a 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/PlatformDatagramChannel.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/PlatformDatagramChannel.kt @@ -9,8 +9,8 @@ package net.mamoe.mirai.utils.io -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.Closeable +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.Closeable import net.mamoe.mirai.utils.MiraiInternalAPI /** diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/PlatformSocket.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/PlatformSocket.kt index 24a6d7d86..70b411fae 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/PlatformSocket.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/PlatformSocket.kt @@ -9,8 +9,8 @@ package net.mamoe.mirai.utils.io -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.Closeable +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.Closeable import net.mamoe.mirai.utils.MiraiInternalAPI /** diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/byteArrays.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/byteArrays.kt index 970a71a7d..6a191ce29 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/byteArrays.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/byteArrays.kt @@ -13,11 +13,11 @@ package net.mamoe.mirai.utils.io -import io.ktor.utils.io.charsets.Charset -import io.ktor.utils.io.charsets.Charsets -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.String -import io.ktor.utils.io.core.use +import kotlinx.io.charsets.Charset +import kotlinx.io.charsets.Charsets +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.String +import kotlinx.io.core.use import net.mamoe.mirai.utils.checkOffsetAndLength import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/chunked.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/chunked.kt index e9c3a0dfc..fc0b54515 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/chunked.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/chunked.kt @@ -10,16 +10,14 @@ package net.mamoe.mirai.utils.io import io.ktor.utils.io.ByteReadChannel -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.Input -import io.ktor.utils.io.core.isNotEmpty -import io.ktor.utils.io.core.readAvailable -import io.ktor.utils.io.pool.useInstance import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.io.InputStream +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.Input +import kotlinx.io.pool.useInstance import net.mamoe.mirai.utils.MiraiInternalAPI diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/conversion.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/conversion.kt index dfd11e4df..c47f22772 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/conversion.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/conversion.kt @@ -11,6 +11,8 @@ package net.mamoe.mirai.utils.io +import kotlinx.io.core.IoBuffer +import kotlinx.io.pool.ObjectPool import kotlin.random.Random import kotlin.random.nextInt @@ -200,3 +202,13 @@ fun ByteArray.toInt(): Int = (this[0].toInt().and(255) shl 24) + (this[1].toInt().and(255) shl 16) + (this[2].toInt().and(255) shl 8) + (this[3].toInt().and( 255 ) shl 0) + +/** + * 从 [IoBuffer.Pool] [borrow][ObjectPool.borrow] 一个 [IoBuffer] 然后将 [this] 写入. + * 注意回收 ([ObjectPool.recycle]) + */ +fun ByteArray.toIoBuffer( + offset: Int = 0, + length: Int = this.size - offset, + pool: ObjectPool<IoBuffer> = IoBuffer.Pool +): IoBuffer = pool.borrow().let { it.writeFully(this, offset, length); it } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/output.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/output.kt index 837541e2a..671e023b3 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/output.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/output.kt @@ -13,7 +13,7 @@ package net.mamoe.mirai.utils.io -import io.ktor.utils.io.core.* +import kotlinx.io.core.* import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.coerceAtMostOrFail import net.mamoe.mirai.utils.cryptor.TEA diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/platform.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/platform.kt index cd9188012..c4b730d91 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/platform.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/platform.kt @@ -12,7 +12,7 @@ package net.mamoe.mirai.utils import io.ktor.client.HttpClient -import io.ktor.utils.io.core.toByteArray +import kotlinx.io.core.toByteArray /** * 时间戳 diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessagePacket.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessagePacket.kt index e36d3bd19..9e2b6c493 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessagePacket.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessagePacket.kt @@ -12,9 +12,9 @@ package net.mamoe.mirai.message import io.ktor.utils.io.ByteWriteChannel -import io.ktor.utils.io.core.Input +import kotlinx.io.core.Input import io.ktor.utils.io.core.Output -import io.ktor.utils.io.core.use +import kotlinx.io.core.use import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.QQ import net.mamoe.mirai.message.data.Image diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt index 63e246166..a28d13071 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt @@ -11,9 +11,9 @@ package net.mamoe.mirai.message -import io.ktor.utils.io.core.Input import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import kotlinx.io.core.Input import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.OfflineImage diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/BotConfigurationJvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/BotConfigurationJvm.kt index 8f62dc5a8..3b7726efe 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/BotConfigurationJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/BotConfigurationJvm.kt @@ -9,7 +9,6 @@ package net.mamoe.mirai.utils -import io.ktor.utils.io.core.use import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -21,6 +20,7 @@ import kotlinx.coroutines.io.writeFully import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext +import kotlinx.io.core.use import net.mamoe.mirai.Bot import net.mamoe.mirai.network.BotNetworkHandler import java.awt.Image diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt index f6b9f8441..4f500aac4 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt @@ -12,13 +12,13 @@ package net.mamoe.mirai.utils import io.ktor.utils.io.ByteReadChannel -import io.ktor.utils.io.core.Input -import io.ktor.utils.io.core.buildPacket -import io.ktor.utils.io.core.copyTo -import io.ktor.utils.io.errors.IOException -import io.ktor.utils.io.streams.asOutput import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.withContext +import kotlinx.io.core.Input +import kotlinx.io.core.buildPacket +import kotlinx.io.core.copyTo +import kotlinx.io.errors.IOException +import kotlinx.io.streams.asOutput import net.mamoe.mirai.utils.io.getRandomString import java.awt.image.BufferedImage import java.io.File 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 49472129a..46d10fe8c 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 @@ -13,7 +13,7 @@ package net.mamoe.mirai.utils import io.ktor.client.HttpClient import io.ktor.client.engine.cio.CIO -import io.ktor.utils.io.pool.useInstance +import kotlinx.io.pool.useInstance import net.mamoe.mirai.utils.io.ByteArrayPool import java.io.* import java.net.InetAddress diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt index e71cbbfdd..8bcbf6f42 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt @@ -9,7 +9,7 @@ package net.mamoe.mirai.utils -import io.ktor.utils.io.core.toByteArray +import kotlinx.io.core.toByteArray import kotlinx.serialization.Serializable import kotlinx.serialization.Transient import kotlinx.serialization.UnstableDefault diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt index 063565c1d..f6c1d2513 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt @@ -9,13 +9,13 @@ package net.mamoe.mirai.utils.io -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.Closeable -import io.ktor.utils.io.core.ExperimentalIoApi -import io.ktor.utils.io.streams.readPacketAtMost -import io.ktor.utils.io.streams.writePacket import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.Closeable +import kotlinx.io.core.ExperimentalIoApi +import kotlinx.io.streams.readPacketAtMost +import kotlinx.io.streams.writePacket import net.mamoe.mirai.utils.MiraiInternalAPI import java.io.BufferedInputStream import java.io.BufferedOutputStream diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocketJvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocketJvm.kt index db26ec821..1cf48c36f 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocketJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocketJvm.kt @@ -9,12 +9,12 @@ package net.mamoe.mirai.utils.io -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.Closeable -import io.ktor.utils.io.nio.readPacketAtMost -import io.ktor.utils.io.nio.writePacket import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.Closeable +import kotlinx.io.nio.readPacketAtMost +import kotlinx.io.nio.writePacket import java.net.InetSocketAddress import java.nio.channels.DatagramChannel import java.nio.channels.ReadableByteChannel From 6b54abe73076a12905efc02c311ddfc6edc2f508 Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Sat, 7 Mar 2020 18:49:59 +0800 Subject: [PATCH 4/9] Revert "Use `ktor.io` than `kotlinx.io`" This reverts commit ffee2e26 --- mirai-core-qqandroid/build.gradle.kts | 2 + .../packet/chat/receive/MessageSvc.kt | 57 +++++++++++++++++++ mirai-core/build.gradle.kts | 5 ++ .../mamoe/mirai/utils/ExternalImageAndroid.kt | 17 +++--- .../kotlin/mirai/test/KReflectionTest.kt | 24 ++++++++ .../kotlin/mirai/test/UnixColorText.kt | 16 ++++++ .../testCaptchaPacket/TestCaptchaPacket.kt | 30 ++++++++++ 7 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 mirai-core/src/jvmTest/kotlin/mirai/test/KReflectionTest.kt create mode 100644 mirai-core/src/jvmTest/kotlin/mirai/test/UnixColorText.kt create mode 100644 mirai-core/src/jvmTest/kotlin/mirai/test/testCaptchaPacket/TestCaptchaPacket.kt diff --git a/mirai-core-qqandroid/build.gradle.kts b/mirai-core-qqandroid/build.gradle.kts index 7f747935b..d081568a8 100644 --- a/mirai-core-qqandroid/build.gradle.kts +++ b/mirai-core-qqandroid/build.gradle.kts @@ -11,6 +11,7 @@ plugins { val kotlinVersion: String by rootProject.ext val atomicFuVersion: String by rootProject.ext val coroutinesVersion: String by rootProject.ext +val kotlinXIoVersion: String by rootProject.ext val coroutinesIoVersion: String by rootProject.ext @@ -66,6 +67,7 @@ kotlin { api(kotlin("stdlib", kotlinVersion)) api("org.jetbrains.kotlinx:atomicfu:$atomicFuVersion") + api(kotlinx("io", kotlinXIoVersion)) api(kotlinx("coroutines-io", coroutinesIoVersion)) api(kotlinx("coroutines-core", coroutinesVersion)) } diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt index 0a83fb747..7e8df470a 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt @@ -9,10 +9,13 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.* import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.discardExact +import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.data.MemberInfo @@ -278,6 +281,60 @@ internal class MessageSvc { } } + internal class MessageSourceFromSendFriend( + val messageRandom: Int, + override val time: Long, + override val qqId: Long, + override val groupId: Long, + val sequenceId: Int + ) : MessageSource { + @UseExperimental(ExperimentalCoroutinesApi::class) + override val id: Long + get() = sequenceId.toLong().shl(32) or + messageRandom.toLong().and(0xFFFFFFFF) + + override suspend fun ensureSequenceIdAvailable() { + // nothing to do + } + + override fun toString(): String { + return "" + } + } + + internal class MessageSourceFromSendGroup( + val messageRandom: Int, + override val time: Long, + override val qqId: Long, + override val groupId: Long// , + // override val sourceMessage: MessageChain + ) : MessageSource { + private lateinit var sequenceIdDeferred: Deferred<Int> + + @UseExperimental(ExperimentalCoroutinesApi::class) + override val id: Long + get() = sequenceIdDeferred.getCompleted().toLong().shl(32) or + messageRandom.toLong().and(0xFFFFFFFF) + + @UseExperimental(MiraiExperimentalAPI::class) + fun startWaitingSequenceId(contact: Contact) { + sequenceIdDeferred = + contact.subscribingGetAsync<OnlinePush.PbPushGroupMsg.SendGroupMessageReceipt, Int>(timeoutMillis = 3000) { + if (it.messageRandom == this@MessageSourceFromSendGroup.messageRandom) { + it.sequenceId + } else null + } + } + + override suspend fun ensureSequenceIdAvailable() { + sequenceIdDeferred.join() + } + + override fun toString(): String { + return "" + } + } + inline fun ToFriend( client: QQAndroidClient, toUin: Long, diff --git a/mirai-core/build.gradle.kts b/mirai-core/build.gradle.kts index 09dde5fb6..04daba6fa 100644 --- a/mirai-core/build.gradle.kts +++ b/mirai-core/build.gradle.kts @@ -11,6 +11,7 @@ plugins { val kotlinVersion: String by rootProject.ext val atomicFuVersion: String by rootProject.ext val coroutinesVersion: String by rootProject.ext +val kotlinXIoVersion: String by rootProject.ext val coroutinesIoVersion: String by rootProject.ext @@ -65,6 +66,7 @@ kotlin { api(kotlin("serialization", kotlinVersion)) api("org.jetbrains.kotlinx:atomicfu:$atomicFuVersion") + api(kotlinx("io", kotlinXIoVersion)) api(kotlinx("coroutines-io", coroutinesIoVersion)) api(kotlinx("coroutines-core", coroutinesVersion)) } @@ -101,6 +103,8 @@ kotlin { dependencies { api(kotlin("reflect", kotlinVersion)) + api(kotlinx("io", kotlinXIoVersion)) + api(kotlinx("io-jvm", kotlinXIoVersion)) api(kotlinx("serialization-runtime", serializationVersion)) api(kotlinx("coroutines-android", coroutinesVersion)) @@ -125,6 +129,7 @@ kotlin { api(kotlin("reflect", kotlinVersion)) api(ktor("client-core-jvm", ktorVersion)) + api(kotlinx("io-jvm", kotlinXIoVersion)) api(kotlinx("serialization-runtime", serializationVersion)) api(kotlinx("coroutines-io", coroutinesIoVersion)) api(kotlinx("coroutines-io-jvm", coroutinesIoVersion)) diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt index 06eaee34e..fb52b514c 100644 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt @@ -13,13 +13,14 @@ package net.mamoe.mirai.utils import android.graphics.Bitmap import android.graphics.BitmapFactory -import io.ktor.utils.io.ByteReadChannel -import io.ktor.utils.io.core.Input -import io.ktor.utils.io.core.copyTo -import io.ktor.utils.io.errors.IOException -import io.ktor.utils.io.streams.asOutput import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.withContext +import kotlinx.io.core.Input +import kotlinx.io.core.IoBuffer +import kotlinx.io.core.copyTo +import kotlinx.io.errors.IOException +import kotlinx.io.streams.asInput +import kotlinx.io.streams.asOutput import java.io.File import java.io.InputStream import java.net.URL @@ -52,7 +53,7 @@ fun File.toExternalImage(): ExternalImage { height = input.height, md5 = this.inputStream().use { it.md5() }, imageFormat = this.nameWithoutExtension, - input = this.inputStream(), + input = this.inputStream().asInput(IoBuffer.Pool), inputSize = this.length(), filename = this.name ) @@ -69,8 +70,8 @@ suspend inline fun File.suspendToExternalImage(): ExternalImage = withContext(IO @Throws(IOException::class) fun URL.toExternalImage(): ExternalImage { val file = createTempFile().apply { deleteOnExit() } - file.outputStream().use { output -> - openStream().use { input -> + file.outputStream().asOutput().use { output -> + openStream().asInput().use { input -> input.copyTo(output) } output.flush() diff --git a/mirai-core/src/jvmTest/kotlin/mirai/test/KReflectionTest.kt b/mirai-core/src/jvmTest/kotlin/mirai/test/KReflectionTest.kt new file mode 100644 index 000000000..65fa88a5b --- /dev/null +++ b/mirai-core/src/jvmTest/kotlin/mirai/test/KReflectionTest.kt @@ -0,0 +1,24 @@ +/* + * 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 + */ + +package mirai.test + +import kotlin.reflect.KProperty + + +class A { + + val valProp: Any = Any() +} + +fun main() { + A::class.members.filterIsInstance<KProperty<*>>().forEach { + println(it.getter.call(A())) + } +} \ No newline at end of file diff --git a/mirai-core/src/jvmTest/kotlin/mirai/test/UnixColorText.kt b/mirai-core/src/jvmTest/kotlin/mirai/test/UnixColorText.kt new file mode 100644 index 000000000..bd77c6548 --- /dev/null +++ b/mirai-core/src/jvmTest/kotlin/mirai/test/UnixColorText.kt @@ -0,0 +1,16 @@ +/* + * 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 + */ + +package mirai.test + +fun main() { + repeat(100) { + println("\u001b[1;${it}m" + it) + } +} \ No newline at end of file diff --git a/mirai-core/src/jvmTest/kotlin/mirai/test/testCaptchaPacket/TestCaptchaPacket.kt b/mirai-core/src/jvmTest/kotlin/mirai/test/testCaptchaPacket/TestCaptchaPacket.kt new file mode 100644 index 000000000..a603177bb --- /dev/null +++ b/mirai-core/src/jvmTest/kotlin/mirai/test/testCaptchaPacket/TestCaptchaPacket.kt @@ -0,0 +1,30 @@ +/* + * 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 + */ + +package mirai.test.testCaptchaPacket + +import net.mamoe.mirai.utils.MiraiInternalAPI +import net.mamoe.mirai.utils.cryptor.TEA.decrypt +import net.mamoe.mirai.utils.io.hexToBytes +import net.mamoe.mirai.utils.io.toUHexString + + +@MiraiInternalAPI +fun main() { + val key = "65 F7 F3 14 E3 94 10 1F DD 95 84 A3 F5 9F AD 94".hexToBytes() + val data = + decrypt( + "8D 4F 6A 70 F8 4A DE 43 AF 75 D1 3F 3A 3F F2 E0 A8 16 1A 46 13 CD B0 51 45 00 29 52 57 75 6D 4A 4C D9 B7 98 8C B0 96 EC 57 4E 67 FB 8D C5 F1 BF 72 38 40 42 19 54 C2 28 F4 72 C8 AE 24 EB 66 B5 D0 45 0B 72 44 81 E2 F6 2B EE C3 85 93 BA CB B7 72 F4 1A 30 F9 5B 3D B0 79 3E F4 0B F2 1A A7 49 60 3B 37 02 60 0C 5D D5 76 76 47 4F B5 B3 F5 CA 58 6C FC D2 41 3E 24 D1 FB 0A 18 53 D8 E5 A5 85 A8 BC 51 54 3B 66 5B 21 C6 7B AF C9 62 F0 AA 9C CF 2E 84 0F CC 15 5B 35 93 49 5C E4 28 49 A7 8A D3 30 A9 6E 36 4E 7A 49 28 69 4D C3 25 39 6E 45 6E 40 F2 86 1E F4 4F 00 A6 9D E6 9B 84 19 69 C1 31 6A 17 BA F0 0D 8A 22 09 86 24 92 F7 22 C3 47 7F F2 BF 94 8A 8A B5 29".hexToBytes(), + key + ) + println(data.toUHexString()) + + //00 02 00 00 08 04 01 E0 00 00 04 56 00 00 00 01 00 00 15 E3 01 00 38 58 CE A0 12 81 31 5C 5E 36 23 5B E4 0E 05 A6 47 BF 7C 1A 7A 35 37 59 90 17 50 66 0C 07 03 77 E4 48 DB 28 0A CF C3 A9 B7 C0 95 D3 9D 00 AA A5 EB FB D6 85 8D 10 61 5A D0 01 03 00 19 02 CA 53 7E F0 7B 32 82 EC 9F DE CF 51 8B A4 93 26 76 EC 42 1C 02 00 74 58 14 00 05 00 00 00 00 00 04 6C 73 64 61 00 40 CE 99 84 E8 F1 59 31 B0 3F 6C 4D 44 09 E4 82 77 96 67 03 A7 3A EA 8F 36 B9 20 79 7E C9 0F 75 3C 2A C3 E1 E5 C6 00 B3 5E 91 5B 47 63 EF AF 30 C0 48 2F 58 23 96 CF 65 2F 4C 75 95 A6 CA 5A 2C 5C 00 10 E1 50 C9 F4 F6 F4 2F D1 7F E9 8C AB B6 1C 38 7B + +} \ No newline at end of file From e60a6bcf68443c1c1f5e4cd1e919599dd86bd189 Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Sat, 7 Mar 2020 22:04:31 +0800 Subject: [PATCH 5/9] Revert "Use `ktor.io` than `kotlinx.io`" --- .../net/mamoe/mirai/qqandroid/QQAndroidBot.kt | 175 +++++++- .../net/mamoe/mirai/qqandroid/QQAndroidBot.kt | 10 +- .../network/QQAndroidBotNetworkHandler.kt | 14 +- .../qqandroid/network/QQAndroidClient.kt | 4 +- .../network/highway/HighwayHelper.kt | 7 +- .../qqandroid/network/highway/highway.kt | 2 +- .../network/protocol/data/proto/Cmd0x857.kt | 408 ++++++++++++++++++ .../packet/chat/receive/MessageSvc.kt | 57 --- .../packet/chat/receive/OnlinePush.kt | 4 +- .../network/protocol/packet/login/WtLogin.kt | 9 +- .../net/mamoe/mirai/qqandroid/QQAndroidBot.kt | 174 +++++++- mirai-core/build.gradle.kts | 3 +- .../androidMain/kotlin/net/mamoe/mirai/Bot.kt | 2 +- .../mirai/contact/ContactJavaHappyAPI.kt | 2 +- .../mirai/message/SendImageUtilsAndroid.kt | 28 +- .../mamoe/mirai/utils/ExternalImageAndroid.kt | 5 +- .../commonMain/kotlin/net.mamoe.mirai/Bot.kt | 4 +- .../net.mamoe.mirai/message/MessagePacket.kt | 2 +- .../net.mamoe.mirai/utils/ExternalImage.kt | 2 +- .../kotlin/net.mamoe.mirai/utils/channels.kt | 27 +- .../net.mamoe.mirai/utils/io/chunked.kt | 2 +- .../src/jvmMain/kotlin/net/mamoe/mirai/Bot.kt | 2 +- .../mirai/contact/ContactJavaHappyAPI.kt | 2 +- .../net/mamoe/mirai/message/MessagePacket.kt | 4 +- .../mamoe/mirai/message/SendImageUtilsJvm.kt | 30 +- .../net/mamoe/mirai/utils/ExternalImageJvm.kt | 2 +- 26 files changed, 856 insertions(+), 125 deletions(-) create mode 100644 mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Cmd0x857.kt diff --git a/mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt b/mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt index be688325d..5040ed74e 100644 --- a/mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt +++ b/mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt @@ -9,10 +9,20 @@ package net.mamoe.mirai.qqandroid +import io.ktor.utils.io.ByteReadChannel +import io.ktor.utils.io.consumeEachBufferRange +import io.ktor.utils.io.core.Input +import io.ktor.utils.io.core.readBytes +import kotlinx.coroutines.io.* +import kotlinx.io.core.* +import kotlinx.io.pool.useInstance import net.mamoe.mirai.BotAccount import net.mamoe.mirai.utils.BotConfiguration import net.mamoe.mirai.utils.Context import net.mamoe.mirai.utils.MiraiInternalAPI +import net.mamoe.mirai.utils.io.ByteArrayPool +import net.mamoe.mirai.utils.io.toReadPacket +import java.nio.ByteBuffer @UseExperimental(MiraiInternalAPI::class) internal actual class QQAndroidBot @@ -20,4 +30,167 @@ actual constructor( context: Context, account: BotAccount, configuration: BotConfiguration -) : QQAndroidBotBase(context, account, configuration) \ No newline at end of file +) : QQAndroidBotBase(context, account, configuration) + +@UseExperimental(MiraiInternalAPI::class) +@Suppress("DEPRECATION") +internal actual fun ByteReadChannel.toKotlinByteReadChannel(): kotlinx.coroutines.io.ByteReadChannel { + return object : kotlinx.coroutines.io.ByteReadChannel { + override val availableForRead: Int + get() = this@toKotlinByteReadChannel.availableForRead + override val isClosedForRead: Boolean + get() = this@toKotlinByteReadChannel.isClosedForRead + override val isClosedForWrite: Boolean + get() = this@toKotlinByteReadChannel.isClosedForWrite + + @Suppress("DEPRECATION_ERROR", "OverridingDeprecatedMember") + override var readByteOrder: ByteOrder + get() = when (this@toKotlinByteReadChannel.readByteOrder) { + io.ktor.utils.io.core.ByteOrder.BIG_ENDIAN -> ByteOrder.BIG_ENDIAN + io.ktor.utils.io.core.ByteOrder.LITTLE_ENDIAN -> ByteOrder.LITTLE_ENDIAN + } + set(value) { + this@toKotlinByteReadChannel.readByteOrder = when (value) { + ByteOrder.BIG_ENDIAN -> io.ktor.utils.io.core.ByteOrder.BIG_ENDIAN + ByteOrder.LITTLE_ENDIAN -> io.ktor.utils.io.core.ByteOrder.LITTLE_ENDIAN + } + } + + @Suppress("DEPRECATION_ERROR", "DEPRECATION", "OverridingDeprecatedMember") + override val totalBytesRead: Long + get() = this@toKotlinByteReadChannel.totalBytesRead + + override fun cancel(cause: Throwable?): Boolean = this@toKotlinByteReadChannel.cancel(cause) + override suspend fun consumeEachBufferRange(visitor: ConsumeEachBufferVisitor) = + this@toKotlinByteReadChannel.consumeEachBufferRange(visitor) + + override suspend fun discard(max: Long): Long = this@toKotlinByteReadChannel.discard(max) + + @Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_OVERRIDE") + @ExperimentalIoApi + override fun <R> lookAhead(visitor: LookAheadSession.() -> R): R { + return this@toKotlinByteReadChannel.lookAhead l@{ + visitor(object : LookAheadSession { + override fun consumed(n: Int) { + return this@l.consumed(n) + } + + override fun request(skip: Int, atLeast: Int): ByteBuffer? { + return this@l.request(skip, atLeast) + } + }) + } + } + + @Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_OVERRIDE") + @ExperimentalIoApi + override suspend fun <R> lookAheadSuspend(visitor: suspend LookAheadSuspendSession.() -> R): R = + this@toKotlinByteReadChannel.lookAheadSuspend l@{ + visitor(object : LookAheadSuspendSession { + override suspend fun awaitAtLeast(n: Int): Boolean { + return this@l.awaitAtLeast(n) + } + + override fun consumed(n: Int) { + return this@l.consumed(n) + } + + override fun request(skip: Int, atLeast: Int): ByteBuffer? { + return this@l.request(skip, atLeast) + } + + }) + } + + override suspend fun read(min: Int, consumer: (ByteBuffer) -> Unit) = + this@toKotlinByteReadChannel.read(min, consumer) + + override suspend fun readAvailable(dst: ByteBuffer): Int = this@toKotlinByteReadChannel.readAvailable(dst) + override suspend fun readAvailable(dst: ByteArray, offset: Int, length: Int): Int = + this@toKotlinByteReadChannel.readAvailable(dst, offset, length) + + override suspend fun readAvailable(dst: IoBuffer): Int { + ByteArrayPool.useInstance { + val read = this@toKotlinByteReadChannel.readAvailable(it, 0, it.size) + dst.writeFully(it, 0, read) + return read + } + } + + override suspend fun readBoolean(): Boolean = this@toKotlinByteReadChannel.readBoolean() + override suspend fun readByte(): Byte = this@toKotlinByteReadChannel.readByte() + override suspend fun readDouble(): Double = this@toKotlinByteReadChannel.readDouble() + override suspend fun readFloat(): Float = this@toKotlinByteReadChannel.readFloat() + override suspend fun readFully(dst: ByteBuffer): Int { + TODO("not implemented") + } + + override suspend fun readFully(dst: ByteArray, offset: Int, length: Int) = + this@toKotlinByteReadChannel.readFully(dst, offset, length) + + override suspend fun readFully(dst: IoBuffer, n: Int) { + ByteArrayPool.useInstance { + dst.writeFully(it, 0, this.readAvailable(it, 0, it.size)) + } + } + + override suspend fun readInt(): Int = this@toKotlinByteReadChannel.readInt() + override suspend fun readLong(): Long = this@toKotlinByteReadChannel.readLong() + override suspend fun readPacket(size: Int, headerSizeHint: Int): ByteReadPacket { + return this@toKotlinByteReadChannel.readPacket(size, headerSizeHint).readBytes().toReadPacket() + } + + override suspend fun readRemaining(limit: Long, headerSizeHint: Int): ByteReadPacket { + return this@toKotlinByteReadChannel.readRemaining(limit, headerSizeHint).readBytes().toReadPacket() + } + + @UseExperimental(ExperimentalIoApi::class) + @ExperimentalIoApi + override fun readSession(consumer: ReadSession.() -> Unit) { + @Suppress("DEPRECATION") + this@toKotlinByteReadChannel.readSession lambda@{ + consumer(object : ReadSession { + override val availableForRead: Int + get() = this@lambda.availableForRead + + override fun discard(n: Int): Int = this@lambda.discard(n) + + override fun request(atLeast: Int): IoBuffer? { + val ioBuffer: io.ktor.utils.io.core.IoBuffer = this@lambda.request(atLeast) ?: return null + val buffer = IoBuffer.Pool.borrow() + val bytes = (ioBuffer as Input).readBytes() + buffer.writeFully(bytes) + return buffer + } + }) + } + } + + override suspend fun readShort(): Short = this@toKotlinByteReadChannel.readShort() + + @Suppress("EXPERIMENTAL_OVERRIDE", "EXPERIMENTAL_API_USAGE") + @ExperimentalIoApi + override suspend fun readSuspendableSession(consumer: suspend SuspendableReadSession.() -> Unit) = + this@toKotlinByteReadChannel.readSuspendableSession l@{ + consumer(object : SuspendableReadSession { + override val availableForRead: Int + get() = this@l.availableForRead + + override suspend fun await(atLeast: Int): Boolean = this@l.await(atLeast) + override fun discard(n: Int): Int = this@l.discard(n) + override fun request(atLeast: Int): IoBuffer? { + @Suppress("DuplicatedCode") val ioBuffer: io.ktor.utils.io.core.IoBuffer = + this@l.request(atLeast) ?: return null + val buffer = IoBuffer.Pool.borrow() + val bytes = (ioBuffer as Input).readBytes() + buffer.writeFully(bytes) + return buffer + } + }) + } + + override suspend fun readUTF8Line(limit: Int): String? = this@toKotlinByteReadChannel.readUTF8Line(limit) + override suspend fun <A : Appendable> readUTF8LineTo(out: A, limit: Int): Boolean = + this@toKotlinByteReadChannel.readUTF8LineTo(out, limit) + } +} \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt index b9fe826c0..eea2e4940 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt @@ -11,8 +11,8 @@ package net.mamoe.mirai.qqandroid import io.ktor.client.request.get import io.ktor.client.statement.HttpResponse -import io.ktor.utils.io.ByteReadChannel import kotlinx.coroutines.CoroutineName +import kotlinx.coroutines.io.ByteReadChannel import net.mamoe.mirai.BotAccount import net.mamoe.mirai.BotImpl import net.mamoe.mirai.LowLevelAPI @@ -222,6 +222,10 @@ internal abstract class QQAndroidBotBase constructor( } override suspend fun openChannel(image: Image): ByteReadChannel { - return Http.get<HttpResponse>(queryImageUrl(image)).content + return Http.get<HttpResponse>(queryImageUrl(image)).content.toKotlinByteReadChannel() } -} \ No newline at end of file +} + +@Suppress("DEPRECATION") +@UseExperimental(MiraiInternalAPI::class) +internal expect fun io.ktor.utils.io.ByteReadChannel.toKotlinByteReadChannel(): ByteReadChannel \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt index f4389c40e..b5a679e19 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt @@ -9,12 +9,15 @@ package net.mamoe.mirai.qqandroid.network -import io.ktor.utils.io.core.* import kotlinx.atomicfu.AtomicRef import kotlinx.atomicfu.atomic import kotlinx.coroutines.* import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.Input +import kotlinx.io.core.buildPacket +import kotlinx.io.core.use import net.mamoe.mirai.data.MultiPacket import net.mamoe.mirai.data.Packet import net.mamoe.mirai.event.* @@ -67,14 +70,14 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler _packetReceiverJob?.join() return this.launch(CoroutineName("Incoming Packet Receiver")) { - while (channel.isOpen) { + while (channel.isOpen && isActive) { val rawInput = try { channel.read() } catch (e: CancellationException) { return@launch } catch (e: Throwable) { if (this@QQAndroidBotNetworkHandler.isActive) { - BotOfflineEvent.Dropped(bot, e).broadcast() + bot.launch { BotOfflineEvent.Dropped(bot, e).broadcast() } } return@launch } @@ -141,10 +144,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler continue@mainloop } is WtLogin.Login.LoginPacketResponse.Captcha.Slider -> { - var ticket = bot.configuration.loginSolver.onSolveSliderCaptcha(bot, response.url) - if (ticket == null) { - ticket = "" - } + val ticket = bot.configuration.loginSolver.onSolveSliderCaptcha(bot, response.url).orEmpty() response = WtLogin.Login.SubCommand2.SubmitSliderCaptcha(bot.client, ticket).sendAndExpect() continue@mainloop } diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt index 9a507ab35..c4cfa9bd8 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt @@ -159,8 +159,8 @@ internal open class QQAndroidClient( val uin: Long get() = _uin @UseExperimental(RawAccountIdUse::class) - @Suppress("PropertyName") - internal var _uin: Long = bot.uin + @Suppress("PropertyName", "DEPRECATION_ERROR") + internal var _uin: Long = bot.account.id var t530: ByteArray? = null var t528: ByteArray? = null diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/HighwayHelper.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/HighwayHelper.kt index c219a9881..e3eb1506a 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/HighwayHelper.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/HighwayHelper.kt @@ -16,10 +16,10 @@ import io.ktor.http.HttpStatusCode import io.ktor.http.URLProtocol import io.ktor.http.content.OutgoingContent import io.ktor.http.userAgent -import io.ktor.utils.io.ByteReadChannel -import io.ktor.utils.io.copyAndClose +import io.ktor.utils.io.ByteWriteChannel import kotlinx.coroutines.InternalCoroutinesApi import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.io.ByteReadChannel import kotlinx.io.InputStream import kotlinx.io.core.Input import kotlinx.io.core.discardExact @@ -30,6 +30,7 @@ import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.qqandroid.network.protocol.data.proto.CSDataHighwayHead import net.mamoe.mirai.utils.MiraiInternalAPI +import net.mamoe.mirai.utils.copyAndClose import net.mamoe.mirai.utils.io.ByteArrayPool import net.mamoe.mirai.utils.io.PlatformSocket import net.mamoe.mirai.utils.io.withUse @@ -67,7 +68,7 @@ internal suspend fun HttpClient.postImage( override val contentType: ContentType = ContentType.Image.Any override val contentLength: Long = inputSize - override suspend fun writeTo(channel: io.ktor.utils.io.ByteWriteChannel) { + override suspend fun writeTo(channel: ByteWriteChannel) { ByteArrayPool.useInstance { buffer: ByteArray -> when (imageInput) { is Input -> { diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/highway.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/highway.kt index b84834661..308d27b82 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/highway.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/highway.kt @@ -11,9 +11,9 @@ package net.mamoe.mirai.qqandroid.network.highway -import io.ktor.utils.io.ByteReadChannel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.io.ByteReadChannel import kotlinx.io.InputStream import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.Input diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Cmd0x857.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Cmd0x857.kt new file mode 100644 index 000000000..2586189c4 --- /dev/null +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Cmd0x857.kt @@ -0,0 +1,408 @@ +/* + * 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:Suppress("SpellCheckingInspection") + +package net.mamoe.mirai.qqandroid.network.protocol.data.proto + +import kotlinx.serialization.SerialId +import kotlinx.serialization.Serializable +import kotlinx.serialization.protobuf.ProtoNumberType +import kotlinx.serialization.protobuf.ProtoType +import net.mamoe.mirai.qqandroid.io.ProtoBuf +import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY + +class GroupOpenSysMsg : ProtoBuf { + @Serializable + class LightApp( + @SerialId(1) val app: String = "", + @SerialId(2) val view: String = "", + @SerialId(3) val desc: String = "", + @SerialId(4) val prompt: String = "", + @SerialId(5) val ver: String = "", + @SerialId(6) val meta: String = "", + @SerialId(7) val config: String = "", + @SerialId(8) val source: Source? = null + ) : ProtoBuf + + @Serializable + class RichMsg( + @SerialId(1) val title: String = "", + @SerialId(2) val desc: String = "", + @SerialId(3) val brief: String = "", + @SerialId(4) val cover: String = "", + @SerialId(5) val url: String = "", + @SerialId(6) val source: Source? = null + ) : ProtoBuf + + @Serializable + class Sender( + @SerialId(1) val uin: Long = 0L, + @SerialId(2) val nick: String = "", + @SerialId(3) val avatar: String = "", + @SerialId(4) val url: String = "" + ) : ProtoBuf + + @Serializable + class Source( + @SerialId(1) val name: String = "", + @SerialId(2) val icon: String = "", + @SerialId(3) val url: String = "" + ) : ProtoBuf + + @Serializable + class SysMsgBody( + @SerialId(1) val groupId: Long = 0L, + @SerialId(2) val appid: Long = 0L, + @SerialId(3) val sender: Sender? = null, + @SerialId(4) val msgType: Int = 0, + @SerialId(5) val content: String = "", + @SerialId(6) val richMsg: RichMsg? = null, + @SerialId(7) val lightApp: LightApp? = null + ) : ProtoBuf +} + +@Serializable +class TroopTips0x857 : ProtoBuf { + @Serializable + class AIOGrayTipsInfo( + @SerialId(1) val optUint32ShowLastest: Int = 0, + @SerialId(2) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(3) val optUint32Remind: Int = 0, + @SerialId(4) val optBytesBrief: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(5) val receiverUin: Long = 0L, + @SerialId(6) val reliaoAdminOpt: Int = 0, + @SerialId(7) val robotGroupOpt: Int = 0 + ) : ProtoBuf + + @Serializable + class AIOTopTipsInfo( + @SerialId(1) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(2) val optUint32Icon: Int = 0, + @SerialId(3) val optEnumAction: Int /* enum */ = 1, + @SerialId(4) val optBytesUrl: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(5) val optBytesData: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(6) val optBytesDataI: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(7) val optBytesDataA: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(8) val optBytesDataP: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + class FloatedTipsInfo( + @SerialId(1) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + class GeneralGrayTipInfo( + @SerialId(1) val busiType: Long = 0L, + @SerialId(2) val busiId: Long = 0L, + @SerialId(3) val ctrlFlag: Int = 0, + @SerialId(4) val c2cType: Int = 0, + @SerialId(5) val serviceType: Int = 0, + @SerialId(6) val templId: Long = 0L, + @SerialId(7) val msgTemplParam: List<TemplParam>? = null, + @SerialId(8) val content: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(10) val tipsSeqId: Long = 0L, + @SerialId(100) val pbReserv: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + class GoldMsgTipsElem( + @SerialId(1) val type: Int = 0, + @SerialId(2) val billno: String = "", + @SerialId(3) val result: Int = 0, + @SerialId(4) val amount: Int = 0, + @SerialId(5) val total: Int = 0, + @SerialId(6) val interval: Int = 0, + @SerialId(7) val finish: Int = 0, + @SerialId(8) val uin: List<Long>? = null, + @SerialId(9) val action: Int = 0 + ) : ProtoBuf + + @Serializable + class GroupInfoChange( + @SerialId(1) val groupHonorSwitch: Int = 0 + ) : ProtoBuf + + @Serializable + class GroupNotifyInfo( + @SerialId(1) val optUint32AutoPullFlag: Int = 0, + @SerialId(2) val optBytesFeedsId: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + class InstCtrl( + @SerialId(1) val msgSendToInst: List<InstInfo>? = null, + @SerialId(2) val msgExcludeInst: List<InstInfo>? = null, + @SerialId(3) val msgFromInst: InstInfo? = null + ) : ProtoBuf + + @Serializable + class InstInfo( + @SerialId(1) val apppid: Int = 0, + @SerialId(2) val instid: Int = 0, + @SerialId(3) val platform: Int = 0, + @SerialId(4) val openAppid: Int = 0, + @SerialId(5) val productid: Int = 0, + @SerialId(6) val ssoBid: Int = 0, + @SerialId(7) val guid: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(8) val verMin: Int = 0, + @SerialId(9) val verMax: Int = 0 + ) : ProtoBuf + + @Serializable + class LbsShareChangePushInfo( + @SerialId(1) val msgType: Int = 0, + @SerialId(2) val msgInfo: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(3) val versionCtrl: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(4) val groupId: Long = 0L, + @SerialId(5) val operUin: Long = 0L, + @SerialId(6) val grayTips: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(7) val msgSeq: Long = 0L, + @SerialId(8) val joinNums: Int = 0, + @SerialId(99) val pushType: Int = 0, + @SerialId(100) val extInfo: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + class LuckyBagNotify( + @SerialId(1) val msgTips: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + class MediaChangePushInfo( + @SerialId(1) val msgType: Int = 0, + @SerialId(2) val msgInfo: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(3) val versionCtrl: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(4) val groupId: Long = 0L, + @SerialId(5) val operUin: Long = 0L, + @SerialId(6) val grayTips: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(7) val msgSeq: Long = 0L, + @SerialId(8) val joinNums: Int = 0, + @SerialId(9) val msgPerSetting: PersonalSetting? = null, + @SerialId(10) val playMode: Int = 0, + @SerialId(99) val mediaType: Int = 0, + @SerialId(100) val extInfo: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf { + @Serializable + class PersonalSetting( + @SerialId(1) val themeId: Int = 0, + @SerialId(2) val playerId: Int = 0, + @SerialId(3) val fontId: Int = 0 + ) : ProtoBuf + } + + @Serializable + class MessageBoxInfo( + @SerialId(1) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(2) val optBytesTitle: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(3) val optBytesButton: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + class MessageRecallReminder( + @SerialId(1) val uin: Long = 0L, + @SerialId(2) val nickname: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(3) val recalledMsgList: List<MessageMeta> = listOf(), + @SerialId(4) val reminderContent: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(5) val userdef: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(6) val groupType: Int = 0, + @SerialId(7) val opType: Int = 0 + ) : ProtoBuf { + @Serializable + class MessageMeta( + @SerialId(1) val seq: Int = 0, + @SerialId(2) val time: Int = 0, + @SerialId(3) val msgRandom: Int = 0, + @SerialId(4) val msgType: Int = 0, + @SerialId(5) val msgFlag: Int = 0, + @SerialId(6) val authorUin: Long = 0L + ) : ProtoBuf + } + + @Serializable + class MiniAppNotify( + @SerialId(1) val msg: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + class NotifyMsgBody( + @SerialId(1) val optEnumType: Int /* enum */ = 1, + @SerialId(2) val optUint64MsgTime: Long = 0L, + @SerialId(3) val optUint64MsgExpires: Long = 0L, + @SerialId(4) val optUint64GroupCode: Long = 0L, + @SerialId(5) val optMsgGraytips: AIOGrayTipsInfo? = null, + @SerialId(6) val optMsgMessagebox: MessageBoxInfo? = null, + @SerialId(7) val optMsgFloatedtips: FloatedTipsInfo? = null, + @SerialId(8) val optMsgToptips: AIOTopTipsInfo? = null, + @SerialId(9) val optMsgRedtips: RedGrayTipsInfo? = null, + @SerialId(10) val optMsgGroupNotify: GroupNotifyInfo? = null, + @SerialId(11) val optMsgRecall: MessageRecallReminder? = null, + @SerialId(12) val optMsgThemeNotify: ThemeStateNotify? = null, + @SerialId(13) val serviceType: Int = 0, + @SerialId(14) val optMsgObjmsgUpdate: NotifyObjmsgUpdate? = null, + @SerialId(15) val optMsgWerewolfPush: WereWolfPush? = null, + // @SerialId(16) val optStcmGameState: ApolloGameStatus.STCMGameMessage? = null, + // @SerialId(17) val aplloMsgPush: ApolloPushMsgInfo.STPushMsgElem? = null, + @SerialId(18) val optMsgGoldtips: GoldMsgTipsElem? = null, + @SerialId(20) val optMsgMiniappNotify: MiniAppNotify? = null, + @SerialId(21) val optUint64SenderUin: Long = 0L, + @SerialId(22) val optMsgLuckybagNotify: LuckyBagNotify? = null, + @SerialId(23) val optMsgTroopformtipsPush: TroopFormGrayTipsInfo? = null, + @SerialId(24) val optMsgMediaPush: MediaChangePushInfo? = null, + @SerialId(26) val optGeneralGrayTip: GeneralGrayTipInfo? = null, + @SerialId(27) val optMsgVideoPush: VideoChangePushInfo? = null, + @SerialId(28) val optLbsShareChangePlusInfo: LbsShareChangePushInfo? = null, + @SerialId(29) val optMsgSingPush: SingChangePushInfo? = null, + @SerialId(30) val optMsgGroupInfoChange: GroupInfoChange? = null + ) : ProtoBuf + + @Serializable + class NotifyObjmsgUpdate( + @SerialId(1) val objmsgId: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(2) val updateType: Int = 0, + @SerialId(3) val extMsg: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + class RedGrayTipsInfo( + @SerialId(1) val optUint32ShowLastest: Int = 0, + @SerialId(2) val senderUin: Long = 0L, + @SerialId(3) val receiverUin: Long = 0L, + @SerialId(4) val senderRichContent: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(5) val receiverRichContent: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(6) val authkey: ByteArray = EMPTY_BYTE_ARRAY, + @ProtoType(ProtoNumberType.SIGNED) @SerialId(7) val sint32Msgtype: Int = 0, + @SerialId(8) val luckyFlag: Int = 0, + @SerialId(9) val hideFlag: Int = 0, + @SerialId(10) val pcBody: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(11) val icon: Int = 0, + @SerialId(12) val luckyUin: Long = 0L, + @SerialId(13) val time: Int = 0, + @SerialId(14) val random: Int = 0, + @SerialId(15) val broadcastRichContent: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(16) val idiom: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(17) val idiomSeq: Int = 0, + @SerialId(18) val idiomAlpha: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(19) val jumpurl: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + class ReqBody( + @SerialId(1) val optUint64GroupCode: Long = 0L, + @SerialId(2) val uint64Memberuins: List<Long>? = null, + @SerialId(3) val optUint32Offline: Int = 0, + @SerialId(4) val msgInstCtrl: InstCtrl? = null, + @SerialId(5) val optBytesMsg: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(6) val optUint32BusiType: Int = 0 + ) : ProtoBuf + + @Serializable + class RspBody( + @SerialId(1) val optUint64GroupCode: Long = 0L + ) : ProtoBuf + + @Serializable + class SingChangePushInfo( + @SerialId(1) val seq: Long = 0L, + @SerialId(2) val actionType: Int = 0, + @SerialId(3) val groupId: Long = 0L, + @SerialId(4) val operUin: Long = 0L, + @SerialId(5) val grayTips: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(6) val joinNums: Int = 0 + ) : ProtoBuf + + @Serializable + class TemplParam( + @SerialId(1) val name: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(2) val value: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + class ThemeStateNotify( + @SerialId(1) val state: Int = 0, + @SerialId(2) val feedsId: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(3) val themeName: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(4) val actionUin: Long = 0L, + @SerialId(5) val createUin: Long = 0L + ) : ProtoBuf + + @Serializable + class TroopFormGrayTipsInfo( + @SerialId(1) val writerUin: Long = 0L, + @SerialId(2) val creatorUin: Long = 0L, + @SerialId(3) val richContent: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(4) val optBytesUrl: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(5) val creatorNick: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + class VideoChangePushInfo( + @SerialId(1) val seq: Long = 0L, + @SerialId(2) val actionType: Int = 0, + @SerialId(3) val groupId: Long = 0L, + @SerialId(4) val operUin: Long = 0L, + @SerialId(5) val grayTips: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(6) val joinNums: Int = 0, + @SerialId(100) val extInfo: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + class WereWolfPush( + @SerialId(1) val pushType: Int = 0, + @SerialId(2) val gameRoom: Long = 0L, + @SerialId(3) val enumGameState: Int = 0, + @SerialId(4) val gameRound: Int = 0, + @SerialId(5) val roles: List<Role>? = null, + @SerialId(6) val speaker: Long = 0L, + @SerialId(7) val judgeUin: Long = 0L, + @SerialId(8) val judgeWords: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(9) val enumOperation: Int = 0, + @SerialId(10) val srcUser: Long = 0L, + @SerialId(11) val dstUser: Long = 0L, + @SerialId(12) val deadUsers: List<Long>? = null, + @SerialId(13) val gameResult: Int = 0, + @SerialId(14) val timeoutSec: Int = 0, + @SerialId(15) val killConfirmed: Int = 0, + @SerialId(16) val judgeNickname: ByteArray = EMPTY_BYTE_ARRAY, + @SerialId(17) val votedTieUsers: List<Long>? = null + ) : ProtoBuf { + @Serializable + class GameRecord( + @SerialId(1) val total: Int = 0, + @SerialId(2) val win: Int = 0, + @SerialId(3) val lose: Int = 0, + @SerialId(4) val draw: Int = 0 + ) : ProtoBuf + + @Serializable + class Role( + @SerialId(1) val uin: Long = 0L, + @SerialId(2) val enumType: Int = 0, + @SerialId(3) val enumState: Int = 0, + @SerialId(4) val canSpeak: Int = 0, + @SerialId(5) val canListen: Int = 0, + @SerialId(6) val position: Int = 0, + @SerialId(7) val canVote: Int = 0, + @SerialId(8) val canVoted: Int = 0, + @SerialId(9) val alreadyChecked: Int = 0, + @SerialId(10) val alreadySaved: Int = 0, + @SerialId(11) val alreadyPoisoned: Int = 0, + @SerialId(12) val playerState: Int = 0, + @SerialId(13) val enumDeadOp: Int = 0, + @SerialId(14) val enumOperation: Int = 0, + @SerialId(15) val dstUser: Long = 0L, + @SerialId(16) val operationRound: Int = 0, + @SerialId(17) val msgGameRecord: GameRecord? = null, + @SerialId(18) val isWerewolf: Int = 0, + @SerialId(19) val defendedUser: Long = 0L, + @SerialId(20) val isSheriff: Int = 0 + ) : ProtoBuf + } +} \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt index 7e8df470a..0a83fb747 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt @@ -9,13 +9,10 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.* import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.discardExact -import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.data.MemberInfo @@ -281,60 +278,6 @@ internal class MessageSvc { } } - internal class MessageSourceFromSendFriend( - val messageRandom: Int, - override val time: Long, - override val qqId: Long, - override val groupId: Long, - val sequenceId: Int - ) : MessageSource { - @UseExperimental(ExperimentalCoroutinesApi::class) - override val id: Long - get() = sequenceId.toLong().shl(32) or - messageRandom.toLong().and(0xFFFFFFFF) - - override suspend fun ensureSequenceIdAvailable() { - // nothing to do - } - - override fun toString(): String { - return "" - } - } - - internal class MessageSourceFromSendGroup( - val messageRandom: Int, - override val time: Long, - override val qqId: Long, - override val groupId: Long// , - // override val sourceMessage: MessageChain - ) : MessageSource { - private lateinit var sequenceIdDeferred: Deferred<Int> - - @UseExperimental(ExperimentalCoroutinesApi::class) - override val id: Long - get() = sequenceIdDeferred.getCompleted().toLong().shl(32) or - messageRandom.toLong().and(0xFFFFFFFF) - - @UseExperimental(MiraiExperimentalAPI::class) - fun startWaitingSequenceId(contact: Contact) { - sequenceIdDeferred = - contact.subscribingGetAsync<OnlinePush.PbPushGroupMsg.SendGroupMessageReceipt, Int>(timeoutMillis = 3000) { - if (it.messageRandom == this@MessageSourceFromSendGroup.messageRandom) { - it.sequenceId - } else null - } - } - - override suspend fun ensureSequenceIdAvailable() { - sequenceIdDeferred.join() - } - - override fun toString(): String { - return "" - } - } - inline fun ToFriend( client: QQAndroidClient, toUin: Long, diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.kt index ed6a5e27e..7ee94ebf8 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.kt @@ -11,7 +11,7 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive -import io.ktor.utils.io.core.* +import kotlinx.io.core.* import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.data.MultiPacketBySequence import net.mamoe.mirai.data.NoPacket @@ -341,7 +341,7 @@ internal class OnlinePush { } } 0x11 -> { - discard(1) + discardExact(1) val proto = readProtoBuf(TroopTips0x857.NotifyMsgBody.serializer()) proto.optMsgRecall?.let { recallReminder -> diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt index 6ee16aa42..69d873d2d 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt @@ -127,7 +127,7 @@ internal class WtLogin { private const val appId = 16L private const val subAppId = 537062845L - @UseExperimental(MiraiInternalAPI::class) + @UseExperimental(MiraiInternalAPI::class, MiraiExperimentalAPI::class) operator fun invoke( client: QQAndroidClient ): OutgoingPacket = buildLoginOutgoingPacket(client, bodyType = 2) { sequenceId -> @@ -288,7 +288,7 @@ internal class WtLogin { } class Picture( - val data: IoBuffer, + val data: ByteArray, val sign: ByteArray ) : Captcha() { override fun toString(): String = "LoginPacketResponse.Captcha.Picture" @@ -394,11 +394,8 @@ internal class WtLogin { imageData.discardExact(2)//image Length val sign = imageData.readBytes(signInfoLength.toInt()) - - val buffer = IoBuffer.Pool.borrow() - imageData.readAvailable(buffer) return LoginPacketResponse.Captcha.Picture( - data = buffer, + data = imageData.readBytes(), sign = sign ) // } else error("UNKNOWN CAPTCHA QUESTION: ${question.toUHexString()}, tlvMap=" + tlvMap.contentToString()) diff --git a/mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt b/mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt index 5ead6b167..62989914b 100644 --- a/mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt +++ b/mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt @@ -9,19 +9,189 @@ package net.mamoe.mirai.qqandroid +import io.ktor.utils.io.ByteReadChannel +import io.ktor.utils.io.consumeEachBufferRange +import io.ktor.utils.io.core.Input +import io.ktor.utils.io.core.readBytes +import kotlinx.coroutines.io.* +import kotlinx.io.core.* +import kotlinx.io.pool.useInstance import net.mamoe.mirai.BotAccount import net.mamoe.mirai.utils.BotConfiguration import net.mamoe.mirai.utils.Context import net.mamoe.mirai.utils.ContextImpl import net.mamoe.mirai.utils.MiraiInternalAPI +import net.mamoe.mirai.utils.io.ByteArrayPool +import net.mamoe.mirai.utils.io.toReadPacket +import java.nio.ByteBuffer @UseExperimental(MiraiInternalAPI::class) @Suppress("FunctionName") -internal fun QQAndroidBot(account: BotAccount, configuration: BotConfiguration): QQAndroidBot = QQAndroidBot(ContextImpl(), account, configuration) +internal fun QQAndroidBot(account: BotAccount, configuration: BotConfiguration): QQAndroidBot = + QQAndroidBot(ContextImpl(), account, configuration) @UseExperimental(MiraiInternalAPI::class) internal actual class QQAndroidBot actual constructor( context: Context, account: BotAccount, configuration: BotConfiguration -) : QQAndroidBotBase(context, account, configuration) \ No newline at end of file +) : QQAndroidBotBase(context, account, configuration) + +@UseExperimental(MiraiInternalAPI::class) +@Suppress("DEPRECATION") +internal actual fun ByteReadChannel.toKotlinByteReadChannel(): kotlinx.coroutines.io.ByteReadChannel { + return object : kotlinx.coroutines.io.ByteReadChannel { + override val availableForRead: Int + get() = this@toKotlinByteReadChannel.availableForRead + override val isClosedForRead: Boolean + get() = this@toKotlinByteReadChannel.isClosedForRead + override val isClosedForWrite: Boolean + get() = this@toKotlinByteReadChannel.isClosedForWrite + + @Suppress("DEPRECATION_ERROR", "OverridingDeprecatedMember") + override var readByteOrder: ByteOrder + get() = when (this@toKotlinByteReadChannel.readByteOrder) { + io.ktor.utils.io.core.ByteOrder.BIG_ENDIAN -> ByteOrder.BIG_ENDIAN + io.ktor.utils.io.core.ByteOrder.LITTLE_ENDIAN -> ByteOrder.LITTLE_ENDIAN + } + set(value) { + this@toKotlinByteReadChannel.readByteOrder = when (value) { + ByteOrder.BIG_ENDIAN -> io.ktor.utils.io.core.ByteOrder.BIG_ENDIAN + ByteOrder.LITTLE_ENDIAN -> io.ktor.utils.io.core.ByteOrder.LITTLE_ENDIAN + } + } + + @Suppress("DEPRECATION_ERROR", "DEPRECATION", "OverridingDeprecatedMember") + override val totalBytesRead: Long + get() = this@toKotlinByteReadChannel.totalBytesRead + + override fun cancel(cause: Throwable?): Boolean = this@toKotlinByteReadChannel.cancel(cause) + override suspend fun consumeEachBufferRange(visitor: ConsumeEachBufferVisitor) = this@toKotlinByteReadChannel.consumeEachBufferRange(visitor) + override suspend fun discard(max: Long): Long = this@toKotlinByteReadChannel.discard(max) + @Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_OVERRIDE") + @ExperimentalIoApi + override fun <R> lookAhead(visitor: LookAheadSession.() -> R): R { + return this@toKotlinByteReadChannel.lookAhead l@{ + visitor(object : LookAheadSession{ + override fun consumed(n: Int) { + return this@l.consumed(n) + } + override fun request(skip: Int, atLeast: Int): ByteBuffer? { + return this@l.request(skip, atLeast) + } + }) + } + } + + @Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_OVERRIDE") + @ExperimentalIoApi + override suspend fun <R> lookAheadSuspend(visitor: suspend LookAheadSuspendSession.() -> R): R = + this@toKotlinByteReadChannel.lookAheadSuspend l@{ + visitor(object : LookAheadSuspendSession { + override suspend fun awaitAtLeast(n: Int): Boolean { + return this@l.awaitAtLeast(n) + } + + override fun consumed(n: Int) { + return this@l.consumed(n) + } + + override fun request(skip: Int, atLeast: Int): ByteBuffer? { + return this@l.request(skip, atLeast) + } + + }) + } + + override suspend fun read(min: Int, consumer: (ByteBuffer) -> Unit) = + this@toKotlinByteReadChannel.read(min, consumer) + + override suspend fun readAvailable(dst: ByteBuffer): Int = this@toKotlinByteReadChannel.readAvailable(dst) + override suspend fun readAvailable(dst: ByteArray, offset: Int, length: Int): Int = + this@toKotlinByteReadChannel.readAvailable(dst, offset, length) + + override suspend fun readAvailable(dst: IoBuffer): Int { + ByteArrayPool.useInstance { + val read = this@toKotlinByteReadChannel.readAvailable(it, 0, it.size) + dst.writeFully(it, 0, read) + return read + } + } + + override suspend fun readBoolean(): Boolean = this@toKotlinByteReadChannel.readBoolean() + override suspend fun readByte(): Byte = this@toKotlinByteReadChannel.readByte() + override suspend fun readDouble(): Double = this@toKotlinByteReadChannel.readDouble() + override suspend fun readFloat(): Float = this@toKotlinByteReadChannel.readFloat() + override suspend fun readFully(dst: ByteBuffer): Int { + TODO("not implemented") + } + + override suspend fun readFully(dst: ByteArray, offset: Int, length: Int) = + this@toKotlinByteReadChannel.readFully(dst, offset, length) + + override suspend fun readFully(dst: IoBuffer, n: Int) { + ByteArrayPool.useInstance { + dst.writeFully(it, 0, this.readAvailable(it, 0, it.size)) + } + } + + override suspend fun readInt(): Int = this@toKotlinByteReadChannel.readInt() + override suspend fun readLong(): Long = this@toKotlinByteReadChannel.readLong() + override suspend fun readPacket(size: Int, headerSizeHint: Int): ByteReadPacket { + return this@toKotlinByteReadChannel.readPacket(size, headerSizeHint).readBytes().toReadPacket() + } + + override suspend fun readRemaining(limit: Long, headerSizeHint: Int): ByteReadPacket { + return this@toKotlinByteReadChannel.readRemaining(limit, headerSizeHint).readBytes().toReadPacket() + } + + @UseExperimental(ExperimentalIoApi::class) + @ExperimentalIoApi + override fun readSession(consumer: ReadSession.() -> Unit) { + @Suppress("DEPRECATION") + this@toKotlinByteReadChannel.readSession lambda@{ + consumer(object : ReadSession { + override val availableForRead: Int + get() = this@lambda.availableForRead + + override fun discard(n: Int): Int = this@lambda.discard(n) + + override fun request(atLeast: Int): IoBuffer? { + val ioBuffer: io.ktor.utils.io.core.IoBuffer = this@lambda.request(atLeast) ?: return null + val buffer = IoBuffer.Pool.borrow() + val bytes = (ioBuffer as Input).readBytes() + buffer.writeFully(bytes) + return buffer + } + }) + } + } + + override suspend fun readShort(): Short = this@toKotlinByteReadChannel.readShort() + + @Suppress("EXPERIMENTAL_OVERRIDE", "EXPERIMENTAL_API_USAGE") + @ExperimentalIoApi + override suspend fun readSuspendableSession(consumer: suspend SuspendableReadSession.() -> Unit) = + this@toKotlinByteReadChannel.readSuspendableSession l@{ + consumer(object : SuspendableReadSession { + override val availableForRead: Int + get() = this@l.availableForRead + + override suspend fun await(atLeast: Int): Boolean = this@l.await(atLeast) + override fun discard(n: Int): Int = this@l.discard(n) + override fun request(atLeast: Int): IoBuffer? { + @Suppress("DuplicatedCode") val ioBuffer: io.ktor.utils.io.core.IoBuffer = + this@l.request(atLeast) ?: return null + val buffer = IoBuffer.Pool.borrow() + val bytes = (ioBuffer as Input).readBytes() + buffer.writeFully(bytes) + return buffer + } + }) + } + + override suspend fun readUTF8Line(limit: Int): String? = this@toKotlinByteReadChannel.readUTF8Line(limit) + override suspend fun <A : Appendable> readUTF8LineTo(out: A, limit: Int): Boolean = + this@toKotlinByteReadChannel.readUTF8LineTo(out, limit) + } +} \ No newline at end of file diff --git a/mirai-core/build.gradle.kts b/mirai-core/build.gradle.kts index 04daba6fa..3192a15a4 100644 --- a/mirai-core/build.gradle.kts +++ b/mirai-core/build.gradle.kts @@ -107,6 +107,7 @@ kotlin { api(kotlinx("io-jvm", kotlinXIoVersion)) api(kotlinx("serialization-runtime", serializationVersion)) api(kotlinx("coroutines-android", coroutinesVersion)) + api(kotlinx("coroutines-io-jvm", coroutinesIoVersion)) api(ktor("client-android", ktorVersion)) } @@ -131,9 +132,7 @@ kotlin { api(ktor("client-core-jvm", ktorVersion)) api(kotlinx("io-jvm", kotlinXIoVersion)) api(kotlinx("serialization-runtime", serializationVersion)) - api(kotlinx("coroutines-io", coroutinesIoVersion)) api(kotlinx("coroutines-io-jvm", coroutinesIoVersion)) - api(kotlinx("io-jvm", coroutinesIoVersion)) api("org.bouncycastle:bcprov-jdk15on:1.64") runtimeOnly(files("build/classes/kotlin/jvm/main")) // classpath is not properly set by IDE diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/Bot.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/Bot.kt index de70962a5..4ed5464d9 100644 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/Bot.kt +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/Bot.kt @@ -2,8 +2,8 @@ package net.mamoe.mirai -import io.ktor.utils.io.ByteReadChannel import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.io.ByteReadChannel import net.mamoe.mirai.contact.* import net.mamoe.mirai.data.AddFriendResult import net.mamoe.mirai.message.MessageReceipt diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/contact/ContactJavaHappyAPI.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/contact/ContactJavaHappyAPI.kt index 515a87d03..64b463145 100644 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/contact/ContactJavaHappyAPI.kt +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/contact/ContactJavaHappyAPI.kt @@ -10,8 +10,8 @@ package net.mamoe.mirai.contact import android.graphics.Bitmap -import io.ktor.utils.io.core.Input import kotlinx.coroutines.Dispatchers +import kotlinx.io.core.Input import net.mamoe.mirai.Bot import net.mamoe.mirai.JavaHappyAPI import net.mamoe.mirai.event.events.* diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/message/SendImageUtilsAndroid.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/message/SendImageUtilsAndroid.kt index a0beee43a..d38892940 100644 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/message/SendImageUtilsAndroid.kt +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/message/SendImageUtilsAndroid.kt @@ -12,9 +12,9 @@ package net.mamoe.mirai.message import android.graphics.Bitmap -import io.ktor.utils.io.core.Input import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import kotlinx.io.core.Input import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.utils.OverFileSizeMaxException @@ -36,28 +36,31 @@ import java.net.URL * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Bitmap.sendTo(contact: Contact) = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) +suspend fun <C : Contact> Bitmap.sendTo(contact: C): MessageReceipt<C> = + withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) /** * 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun URL.sendAsImageTo(contact: Contact) = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) +suspend fun <C : Contact> URL.sendAsImageTo(contact: C): MessageReceipt<C> = + withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) /** * 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Input.sendAsImageTo(contact: Contact) = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) +suspend fun <C : Contact> Input.sendAsImageTo(contact: C): MessageReceipt<C> = + withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) /** * 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun InputStream.sendAsImageTo(contact: Contact) = +suspend fun <C : Contact> InputStream.sendAsImageTo(contact: C): MessageReceipt<C> = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) /** @@ -65,9 +68,9 @@ suspend fun InputStream.sendAsImageTo(contact: Contact) = * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun File.sendAsImageTo(contact: Contact) { +suspend fun <C : Contact> File.sendAsImageTo(contact: C): MessageReceipt<C> { require(this.exists() && this.canRead()) - withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) + return withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) } // endregion @@ -124,35 +127,36 @@ suspend fun File.uploadAsImage(contact: Contact): Image { * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun Contact.sendImage(bufferedImage: Bitmap) = bufferedImage.sendTo(this) +suspend inline fun <C : Contact> C.sendImage(bufferedImage: Bitmap): MessageReceipt<C> = bufferedImage.sendTo(this) /** * 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun Contact.sendImage(imageUrl: URL) = imageUrl.sendAsImageTo(this) +suspend inline fun <C : Contact> C.sendImage(imageUrl: URL): MessageReceipt<C> = imageUrl.sendAsImageTo(this) /** * 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun Contact.sendImage(imageInput: Input) = imageInput.sendAsImageTo(this) +suspend inline fun <C : Contact> C.sendImage(imageInput: Input): MessageReceipt<C> = imageInput.sendAsImageTo(this) /** * 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun Contact.sendImage(imageStream: InputStream) = imageStream.sendAsImageTo(this) +suspend inline fun <C : Contact> C.sendImage(imageStream: InputStream): MessageReceipt<C> = + imageStream.sendAsImageTo(this) /** * 在 [Dispatchers.IO] 中将文件作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun Contact.sendImage(file: File) = file.sendAsImageTo(this) +suspend inline fun <C : Contact> C.sendImage(file: File): MessageReceipt<C> = file.sendAsImageTo(this) // endregion diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt index fb52b514c..0cced476e 100644 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt @@ -31,7 +31,7 @@ import java.net.URL /** - * 读取 [BufferedImage] 的属性, 然后构造 [ExternalImage] + * 读取 [Bitmap] 的属性, 然后构造 [ExternalImage] */ @Throws(IOException::class) fun Bitmap.toExternalImage(formatName: String = "gif"): Nothing { @@ -123,6 +123,7 @@ fun Input.toExternalImage(): ExternalImage { */ suspend inline fun Input.suspendToExternalImage(): ExternalImage = withContext(IO) { toExternalImage() } +/* /** * 保存为临时文件然后调用 [File.toExternalImage]. */ @@ -134,4 +135,4 @@ suspend fun ByteReadChannel.toExternalImage(): ExternalImage { } return file.suspendToExternalImage() -} \ No newline at end of file +}*/ \ No newline at end of file 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 54bb1308e..48188f8fb 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt @@ -11,10 +11,10 @@ package net.mamoe.mirai -import io.ktor.utils.io.ByteReadChannel import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job +import kotlinx.coroutines.io.ByteReadChannel import kotlinx.coroutines.launch import net.mamoe.mirai.contact.* import net.mamoe.mirai.data.AddFriendResult @@ -89,7 +89,7 @@ expect abstract class Bot() : CoroutineScope, LowLevelBotAPIAccessor { // region contacts /** - * [_lowLevelNewQQ.id] 与 [Bot.uin] 相同的 [_lowLevelNewQQ] 实例 + * [QQ.id] 与 [Bot.uin] 相同的 [_lowLevelNewQQ] 实例 */ abstract val selfQQ: QQ diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessagePacket.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessagePacket.kt index 492c654ac..5fba59979 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessagePacket.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessagePacket.kt @@ -11,7 +11,7 @@ package net.mamoe.mirai.message -import io.ktor.utils.io.ByteReadChannel +import kotlinx.coroutines.io.ByteReadChannel import net.mamoe.mirai.Bot import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Group diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt index b26e7163e..eaa009dcd 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt @@ -11,7 +11,7 @@ package net.mamoe.mirai.utils -import io.ktor.utils.io.ByteReadChannel +import kotlinx.coroutines.io.ByteReadChannel import kotlinx.io.InputStream import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.Input diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/channels.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/channels.kt index c544f09c4..f823915f7 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/channels.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/channels.kt @@ -14,8 +14,9 @@ package net.mamoe.mirai.utils -import io.ktor.utils.io.ByteReadChannel -import io.ktor.utils.io.readAvailable +import kotlinx.coroutines.io.ByteReadChannel +import kotlinx.coroutines.io.ByteWriteChannel +import kotlinx.coroutines.io.readAvailable import kotlinx.io.OutputStream import kotlinx.io.core.Output import kotlinx.io.pool.useInstance @@ -120,6 +121,7 @@ suspend fun ByteReadChannel.copyAndClose(dst: Output) { * 从接收者管道读取所有数据并写入 [dst], 最终关闭 [dst] */ suspend fun ByteReadChannel.copyAndClose(dst: ByteWriteChannel) { + @Suppress("DuplicatedCode") try { @UseExperimental(MiraiInternalAPI::class) ByteArrayPool.useInstance { buffer -> @@ -130,7 +132,26 @@ suspend fun ByteReadChannel.copyAndClose(dst: ByteWriteChannel) { } } finally { @Suppress("DuplicatedCode") - dst.close() + dst.close(null) + } +} + +/** + * 从接收者管道读取所有数据并写入 [dst], 最终关闭 [dst] + */ +suspend fun ByteReadChannel.copyAndClose(dst: io.ktor.utils.io.ByteWriteChannel) { + @Suppress("DuplicatedCode") + try { + @UseExperimental(MiraiInternalAPI::class) + ByteArrayPool.useInstance { buffer -> + var size: Int + while (this.readAvailable(buffer).also { size = it } > 0) { + dst.writeFully(buffer, 0, size) + } + } + } finally { + @Suppress("DuplicatedCode") + dst.close(null) } } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/chunked.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/chunked.kt index fc0b54515..766ab5986 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/chunked.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/chunked.kt @@ -9,11 +9,11 @@ package net.mamoe.mirai.utils.io -import io.ktor.utils.io.ByteReadChannel import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.io.ByteReadChannel import kotlinx.io.InputStream import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.Input diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/Bot.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/Bot.kt index 93c0ebd52..bdf62b9d0 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/Bot.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/Bot.kt @@ -2,7 +2,7 @@ package net.mamoe.mirai -import io.ktor.utils.io.ByteReadChannel +import kotlinx.coroutines.io.ByteReadChannel import kotlinx.coroutines.CoroutineScope import net.mamoe.mirai.contact.* import net.mamoe.mirai.data.AddFriendResult diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/ContactJavaHappyAPI.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/ContactJavaHappyAPI.kt index e5169ab98..d8cd329c9 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/ContactJavaHappyAPI.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/ContactJavaHappyAPI.kt @@ -9,8 +9,8 @@ package net.mamoe.mirai.contact -import io.ktor.utils.io.core.Input import kotlinx.coroutines.Dispatchers +import kotlinx.io.core.Input import net.mamoe.mirai.Bot import net.mamoe.mirai.JavaHappyAPI import net.mamoe.mirai.event.events.* diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessagePacket.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessagePacket.kt index 9e2b6c493..2ae09dcef 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessagePacket.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessagePacket.kt @@ -11,9 +11,9 @@ package net.mamoe.mirai.message -import io.ktor.utils.io.ByteWriteChannel +import kotlinx.coroutines.io.ByteWriteChannel import kotlinx.io.core.Input -import io.ktor.utils.io.core.Output +import kotlinx.io.core.Output import kotlinx.io.core.use import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.QQ diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt index a28d13071..f045ac98f 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt @@ -37,28 +37,32 @@ import java.net.URL * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun <C : Contact> BufferedImage.sendTo(contact: C): MessageReceipt<C> = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) +suspend fun <C : Contact> BufferedImage.sendTo(contact: C): MessageReceipt<C> = + withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) /** * 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun <C : Contact> URL.sendAsImageTo(contact: C): MessageReceipt<C> = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) +suspend fun <C : Contact> URL.sendAsImageTo(contact: C): MessageReceipt<C> = + withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) /** * 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun <C : Contact> Input.sendAsImageTo(contact: C): MessageReceipt<C> = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) +suspend fun <C : Contact> Input.sendAsImageTo(contact: C): MessageReceipt<C> = + withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) /** * 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun <C : Contact> InputStream.sendAsImageTo(contact: C): MessageReceipt<C> = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) +suspend fun <C : Contact> InputStream.sendAsImageTo(contact: C): MessageReceipt<C> = + withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact) /** * 在 [Dispatchers.IO] 中将文件作为图片发送到指定联系人 @@ -79,28 +83,32 @@ suspend fun <C : Contact> File.sendAsImageTo(contact: C): MessageReceipt<C> { * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun BufferedImage.upload(contact: Contact): OfflineImage = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) +suspend fun BufferedImage.upload(contact: Contact): OfflineImage = + withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) /** * 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片上传后构造 [Image] * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun URL.uploadAsImage(contact: Contact): OfflineImage = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) +suspend fun URL.uploadAsImage(contact: Contact): OfflineImage = + withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) /** * 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片上传后构造 [Image] * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Input.uploadAsImage(contact: Contact): OfflineImage = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) +suspend fun Input.uploadAsImage(contact: Contact): OfflineImage = + withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) /** * 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片上传后构造 [Image] * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun InputStream.uploadAsImage(contact: Contact): OfflineImage = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) +suspend fun InputStream.uploadAsImage(contact: Contact): OfflineImage = + withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) /** * 在 [Dispatchers.IO] 中将文件作为图片上传后构造 [Image] @@ -121,7 +129,8 @@ suspend fun File.uploadAsImage(contact: Contact): OfflineImage { * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun <C : Contact> C.sendImage(bufferedImage: BufferedImage): MessageReceipt<C> = bufferedImage.sendTo(this) +suspend inline fun <C : Contact> C.sendImage(bufferedImage: BufferedImage): MessageReceipt<C> = + bufferedImage.sendTo(this) /** * 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片发送到指定联系人 @@ -142,7 +151,8 @@ suspend inline fun <C : Contact> C.sendImage(imageInput: Input): MessageReceipt< * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend inline fun <C : Contact> C.sendImage(imageStream: InputStream): MessageReceipt<C> = imageStream.sendAsImageTo(this) +suspend inline fun <C : Contact> C.sendImage(imageStream: InputStream): MessageReceipt<C> = + imageStream.sendAsImageTo(this) /** * 在 [Dispatchers.IO] 中将文件作为图片发送到指定联系人 diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt index 4f500aac4..20a53c769 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt @@ -11,7 +11,7 @@ package net.mamoe.mirai.utils -import io.ktor.utils.io.ByteReadChannel +import kotlinx.coroutines.io.ByteReadChannel import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.withContext import kotlinx.io.core.Input From 61ca490b5db7f98faf6af6ce2debbf47a3b4ab6f Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Sat, 7 Mar 2020 22:23:10 +0800 Subject: [PATCH 6/9] Rearrange dependencies --- build.gradle.kts | 14 ++++++-------- mirai-core/build.gradle.kts | 31 +++++++++++-------------------- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 41260dc15..583a6598e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,12 +4,11 @@ import java.util.* buildscript { repositories { mavenLocal() - maven { setUrl("https://mirrors.huaweicloud.com/repository/maven") } + maven(url = "https://mirrors.huaweicloud.com/repository/maven") jcenter() - mavenCentral() + // mavenCentral() google() - maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") } - maven { setUrl("https://dl.bintray.com/kotlin/kotlin-dev") } + // maven (url="https://dl.bintray.com/kotlin/kotlin-eap") } dependencies { @@ -41,11 +40,10 @@ allprojects { repositories { mavenLocal() - maven { setUrl("https://mirrors.huaweicloud.com/repository/maven") } + maven(url = "https://mirrors.huaweicloud.com/repository/maven") jcenter() - mavenCentral() + // mavenCentral() google() - maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") } - maven { setUrl("https://dl.bintray.com/kotlin/kotlin-dev") } + // maven (url="https://dl.bintray.com/kotlin/kotlin-eap") } } \ No newline at end of file diff --git a/mirai-core/build.gradle.kts b/mirai-core/build.gradle.kts index 3192a15a4..04871a446 100644 --- a/mirai-core/build.gradle.kts +++ b/mirai-core/build.gradle.kts @@ -52,49 +52,40 @@ kotlin { ) } - jvm("jvm") { + targets { + jvm() + android() } sourceSets { all { languageSettings.enableLanguageFeature("InlineClasses") - languageSettings.useExperimentalAnnotation("kotlin.Experimental") + } + commonMain { dependencies { api(kotlin("stdlib", kotlinVersion)) api(kotlin("serialization", kotlinVersion)) + api(kotlin("reflect", kotlinVersion)) - api("org.jetbrains.kotlinx:atomicfu:$atomicFuVersion") + api(kotlinx("coroutines-core-common", coroutinesVersion)) + api(kotlinx("serialization-runtime-common", serializationVersion)) api(kotlinx("io", kotlinXIoVersion)) api(kotlinx("coroutines-io", coroutinesIoVersion)) api(kotlinx("coroutines-core", coroutinesVersion)) - } - } - commonMain { - dependencies { - api(kotlin("reflect", kotlinVersion)) - api(kotlin("serialization", kotlinVersion)) - api(kotlinx("coroutines-core-common", coroutinesVersion)) - api(kotlinx("serialization-runtime-common", serializationVersion)) - api(ktor("http-cio", ktorVersion)) - api(ktor("http", ktorVersion)) - api(ktor("client-core-jvm", ktorVersion)) + api("org.jetbrains.kotlinx:atomicfu-common:$atomicFuVersion") + api(ktor("client-cio", ktorVersion)) api(ktor("client-core", ktorVersion)) api(ktor("network", ktorVersion)) - //implementation("io.ktor:ktor-io:1.3.0-beta-1") - - //runtimeOnly(files("build/classes/kotlin/metadata/main")) // classpath is not properly set by IDE } } commonTest { dependencies { implementation(kotlin("test-annotations-common")) implementation(kotlin("test-common")) - - //runtimeOnly(files("build/classes/kotlin/metadata/test")) // classpath is not properly set by IDE } } @@ -103,7 +94,6 @@ kotlin { dependencies { api(kotlin("reflect", kotlinVersion)) - api(kotlinx("io", kotlinXIoVersion)) api(kotlinx("io-jvm", kotlinXIoVersion)) api(kotlinx("serialization-runtime", serializationVersion)) api(kotlinx("coroutines-android", coroutinesVersion)) @@ -133,6 +123,7 @@ kotlin { api(kotlinx("io-jvm", kotlinXIoVersion)) api(kotlinx("serialization-runtime", serializationVersion)) api(kotlinx("coroutines-io-jvm", coroutinesIoVersion)) + api(kotlinx("coroutines-core", coroutinesVersion)) api("org.bouncycastle:bcprov-jdk15on:1.64") runtimeOnly(files("build/classes/kotlin/jvm/main")) // classpath is not properly set by IDE From 3d9b598d576ad09efa633b81dfab07dce219dbb5 Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Sat, 7 Mar 2020 22:45:12 +0800 Subject: [PATCH 7/9] Improve Heartbeat --- .../mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt index b5a679e19..3cfa695b7 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt @@ -338,6 +338,14 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler suspend fun doHeartBeat(): Exception? { val lastException: Exception? try { + kotlin.runCatching { + Heartbeat.Alive(bot.client) + .sendAndExpect<Heartbeat.Alive.Response>( + timeoutMillis = bot.configuration.heartbeatTimeoutMillis, + retry = 2 + ) + return null + } Heartbeat.Alive(bot.client) .sendAndExpect<Heartbeat.Alive.Response>( timeoutMillis = bot.configuration.heartbeatTimeoutMillis, From c334321fe1217d604697cf86db1eba87c1dae886 Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Sun, 8 Mar 2020 00:02:10 +0800 Subject: [PATCH 8/9] 0.26.0 --- CHANGELOG.md | 4 ++++ gradle.properties | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af0b5fbf0..f62f4da7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ 开发版本. 频繁更新, 不保证高稳定性 +## `0.26.0` 2020/3/7 +- 使用 `kotlinx.io` 而不是 `ktor.io` +- 修复 #111, #108, #116, #112 + ## `0.25.0` 2020/3/6 - 适配 8.2.7 版本(2020 年 3 月)协议 - 全面的 `Image` 类型: Online/Offline Image, Friend/Group Image diff --git a/gradle.properties b/gradle.properties index c24366539..bddc62b33 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # style guide kotlin.code.style=official # config -miraiVersion=0.25.0 +miraiVersion=0.26.0 kotlin.incremental.multiplatform=true kotlin.parallel.tasks.in.project=true # kotlin From 1b8a87b4cebd4931798534efcf6ccfb3791cd7be Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Sun, 8 Mar 2020 00:08:11 +0800 Subject: [PATCH 9/9] Fix build --- mirai-core/build.gradle.kts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mirai-core/build.gradle.kts b/mirai-core/build.gradle.kts index 04871a446..decb95aa3 100644 --- a/mirai-core/build.gradle.kts +++ b/mirai-core/build.gradle.kts @@ -52,10 +52,7 @@ kotlin { ) } - targets { - jvm() - android() - } + jvm() sourceSets { all {