From 71de716e927776f9e223d9e0034651e6e170dbfb Mon Sep 17 00:00:00 2001 From: Him188 Date: Sun, 8 Mar 2020 20:26:37 +0800 Subject: [PATCH 01/10] Fix compilation bug --- .../src/jvmMain/kotlin/net/mamoe/mirai/utils/MiraiLoggerJvm.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/MiraiLoggerJvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/MiraiLoggerJvm.kt index 7bed2b5b8..17d60ee0d 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/MiraiLoggerJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/MiraiLoggerJvm.kt @@ -15,7 +15,7 @@ import java.util.* /** * JVM 控制台日志实现 */ -actual open class PlatformLogger @JvmOverloads constructor( +actual open class PlatformLogger constructor( override val identity: String? = "Mirai", open val output: (String) -> Unit ) : MiraiLoggerPlatformBase() { From 8bd6dfcf2ca7096642d637a6712c99b1503d13f1 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sun, 8 Mar 2020 20:44:36 +0800 Subject: [PATCH 02/10] Change Retentions --- .../kotlin/net.mamoe.mirai/utils/annotataions.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/annotataions.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/annotataions.kt index 60411fdb3..aa6535a7f 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/annotataions.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/annotataions.kt @@ -17,7 +17,7 @@ import kotlin.annotation.AnnotationTarget.* * 这些 API 可能会在任意时刻更改, 且不会发布任何预警. * 非常不建议在发行版本中使用这些 API. */ -@Retention(AnnotationRetention.BINARY) +@Retention(AnnotationRetention.SOURCE) @RequiresOptIn(level = RequiresOptIn.Level.ERROR) @Target( CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR, @@ -35,7 +35,7 @@ annotation class MiraiInternalAPI( * 这些 API 不具有稳定性, 且可能会在任意时刻更改. * 不建议在发行版本中使用这些 API. */ -@Retention(AnnotationRetention.BINARY) +@Retention(AnnotationRetention.SOURCE) @RequiresOptIn(level = RequiresOptIn.Level.WARNING) @Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR) annotation class MiraiExperimentalAPI( @@ -48,7 +48,7 @@ annotation class MiraiExperimentalAPI( * 这些 API 不具有稳定性, 可能会在任意时刻更改, 并且效率非常低下. * 非常不建议在发行版本中使用这些 API. */ -@Retention(AnnotationRetention.BINARY) +@Retention(AnnotationRetention.SOURCE) @RequiresOptIn(level = RequiresOptIn.Level.WARNING) @Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR) annotation class MiraiDebugAPI( @@ -59,6 +59,6 @@ annotation class MiraiDebugAPI( * 标记一个自 Mirai 某个版本起才支持的 API. */ @Target(CLASS, PROPERTY, FIELD, CONSTRUCTOR, FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER, TYPEALIAS) -@Retention(AnnotationRetention.BINARY) +@Retention(AnnotationRetention.SOURCE) @MustBeDocumented annotation class SinceMirai(val version: String) \ No newline at end of file From 9f988e7d04f8cfbfc898309fa53066fbc053057f Mon Sep 17 00:00:00 2001 From: Him188 Date: Sun, 8 Mar 2020 21:01:31 +0800 Subject: [PATCH 03/10] Remove ImageLink --- .../kotlin/net.mamoe.mirai/data/ImageLink.kt | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 mirai-core/src/commonMain/kotlin/net.mamoe.mirai/data/ImageLink.kt 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 deleted file mode 100644 index 3cef0c4a3..000000000 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/data/ImageLink.kt +++ /dev/null @@ -1,26 +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 - */ - -package net.mamoe.mirai.data - -import io.ktor.client.request.get -import kotlinx.io.core.ByteReadPacket -import kotlinx.io.core.readBytes -import net.mamoe.mirai.utils.Http - -interface ImageLink { - /** - * 原图 - */ - val original: String - - suspend fun downloadAsByteArray(): ByteArray = download().readBytes() - - suspend fun download(): ByteReadPacket = Http.get(original) -} \ No newline at end of file From 243b2ea7318441e2b92e9f46b84ffc232bc265cf Mon Sep 17 00:00:00 2001 From: Him188 Date: Sun, 8 Mar 2020 21:14:41 +0800 Subject: [PATCH 04/10] Gather all platform-specified utilities into a `MiraiPlatformUtils` --- .../net/mamoe/mirai/qqandroid/ContactImpl.kt | 3 +- .../net/mamoe/mirai/qqandroid/QQAndroidBot.kt | 2 +- .../mamoe/mirai/qqandroid/message/messages.kt | 42 ++++- .../qqandroid/network/QQAndroidClient.kt | 3 +- .../qqandroid/network/highway/highway.kt | 3 +- .../network/protocol/packet/PacketFactory.kt | 2 +- .../qqandroid/network/protocol/packet/Tlv.kt | 15 +- .../network/protocol/packet/login/StatSvc.kt | 6 +- .../network/protocol/packet/login/WtLogin.kt | 2 +- .../mamoe/mirai/utils/ExternalImageAndroid.kt | 3 +- .../net/mamoe/mirai/utils/SystemDeviceInfo.kt | 5 + .../mamoe/mirai/utils/cryptor/ECDHAndroid.kt | 4 +- .../net/mamoe/mirai/utils/platformAndroid.kt | 159 +++++++++--------- .../kotlin/net.mamoe.mirai/BotAccount.kt | 4 +- .../net.mamoe.mirai/utils/DeviceInfo.kt | 8 +- .../kotlin/net.mamoe.mirai/utils/platform.kt | 37 ++-- .../net/mamoe/mirai/utils/ExternalImageJvm.kt | 5 +- .../net/mamoe/mirai/utils/PlatformUtilsJvm.kt | 145 +++++++++------- .../net/mamoe/mirai/utils/SystemDeviceInfo.kt | 4 +- .../net/mamoe/mirai/utils/cryptor/ECDHJvm.kt | 6 +- 20 files changed, 271 insertions(+), 187 deletions(-) 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 b73860daa..d67a04053 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 @@ -78,6 +78,7 @@ internal class QQImpl( return MessageReceipt(source, this, null) } + @OptIn(MiraiInternalAPI::class) override suspend fun uploadImage(image: ExternalImage): OfflineFriendImage = try { if (BeforeImageUploadEvent(this, image).broadcast().isCancelled) { throw EventCancelledException("cancelled by BeforeImageUploadEvent.ToGroup") @@ -111,7 +112,7 @@ internal class QQImpl( ImageUploadEvent.Succeed(this@QQImpl, image, it).broadcast() } is LongConn.OffPicUp.Response.RequireUpload -> { - Http.postImage( + MiraiPlatformUtils.Http.postImage( "0x6ff0070", bot.uin, null, 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 af7b7b02f..b87883f51 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 @@ -222,7 +222,7 @@ internal abstract class QQAndroidBotBase constructor( } override suspend fun openChannel(image: Image): ByteReadChannel { - return Http.get(queryImageUrl(image)).content.toKotlinByteReadChannel() + return MiraiPlatformUtils.Http.get(queryImageUrl(image)).content.toKotlinByteReadChannel() } } 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 7a64a5a6e..51a8e7451 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,18 +9,14 @@ package net.mamoe.mirai.qqandroid.message -import kotlinx.io.core.buildPacket -import kotlinx.io.core.discardExact -import kotlinx.io.core.readBytes -import kotlinx.io.core.readUInt +import kotlinx.io.core.* import net.mamoe.mirai.LowLevelAPI import net.mamoe.mirai.contact.Member import net.mamoe.mirai.message.data.* import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgComm -import net.mamoe.mirai.utils.ExternalImage -import net.mamoe.mirai.utils.MiraiDebugAPI -import net.mamoe.mirai.utils.MiraiInternalAPI +import net.mamoe.mirai.utils.* +import net.mamoe.mirai.utils.io.encodeToString import net.mamoe.mirai.utils.io.hexToBytes import net.mamoe.mirai.utils.io.read import net.mamoe.mirai.utils.io.toByteArray @@ -222,7 +218,7 @@ private val atAllData = ImMsgBody.Elem( ) ) -@OptIn(MiraiInternalAPI::class) +@OptIn(MiraiInternalAPI::class, MiraiExperimentalAPI::class) internal fun MessageChain.toRichTextElems(forGroup: Boolean): MutableList { val elements = mutableListOf() @@ -243,6 +239,14 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean): MutableList elements.add( + ImMsgBody.Elem( + richMsg = ImMsgBody.RichMsg( + serviceId = it.serviceId, + template1 = byteArrayOf(1) + MiraiPlatformUtils.zip(it.content.toByteArray()) + ) + ) + ) is OfflineGroupImage -> elements.add(ImMsgBody.Elem(customFace = it.toJceData())) is OnlineGroupImageImpl -> elements.add(ImMsgBody.Elem(customFace = it.delegate)) is OnlineFriendImageImpl -> elements.add(ImMsgBody.Elem(notOnlineImage = it.delegate)) @@ -400,6 +404,28 @@ internal fun List.joinToMessageChain(message: MessageChainBuilde } } } + it.richMsg != null -> { + when (it.richMsg.serviceId) { + 60 -> message.add( + XMLMessage( + content = MiraiPlatformUtils.unzip(it.richMsg.template1, 1).encodeToString() + ) + ) + else -> { + @Suppress("DEPRECATION") + MiraiLogger.debug { + "unknown richMsg.serviceId: ${it.richMsg.serviceId}, content=${it.richMsg.template1.contentToString()}, \ntryUnzip=${ + kotlin.runCatching { + MiraiPlatformUtils.unzip(it.richMsg.template1, 1).encodeToString() + }.getOrElse { "" } + }" + } + } + } + } + else -> { + println(it._miraiContentToString()) + } } } 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 8cf12fb40..3abcf94ee 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 @@ -191,8 +191,9 @@ internal open class QQAndroidClient( lateinit var t104: ByteArray } +@OptIn(MiraiInternalAPI::class) internal fun generateTgtgtKey(guid: ByteArray): ByteArray = - md5(getRandomByteArray(16) + guid) + MiraiPlatformUtils.md5(getRandomByteArray(16) + guid) internal class ReserveUinInfo( 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 b14d0627a..64c570031 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 @@ -26,6 +26,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.io.* import kotlinx.serialization.InternalSerializationApi +import net.mamoe.mirai.utils.MiraiPlatformUtils @OptIn(MiraiInternalAPI::class, InternalSerializationApi::class) internal fun createImageDataPacketSequence( // RequestDataTrans @@ -77,7 +78,7 @@ internal fun createImageDataPacketSequence( // RequestDataTrans dataoffset = offset, filesize = dataSize.toLong(), serviceticket = uKey, - md5 = net.mamoe.mirai.utils.md5(chunkedInput.buffer, 0, chunkedInput.bufferSize), + md5 = MiraiPlatformUtils.md5(chunkedInput.buffer, 0, chunkedInput.bufferSize), fileMd5 = fileMd5, flag = 0, rtcode = 0 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 e260813a4..dfb85b6b3 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 @@ -342,7 +342,7 @@ internal object KnownPacketFactories { 1 -> { input.discardExact(4) input.useBytes { data, length -> - data.unzip(length = length).let { + MiraiPlatformUtils.unzip(data, 0, length).let { val size = it.toInt() if (size == it.size || size == it.size + 4) { it.toReadPacket(offset = 4) 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 7f5d44ac1..e527fe5ce 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 @@ -15,9 +15,10 @@ 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.MiraiInternalAPI +import net.mamoe.mirai.utils.MiraiPlatformUtils import net.mamoe.mirai.utils.currentTimeMillis import net.mamoe.mirai.utils.io.* -import net.mamoe.mirai.utils.md5 import kotlin.random.Random /** @@ -76,6 +77,7 @@ fun BytePacketBuilder.t18( } shouldEqualsTo 22 } +@OptIn(MiraiInternalAPI::class) fun BytePacketBuilder.t106( appId: Long = 16L, subAppId: Long = 537062845L, @@ -96,7 +98,7 @@ fun BytePacketBuilder.t106( guid?.requireSize(16) writeShortLVPacket { - encryptAndWrite(md5(passwordMd5 + ByteArray(4) + (salt.takeIf { it != 0L } ?: uin).toInt().toByteArray())) { + encryptAndWrite(MiraiPlatformUtils.md5(passwordMd5 + ByteArray(4) + (salt.takeIf { it != 0L } ?: uin).toInt().toByteArray())) { writeShort(4)//TGTGTVer writeInt(Random.nextInt()) writeInt(5)//ssoVer @@ -321,12 +323,13 @@ fun BytePacketBuilder.t144( } } +@OptIn(MiraiInternalAPI::class) fun BytePacketBuilder.t109( androidId: ByteArray ) { writeShort(0x109) writeShortLVPacket { - writeFully(md5(androidId)) + writeFully(MiraiPlatformUtils.md5(androidId)) } shouldEqualsTo 16 } @@ -556,21 +559,23 @@ fun BytePacketBuilder.t400( } } +@OptIn(MiraiInternalAPI::class) fun BytePacketBuilder.t187( macAddress: ByteArray ) { writeShort(0x187) writeShortLVPacket { - writeFully(md5(macAddress)) // may be md5 + writeFully(MiraiPlatformUtils.md5(macAddress)) // may be md5 } } +@OptIn(MiraiInternalAPI::class) fun BytePacketBuilder.t188( androidId: ByteArray ) { writeShort(0x188) writeShortLVPacket { - writeFully(md5(androidId)) + writeFully(MiraiPlatformUtils.md5(androidId)) } shouldEqualsTo 16 } 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 67c21ca29..d4f65ae25 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 @@ -23,9 +23,10 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory import net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket import net.mamoe.mirai.qqandroid.utils.NetworkType +import net.mamoe.mirai.utils.MiraiInternalAPI +import net.mamoe.mirai.utils.MiraiPlatformUtils import net.mamoe.mirai.utils.io.encodeToString import net.mamoe.mirai.utils.io.toReadPacket -import net.mamoe.mirai.utils.localIpAddress @Suppress("EnumEntryName") internal enum class RegPushReason { @@ -89,6 +90,7 @@ internal class StatSvc { private const val subAppId = 537062845L + @OptIn(MiraiInternalAPI::class) operator fun invoke( client: QQAndroidClient, regPushReason: RegPushReason = RegPushReason.appRegister @@ -138,7 +140,7 @@ internal class StatSvc { strOSVer = client.device.version.release.encodeToString(), uOldSSOIp = 0, - uNewSSOIp = localIpAddress().split(".").foldIndexed(0L) { index: Int, acc: Long, s: String -> + uNewSSOIp = MiraiPlatformUtils.localIpAddress().split(".").foldIndexed(0L) { index: Int, acc: Long, s: String -> acc or ((s.toLong() shl (index * 16))) }, strVendorName = "MIUI", 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 a08646b24..5b7365394 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 @@ -84,7 +84,7 @@ internal class WtLogin { t8(2052) t104(client.t104) t116(150470524, 66560) - t401(md5(client.device.guid + "stMNokHgxZUGhsYp".toByteArray() + t402)) + t401(MiraiPlatformUtils.md5(client.device.guid + "stMNokHgxZUGhsYp".toByteArray() + t402)) } } } 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 71d3764e2..2f433f224 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 @@ -44,6 +44,7 @@ fun Bitmap.toExternalImage(formatName: String = "gif"): ExternalImage { /** * 读取文件头识别图片属性, 然后构造 [ExternalImage] */ +@OptIn(MiraiInternalAPI::class) @Throws(IOException::class) fun File.toExternalImage(): ExternalImage { val input = BitmapFactory.decodeFile(this.absolutePath) @@ -52,7 +53,7 @@ fun File.toExternalImage(): ExternalImage { return ExternalImage( width = input.width, height = input.height, - md5 = this.inputStream().use { it.md5() }, + md5 = this.inputStream().use { MiraiPlatformUtils.md5(it) }, imageFormat = this.nameWithoutExtension, input = this.inputStream().asInput(IoBuffer.Pool), inputSize = this.length(), 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 7cc35df53..3466ec9b6 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 @@ -21,6 +21,8 @@ import kotlinx.serialization.Transient import kotlinx.serialization.UnstableDefault import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonConfiguration +import net.mamoe.mirai.utils.MiraiPlatformUtils.localIpAddress +import net.mamoe.mirai.utils.MiraiPlatformUtils.md5 import java.io.File /** @@ -102,6 +104,7 @@ actual open class SystemDeviceInfo actual constructor() : DeviceInfo() { (context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager).connectionInfo.ssid.toByteArray() }.getOrElse { byteArrayOf() } + @OptIn(MiraiInternalAPI::class) override val imsiMd5: ByteArray @SuppressLint("HardwareIds") get() = md5(kotlin.runCatching { @@ -117,6 +120,8 @@ actual open class SystemDeviceInfo actual constructor() : DeviceInfo() { (context.applicationContext.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager).deviceId } }.getOrElse { "" } + + @OptIn(MiraiInternalAPI::class) override val ipAddress: ByteArray get() = localIpAddress().split(".").map { it.toByte() }.takeIf { it.size == 4 }?.toByteArray() ?: byteArrayOf() override val androidId: ByteArray get() = Build.ID.toByteArray() override val apn: ByteArray get() = "wifi".toByteArray() diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHAndroid.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHAndroid.kt index 5fe233778..c5b1df78a 100644 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHAndroid.kt +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHAndroid.kt @@ -10,7 +10,8 @@ package net.mamoe.mirai.utils.cryptor import android.annotation.SuppressLint -import net.mamoe.mirai.utils.md5 +import net.mamoe.mirai.utils.MiraiInternalAPI +import net.mamoe.mirai.utils.MiraiPlatformUtils.md5 import java.security.* import java.security.spec.ECGenParameterSpec import java.security.spec.X509EncodedKeySpec @@ -71,6 +72,7 @@ actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) { .genKeyPair()) } + @OptIn(MiraiInternalAPI::class) actual fun calculateShareKey( privateKey: ECDHPrivateKey, publicKey: ECDHPublicKey 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 8cb421f09..e8a1157dd 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 @@ -7,6 +7,8 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ +@file:Suppress("NOTHING_TO_INLINE") + package net.mamoe.mirai.utils import io.ktor.client.HttpClient @@ -15,88 +17,93 @@ import io.ktor.util.KtorExperimentalAPI import kotlinx.io.pool.useInstance import net.mamoe.mirai.utils.io.ByteArrayPool import java.io.ByteArrayOutputStream -import java.io.DataInput -import java.io.EOFException import java.io.InputStream import java.net.InetAddress import java.security.MessageDigest +import java.util.zip.Deflater import java.util.zip.Inflater -/** - * Ktor HttpClient. 不同平台使用不同引擎. - */ -@OptIn(KtorExperimentalAPI::class) -actual val Http: HttpClient - get() = HttpClient(CIO) - -/** - * Localhost 解析 - */ -actual fun localIpAddress(): String = runCatching { - InetAddress.getLocalHost().hostAddress -}.getOrElse { "192.168.1.123" } - -/** - * MD5 算法 - * - * @return 16 bytes - */ -actual fun md5(byteArray: ByteArray, offset: Int, length: Int): ByteArray = - MessageDigest.getInstance("MD5").apply { update(byteArray, offset, length) }.digest() - -fun InputStream.md5(): ByteArray { - val digest = MessageDigest.getInstance("md5") - digest.reset() - this.readInSequence { - digest.update(it.toByte()) - } - return digest.digest() -} - -fun DataInput.md5(): ByteArray { - val digest = MessageDigest.getInstance("md5") - digest.reset() - val buffer = byteArrayOf(1) - while (true) { - try { - this.readFully(buffer) - } catch (e: EOFException) { - break - } - digest.update(buffer[0]) - } - return digest.digest() -} - -private inline fun InputStream.readInSequence(block: (Int) -> Unit) { - var read: Int - while (this.read().also { read = it } != -1) { - block(read) - } -} - -@OptIn(MiraiInternalAPI::class) -actual fun ByteArray.unzip(offset: Int, length: Int): ByteArray { - this.checkOffsetAndLength(offset, length) - if (length == 0) return ByteArray(0) - - val inflater = Inflater() - inflater.reset() - ByteArrayOutputStream().use { output -> - inflater.setInput(this, offset, length) - ByteArrayPool.useInstance { - while (!inflater.finished()) { - output.write(it, 0, inflater.inflate(it)) - } - } - - inflater.end() - return output.toByteArray() - } -} - /** * 时间戳 */ -actual val currentTimeMillis: Long get() = System.currentTimeMillis() \ No newline at end of file +actual val currentTimeMillis: Long get() = System.currentTimeMillis() + +@MiraiInternalAPI +actual object MiraiPlatformUtils { + actual fun unzip(data: ByteArray, offset: Int, length: Int): ByteArray { + data.checkOffsetAndLength(offset, length) + if (length == 0) return ByteArray(0) + + val inflater = Inflater() + inflater.reset() + ByteArrayOutputStream().use { output -> + inflater.setInput(data, offset, length) + ByteArrayPool.useInstance { + while (!inflater.finished()) { + output.write(it, 0, inflater.inflate(it)) + } + } + + inflater.end() + return output.toByteArray() + } + } + + actual fun zip(data: ByteArray, offset: Int, length: Int): ByteArray { + data.checkOffsetAndLength(offset, length) + if (length == 0) return ByteArray(0) + + val inflater = Deflater() + inflater.reset() + ByteArrayOutputStream().use { output -> + inflater.setInput(data, offset, length) + ByteArrayPool.useInstance { + while (!inflater.finished()) { + output.write(it, 0, inflater.deflate(it)) + } + } + + inflater.end() + return output.toByteArray() + } + } + + actual fun md5(data: ByteArray, offset: Int, length: Int): ByteArray { + data.checkOffsetAndLength(offset, length) + return MessageDigest.getInstance("MD5").apply { update(data, offset, length) }.digest() + } + + actual inline fun md5(str: String): ByteArray = md5(str.toByteArray()) + + /** + * Ktor HttpClient. 不同平台使用不同引擎. + */ + @OptIn(KtorExperimentalAPI::class) + actual val Http: HttpClient + get() = HttpClient(CIO) + + /** + * Localhost 解析 + */ + actual fun localIpAddress(): String = runCatching { + InetAddress.getLocalHost().hostAddress + }.getOrElse { "192.168.1.123" } + + fun md5(stream: InputStream): ByteArray { + val digest = MessageDigest.getInstance("md5") + digest.reset() + stream.readInSequence { + digest.update(it.toByte()) + } + return digest.digest() + } + + + private inline fun InputStream.readInSequence(block: (Int) -> Unit) { + var read: Int + while (this.read().also { read = it } != -1) { + block(read) + } + } +} \ No newline at end of file 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 01968d154..c8a87b302 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotAccount.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotAccount.kt @@ -14,7 +14,7 @@ package net.mamoe.mirai import kotlinx.io.core.toByteArray import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.MiraiInternalAPI -import net.mamoe.mirai.utils.md5 +import net.mamoe.mirai.utils.MiraiPlatformUtils import kotlin.annotation.AnnotationTarget.* @MiraiInternalAPI @@ -28,7 +28,7 @@ data class BotAccount( @MiraiInternalAPI val passwordMd5: ByteArray // md5 ) { - constructor(id: Long, passwordPlainText: String) : this(id, md5(passwordPlainText.toByteArray())) + constructor(id: Long, passwordPlainText: String) : this(id, MiraiPlatformUtils.md5(passwordPlainText.toByteArray())) override fun equals(other: Any?): Boolean { if (this === other) return true diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/DeviceInfo.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/DeviceInfo.kt index b44ed6cbb..2000b3889 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/DeviceInfo.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/DeviceInfo.kt @@ -94,6 +94,7 @@ abstract class DeviceInfo { } } +@OptIn(MiraiInternalAPI::class) @Serializable class DeviceInfoData( override val display: ByteArray, @@ -122,7 +123,8 @@ class DeviceInfoData( @OptIn(ExperimentalUnsignedTypes::class) override val ipAddress: ByteArray - get() = localIpAddress().split(".").map { it.toUByte().toByte() }.takeIf { it.size == 4 }?.toByteArray() + get() = MiraiPlatformUtils.localIpAddress().split(".").map { it.toUByte().toByte() }.takeIf { it.size == 4 } + ?.toByteArray() ?: byteArrayOf() override val androidId: ByteArray get() = display @@ -138,7 +140,9 @@ class DeviceInfoData( /** * Defaults "%4;7t>;28` and `ByteArray` internal fun ByteArray.checkOffsetAndLength(offset: Int, length: Int) { 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 20a53c769..47bfd47db 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,8 +11,8 @@ package net.mamoe.mirai.utils -import kotlinx.coroutines.io.ByteReadChannel import kotlinx.coroutines.Dispatchers.IO +import kotlinx.coroutines.io.ByteReadChannel import kotlinx.coroutines.withContext import kotlinx.io.core.Input import kotlinx.io.core.buildPacket @@ -60,6 +60,7 @@ suspend inline fun BufferedImage.suspendToExternalImage(): ExternalImage = withC /** * 读取文件头识别图片属性, 然后构造 [ExternalImage] */ +@OptIn(MiraiInternalAPI::class) @Throws(IOException::class) fun File.toExternalImage(): ExternalImage { val input = ImageIO.createImageInputStream(this) @@ -71,7 +72,7 @@ fun File.toExternalImage(): ExternalImage { return ExternalImage( width = image.getWidth(0), height = image.getHeight(0), - md5 = this.inputStream().md5(), // dont change + md5 = MiraiPlatformUtils.md5(this.inputStream()), // dont change imageFormat = image.formatName, input = this.inputStream(), filename = this.name 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 494cfbe05..1b316fe72 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 @@ -7,78 +7,103 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ -@file:Suppress("EXPERIMENTAL_API_USAGE") +@file:Suppress("EXPERIMENTAL_API_USAGE", "NOTHING_TO_INLINE") package net.mamoe.mirai.utils import io.ktor.client.HttpClient import io.ktor.client.engine.cio.CIO +import io.ktor.util.KtorExperimentalAPI import kotlinx.io.pool.useInstance import net.mamoe.mirai.utils.io.ByteArrayPool -import java.io.* +import java.io.ByteArrayOutputStream +import java.io.InputStream +import java.io.OutputStream import java.net.InetAddress import java.security.MessageDigest +import java.util.zip.Deflater import java.util.zip.Inflater -actual fun md5(byteArray: ByteArray, offset: Int, length: Int): ByteArray = - MessageDigest.getInstance("MD5").apply { update(byteArray, offset, length) }.digest() - -fun InputStream.md5(): ByteArray = this.use { - val digest = MessageDigest.getInstance("md5") - digest.reset() - this.use { input -> - object : OutputStream() { - override fun write(b: Int) { - digest.update(b.toByte()) - } - }.use { output -> - input.copyTo(output) - } - } - return digest.digest() -} - -fun DataInput.md5(): ByteArray { - val digest = MessageDigest.getInstance("md5") - digest.reset() - val buffer = byteArrayOf(1) - while (true) { - try { - this.readFully(buffer) - } catch (e: EOFException) { - break - } - digest.update(buffer[0]) - } - return digest.digest() -} - -actual fun localIpAddress(): String = InetAddress.getLocalHost().hostAddress - -actual val Http: HttpClient get() = HttpClient(CIO) - -@OptIn(MiraiInternalAPI::class) -actual fun ByteArray.unzip(offset: Int, length: Int): ByteArray { - this.checkOffsetAndLength(offset, length) - if (length == 0) return ByteArray(0) - - val inflater = Inflater() - inflater.reset() - ByteArrayOutputStream().use { output -> - inflater.setInput(this, offset, length) - ByteArrayPool.useInstance { - while (!inflater.finished()) { - output.write(it, 0, inflater.inflate(it)) - } - } - - inflater.end() - return output.toByteArray() - } -} - /** * 时间戳 */ actual val currentTimeMillis: Long - get() = System.currentTimeMillis() \ No newline at end of file + get() = System.currentTimeMillis() + +@MiraiInternalAPI +actual object MiraiPlatformUtils { + actual fun unzip(data: ByteArray, offset: Int, length: Int): ByteArray { + data.checkOffsetAndLength(offset, length) + if (length == 0) return ByteArray(0) + + val inflater = Inflater() + inflater.reset() + ByteArrayOutputStream().use { output -> + inflater.setInput(data, offset, length) + ByteArrayPool.useInstance { + while (!inflater.finished()) { + output.write(it, 0, inflater.inflate(it)) + } + } + + inflater.end() + return output.toByteArray() + } + } + + actual fun zip(data: ByteArray, offset: Int, length: Int): ByteArray { + data.checkOffsetAndLength(offset, length) + if (length == 0) return ByteArray(0) + + val inflater = Deflater() + inflater.reset() + ByteArrayOutputStream().use { output -> + inflater.setInput(data, offset, length) + ByteArrayPool.useInstance { + while (!inflater.finished()) { + output.write(it, 0, inflater.deflate(it)) + } + } + + inflater.end() + return output.toByteArray() + } + } + + actual fun md5(data: ByteArray, offset: Int, length: Int): ByteArray { + data.checkOffsetAndLength(offset, length) + return MessageDigest.getInstance("MD5").apply { update(data, offset, length) }.digest() + } + + actual inline fun md5(str: String): ByteArray = md5(str.toByteArray()) + + /** + * Ktor HttpClient. 不同平台使用不同引擎. + */ + @OptIn(KtorExperimentalAPI::class) + actual val Http: HttpClient + get() = HttpClient(CIO) + + /** + * Localhost 解析 + */ + actual fun localIpAddress(): String = runCatching { + InetAddress.getLocalHost().hostAddress + }.getOrElse { "192.168.1.123" } + + fun md5(stream: InputStream): ByteArray { + val digest = MessageDigest.getInstance("md5") + digest.reset() + stream.use { input -> + object : OutputStream() { + override fun write(b: Int) { + digest.update(b.toByte()) + } + }.use { output -> + input.copyTo(output) + } + } + return digest.digest() + } + +} \ No newline at end of file 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 efb5cfd47..c9c6729aa 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 @@ -15,6 +15,8 @@ import kotlinx.serialization.Transient import kotlinx.serialization.UnstableDefault import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonConfiguration +import net.mamoe.mirai.utils.MiraiPlatformUtils.localIpAddress +import net.mamoe.mirai.utils.MiraiPlatformUtils.md5 import net.mamoe.mirai.utils.io.getRandomByteArray import net.mamoe.mirai.utils.io.getRandomString import java.io.File @@ -37,7 +39,7 @@ fun File.loadAsDeviceInfo(context: Context = ContextImpl()): DeviceInfo { private val JSON = Json(JsonConfiguration.Stable) @Serializable -@OptIn(ExperimentalUnsignedTypes::class) +@OptIn(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class) actual open class SystemDeviceInfo actual constructor() : DeviceInfo() { actual constructor(context: Context) : this() { this.context = context diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHJvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHJvm.kt index 67ac25325..3db9de92b 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHJvm.kt @@ -9,7 +9,8 @@ package net.mamoe.mirai.utils.cryptor -import net.mamoe.mirai.utils.md5 +import net.mamoe.mirai.utils.MiraiInternalAPI +import net.mamoe.mirai.utils.MiraiPlatformUtils import org.bouncycastle.jce.provider.BouncyCastleProvider import java.security.* import java.security.spec.ECGenParameterSpec @@ -58,6 +59,7 @@ actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) { .genKeyPair()) } + @OptIn(MiraiInternalAPI::class) actual fun calculateShareKey( privateKey: ECDHPrivateKey, publicKey: ECDHPublicKey @@ -65,7 +67,7 @@ actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) { val instance = KeyAgreement.getInstance("ECDH", "BC") instance.init(privateKey) instance.doPhase(publicKey, true) - return md5(instance.generateSecret()) + return MiraiPlatformUtils.md5(instance.generateSecret()) } actual fun constructPublicKey(key: ByteArray): ECDHPublicKey { From 21abfe4a64d35c24cc53c8611acef48a32b8b2f9 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sun, 8 Mar 2020 22:04:11 +0800 Subject: [PATCH 05/10] Fix zip and unzip --- .../net/mamoe/mirai/utils/platformAndroid.kt | 16 ++++--------- .../PlatformUtilsTest.kt | 24 +++++++++++++++++++ .../net/mamoe/mirai/utils/PlatformUtilsJvm.kt | 16 ++++--------- 3 files changed, 34 insertions(+), 22 deletions(-) create mode 100644 mirai-core/src/commonTest/kotlin/net.mamoe.mirai.utils/PlatformUtilsTest.kt 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 e8a1157dd..54f7f60ba 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 @@ -54,18 +54,12 @@ actual object MiraiPlatformUtils { data.checkOffsetAndLength(offset, length) if (length == 0) return ByteArray(0) - val inflater = Deflater() - inflater.reset() - ByteArrayOutputStream().use { output -> - inflater.setInput(data, offset, length) - ByteArrayPool.useInstance { - while (!inflater.finished()) { - output.write(it, 0, inflater.deflate(it)) - } - } + val deflater = Deflater() + deflater.setInput(data, offset, length) + deflater.finish() - inflater.end() - return output.toByteArray() + ByteArrayPool.useInstance { + return it.take(deflater.deflate(it)).toByteArray().also { deflater.end() } } } diff --git a/mirai-core/src/commonTest/kotlin/net.mamoe.mirai.utils/PlatformUtilsTest.kt b/mirai-core/src/commonTest/kotlin/net.mamoe.mirai.utils/PlatformUtilsTest.kt new file mode 100644 index 000000000..9bf4d397b --- /dev/null +++ b/mirai-core/src/commonTest/kotlin/net.mamoe.mirai.utils/PlatformUtilsTest.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 net.mamoe.mirai.utils + +import kotlinx.io.core.toByteArray +import net.mamoe.mirai.utils.io.encodeToString +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class PlatformUtilsTest { + + @OptIn(MiraiInternalAPI::class) + @Test + fun testZip() { + assertEquals("test", MiraiPlatformUtils.unzip(MiraiPlatformUtils.zip("test".toByteArray())).encodeToString()) + } +} \ No newline at end of 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 1b316fe72..e40057fcd 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt @@ -55,18 +55,12 @@ actual object MiraiPlatformUtils { data.checkOffsetAndLength(offset, length) if (length == 0) return ByteArray(0) - val inflater = Deflater() - inflater.reset() - ByteArrayOutputStream().use { output -> - inflater.setInput(data, offset, length) - ByteArrayPool.useInstance { - while (!inflater.finished()) { - output.write(it, 0, inflater.deflate(it)) - } - } + val deflater = Deflater() + deflater.setInput(data, offset, length) + deflater.finish() - inflater.end() - return output.toByteArray() + ByteArrayPool.useInstance { + return it.take(deflater.deflate(it)).toByteArray().also { deflater.end() } } } From 584b5e9822911970a1cd321bed25e7bcd7d608bf Mon Sep 17 00:00:00 2001 From: Him188 Date: Sun, 8 Mar 2020 22:05:08 +0800 Subject: [PATCH 06/10] xml and Json messages support --- .../mamoe/mirai/qqandroid/message/messages.kt | 28 ++++++-------- .../net.mamoe.mirai/message/data/Json.kt | 24 ++++++++++++ .../message/data/MessageChain.kt | 9 +++-- .../message/data/RichMessage.kt | 29 +++++++++++++++ .../net.mamoe.mirai/message/data/XML.kt | 37 +++++++++++-------- 5 files changed, 92 insertions(+), 35 deletions(-) create mode 100644 mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Json.kt create mode 100644 mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt 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 51a8e7451..bed9a11b5 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 @@ -273,9 +273,9 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean): MutableList()){ - elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = "78 00 F8 01 00 C8 02 00".hexToBytes()))) - // } + if (this.any()) { + elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = "08 09 78 00 C8 01 00 F0 01 00 F8 01 00 90 02 00 C8 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 02 08 03 90 04 80 80 80 10 B8 04 00 C0 04 00".hexToBytes()))) + } else elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = "78 00 F8 01 00 C8 02 00".hexToBytes()))) return elements } @@ -343,6 +343,10 @@ internal class OnlineFriendImageImpl( internal fun MsgComm.Msg.toMessageChain(): MessageChain { val elements = this.msgBody.richText.elems + if (this.msgHead.fromUin == 1040400290L){ + println(this._miraiContentToString()) + } + return buildMessageChain(elements.size + 1) { +MessageSourceFromMsg(delegate = this@toMessageChain) elements.joinToMessageChain(this) @@ -405,27 +409,19 @@ internal fun List.joinToMessageChain(message: MessageChainBuilde } } it.richMsg != null -> { + println(this._miraiContentToString()) + val content = MiraiPlatformUtils.unzip(it.richMsg.template1, 1).encodeToString() when (it.richMsg.serviceId) { - 60 -> message.add( - XMLMessage( - content = MiraiPlatformUtils.unzip(it.richMsg.template1, 1).encodeToString() - ) - ) + 1 -> message.add(JsonMessage(content)) + 60 -> message.add(XmlMessage(content)) else -> { @Suppress("DEPRECATION") MiraiLogger.debug { - "unknown richMsg.serviceId: ${it.richMsg.serviceId}, content=${it.richMsg.template1.contentToString()}, \ntryUnzip=${ - kotlin.runCatching { - MiraiPlatformUtils.unzip(it.richMsg.template1, 1).encodeToString() - }.getOrElse { "" } - }" + "unknown richMsg.serviceId: ${it.richMsg.serviceId}, content=${it.richMsg.template1.contentToString()}, \ntryUnzip=${content}" } } } } - else -> { - println(it._miraiContentToString()) - } } } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Json.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Json.kt new file mode 100644 index 000000000..98407774c --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Json.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 net.mamoe.mirai.message.data + +import net.mamoe.mirai.utils.MiraiExperimentalAPI +import net.mamoe.mirai.utils.SinceMirai + +@SinceMirai("0.27.0") +@OptIn(MiraiExperimentalAPI::class) +class JsonMessage(override val content: String) : RichMessage { + companion object Key : Message.Key + + override val serviceId: Int + get() = 1 + + override fun toString(): String = content +} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt index 8426a0aef..ea61fa3ed 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt @@ -61,7 +61,7 @@ interface MessageChain : Message, Iterable { fun getOrNull(key: Message.Key): M? = firstOrNull(key) /** - * 遍历每一个有内容的消息, 即 [At], [AtAll], [PlainText], [Image], [Face], [XMLMessage], [QuoteReply]. + * 遍历每一个有内容的消息, 即 [At], [AtAll], [PlainText], [Image], [Face], [XmlMessage], [QuoteReply]. * 仅供 `Java` 使用 */ @Suppress("FunctionName", "INAPPLICABLE_JVM_NAME") @@ -73,7 +73,7 @@ interface MessageChain : Message, Iterable { } /** - * 遍历每一个消息, 即 [MessageSource] [At], [AtAll], [PlainText], [Image], [Face], [XMLMessage], [QuoteReply]. + * 遍历每一个消息, 即 [MessageSource] [At], [AtAll], [PlainText], [Image], [Face], [XmlMessage], [QuoteReply]. * 仅供 `Java` 使用 */ @Suppress("FunctionName", "INAPPLICABLE_JVM_NAME") @@ -88,7 +88,7 @@ interface MessageChain : Message, Iterable { // region accessors /** - * 遍历每一个有内容的消息, 即 [At], [AtAll], [PlainText], [Image], [Face], [XMLMessage], [QuoteReply] + * 遍历每一个有内容的消息, 即 [At], [AtAll], [PlainText], [Image], [Face], [XmlMessage], [QuoteReply] */ @JvmSynthetic inline fun MessageChain.foreachContent(block: (Message) -> Unit) { @@ -130,6 +130,9 @@ fun MessageChain.firstOrNull(key: Message.Key): M? = when (key) Face -> first() QuoteReply -> first() MessageSource -> first() + XmlMessage -> first() + JsonMessage -> first() + RichMessage -> first() else -> null } as M? diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt new file mode 100644 index 000000000..27601e147 --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt @@ -0,0 +1,29 @@ +/* + * 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 net.mamoe.mirai.message.data + +import net.mamoe.mirai.utils.MiraiExperimentalAPI +import net.mamoe.mirai.utils.SinceMirai + +/** + * XML 消息等富文本消息 + * + * @see XmlMessage + */ +@SinceMirai("0.27.0") +interface RichMessage : MessageContent { + companion object Key : Message.Key + + @MiraiExperimentalAPI + val serviceId: Int + + @MiraiExperimentalAPI + val content: String +} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/XML.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/XML.kt index fb01e7c6c..55a55303c 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/XML.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/XML.kt @@ -15,6 +15,7 @@ package net.mamoe.mirai.message.data import net.mamoe.mirai.utils.MiraiExperimentalAPI +import net.mamoe.mirai.utils.SinceMirai import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName @@ -23,20 +24,25 @@ import kotlin.jvm.JvmName * * @see buildXMLMessage */ -@MiraiExperimentalAPI -inline class XMLMessage(val stringValue: String) : Message, MessageContent { - override fun followedBy(tail: Message): Nothing = error("XMLMessage Message cannot be followed") - override fun toString(): String = stringValue +@SinceMirai("0.27.0") +@OptIn(MiraiExperimentalAPI::class) +class XmlMessage constructor(override val content: String) : RichMessage { + companion object Key : Message.Key + + override val serviceId: Int get() = 60 + + override fun toString(): String = content } /** * 构造一条 XML 消息 */ -@MiraiExperimentalAPI("还未支持") -inline fun buildXMLMessage(block: @XMLDsl XMLMessageBuilder.() -> Unit): XMLMessage = - XMLMessage(XMLMessageBuilder().apply(block).text) +@SinceMirai("0.27.0") +@MiraiExperimentalAPI +inline fun buildXMLMessage(block: @XMLDsl XMLMessageBuilder.() -> Unit): XmlMessage = + XmlMessage(XMLMessageBuilder().apply(block).text) -@Suppress("NOTHING_TO_INLINE") +@SinceMirai("0.27.0") @XMLDsl class ItemBuilder( var bg: Int = 0, @@ -46,21 +52,20 @@ class ItemBuilder( internal val builder: StringBuilder = StringBuilder() val text: String get() = "$builder" - inline fun summary(text: String, color: String = "#FFFFFF") { + fun summary(text: String, color: String = "#000000") { this.builder.append("$text") } - inline fun title(text: String, size: Int = 18, color: String = "#FFFFFF") { + fun title(text: String, size: Int = 25, color: String = "#000000") { this.builder.append("$text") } - inline fun picture(coverUrl: String) { + fun picture(coverUrl: String) { this.builder.append("") } } @XMLDsl -@Suppress("NOTHING_TO_INLINE") class XMLMessageBuilder( var templateId: Int = 1, var serviceId: Int = 1, @@ -70,7 +75,7 @@ class XMLMessageBuilder( */ var actionData: String = "", /** - * 摘要 + * 摘要, 在官方客户端内消息列表中显示 */ var brief: String = "", var flag: Int = 3, @@ -89,11 +94,11 @@ class XMLMessageBuilder( "" @XMLDsl - inline fun item(block: @XMLDsl ItemBuilder.() -> Unit) { + fun item(block: @XMLDsl ItemBuilder.() -> Unit) { builder.append(ItemBuilder().apply(block).text) } - inline fun source(name: String, iconURL: String = "") { + fun source(name: String, iconURL: String = "") { sourceName = name sourceIconURL = iconURL } @@ -101,4 +106,4 @@ class XMLMessageBuilder( @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE) @DslMarker -internal annotation class XMLDsl \ No newline at end of file +annotation class XMLDsl \ No newline at end of file From a64c0613776124218596d454537d36be4e43af79 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sun, 8 Mar 2020 22:14:59 +0800 Subject: [PATCH 07/10] Support `LightApp` message --- .../mamoe/mirai/qqandroid/message/messages.kt | 20 ++++++++++++++-- .../net.mamoe.mirai/message/data/Json.kt | 5 +--- .../net.mamoe.mirai/message/data/LightApp.kt | 24 +++++++++++++++++++ .../message/data/MessageChain.kt | 1 + .../message/data/RichMessage.kt | 3 --- .../net.mamoe.mirai/message/data/XML.kt | 2 +- 6 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/LightApp.kt 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 bed9a11b5..53b1486b8 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 @@ -239,10 +239,21 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean): MutableList elements.add( + ImMsgBody.Elem( + lightApp = ImMsgBody.LightAppElem( + data = byteArrayOf(1) + MiraiPlatformUtils.zip(it.content.toByteArray()) + ) + ) + ) is RichMessage -> elements.add( ImMsgBody.Elem( richMsg = ImMsgBody.RichMsg( - serviceId = it.serviceId, + serviceId = when (it) { + is XmlMessage -> 60 + is JsonMessage -> 1 + else -> error("unsupported RichMessage") + }, template1 = byteArrayOf(1) + MiraiPlatformUtils.zip(it.content.toByteArray()) ) ) @@ -274,6 +285,7 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean): MutableList()) { + // 08 09 78 00 A0 01 81 DC 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 02 08 03 90 04 80 80 80 10 B8 04 00 C0 04 00 elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = "08 09 78 00 C8 01 00 F0 01 00 F8 01 00 90 02 00 C8 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 02 08 03 90 04 80 80 80 10 B8 04 00 C0 04 00".hexToBytes()))) } else elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = "78 00 F8 01 00 C8 02 00".hexToBytes()))) @@ -343,7 +355,7 @@ internal class OnlineFriendImageImpl( internal fun MsgComm.Msg.toMessageChain(): MessageChain { val elements = this.msgBody.richText.elems - if (this.msgHead.fromUin == 1040400290L){ + if (this.msgHead.fromUin == 1040400290L) { println(this._miraiContentToString()) } @@ -408,6 +420,10 @@ internal fun List.joinToMessageChain(message: MessageChainBuilde } } } + it.lightApp != null -> { + val content = MiraiPlatformUtils.unzip(it.lightApp.data, 1).encodeToString() + message.add(LightApp(content)) + } it.richMsg != null -> { println(this._miraiContentToString()) val content = MiraiPlatformUtils.unzip(it.richMsg.template1, 1).encodeToString() diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Json.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Json.kt index 98407774c..cb8619ca7 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Json.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Json.kt @@ -16,9 +16,6 @@ import net.mamoe.mirai.utils.SinceMirai @OptIn(MiraiExperimentalAPI::class) class JsonMessage(override val content: String) : RichMessage { companion object Key : Message.Key - - override val serviceId: Int - get() = 1 - + // serviceId = 1 override fun toString(): String = content } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/LightApp.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/LightApp.kt new file mode 100644 index 000000000..f5b187b38 --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/LightApp.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 net.mamoe.mirai.message.data + +import net.mamoe.mirai.utils.MiraiExperimentalAPI +import net.mamoe.mirai.utils.SinceMirai + +/** + * 小程序, 如音乐分享 + */ +@OptIn(MiraiExperimentalAPI::class) +@SinceMirai("0.27.0") +class LightApp constructor(override val content: String) : RichMessage { + companion object Key : Message.Key + + override fun toString(): String = content +} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt index ea61fa3ed..a12e28029 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt @@ -133,6 +133,7 @@ fun MessageChain.firstOrNull(key: Message.Key): M? = when (key) XmlMessage -> first() JsonMessage -> first() RichMessage -> first() + LightApp -> first() else -> null } as M? diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt index 27601e147..2363e3dcb 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt @@ -21,9 +21,6 @@ import net.mamoe.mirai.utils.SinceMirai interface RichMessage : MessageContent { companion object Key : Message.Key - @MiraiExperimentalAPI - val serviceId: Int - @MiraiExperimentalAPI val content: String } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/XML.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/XML.kt index 55a55303c..a61c6d535 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/XML.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/XML.kt @@ -29,7 +29,7 @@ import kotlin.jvm.JvmName class XmlMessage constructor(override val content: String) : RichMessage { companion object Key : Message.Key - override val serviceId: Int get() = 60 + // override val serviceId: Int get() = 60 override fun toString(): String = content } From e51cf7ee71d5d774d015bdcaf11b8749f0dd5e65 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sun, 8 Mar 2020 22:16:04 +0800 Subject: [PATCH 08/10] Remove debugging logs --- .../kotlin/net/mamoe/mirai/qqandroid/message/messages.kt | 5 ----- 1 file changed, 5 deletions(-) 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 53b1486b8..870881314 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 @@ -355,10 +355,6 @@ internal class OnlineFriendImageImpl( internal fun MsgComm.Msg.toMessageChain(): MessageChain { val elements = this.msgBody.richText.elems - if (this.msgHead.fromUin == 1040400290L) { - println(this._miraiContentToString()) - } - return buildMessageChain(elements.size + 1) { +MessageSourceFromMsg(delegate = this@toMessageChain) elements.joinToMessageChain(this) @@ -425,7 +421,6 @@ internal fun List.joinToMessageChain(message: MessageChainBuilde message.add(LightApp(content)) } it.richMsg != null -> { - println(this._miraiContentToString()) val content = MiraiPlatformUtils.unzip(it.richMsg.template1, 1).encodeToString() when (it.richMsg.serviceId) { 1 -> message.add(JsonMessage(content)) From 4a0333524b69ccc0addc8ee67e0954346b4eb7f1 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sun, 8 Mar 2020 22:21:10 +0800 Subject: [PATCH 09/10] Update docs and OptIn annotations --- .../commonMain/kotlin/net.mamoe.mirai/message/data/Json.kt | 6 ++++++ .../kotlin/net.mamoe.mirai/message/data/LightApp.kt | 2 +- .../kotlin/net.mamoe.mirai/message/data/RichMessage.kt | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Json.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Json.kt index cb8619ca7..739bd907e 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Json.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Json.kt @@ -12,10 +12,16 @@ package net.mamoe.mirai.message.data import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.SinceMirai +/** + * Json 消息. + * + * @see LightApp 一些消息实际上是 [LightApp] + */ @SinceMirai("0.27.0") @OptIn(MiraiExperimentalAPI::class) class JsonMessage(override val content: String) : RichMessage { companion object Key : Message.Key + // serviceId = 1 override fun toString(): String = content } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/LightApp.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/LightApp.kt index f5b187b38..7c7277d67 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/LightApp.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/LightApp.kt @@ -13,7 +13,7 @@ import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.SinceMirai /** - * 小程序, 如音乐分享 + * 小程序分享, 如音乐分享 */ @OptIn(MiraiExperimentalAPI::class) @SinceMirai("0.27.0") diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt index 2363e3dcb..af967da8e 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt @@ -9,18 +9,18 @@ package net.mamoe.mirai.message.data -import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.SinceMirai /** * XML 消息等富文本消息 * * @see XmlMessage + * @see JsonMessage + * @see LightApp */ @SinceMirai("0.27.0") interface RichMessage : MessageContent { companion object Key : Message.Key - @MiraiExperimentalAPI val content: String } \ No newline at end of file From 454057f56ff1469e617561839d5f2df2daa0dfa8 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sun, 8 Mar 2020 22:22:03 +0800 Subject: [PATCH 10/10] 0.27.0 --- CHANGELOG.md | 3 +++ gradle.properties | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5db46b72f..c5e69ff72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ 开发版本. 频繁更新, 不保证高稳定性 +## `0.27.0` 2020/3/8 +- 支持 `XML`, `Json`, `LightApp` 等 `RichMessage` + ## `0.26.2` 2020/3/8 - 新增 `MessageChain.repeat` 与 `MessageChain.times` - JVM 平台下 `PlatformLogger` 可重定向输出 diff --git a/gradle.properties b/gradle.properties index c50161ef2..0e6d334e3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # style guide kotlin.code.style=official # config -miraiVersion=0.26.2 +miraiVersion=0.27.0 kotlin.incremental.multiplatform=true kotlin.parallel.tasks.in.project=true # kotlin