From 955d2664fd23018f4e954a34dbd29841302dcfa6 Mon Sep 17 00:00:00 2001 From: Him188 Date: Wed, 27 May 2020 22:34:10 +0800 Subject: [PATCH 01/11] Add docs --- .../net.mamoe.mirai/event/events/message.kt | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/message.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/message.kt index f45725a88..d39413381 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/message.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/message.kt @@ -30,6 +30,8 @@ import kotlin.jvm.JvmName /** * 主动发送消息 + * + * @see Contact.sendMessage 发送消息. 为广播这个事件的唯一途径 */ sealed class MessageSendEvent : BotEvent, BotActiveEvent, AbstractEvent() { abstract val target: Contact @@ -54,6 +56,8 @@ sealed class MessageSendEvent : BotEvent, BotActiveEvent, AbstractEvent() { /** * 消息撤回事件. 可是任意消息被任意人撤回. + * + * @see Contact.recall 撤回消息. 为广播这个事件的唯一途径 */ sealed class MessageRecallEvent : BotEvent, AbstractEvent() { /** @@ -127,7 +131,12 @@ val MessageRecallEvent.isByBot: Boolean /** - * 图片上传前. 可以阻止上传 + * 图片上传前. 可以阻止上传. + * + * 此事件总是在 [ImageUploadEvent] 之前广播. + * 若此事件被取消, [ImageUploadEvent] 不会广播. + * + * @see Contact.uploadImage 上传图片. 为广播这个事件的唯一途径 */ data class BeforeImageUploadEvent internal constructor( val target: Contact, @@ -138,7 +147,12 @@ data class BeforeImageUploadEvent internal constructor( } /** - * 图片上传完成 + * 图片上传完成. + * + * 此事件总是在 [BeforeImageUploadEvent] 之后广播. + * 若 [BeforeImageUploadEvent] 被取消, 此事件不会广播. + * + * @see Contact.uploadImage 上传图片. 为广播这个事件的唯一途径 * * @see Succeed * @see Failed From e8b0e0efa507684e6032bb02b111b3f315c8aa07 Mon Sep 17 00:00:00 2001 From: Him188 Date: Thu, 28 May 2020 12:51:30 +0800 Subject: [PATCH 02/11] Update docs --- .../net.mamoe.mirai/message/data/Message.kt | 15 ++++++++++++++- .../message/data/MessageChain.kt | 17 ++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt index ddb5e707b..c97275095 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt @@ -49,7 +49,7 @@ import kotlin.jvm.JvmSynthetic * - 连接 [Message] 与 [Message], [String], (使用操作符 [Message.plus]): * ``` * val text = PlainText("Hello ") + PlainText("world") + "!" - * friend.sendMessage(text) + * friend.sendMessage(text) // "Hello world!" * ``` * 但注意: 不能 `String + Message`. 只能 `Message + String` * @@ -177,18 +177,31 @@ interface Message { // must be interface. Don't consider any changes. } } + /** 将 [another] 按顺序连接到这个消息的尾部. */ /* final */ operator fun plus(another: MessageChain): MessageChain = this + another as Message + + /** 将 [another] 按顺序连接到这个消息的尾部. */ /* final */ operator fun plus(another: Message): MessageChain = this.followedBy(another) + + /** 将 [another] 连接到这个消息的尾部. */ /* final */ operator fun plus(another: SingleMessage): MessageChain = this.followedBy(another) + + /** 将 [another] 作为 [PlainText] 连接到这个消息的尾部. */ /* final */ operator fun plus(another: String): MessageChain = this.followedBy(another.toMessage()) + + /** 将 [another] 作为 [PlainText] 连接到这个消息的尾部. */ /* final */ operator fun plus(another: CharSequence): MessageChain = this.followedBy(another.toString().toMessage()) + + /** 将 [another] 按顺序连接到这个消息的尾部. */ /* final */ operator fun plus(another: Iterable): MessageChain = another.fold(this, Message::plus).asMessageChain() + /** 将 [another] 按顺序连接到这个消息的尾部. */ @JvmName("plusIterableString") /* final */ operator fun plus(another: Iterable): MessageChain = another.fold(this, Message::plus).asMessageChain() + /** 将 [another] 按顺序连接到这个消息的尾部. */ /* final */ operator fun plus(another: Sequence): MessageChain = another.fold(this, Message::plus).asMessageChain() } 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 8710f03a6..1a2d739a6 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 @@ -62,7 +62,22 @@ interface MessageChain : Message, List, RandomAccess { /** * 获取第一个类型为 [key] 的 [Message] 实例. 若不存在此实例, 返回 `null` * + * ### Kotlin 使用方法 + * ``` + * val chain: MessageChain = ... + * + * val at = Message[At] // At 为伴生对象 + * ``` + * + * ### Java 使用方法 + * ```java + * MessageChain chain = ... + * chain.first(At.Key) + * ``` + * * @param key 由各个类型消息的伴生对象持有. 如 [PlainText.Key] + * + * @see MessageChain.getOrFail 在找不到此类型的元素时抛出 [NoSuchElementException] */ @JvmName("first") final operator fun get(key: Message.Key): M? = firstOrNull(key) @@ -93,7 +108,7 @@ interface MessageChain : Message, List, RandomAccess { // region accessors /** - * 获取第一个类型为 [key] 的 [Message] 实例 + * 获取第一个类型为 [key] 的 [Message] 实例, 在找不到此类型的元素时抛出 [NoSuchElementException] * * @param key 由各个类型消息的伴生对象持有. 如 [PlainText.Key] */ From ab6269b3aef6551c1824912ba59294f35807f79c Mon Sep 17 00:00:00 2001 From: Him188 Date: Thu, 28 May 2020 12:53:54 +0800 Subject: [PATCH 03/11] (internal) Extendable Image.originUrl --- .../mirai/qqandroid/QQAndroidBot.common.kt | 14 +--- .../net.mamoe.mirai/message/data/Image.kt | 68 ++++++++++++++----- 2 files changed, 55 insertions(+), 27 deletions(-) diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.common.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.common.kt index b430bb92a..761fb510b 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.common.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.common.kt @@ -721,17 +721,9 @@ internal abstract class QQAndroidBotBase constructor( @Suppress("DEPRECATION", "OverridingDeprecatedMember") override suspend fun queryImageUrl(image: Image): String = when (image) { - is OnlineFriendImageImpl -> image.originUrl - is OnlineGroupImageImpl -> image.originUrl - is OfflineGroupImage -> constructOfflineImageUrl(image) - is OfflineFriendImage -> constructOfflineImageUrl(image) - else -> error("Internal error: unsupported image class: ${image::class.simpleName}") - } - - private fun constructOfflineImageUrl(image: Image): String = when (image) { - is GroupImage -> "http://gchat.qpic.cn/gchatpic_new/${id}/0-0-${image.imageId.substring(1..36) - .replace("-", "")}/0?term=2" - is FriendImage -> "http://c2cpicdw.qpic.cn/offpic_new/${id}/${image.imageId}/0?term=2" + is ConstOriginUrlAware -> image.originUrl + is DeferredOriginUrlAware -> image.getUrl(this) + is SuspendDeferredOriginUrlAware -> image.getUrl(this) else -> error("Internal error: unsupported image class: ${image::class.simpleName}") } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt index b9e4d8d59..bc9d55110 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt @@ -24,9 +24,7 @@ import kotlinx.serialization.Serializable import net.mamoe.mirai.Bot import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Group -import net.mamoe.mirai.utils.ExternalImage -import net.mamoe.mirai.utils.MiraiInternalAPI -import net.mamoe.mirai.utils.PlannedRemoval +import net.mamoe.mirai.utils.* import kotlin.js.JsName import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName @@ -97,19 +95,32 @@ expect interface Image : Message, MessageContent { internal val DoNotImplementThisClass: Nothing? } +internal interface ConstOriginUrlAware : Image { + val originUrl: String +} + +internal interface DeferredOriginUrlAware : Image { + fun getUrl(bot: Bot): String +} + +internal interface SuspendDeferredOriginUrlAware : Image { + suspend fun getUrl(bot: Bot): String +} + /** - * 群图片. - * - * @property imageId 形如 `{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.mirai` (后缀一定为 `".mirai"`) - * @see Image 查看更多说明 + * 由 [ExternalImage] 委托的 [Image] 类型. 用于 [ExternalImage.plus] */ -@PlannedRemoval("1.2.0") // make internal +@SinceMirai("1.1.0") +@MiraiExperimentalAPI("Will be renamed to OfflineImage on 1.2.0") @Suppress("DEPRECATION_ERROR") -// CustomFace -sealed class GroupImage : AbstractImage() { - companion object Key : Message.Key { - override val typeName: String get() = "GroupImage" +internal class ExperimentalDeferredImage internal constructor( + val externalImage: ExternalImage +) : AbstractImage(), SuspendDeferredOriginUrlAware { + override suspend fun getUrl(bot: Bot): String { + TODO() } + + override val imageId: String = externalImage.calculateImageResourceId() } /** @@ -221,12 +232,13 @@ internal const val ONLINE_OFFLINE_DEPRECATION_MESSAGE = """ level = DeprecationLevel.WARNING, replaceWith = ReplaceWith("Image", "net.mamoe.mirai.message.data.Image") ) -interface OnlineImage : Image { +@Suppress("EXPOSED_SUPER_INTERFACE") +interface OnlineImage : Image, ConstOriginUrlAware { companion object Key : Message.Key { override val typeName: String get() = "OnlineImage" } - val originUrl: String + override val originUrl: String } /** @@ -271,7 +283,12 @@ suspend fun OfflineImage.queryUrl(): String { @Serializable data class OfflineGroupImage( override val imageId: String -) : GroupImage(), OfflineImage { +) : GroupImage(), OfflineImage, DeferredOriginUrlAware { + override fun getUrl(bot: Bot): String { + return "http://gchat.qpic.cn/gchatpic_new/${bot.id}/0-0-${imageId.substring(1..36) + .replace("-", "")}/0?term=2" + } + init { @Suppress("DEPRECATION") require(imageId matches GROUP_IMAGE_ID_REGEX) { @@ -305,7 +322,11 @@ abstract class OnlineGroupImage : GroupImage(), OnlineImage @Serializable data class OfflineFriendImage( override val imageId: String -) : FriendImage(), OfflineImage { +) : FriendImage(), OfflineImage, DeferredOriginUrlAware { + override fun getUrl(bot: Bot): String { + return "http://c2cpicdw.qpic.cn/offpic_new/${bot.id}/${this.imageId}/0?term=2" + } + init { require(imageId matches FRIEND_IMAGE_ID_REGEX_1 || imageId matches FRIEND_IMAGE_ID_REGEX_2) { "Illegal imageId. It must matches either FRIEND_IMAGE_ID_REGEX_1 or FRIEND_IMAGE_ID_REGEX_2" @@ -324,6 +345,21 @@ data class OfflineFriendImage( ) abstract class OnlineFriendImage : FriendImage(), OnlineImage + +/** + * 群图片. + * + * @property imageId 形如 `{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.mirai` (后缀一定为 `".mirai"`) + * @see Image 查看更多说明 + */ +@PlannedRemoval("1.2.0") // make internal +@Suppress("DEPRECATION_ERROR") +// CustomFace +sealed class GroupImage : AbstractImage() { + companion object Key : Message.Key { + override val typeName: String get() = "GroupImage" + } +} // endregion From a5d613cf67a45e77f50abafc7376554091b67f6a Mon Sep 17 00:00:00 2001 From: Him188 Date: Thu, 28 May 2020 13:38:49 +0800 Subject: [PATCH 04/11] Add Bot.botInstancesSequence --- mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt | 9 +++++++++ 1 file changed, 9 insertions(+) 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 22a898e2b..9fe0eaa0d 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt @@ -84,6 +84,15 @@ abstract class Bot internal constructor( val botInstances: List get() = _instances.asSequence().mapNotNull { it.get() }.toList() + /** + * 复制一份此时的 [Bot] 实例列表. + */ + @MiraiExperimentalAPI + @SinceMirai("1.1.0") + @JvmStatic + val botInstancesSequence: Sequence + get() = _instances.asSequence().mapNotNull { it.get() } + /** * 遍历每一个 [Bot] 实例 */ From 2bcd1a7a7da80277342c04e706a91ae421cecf7d Mon Sep 17 00:00:00 2001 From: Him188 Date: Thu, 28 May 2020 13:43:35 +0800 Subject: [PATCH 05/11] Add docs --- .../commonMain/kotlin/net.mamoe.mirai/Bot.kt | 12 ++--- .../net.mamoe.mirai/message/MessageEvent.kt | 13 +++-- .../net.mamoe.mirai/message/MessageReceipt.kt | 36 +++++++++++-- .../net.mamoe.mirai/message/data/Image.kt | 14 ++++-- .../message/data/MessageSource.kt | 50 ++++++++++++++----- .../net.mamoe.mirai/utils/ExternalImage.kt | 19 ++++--- .../net/mamoe/mirai/utils/ExternalImageJvm.kt | 17 +++++-- 7 files changed, 120 insertions(+), 41 deletions(-) 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 9fe0eaa0d..348b2b999 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt @@ -209,13 +209,13 @@ abstract class Bot internal constructor( * [Bot] 撤回自己的消息不需要权限. * [Bot] 撤回群员的消息需要管理员权限. * - * @param source 消息源. 可从 [MessageReceipt.source] 获得, 或从消息事件中的 [MessageChain] 获得. + * @param source 消息源. 可从 [MessageReceipt.source] 获得, 或从消息事件中的 [MessageChain] 获得, 或通过 [buildMessageSource] 构建. * - * @throws PermissionDeniedException 当 [Bot] 无权限操作时 - * @throws IllegalStateException 当这条消息已经被撤回时 (仅同步主动操作) + * @throws PermissionDeniedException 当 [Bot] 无权限操作时抛出 + * @throws IllegalStateException 当这条消息已经被撤回时抛出 (仅同步主动操作) * * @see Bot.recall (扩展函数) 接受参数 [MessageChain] - * @see MessageSource.recall + * @see MessageSource.recall 撤回消息扩展 */ @JvmSynthetic abstract suspend fun recall(source: MessageSource) @@ -242,7 +242,7 @@ abstract class Bot internal constructor( * @param fromUin 为用户时为 [Friend.id], 为群时需使用 [Group.calculateGroupUinByGroupCode] 计算 * @param targetUin 为用户时为 [Friend.id], 为群时需使用 [Group.calculateGroupUinByGroupCode] 计算 */ - @MiraiExperimentalAPI + @MiraiExperimentalAPI("This is very experimental and is subject to change.") abstract fun constructMessageSource( kind: OfflineMessageSource.Kind, fromUin: Long, targetUin: Long, @@ -345,7 +345,7 @@ abstract class Bot internal constructor( * 获取 [Job] 的协程 [Job]. 此 [Job] 为一个 [SupervisorJob] */ @get:JvmSynthetic -inline val Bot.supervisorJob: CompletableJob +val Bot.supervisorJob: CompletableJob get() = this.coroutineContext[Job] as CompletableJob /** diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageEvent.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageEvent.kt index 4c71d02b3..ab0325413 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageEvent.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageEvent.kt @@ -77,13 +77,20 @@ abstract class MessageEvent : @PlannedRemoval("1.2.0") ContactMessage(), */ abstract override val senderName: String - /** 消息内容 */ + /** + * 消息内容. + * + * 第一个元素一定为 [MessageSource], 存储此消息的发送人, 发送时间, 收信人, 消息 id 等数据. + * 随后的元素为拥有顺序的真实消息内容. + */ abstract override val message: MessageChain - /** 消息发送时间 (由服务器提供) */ + /** 消息发送时间 (由服务器提供, 可能与本地有时差) */ abstract override val time: Int - /** 消息源 */ + /** + * 消息源. 来自 [message] 的第一个元素, + */ override val source: OnlineMessageSource.Incoming get() = message.source as OnlineMessageSource.Incoming } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt index 160d525ab..ca78c801f 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt @@ -41,7 +41,7 @@ import kotlin.jvm.JvmSynthetic * @see MessageReceipt.sourceId 源 id * @see MessageReceipt.sourceTime 源时间 */ -open class MessageReceipt( +open class MessageReceipt @MiraiExperimentalAPI("The constructor is subject to change.") constructor( /** * 指代发送出去的消息. */ @@ -51,38 +51,68 @@ open class MessageReceipt( */ val target: C, - @MiraiExperimentalAPI + /** + * @see Group.botAsMember + */ + @MiraiExperimentalAPI("This is subject to change.") val botAsMember: Member? ) { /** * 是否为发送给群的消息的回执 */ - val isToGroup: Boolean = target is Group + val isToGroup: Boolean get() = target is Group + /** + * 引用这条消息并回复. + * + * 仅供 Java 使用. + * + * 仅供 Java 使用: `MessageReceipt.quoteReply(message)` + */ @JavaFriendlyAPI @JvmName("quoteReply") fun __quoteReplyBlockingForJava__(message: Message): MessageReceipt { return runBlocking { return@runBlocking quoteReply(message) } } + /** + * 引用这条消息并回复. + * + * 仅供 Java 使用: `MessageReceipt.quoteReply(message)` + */ @JavaFriendlyAPI @JvmName("quoteReply") fun __quoteReplyBlockingForJava__(message: String): MessageReceipt { return runBlocking { quoteReply(message) } } + /** + * 撤回这条消息. [recall] 或 [recallIn] 只能被调用一次. + * + * 仅供 Java 使用: `MessageReceipt.recall()` + */ @JavaFriendlyAPI @JvmName("recall") fun __recallBlockingForJava__() { return runBlocking { recall() } } + /** + * 撤回这条消息. [recall] 或 [recallIn] 只能被调用一次. + * + * 仅供 Java 使用: `MessageReceipt.recallIn(timeMillis)` + */ @JavaFriendlyAPI @JvmName("recallIn") fun __recallInBlockingForJava__(timeMillis: Long): Job { return recallIn(timeMillis = timeMillis) } + /** + * 引用这条消息. + * + * 仅供 Java 使用: `MessageReceipt.quote()` + */ @JavaFriendlyAPI @JvmName("quote") fun __quoteBlockingForJava__(): QuoteReply { diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt index bc9d55110..e72a2b078 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt @@ -20,6 +20,7 @@ package net.mamoe.mirai.message.data +import kotlinx.io.core.copyTo import kotlinx.serialization.Serializable import net.mamoe.mirai.Bot import net.mamoe.mirai.contact.Contact @@ -196,8 +197,8 @@ fun Image(imageId: String): OfflineImage = when { /** * 查询原图下载链接. * - * 当图片为从服务器接收的消息中的图片时, 可以直接获取下载链接, 本函数不会挂起协程. - * 其他情况下协程可能会挂起并向服务器查询下载链接, 或不挂起并拼接一个链接. + * - 当图片为从服务器接收的消息中的图片时, 可以直接获取下载链接, 本函数不会挂起协程. + * - 其他情况下协程可能会挂起并向服务器查询下载链接, 或不挂起并拼接一个链接. * * @return 原图 HTTP 下载链接 (非 HTTPS) * @throws IllegalStateException 当无任何 [Bot] 在线时抛出 (因为无法获取相关协议) @@ -206,12 +207,15 @@ fun Image(imageId: String): OfflineImage = when { suspend fun Image.queryUrl(): String { @Suppress("DEPRECATION") return when (this) { - is OnlineImage -> this.originUrl - else -> Bot._instances.peekFirst()?.get()?.queryImageUrl(this) - ?: error("No Bot available to query image url") + is ConstOriginUrlAware -> this.originUrl + is DeferredOriginUrlAware -> this.getUrl(firstOnlineBotInstance) + is SuspendDeferredOriginUrlAware -> this.getUrl(firstOnlineBotInstance) + else -> error("Internal error: unsupported Image class: ${this::class}") } } +internal val firstOnlineBotInstance: Bot get() = Bot.botInstancesSequence.firstOrNull() ?: error("No Bot available") + ///////////////////////// ///// 以下 API 已弃用 ///// diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt index 02e43c8eb..032ed4878 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt @@ -9,7 +9,7 @@ @file:JvmMultifileClass @file:JvmName("MessageUtils") -@file:Suppress("NOTHING_TO_INLINE", "unused", "INAPPLICABLE_JVM_NAME", "DEPRECATION_ERROR") +@file:Suppress("NOTHING_TO_INLINE", "unused", "INAPPLICABLE_JVM_NAME", "DEPRECATION_ERROR", "UnUsedImport") package net.mamoe.mirai.message.data @@ -18,6 +18,8 @@ import net.mamoe.mirai.Bot import net.mamoe.mirai.contact.* import net.mamoe.mirai.message.MessageEvent import net.mamoe.mirai.message.MessageReceipt +import net.mamoe.mirai.message.quote +import net.mamoe.mirai.message.recall import net.mamoe.mirai.recallIn import net.mamoe.mirai.utils.LazyProperty import kotlin.coroutines.CoroutineContext @@ -27,7 +29,9 @@ import kotlin.jvm.JvmName import kotlin.jvm.JvmSynthetic /** - * 消息源, 它存在于 [MessageChain] 中, 用于表示这个消息的来源. + * 消息源. 消息源存在于 [MessageChain] 中, 用于表示这个消息的来源, 也可以用来分辨 [MessageChain]. + * + * 对于来自 [MessageEvent.message] 的 [MessageChain] * * * ### 组成 @@ -47,6 +51,7 @@ import kotlin.jvm.JvmSynthetic * #### content * - [originalMessage] 消息内容 * + * ### 使用 * * 消息源可用于 [引用回复][QuoteReply] 或 [撤回][Bot.recall]. * @@ -55,6 +60,8 @@ import kotlin.jvm.JvmSynthetic * * @see OnlineMessageSource 在线消息的 [MessageSource] * @see OfflineMessageSource 离线消息的 [MessageSource] + * + * @see buildMessageSource 构造一个 [OfflineMessageSource] */ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle { companion object Key : Message.Key { @@ -344,6 +351,10 @@ inline fun MessageChain.quote(): QuoteReply = QuoteReply(this.source) /** * 撤回这条消息. 可撤回自己 2 分钟内发出的消息, 和任意时间的群成员的消息. * + * **注意:** 仅从服务器接收的消息 (即来自 [MessageEvent.message]), 或手动添加了 [MessageSource] 元素的 [MessageChain] 才可以撤回. + * + * *提示: 若要撤回一条机器人自己发出的消息, 使用 [Contact.sendMessage] 返回的 [MessageReceipt] 中的 [MessageReceipt.recall]* + * * [Bot] 撤回自己的消息不需要权限. * [Bot] 撤回群员的消息需要管理员权限. * @@ -376,55 +387,64 @@ inline fun MessageSource.recallIn( /** * 消息 id. - * 仅从服务器接收的消息才可以获取 + * + * 仅从服务器接收的消息 (即来自 [MessageEvent.message]), 或手动添加了 [MessageSource] 元素的 [MessageChain] 才可以获取消息源. * * @see MessageSource.id */ @get:JvmSynthetic -inline val MessageChain.id: Int +val MessageChain.id: Int get() = this.source.id /** * 消息内部 id. - * 仅从服务器接收的消息才可以获取 + * + * 仅从服务器接收的消息 (即来自 [MessageEvent.message]), 或手动添加了 [MessageSource] 元素的 [MessageChain] 才可以获取消息源. * * @see MessageSource.id */ @get:JvmSynthetic -inline val MessageChain.internalId: Int +val MessageChain.internalId: Int get() = this.source.internalId /** * 消息时间. - * 仅从服务器接收的消息才可以获取 + * + * 仅从服务器接收的消息 (即来自 [MessageEvent.message]), 或手动添加了 [MessageSource] 元素的 [MessageChain] 才可以获取消息源. * * @see MessageSource.id */ @get:JvmSynthetic -inline val MessageChain.time: Int +val MessageChain.time: Int get() = this.source.time /** * 消息内部 id. - * 仅从服务器接收的消息才可以获取 + * + * 仅从服务器接收的消息 (即来自 [MessageEvent.message]), 或手动添加了 [MessageSource] 元素的 [MessageChain] 才可以获取. 否则将抛出异常 [NoSuchElementException] * * @see MessageSource.id */ @get:JvmSynthetic -inline val MessageChain.bot: Bot +val MessageChain.bot: Bot get() = this.source.bot /** - * 获取这条消息源 - * 仅从服务器接收的消息才可以获取消息源 + * 获取这条消息的 [消息源][MessageSource]. + * + * 仅从服务器接收的消息 (即来自 [MessageEvent.message]), 或手动添加了 [MessageSource] 元素的 [MessageChain] 才可以获取消息源, 否则将抛出异常 [NoSuchElementException] */ @get:JvmSynthetic -inline val MessageChain.source: MessageSource +val MessageChain.source: MessageSource get() = this.getOrFail(MessageSource) /** * 撤回这条消息. 可撤回自己 2 分钟内发出的消息, 和任意时间的群成员的消息. * + * **注意:** 仅从服务器接收的消息 (即来自 [MessageEvent.message]), 或手动添加了 [MessageSource] 元素的 [MessageChain] 才可以撤回. + * + * *提示: 若要撤回一条机器人自己发出的消息, 使用 [Contact.sendMessage] 返回的 [MessageReceipt] 中的 [MessageReceipt.recall]* + * * [Bot] 撤回自己的消息不需要权限. * [Bot] 撤回群员的消息需要管理员权限. * @@ -439,6 +459,10 @@ suspend inline fun MessageChain.recall() = this.source.recall() /** * 在一段时间后撤回这条消息. 可撤回自己 2 分钟内发出的消息, 和任意时间的群成员的消息. * + * **注意:** 仅从服务器接收的消息 (即来自 [MessageEvent.message]), 或手动添加了 [MessageSource] 元素的 [MessageChain] 才可以撤回. + * + * *提示: 若要撤回一条机器人自己发出的消息, 使用 [Contact.sendMessage] 返回的 [MessageReceipt] 中的 [MessageReceipt.recall]* + * * [Bot] 撤回自己的消息不需要权限. * [Bot] 撤回群员的消息需要管理员权限. * 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 478894308..679692180 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 @@ -15,11 +15,11 @@ import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.User import net.mamoe.mirai.message.MessageReceipt -import net.mamoe.mirai.message.data.Image -import net.mamoe.mirai.message.data.sendTo +import net.mamoe.mirai.message.data.* import net.mamoe.mirai.utils.internal.DeferredReusableInput import net.mamoe.mirai.utils.internal.ReusableInput import kotlin.jvm.JvmField +import kotlin.jvm.JvmName import kotlin.jvm.JvmSynthetic /** @@ -81,7 +81,10 @@ class ExternalImage internal constructor( */ /** - * 将图片作为单独的消息发送给指定联系人 + * 将图片作为单独的消息发送给指定联系人. + * + * @see Contact.uploadImage 上传图片 + * @see Contact.sendMessage 最终调用, 发送消息. */ @JvmSynthetic suspend fun ExternalImage.sendTo(contact: C): MessageReceipt = when (contact) { @@ -91,10 +94,12 @@ suspend fun ExternalImage.sendTo(contact: C): MessageReceipt = } /** - * 上传图片并通过图片 ID 构造 [Image] - * 这个函数可能需消耗一段时间 + * 上传图片并构造 [Image]. + * 这个函数可能需消耗一段时间. * - * @see contact 图片上传对象. 由于好友图片与群图片不通用, 上传时必须提供目标联系人 + * @param contact 图片上传对象. 由于好友图片与群图片不通用, 上传时必须提供目标联系人 + * + * @see Contact.uploadImage 最终调用, 上传图片. */ @JvmSynthetic suspend fun ExternalImage.upload(contact: Contact): Image = when (contact) { @@ -105,6 +110,8 @@ suspend fun ExternalImage.upload(contact: Contact): Image = when (contact) { /** * 将图片作为单独的消息发送给 [this] + * + * @see Contact.sendMessage 最终调用, 发送消息. */ @JvmSynthetic suspend inline fun C.sendImage(image: ExternalImage): MessageReceipt = image.sendTo(this) 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 52ce17c6c..d9f1b5ea4 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 @@ -13,6 +13,8 @@ package net.mamoe.mirai.utils import kotlinx.io.core.Input import net.mamoe.mirai.Bot +import net.mamoe.mirai.message.data.Message +import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.utils.internal.DeferredReusableInput import net.mamoe.mirai.utils.internal.asReusableInput import java.awt.image.BufferedImage @@ -64,21 +66,26 @@ fun Input.toExternalImage(): ExternalImage = ExternalImage(DeferredReusableInput @PlannedRemoval("1.2.0") +@Suppress("RedundantSuspendModifier") @Deprecated("no need", ReplaceWith("toExternalImage()")) -fun Input.suspendToExternalImage(): ExternalImage = toExternalImage() +suspend fun Input.suspendToExternalImage(): ExternalImage = toExternalImage() +@Suppress("RedundantSuspendModifier") @PlannedRemoval("1.2.0") @Deprecated("no need", ReplaceWith("toExternalImage()")) -fun InputStream.suspendToExternalImage(): ExternalImage = toExternalImage() +suspend fun InputStream.suspendToExternalImage(): ExternalImage = toExternalImage() +@Suppress("RedundantSuspendModifier") @PlannedRemoval("1.2.0") @Deprecated("no need", ReplaceWith("toExternalImage()")) -fun URL.suspendToExternalImage(): ExternalImage = toExternalImage() +suspend fun URL.suspendToExternalImage(): ExternalImage = toExternalImage() +@Suppress("RedundantSuspendModifier") @PlannedRemoval("1.2.0") @Deprecated("no need", ReplaceWith("toExternalImage()")) -fun File.suspendToExternalImage(): ExternalImage = toExternalImage() +suspend fun File.suspendToExternalImage(): ExternalImage = toExternalImage() +@Suppress("RedundantSuspendModifier") @PlannedRemoval("1.2.0") @Deprecated("no need", ReplaceWith("toExternalImage()")) -fun BufferedImage.suspendToExternalImage(): ExternalImage = toExternalImage() +suspend fun BufferedImage.suspendToExternalImage(): ExternalImage = toExternalImage() From 507b35dcb7cb82d4398340f5c100a5fbf0135cf6 Mon Sep 17 00:00:00 2001 From: Him188 Date: Thu, 28 May 2020 13:44:53 +0800 Subject: [PATCH 06/11] Rearrange internal implementations --- .../utils/FileCacheStrategy.common.kt | 26 +++++++++---------- .../utils/internal/ReusableInput.kt | 6 +++++ .../utils/internal/md5.common.kt | 2 +- .../mirai/utils/FileCacheStrategy.jvm.kt | 22 ++++++---------- .../utils/internal/asReusableInput.jvm.kt | 15 +++++++++++ .../net/mamoe/mirai/utils/internal/md5.jvm.kt | 1 + 6 files changed, 43 insertions(+), 29 deletions(-) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/FileCacheStrategy.common.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/FileCacheStrategy.common.kt index f18ab7d6f..95a7dba1e 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/FileCacheStrategy.common.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/FileCacheStrategy.common.kt @@ -1,8 +1,11 @@ package net.mamoe.mirai.utils +import kotlinx.io.core.Closeable import kotlinx.io.core.Input +import kotlinx.io.core.use import kotlinx.io.errors.IOException -import net.mamoe.mirai.utils.internal.InputStream +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract /** * 缓存策略. @@ -19,14 +22,6 @@ expect interface FileCacheStrategy { @Throws(IOException::class) fun newImageCache(input: Input): ExternalImage - /** - * 将 [input] 缓存为 [ExternalImage]. - * 此函数应 close 这个 [InputStream] - */ - @MiraiExperimentalAPI - @Throws(IOException::class) - fun newImageCache(input: InputStream): ExternalImage - /** * 将 [input] 缓存为 [ExternalImage]. * 此 [input] 的内容应是不变的. @@ -49,12 +44,15 @@ expect interface FileCacheStrategy { @Throws(IOException::class) override fun newImageCache(input: Input): ExternalImage - @MiraiExperimentalAPI - @Throws(IOException::class) - override fun newImageCache(input: InputStream): ExternalImage - @MiraiExperimentalAPI @Throws(IOException::class) override fun newImageCache(input: ByteArray): ExternalImage } -} \ No newline at end of file +} + +internal inline fun I.withOut(output: O, block: I.(output: O) -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return use { output.use { block(this, output) } } +} diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/internal/ReusableInput.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/internal/ReusableInput.kt index 3f560243f..52c176589 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/internal/ReusableInput.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/internal/ReusableInput.kt @@ -1,6 +1,7 @@ package net.mamoe.mirai.utils.internal import io.ktor.utils.io.ByteWriteChannel +import kotlinx.io.core.Input internal interface ReusableInput { val md5: ByteArray @@ -8,4 +9,9 @@ internal interface ReusableInput { fun chunkedFlow(sizePerPacket: Int): ChunkedFlowSession suspend fun writeTo(out: ByteWriteChannel): Long + + /** + * Remember to close. + */ + fun asInput(): Input } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/internal/md5.common.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/internal/md5.common.kt index 6a30b73ac..1519fa8e8 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/internal/md5.common.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/internal/md5.common.kt @@ -5,7 +5,7 @@ package net.mamoe.mirai.utils.internal import kotlinx.io.pool.DefaultPool import kotlinx.io.pool.ObjectPool -expect abstract class InputStream { +internal expect abstract class InputStream { open fun available(): Int open fun close() abstract fun read(): Int diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/FileCacheStrategy.jvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/FileCacheStrategy.jvm.kt index 3b499c55c..2ddcb56d3 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/FileCacheStrategy.jvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/FileCacheStrategy.jvm.kt @@ -2,10 +2,9 @@ package net.mamoe.mirai.utils -import kotlinx.io.core.Closeable -import kotlinx.io.core.Input -import kotlinx.io.core.readAvailable -import kotlinx.io.core.readBytes +import kotlinx.io.core.* +import kotlinx.io.streams.asInput +import kotlinx.io.streams.asOutput import net.mamoe.mirai.Bot import net.mamoe.mirai.utils.internal.InputStream import net.mamoe.mirai.utils.internal.asReusableInput @@ -16,10 +15,11 @@ import java.io.IOException import java.io.OutputStream import java.net.URL import java.security.MessageDigest +import java.util.* import javax.imageio.ImageIO -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract +import kotlin.io.use /** * 缓存策略. @@ -44,7 +44,7 @@ actual interface FileCacheStrategy { */ @MiraiExperimentalAPI @Throws(IOException::class) - actual fun newImageCache(input: InputStream): ExternalImage + fun newImageCache(input: InputStream): ExternalImage /** * 将 [input] 缓存为 [ExternalImage]. @@ -87,7 +87,7 @@ actual interface FileCacheStrategy { @MiraiExperimentalAPI @Throws(IOException::class) - actual override fun newImageCache(input: InputStream): ExternalImage { + override fun newImageCache(input: InputStream): ExternalImage { return newImageCache(input.readBytes()) } @@ -186,12 +186,6 @@ actual interface FileCacheStrategy { } } -internal inline fun I.withOut(output: O, block: I.(output: O) -> R): R { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - return use { output.use { block(this, output) } } -} @Throws(IOException::class) internal fun Input.copyTo(out: OutputStream, bufferSize: Int = DEFAULT_BUFFER_SIZE): Long { @@ -204,4 +198,4 @@ internal fun Input.copyTo(out: OutputStream, bufferSize: Int = DEFAULT_BUFFER_SI bytes = readAvailable(buffer) } return bytesCopied -} +} \ No newline at end of file diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/internal/asReusableInput.jvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/internal/asReusableInput.jvm.kt index 168b043f8..349ccac39 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/internal/asReusableInput.jvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/internal/asReusableInput.jvm.kt @@ -4,6 +4,9 @@ import io.ktor.utils.io.ByteWriteChannel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.withContext +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.Input +import kotlinx.io.streams.asInput import net.mamoe.mirai.message.data.toLongUnsigned import java.io.File import java.io.InputStream @@ -28,6 +31,10 @@ internal actual fun ByteArray.asReusableInput(): ReusableInput { out.flush() return this@asReusableInput.size.toLongUnsigned() } + + override fun asInput(): Input { + return ByteReadPacket(this@asReusableInput) + } } } @@ -50,6 +57,10 @@ internal fun File.asReusableInput(deleteOnClose: Boolean): ReusableInput { override suspend fun writeTo(out: ByteWriteChannel): Long { return inputStream().use { it.copyTo(out) } } + + override fun asInput(): Input { + return inputStream().asInput() + } } } @@ -72,6 +83,10 @@ internal fun File.asReusableInput(deleteOnClose: Boolean, md5: ByteArray): Reusa override suspend fun writeTo(out: ByteWriteChannel): Long { return inputStream().use { it.copyTo(out) } } + + override fun asInput(): Input { + return inputStream().asInput() + } } } diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/internal/md5.jvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/internal/md5.jvm.kt index 3e997fb4b..3b08a5a90 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/internal/md5.jvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/internal/md5.jvm.kt @@ -19,4 +19,5 @@ internal actual fun InputStream.md5(): ByteArray { return digest.digest() } +@Suppress("ACTUAL_WITHOUT_EXPECT") internal actual typealias InputStream = java.io.InputStream \ No newline at end of file From 0c169d0068f54a6775129bd3beb97b8cba13fce1 Mon Sep 17 00:00:00 2001 From: Him188 Date: Thu, 28 May 2020 13:50:52 +0800 Subject: [PATCH 07/11] Improve stability, returns -1 for sequenceId when failed to fetch from server --- .../net/mamoe/mirai/qqandroid/message/outgoingSourceImpl.kt | 4 ++-- .../kotlin/net.mamoe.mirai/message/data/MessageSource.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/outgoingSourceImpl.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/outgoingSourceImpl.kt index b26951e7b..d79de032b 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/outgoingSourceImpl.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/outgoingSourceImpl.kt @@ -128,8 +128,8 @@ internal class MessageSourceToGroupImpl( @OptIn(ExperimentalCoroutinesApi::class) override val sequenceId: Int get() = when { - sequenceIdDeferred.isCompleted -> sequenceIdDeferred.getCompleted() ?: 0 - !sequenceIdDeferred.isActive -> 0 + sequenceIdDeferred.isCompleted -> sequenceIdDeferred.getCompleted() ?: -1 + !sequenceIdDeferred.isActive -> -1 else -> error("sequenceId not yet available") } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt index 032ed4878..a4ad9dad4 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt @@ -76,7 +76,7 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle Date: Thu, 28 May 2020 13:51:06 +0800 Subject: [PATCH 08/11] Improve performance when log is disabled --- .../protocol/packet/chat/receive/OnlinePush.PbPushGroupMsg.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.PbPushGroupMsg.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.PbPushGroupMsg.kt index 7c07f466d..0610d1b44 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.PbPushGroupMsg.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.PbPushGroupMsg.kt @@ -8,6 +8,7 @@ */ @file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") + package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive import kotlinx.io.core.ByteReadPacket @@ -32,6 +33,7 @@ import net.mamoe.mirai.qqandroid.utils._miraiContentToString import net.mamoe.mirai.qqandroid.utils.encodeToString import net.mamoe.mirai.qqandroid.utils.io.serialization.loadAs import net.mamoe.mirai.qqandroid.utils.io.serialization.readProtoBuf +import net.mamoe.mirai.utils.warning /** * 接受群消息 @@ -106,7 +108,7 @@ internal object OnlinePushPbPushGroupMsg : IncomingPacketFactory("Onlin flags and 8 != 0 -> MemberPermission.OWNER flags == 0 -> MemberPermission.MEMBER else -> { - bot.logger.warning("判断群 ${sender.group.id} 的群员 ${sender.id} 的权限失败: ${flags._miraiContentToString()}. 请完整截图或复制此日志并确认其真实权限后发送给 mirai 维护者以帮助解决问题.") + bot.logger.warning { "判断群 ${sender.group.id} 的群员 ${sender.id} 的权限失败: ${flags._miraiContentToString()}. 请完整截图或复制此日志并确认其真实权限后发送给 mirai 维护者以帮助解决问题." } sender.permission } }, From ddf8ecf744649256e185fedee70ef314b8ebbcaa Mon Sep 17 00:00:00 2001 From: Him188 Date: Thu, 28 May 2020 13:54:19 +0800 Subject: [PATCH 09/11] Fix build --- .../mamoe/mirai/utils/internal/DeferredReusableInput.jvm.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/internal/DeferredReusableInput.jvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/internal/DeferredReusableInput.jvm.kt index 8373e3543..94fda1183 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/internal/DeferredReusableInput.jvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/internal/DeferredReusableInput.jvm.kt @@ -5,7 +5,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import kotlinx.io.core.Input import net.mamoe.mirai.utils.FileCacheStrategy -import net.mamoe.mirai.utils.MiraiExperimentalAPI import java.awt.image.BufferedImage import java.net.URL @@ -45,5 +44,9 @@ internal actual class DeferredReusableInput actual constructor( return delegate?.writeTo(out) ?: error("DeferredReusableInput not yet initialized") } + override fun asInput(): Input { + return delegate?.asInput() ?: error("DeferredReusableInput not yet initialized") + } + actual val initialized: Boolean get() = delegate != null } \ No newline at end of file From 637e43ac2ef8a254c1a74af02675d4ea785b8754 Mon Sep 17 00:00:00 2001 From: Him188 Date: Thu, 28 May 2020 14:00:55 +0800 Subject: [PATCH 10/11] Mark `PttMessage` and `Voice` with `@MiraiExperimentalAPI` --- .../commonMain/kotlin/net.mamoe.mirai/message/data/Voice.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Voice.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Voice.kt index 244c2608b..444c3f8a8 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Voice.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Voice.kt @@ -1,8 +1,11 @@ package net.mamoe.mirai.message.data +import net.mamoe.mirai.utils.MiraiExperimentalAPI + /** * 需要通过上传到服务器的消息,如语音、文件 */ +@MiraiExperimentalAPI abstract class PttMessage : MessageContent { companion object Key : Message.Key { @@ -18,6 +21,7 @@ abstract class PttMessage : MessageContent { /** * 语音消息, 目前只支持接收和转发 */ +@MiraiExperimentalAPI class Voice( override val fileName: String, override val md5: ByteArray, From db38750e1d215fd899030e6f6e6b6e6099ac77e1 Mon Sep 17 00:00:00 2001 From: Him188 Date: Thu, 28 May 2020 14:03:25 +0800 Subject: [PATCH 11/11] Remove `@ExperimentalCoroutinesApi` since `Flow.fold` is now stable --- .../commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt index c97275095..9da5c4e3f 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt @@ -17,7 +17,6 @@ package net.mamoe.mirai.message.data -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.fold import net.mamoe.mirai.contact.Contact @@ -208,7 +207,6 @@ interface Message { // must be interface. Don't consider any changes. @MiraiExperimentalAPI @JvmSynthetic -@ExperimentalCoroutinesApi suspend inline operator fun Message.plus(another: Flow): MessageChain = another.fold(this) { acc, it -> acc + it }.asMessageChain()