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 af5152c68..cda099b25 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 @@ -24,10 +24,7 @@ import kotlinx.serialization.UnstableDefault import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonConfiguration import kotlinx.serialization.json.int -import net.mamoe.mirai.Bot -import net.mamoe.mirai.BotImpl -import net.mamoe.mirai.LowLevelAPI -import net.mamoe.mirai.ThisApiMustBeUsedInWithConnectionLockBlock +import net.mamoe.mirai.* import net.mamoe.mirai.contact.* import net.mamoe.mirai.data.* import net.mamoe.mirai.event.broadcast @@ -82,10 +79,18 @@ internal class QQAndroidBot constructor( @OptIn(LowLevelAPI::class) override suspend fun acceptNewFriendRequest(event: NewFriendRequestEvent) { + check(event.bot === this) { + "the request $event is from Bot ${event.bot.id} but you are responding with bot ${this.id}" + } + check(event.responded.compareAndSet(false, true)) { "the request $this has already been responded" } + check(!friends.contains(event.fromId)) { + "the request $event is outdated: You had already responded it on another device." + } + network.run { NewContact.SystemMsgNewFriend.Action( bot.client, @@ -100,8 +105,16 @@ internal class QQAndroidBot constructor( } override suspend fun rejectNewFriendRequest(event: NewFriendRequestEvent, blackList: Boolean) { + check(event.bot === this) { + "the request $event is from Bot ${event.bot.id} but you are responding with bot ${this.id}" + } + check(event.responded.compareAndSet(false, true)) { - "the request $this has already been responded" + "the request $event has already been responded" + } + + check(!friends.contains(event.fromId)) { + "the request $event is outdated: You had already responded it on another device." } network.run { @@ -116,10 +129,16 @@ internal class QQAndroidBot constructor( @OptIn(LowLevelAPI::class) override suspend fun acceptMemberJoinRequest(event: MemberJoinRequestEvent) { + @Suppress("DuplicatedCode") + checkGroupPermission(event.bot, event.group) { event::class.simpleName ?: "" } check(event.responded.compareAndSet(false, true)) { "the request $this has already been responded" } + check(!event.group.members.contains(event.fromId)) { + "the request $this is outdated: Another operator has already responded it." + } + network.run { NewContact.SystemMsgNewGroup.Action( bot.client, @@ -137,11 +156,17 @@ internal class QQAndroidBot constructor( } } + @Suppress("DuplicatedCode") @OptIn(LowLevelAPI::class) override suspend fun rejectMemberJoinRequest(event: MemberJoinRequestEvent, blackList: Boolean) { + checkGroupPermission(event.bot, event.group) { event::class.simpleName ?: "" } check(event.responded.compareAndSet(false, true)) { "the request $this has already been responded" } + + check(!event.group.members.contains(event.fromId)) { + "the request $this is outdated: Another operator has already responded it." + } network.run { NewContact.SystemMsgNewGroup.Action( bot.client, @@ -152,7 +177,22 @@ internal class QQAndroidBot constructor( } } + private inline fun checkGroupPermission(eventBot: Bot, eventGroup: Group, eventName: () -> String) { + val group = this.getGroupOrNull(eventGroup.id) + ?: kotlin.run { + if (this == eventBot) { + error("A ${eventName()} is outdated. Group ${eventGroup.id} not found for bot ${this.id}. " + + "This is because bot isn't in the group anymore") + } else { + error("A ${eventName()} is from bot ${eventBot.id}, but you are trying to respond it using bot ${this.id} who isn't a member of the group ${eventGroup.id}") + } + } + + group.checkBotPermissionOperator() + } + override suspend fun ignoreMemberJoinRequest(event: MemberJoinRequestEvent, blackList: Boolean) { + checkGroupPermission(event.bot, event.group) { event::class.simpleName ?: "" } check(event.responded.compareAndSet(false, true)) { "the request $this has already been responded" } 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 dd690c85f..78897648c 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 @@ -44,7 +44,7 @@ import kotlin.jvm.JvmSynthetic @OptIn(MiraiInternalAPI::class) open class MessageReceipt( /** - * 指代发送出去的消息 + * 指代发送出去的消息. */ val source: OnlineMessageSource.Outgoing, /** diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/AtAll.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/AtAll.kt index d5385162d..6a127cc42 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/AtAll.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/AtAll.kt @@ -12,11 +12,9 @@ package net.mamoe.mirai.message.data -import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.SinceMirai import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName -import kotlin.jvm.JvmSynthetic private const val displayA = "@全体成员" @@ -50,15 +48,6 @@ object AtAll : } // 自动为消息补充 " " - @OptIn(MiraiInternalAPI::class) - @Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) - @Suppress("INAPPLICABLE_JVM_NAME", "EXPOSED_FUNCTION_RETURN_TYPE") - @JvmName("followedBy") - @JvmSynthetic - override fun followedBy1(tail: Message): CombinedMessage { - return followedByInternalForBinaryCompatibility(tail) - } - override fun followedBy(tail: Message): MessageChain { if (tail is PlainText && tail.stringValue.startsWith(' ')) { return super.followedBy(tail) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/HummerMessage.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/HummerMessage.kt index cb544f1f1..edb23949a 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/HummerMessage.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/HummerMessage.kt @@ -8,6 +8,8 @@ */ @file:Suppress("unused", "NOTHING_TO_INLINE") +@file:JvmMultifileClass +@file:JvmName("MessageUtils") // since 0.39.1 package net.mamoe.mirai.message.data @@ -15,10 +17,7 @@ import net.mamoe.mirai.message.data.PokeMessage.Types import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.SinceMirai -import kotlin.jvm.JvmField -import kotlin.jvm.JvmName -import kotlin.jvm.JvmStatic -import kotlin.jvm.JvmSynthetic +import kotlin.jvm.* /** * 一些特殊的消息 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 33140a9e2..634ad1c04 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 @@ -19,7 +19,6 @@ import net.mamoe.mirai.Bot import net.mamoe.mirai.BotImpl 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.SinceMirai @@ -38,7 +37,7 @@ import kotlin.jvm.JvmSynthetic * * ### [toString] 和 [contentToString] * - [toString] 固定返回 `[mirai:image:]` 格式字符串, 其中 `` 代表 [imageId]. - * - [contentToString] 固定返回 `"[图片]"` + * - [contentToString] 固定返回 ```"[图片]"``` * * ### 上传和发送图片 * @see Contact.uploadImage 上传 [图片文件][ExternalImage] 并得到 [Image] 消息 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 b0bbc6b29..a9d428bd6 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 @@ -8,6 +8,8 @@ */ @file:Suppress("MemberVisibilityCanBePrivate", "unused", "EXPERIMENTAL_API_USAGE", "NOTHING_TO_INLINE") +@file:JvmMultifileClass +@file:JvmName("MessageUtils") package net.mamoe.mirai.message.data @@ -17,6 +19,7 @@ import net.mamoe.mirai.message.data.Message.Key import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.PlannedRemoval import net.mamoe.mirai.utils.SinceMirai +import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName import kotlin.jvm.JvmSynthetic @@ -313,6 +316,8 @@ interface SingleMessage : Message, CharSequence, Comparable { /** * 消息元数据, 即不含内容的元素. * + * 所有子类的 [contentToString] 都应该返回空字符串. + * * @see MessageSource 消息源 * @see QuoteReply 引用回复 * @see CustomMessageMetadata 自定义元数据 @@ -328,11 +333,12 @@ interface MessageMetadata : SingleMessage { /** * 约束一个 [MessageChain] 中只存在这一种类型的元素. 新元素将会替换旧元素, 保持原顺序. + * * 实现此接口的元素将会在连接时自动处理替换. */ @SinceMirai("0.34.0") interface ConstrainSingle : MessageMetadata { - val key: Message.Key + val key: Key } /** 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 dc2eb87fc..2cb94afaa 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 @@ -142,9 +142,7 @@ inline fun MessageChain.allContent(block: (MessageContent) -> Boolean): Boolean this.forEach { if (it !is MessageMetadata) { check(it is MessageContent) { "internal error: Message must be either MessageMetaData or MessageContent" } - if (!block(it)) { - return false - } + if (!block(it)) return false } } return true @@ -158,9 +156,7 @@ inline fun MessageChain.noneContent(block: (MessageContent) -> Boolean): Boolean this.forEach { if (it !is MessageMetadata) { check(it is MessageContent) { "internal error: Message must be either MessageMetaData or MessageContent" } - if (block(it)) { - return false - } + if (block(it)) return false } } return true 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 bf590985d..9bc377265 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 @@ -29,6 +29,25 @@ import kotlin.jvm.JvmSynthetic /** * 消息源, 它存在于 [MessageChain] 中, 用于表示这个消息的来源. * + * + * ### 组成 + * MessageSource 由 metadata (元数据), form & target, content 组成 + * + * #### metadata + * - [id] 消息 id (序列号) + * - [internalId] 消息内部 id + * - [time] 时间 + * + * 官方客户端通过 metadata 这三个数据定位消息, 撤回和引用回复都是如此. + * + * #### form & target + * - [fromId] 消息发送人 + * - [targetId] 消息发送目标 + * + * #### content + * - [originalMessage] 消息内容 + * + * * 消息源可用于 [引用回复][QuoteReply] 或 [撤回][Bot.recall]. * * @see Bot.recall 撤回一条消息 @@ -52,50 +71,74 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle { @@ -266,6 +312,8 @@ sealed class OnlineMessageSource : MessageSource() { /** * 由一条消息中的 [QuoteReply] 得到的 [MessageSource]. * 此消息源可能来自一条与机器人无关的消息. 因此无法提供对象化的 `sender` 或 `target` 获取. + * + * @see buildMessageSource 构建一个 [OfflineMessageSource] */ @SinceMirai("0.33.0") abstract class OfflineMessageSource : MessageSource() { @@ -290,6 +338,9 @@ abstract class OfflineMessageSource : MessageSource() { // final override fun toString(): String = "OfflineMessageSource(sender=$senderId, target=$targetId)" } +/** + * 判断是否是发送给群, 或从群接收的消息的消息源 + */ // inline for future removal inline fun MessageSource.isAboutGroup(): Boolean { return when (this) { @@ -298,6 +349,9 @@ inline fun MessageSource.isAboutGroup(): Boolean { } } +/** + * 判断是否是发送给临时会话, 或从临时会话接收的消息的消息源 + */ inline fun MessageSource.isAboutTemp(): Boolean { return when (this) { is OnlineMessageSource -> subject is Member @@ -305,6 +359,9 @@ inline fun MessageSource.isAboutTemp(): Boolean { } } +/** + * 判断是否是发送给好友, 或从好友接收的消息的消息源 + */ // inline for future removal inline fun MessageSource.isAboutFriend(): Boolean { return when (this) { @@ -315,6 +372,7 @@ inline fun MessageSource.isAboutFriend(): Boolean { /** * 引用这条消息 + * @see QuoteReply */ fun MessageSource.quote(): QuoteReply { @OptIn(MiraiInternalAPI::class) @@ -323,17 +381,37 @@ fun MessageSource.quote(): QuoteReply { /** * 引用这条消息 + * @see QuoteReply */ fun MessageChain.quote(): QuoteReply { @OptIn(MiraiInternalAPI::class) return QuoteReply(this.source as? OnlineMessageSource ?: error("only online messages can be quoted")) } +/** + * 撤回这条消息. 可撤回自己 2 分钟内发出的消息, 和任意时间的群成员的消息. + * + * [Bot] 撤回自己的消息不需要权限. + * [Bot] 撤回群员的消息需要管理员权限. + * + * @throws PermissionDeniedException 当 [Bot] 无权限操作时 + * @throws IllegalStateException 当这条消息已经被撤回时 (仅同步主动操作) + * + * @see Bot.recall + */ @JvmSynthetic suspend inline fun MessageSource.recall() = bot.recall(this) /** - * 撤回这条消息 + * 在一段时间后撤回这条消息. 可撤回自己 2 分钟内发出的消息, 和任意时间的群成员的消息. + * + * [Bot] 撤回自己的消息不需要权限. + * [Bot] 撤回群员的消息需要管理员权限. + * + * @throws PermissionDeniedException 当 [Bot] 无权限操作时 + * @throws IllegalStateException 当这条消息已经被撤回时 (仅同步主动操作) + * + * @see Bot.recall */ @JvmSynthetic inline fun MessageSource.recallIn( @@ -345,7 +423,7 @@ inline fun MessageSource.recallIn( /** * 消息 id. - * 仅从服务器接收的消息才可以获取 id + * 仅从服务器接收的消息才可以获取 * * @see MessageSource.id */ @@ -353,6 +431,36 @@ inline fun MessageSource.recallIn( inline val MessageChain.id: Int get() = this.source.id +/** + * 消息内部 id. + * 仅从服务器接收的消息才可以获取 + * + * @see MessageSource.id + */ +@get:JvmSynthetic +inline val MessageChain.internalId: Int + get() = this.source.internalId + +/** + * 消息时间. + * 仅从服务器接收的消息才可以获取 + * + * @see MessageSource.id + */ +@get:JvmSynthetic +inline val MessageChain.time: Int + get() = this.source.time + +/** + * 消息内部 id. + * 仅从服务器接收的消息才可以获取 + * + * @see MessageSource.id + */ +@get:JvmSynthetic +inline val MessageChain.bot: Bot + get() = this.source.bot + /** * 获取这条消息源 * 仅从服务器接收的消息才可以获取消息源 @@ -361,9 +469,31 @@ inline val MessageChain.id: Int inline val MessageChain.source: MessageSource get() = this[MessageSource] +/** + * 撤回这条消息. 可撤回自己 2 分钟内发出的消息, 和任意时间的群成员的消息. + * + * [Bot] 撤回自己的消息不需要权限. + * [Bot] 撤回群员的消息需要管理员权限. + * + * @throws PermissionDeniedException 当 [Bot] 无权限操作时 + * @throws IllegalStateException 当这条消息已经被撤回时 (仅同步主动操作) + * + * @see Bot.recall + */ @JvmSynthetic suspend inline fun MessageChain.recall() = this.source.recall() +/** + * 在一段时间后撤回这条消息. 可撤回自己 2 分钟内发出的消息, 和任意时间的群成员的消息. + * + * [Bot] 撤回自己的消息不需要权限. + * [Bot] 撤回群员的消息需要管理员权限. + * + * @throws PermissionDeniedException 当 [Bot] 无权限操作时 + * @throws IllegalStateException 当这条消息已经被撤回时 (仅同步主动操作) + * + * @see Bot.recall + */ @JvmSynthetic inline fun MessageChain.recallIn( millis: Long, diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/OfflineMessageSource.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/OfflineMessageSource.kt index f9aabcbcb..2d9e25fca 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/OfflineMessageSource.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/OfflineMessageSource.kt @@ -25,6 +25,9 @@ import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName import kotlin.jvm.JvmSynthetic +/** + * 将在线消息源转换为离线消息源. + */ @SinceMirai("0.39.0") @JvmName("toOfflineMessageSource") fun OnlineMessageSource.toOffline(): OfflineMessageSource = @@ -60,6 +63,14 @@ interface MessageSourceAmender { var internalId: Int var originalMessage: MessageChain + + /** 从另一个 [MessageSource] 中复制 [id], [internalId], [time]*/ + @SinceMirai("0.39.2") + fun metadataFrom(another: MessageSource) { + this.id = another.id + this.internalId = another.internalId + this.time = another.time + } } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/QuoteReply.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/QuoteReply.kt index 4386e06d7..49d09d586 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/QuoteReply.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/QuoteReply.kt @@ -15,7 +15,6 @@ package net.mamoe.mirai.message.data import kotlinx.coroutines.Job import net.mamoe.mirai.Bot -import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.SinceMirai import kotlin.coroutines.CoroutineContext @@ -29,10 +28,19 @@ import kotlin.jvm.JvmSynthetic /** * 引用回复. * - * 可以引用一条群消息并发送给一个好友, 或是引用好友消息发送给群. - * 可以引用自己发出的消息. 详见 [MessageReceipt.quote] + * 支持引用任何一条消息发送给任何人. * - * @see MessageSource 获取更多信息 + * #### [source] 的类型: + * - 在发送引用回复时, [source] 类型为 [OnlineMessageSource] 或 [OfflineMessageSource] + * - 在接收引用回复时, [source] 类型一定为 [OfflineMessageSource] + * + * #### 原消息内容 + * 引用回复的原消息内容完全由 [source] 中 [MessageSource.originalMessage] 控制, 客户端不会自行寻找原消息. + * + * #### 客户端内跳转 + * 客户端在跳转原消息时, 会通过 [MessageSource.id] 等 metadata + * + * @see MessageSource 获取有关消息源的更多信息 */ @OptIn(MiraiExperimentalAPI::class) @SinceMirai("0.33.0") @@ -50,26 +58,52 @@ class QuoteReply(val source: MessageSource) : Message, MessageMetadata, Constrai override fun hashCode(): Int = source.hashCode() } +/** + * @see MessageSource.id + */ @get:JvmSynthetic inline val QuoteReply.id: Int get() = source.id +/** + * @see MessageSource.internalId + */ +@SinceMirai("0.39.2") +@get:JvmSynthetic +inline val QuoteReply.internalId: Int + get() = source.internalId + +/** + * @see MessageSource.fromId + */ @get:JvmSynthetic inline val QuoteReply.fromId: Long get() = source.fromId +/** + * @see MessageSource.targetId + */ @get:JvmSynthetic inline val QuoteReply.targetId: Long get() = source.targetId +/** + * @see MessageSource.originalMessage + */ @get:JvmSynthetic inline val QuoteReply.originalMessage: MessageChain get() = source.originalMessage +/** + * @see MessageSource.time + */ @get:JvmSynthetic inline val QuoteReply.time: Int get() = source.time +/** + * @see MessageSource.bot + */ @get:JvmSynthetic inline val QuoteReply.bot: Bot get() = source.bot @@ -78,6 +112,9 @@ inline val QuoteReply.bot: Bot @JvmSynthetic suspend inline fun QuoteReply.recall() = this.source.recall() +/** + * 在一段时间后撤回这条消息. + */ @JvmOverloads inline fun QuoteReply.recallIn( millis: Long, diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/_HummerMessage.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/_HummerMessage.kt new file mode 100644 index 000000000..88dcc2889 --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/_HummerMessage.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2020 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + +@file:JvmName("HummerMessageKt") +@file:Suppress("NOTHING_TO_INLINE") + +package net.mamoe.mirai.message.data + +import net.mamoe.mirai.utils.PlannedRemoval +import net.mamoe.mirai.utils.SinceMirai +import kotlin.jvm.JvmName +import kotlin.jvm.JvmSynthetic + + +/* +因为文件改名为做的兼容 + */ + +@PlannedRemoval("1.0.0") +@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) +@JvmName("flash") +@SinceMirai("0.33.0") +inline fun Image.flash2(): FlashImage = FlashImage(this) + +@PlannedRemoval("1.0.0") +@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) +@JvmName("flash") +@JvmSynthetic +@SinceMirai("0.33.0") +inline fun GroupImage.flash2(): GroupFlashImage = FlashImage(this) as GroupFlashImage + +@PlannedRemoval("1.0.0") +@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) +@JvmName("flash") +@JvmSynthetic +@SinceMirai("0.33.0") +inline fun FriendImage.flash2(): FriendFlashImage = FlashImage(this) as FriendFlashImage 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 new file mode 100644 index 000000000..364b34e22 --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/_Message.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2020 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + +@file:JvmName("MessageKt") +@file:Suppress("NOTHING_TO_INLINE") + +package net.mamoe.mirai.message.data + +import net.mamoe.mirai.utils.PlannedRemoval +import kotlin.jvm.JvmName + + +/* +因为文件改名为做的兼容 + */ + +@PlannedRemoval("1.0.0") +@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) +@JvmName("isPlain") +inline fun Message.isPlain2(): Boolean = this is PlainText + +@PlannedRemoval("1.0.0") +@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) +@JvmName("isNotPlain") +inline fun Message.isNotPlain2(): Boolean = this !is PlainText + +@PlannedRemoval("1.0.0") +@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) +@JvmName("repeat") +// inline: for future removal +inline fun Message.repeat2(count: Int): MessageChain { + if (this is ConstrainSingle<*>) { + // fast-path + return this.asMessageChain() + } + return buildMessageChain(count) { + add(this@repeat2) + } +} diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/builder.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/builder.kt index 40ec15125..79e0c2777 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/builder.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/builder.kt @@ -42,6 +42,8 @@ inline fun buildMessageChain(initialSize: Int, block: MessageChainBuilder.() -> /** * [MessageChain] 构建器. * 多个连续的 [String] 会被连接为单个 [PlainText] 以优化性能. + * + * * **注意:** 无并发安全性. * * @see buildMessageChain 推荐使用 @@ -91,6 +93,7 @@ open class MessageChainBuilder private constructor( return addAll(elements.flatten()) } + @JvmSynthetic operator fun Message.unaryPlus() { checkBuilt() flushCache() @@ -98,22 +101,26 @@ open class MessageChainBuilder private constructor( } + @JvmSynthetic operator fun String.unaryPlus() { checkBuilt() add(this) } + @JvmSynthetic // they should use add operator fun plusAssign(plain: String) { checkBuilt() withCache { append(plain) } } + @JvmSynthetic // they should use add operator fun plusAssign(message: Message) { checkBuilt() flushCache() this.add(message) } + @JvmSynthetic // they should use add operator fun plusAssign(message: SingleMessage) { // avoid resolution ambiguity checkBuilt() flushCache() @@ -125,6 +132,7 @@ open class MessageChainBuilder private constructor( withCache { append(plain) } } + @JvmSynthetic // they should use add operator fun plusAssign(charSequence: CharSequence) { checkBuilt() withCache { append(charSequence) } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/impl.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/impl.kt index 620a7b5c4..5942f5ed9 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/impl.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/impl.kt @@ -311,9 +311,11 @@ internal class SingleMessageChainImpl constructor( @SharedImmutable +@get:JvmSynthetic internal val EMPTY_BYTE_ARRAY = ByteArray(0) +@JvmSynthetic @Suppress("NOTHING_TO_INLINE") // no stack waste internal inline fun Char.hexDigitToByte(): Int { return when (this) { @@ -324,6 +326,7 @@ internal inline fun Char.hexDigitToByte(): Int { } } +@JvmSynthetic internal fun String.skipToSecondHyphen(): Int { var count = 0 this.forEachIndexed { index, c -> @@ -332,6 +335,7 @@ internal fun String.skipToSecondHyphen(): Int { error("cannot find two hyphens") } +@JvmSynthetic internal fun String.imageIdToMd5(offset: Int): ByteArray { val result = ByteArray(16) var cur = 0