diff --git a/mirai-core-api/src/commonMain/kotlin/IMirai.kt b/mirai-core-api/src/commonMain/kotlin/IMirai.kt index 151fe8412..f1e453172 100644 --- a/mirai-core-api/src/commonMain/kotlin/IMirai.kt +++ b/mirai-core-api/src/commonMain/kotlin/IMirai.kt @@ -59,6 +59,12 @@ public interface IMirai : LowLevelApiAccessor { @MiraiInternalApi public val Http: HttpClient + public fun getUin(contactOrBot: ContactOrBot): Long { + return if (contactOrBot is Group) + calculateGroupUinByGroupCode(contactOrBot.id) + else contactOrBot.id + } + /** * 使用 groupCode 计算 groupUin. 这两个值仅在 mirai 内部协议区分, 一般人使用时无需在意. */ @@ -137,15 +143,11 @@ public interface IMirai : LowLevelApiAccessor { * * @param ids 即 [MessageSource.ids] * @param internalIds 即 [MessageSource.internalIds] - * - * @param fromUin 为用户时为 [Friend.id], 为群时需使用 [IMirai.calculateGroupUinByGroupCode] 计算 - * @param targetUin 为用户时为 [Friend.id], 为群时需使用 [IMirai.calculateGroupUinByGroupCode] 计算 */ - @MiraiExperimentalApi("This is very experimental and is subject to change.") public fun constructMessageSource( botId: Long, kind: MessageSourceKind, - fromUin: Long, targetUin: Long, + fromId: Long, targetId: Long, ids: IntArray, time: Int, internalIds: IntArray, originalMessage: MessageChain ): OfflineMessageSource diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/MessageSource.kt b/mirai-core-api/src/commonMain/kotlin/message/data/MessageSource.kt index 04de05096..76986de20 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/MessageSource.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/MessageSource.kt @@ -66,7 +66,7 @@ import net.mamoe.mirai.utils.safeCast * @see OnlineMessageSource 在线消息的 [MessageSource] * @see OfflineMessageSource 离线消息的 [MessageSource] * - * @see buildMessageSource 构造一个 [OfflineMessageSource] + * @see buildMessageSource 构建一个 [OfflineMessageSource] */ @Serializable(MessageSource.Serializer::class) public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle { @@ -445,6 +445,8 @@ public sealed class OnlineMessageSource : MessageSource() { * 此消息源可能来自一条与机器人无关的消息. 因此无法提供对象化的 `sender` 或 `target` 获取. * * @see buildMessageSource 构建一个 [OfflineMessageSource] + * @see IMirai.constructMessageSource + * @see OnlineMessageSource.toOffline */ public abstract class OfflineMessageSource : MessageSource() { public companion object Key : diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/MessageSourceBuilder.kt b/mirai-core-api/src/commonMain/kotlin/message/data/MessageSourceBuilder.kt index 27f5f7314..ddcd7a8f0 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/MessageSourceBuilder.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/MessageSourceBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 Mamoe Technologies and contributors. + * Copyright 2019-2021 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. @@ -14,14 +14,12 @@ package net.mamoe.mirai.message.data import net.mamoe.mirai.Bot +import net.mamoe.mirai.IMirai import net.mamoe.mirai.Mirai -import net.mamoe.mirai.contact.* -import net.mamoe.mirai.message.data.MessageSource.Key.isAboutFriend -import net.mamoe.mirai.message.data.MessageSource.Key.isAboutGroup -import net.mamoe.mirai.message.data.MessageSource.Key.isAboutTemp +import net.mamoe.mirai.contact.ContactOrBot import net.mamoe.mirai.message.data.MessageSource.Key.quote import net.mamoe.mirai.message.data.MessageSource.Key.recall -import net.mamoe.mirai.utils.MiraiExperimentalApi +import net.mamoe.mirai.message.data.MessageSourceBuilder.Companion.create import net.mamoe.mirai.utils.currentTimeSeconds /** @@ -29,7 +27,7 @@ import net.mamoe.mirai.utils.currentTimeSeconds */ @JvmName("toOfflineMessageSource") public fun OnlineMessageSource.toOffline(): OfflineMessageSource = - OfflineMessageSourceByOnline(this) + Mirai.constructMessageSource(botId, kind, fromId, targetId, ids, time, internalIds, originalMessage) /////////////// //// AMEND //// @@ -41,24 +39,27 @@ public fun OnlineMessageSource.toOffline(): OfflineMessageSource = * * @see buildMessageSource 查看更多说明 */ -@MiraiExperimentalApi @JvmName("copySource") public fun MessageSource.copyAmend( block: MessageSourceAmender.() -> Unit -): OfflineMessageSource = toMutableOffline().apply(block) +): OfflineMessageSource = MessageSourceAmender(this).apply(block).run { + Mirai.constructMessageSource(botId, kind, fromId, targetId, ids, time, internalIds, originalMessage) +} /** * 仅于 [copyAmend] 中修改 [MessageSource] */ -public interface MessageSourceAmender { - public var kind: MessageSourceKind - public var fromUin: Long - public var targetUin: Long - public var ids: IntArray - public var time: Int - public var internalIds: IntArray +public class MessageSourceAmender internal constructor( + origin: MessageSource, +) : MessageSourceBuilder() { + public var kind: MessageSourceKind = origin.kind + public var originalMessage: MessageChain = origin.originalMessage - public var originalMessage: MessageChain + public override var fromId: Long = origin.fromId + public override var targetId: Long = origin.targetId + public override var ids: IntArray = origin.ids + public override var time: Int = origin.time + public override var internalIds: IntArray = origin.internalIds /** 从另一个 [MessageSource] 中复制 [ids], [internalIds], [time]*/ public fun metadataFrom(another: MessageSource) { @@ -78,8 +79,8 @@ public interface MessageSourceAmender { * 构建一个 [OfflineMessageSource] * * ### 参数 - * 一个 [OfflineMessageSource] 须要以下参数: - * - 发送人和发送目标: 通过 [MessageSourceBuilder.sendTo] 设置 + * 一个 [OfflineMessageSource] 需要以下参数: + * - 发送人和发送目标: 通过 [MessageSourceBuilder.sender], [MessageSourceBuilder.target] 设置 * - 消息元数据 (即 [MessageSource.ids], [MessageSource.internalIds], [MessageSource.time]) * 元数据用于 [撤回][MessageSource.recall], [引用回复][MessageSource.quote], 和官方客户端定位原消息. * 可通过 [MessageSourceBuilder.ids], [MessageSourceBuilder.time], [MessageSourceBuilder.internalIds] 设置 @@ -92,8 +93,9 @@ public interface MessageSourceAmender { * * ### 实例 * ``` - * bot.buildMessageSource { - * bot sendTo target // 指定发送人和发送目标 + * bot.buildMessageSource(MessageSourceKind.GROUP) { + * from(bot) + * target(target) * metadata(source) // 从另一个消息源复制 ids, internalIds, time * * messages { // 指定消息内容 @@ -101,40 +103,49 @@ public interface MessageSourceAmender { * } * } * ``` + * + * @see copyAmend */ -@JvmSynthetic -@MiraiExperimentalApi -public fun Bot.buildMessageSource(block: MessageSourceBuilder.() -> Unit): MessageSource { - val builder = MessageSourceBuilderImpl().apply(block) - return Mirai.constructMessageSource( - this.id, - builder.kind ?: error("You must call `Contact.sendTo(Contact)` when `buildMessageSource`"), - builder.fromUin, - builder.targetUin, - builder.ids, - builder.time, - builder.internalIds, - builder.originalMessages.build() - ) +public fun IMirai.buildMessageSource( + botId: Long, + kind: MessageSourceKind, + block: MessageSourceBuilder.() -> Unit +): OfflineMessageSource = MessageSourceBuilder.create().apply(block).run { + Mirai.constructMessageSource(botId, kind, fromId, targetId, ids, time, internalIds, originalMessages.build()) } /** + * 构建一个 [OfflineMessageSource] + * * @see buildMessageSource */ -public abstract class MessageSourceBuilder { - internal abstract var kind: MessageSourceKind? - internal abstract var fromUin: Long - internal abstract var targetUin: Long +public fun Bot.buildMessageSource( + kind: MessageSourceKind, + block: MessageSourceBuilder.() -> Unit +): OfflineMessageSource = Mirai.buildMessageSource(this.id, kind, block) - internal abstract var ids: IntArray - internal abstract var time: Int - internal abstract var internalIds: IntArray + +/** + * @see buildMessageSource + * @see create + */ +public open class MessageSourceBuilder internal constructor() { + public open var fromId: Long = 0 + public open var targetId: Long = 0 + + public open var ids: IntArray = intArrayOf() + + /** + * seconds + * @see MessageSource.time + */ + public open var time: Int = currentTimeSeconds().toInt() + public open var internalIds: IntArray = intArrayOf() @PublishedApi internal val originalMessages: MessageChainBuilder = MessageChainBuilder() public fun time(from: MessageSource): MessageSourceBuilder = apply { this.time = from.time } - public val now: Int get() = currentTimeSeconds().toInt() public fun time(value: Int): MessageSourceBuilder = apply { this.time = value } public fun internalId(from: MessageSource): MessageSourceBuilder = apply { this.internalIds = from.internalIds } @@ -158,11 +169,10 @@ public abstract class MessageSourceBuilder { * 从另一个 [MessageSource] 复制所有信息, 包括消息内容. 不会清空已有消息. */ public fun allFrom(source: MessageSource): MessageSourceBuilder { - this.kind = determineKind(source) this.ids = source.ids this.time = source.time - this.fromUin = source.fromId - this.targetUin = source.targetId + this.fromId = source.fromId + this.targetId = source.targetId this.internalIds = source.internalIds this.originalMessages.addAll(source.originalMessage) return this @@ -194,101 +204,38 @@ public abstract class MessageSourceBuilder { public fun clearMessages(): MessageSourceBuilder = apply { this.originalMessages.clear() } /** - * 设置 [发送人][this] 和 [发送目标][target], 并自动判断 [kind] + * 设置发信人 */ - @JvmSynthetic - public abstract infix fun ContactOrBot.sendTo(target: ContactOrBot): MessageSourceBuilder + public fun sender(sender: ContactOrBot): MessageSourceBuilder = apply { + this.fromId = Mirai.getUin(sender) + } + + /** + * @see IMirai.getUin + */ + public fun sender(uin: Long): MessageSourceBuilder = apply { + this.fromId = uin + } + + /** + * 设置发信目标 + */ + public fun target(target: ContactOrBot): MessageSourceBuilder = apply { + this.targetId = Mirai.getUin(target) + } + + /** + * @see IMirai.getUin + */ + public fun target(uin: Long): MessageSourceBuilder = apply { + this.targetId = uin + } public fun setSenderAndTarget(sender: ContactOrBot, target: ContactOrBot): MessageSourceBuilder = - sender sendTo target -} + sender(sender).target(target) - -////////////////// -//// INTERNAL //// -////////////////// - - -internal class MessageSourceBuilderImpl : MessageSourceBuilder() { - override var kind: MessageSourceKind? = null - override var fromUin: Long = 0 - override var targetUin: Long = 0 - - override var ids: IntArray = intArrayOf() - override var time: Int = currentTimeSeconds().toInt() - override var internalIds: IntArray = intArrayOf() - - @JvmSynthetic - override fun ContactOrBot.sendTo(target: ContactOrBot): MessageSourceBuilder { - fromUin = if (this is Group) { - Mirai.calculateGroupUinByGroupCode(this.id) - } else this.id - - targetUin = if (target is Group) { - Mirai.calculateGroupUinByGroupCode(target.id) - } else target.id - - check(this != target) { "sender and target mustn't be the same" } - - kind = when { - this is Group || target is Group -> MessageSourceKind.GROUP - this is Member || target is Member -> MessageSourceKind.TEMP - this is Bot && target is Friend -> MessageSourceKind.FRIEND - this is Friend && target is Bot -> MessageSourceKind.FRIEND - this is Stranger || target is Stranger -> MessageSourceKind.STRANGER - else -> throw IllegalArgumentException("Cannot determine source kind for sender $this and target $target") - } - return this@MessageSourceBuilderImpl + public companion object { + @JvmStatic + public fun create(): MessageSourceBuilder = MessageSourceBuilder() } -} - - -@JvmSynthetic -internal fun MessageSource.toMutableOffline(): MutableOfflineMessageSourceByOnline = - MutableOfflineMessageSourceByOnline(this) - -internal class MutableOfflineMessageSourceByOnline( - origin: MessageSource -) : OfflineMessageSource(), MessageSourceAmender { - override var kind: MessageSourceKind = determineKind(origin) - override var fromUin: Long - get() = fromId - set(value) { - fromId = value - } - override var targetUin: Long - get() = targetId - set(value) { - targetId = value - } - override val botId: Long = origin.botId - override var ids: IntArray = origin.ids - override var internalIds: IntArray = origin.internalIds - override var time: Int = origin.time - override var fromId: Long = origin.fromId - override var targetId: Long = origin.targetId - override var originalMessage: MessageChain = origin.originalMessage -} - -private fun determineKind(source: MessageSource): MessageSourceKind { - return when { - source.isAboutGroup() -> MessageSourceKind.GROUP - source.isAboutFriend() -> MessageSourceKind.FRIEND - source.isAboutTemp() -> MessageSourceKind.TEMP - else -> error("stub") - } -} - -internal class OfflineMessageSourceByOnline( - private val onlineMessageSource: OnlineMessageSource -) : OfflineMessageSource() { - override val kind: MessageSourceKind - get() = onlineMessageSource.kind - override val botId: Long get() = onlineMessageSource.botId - override val ids: IntArray get() = onlineMessageSource.ids - override val internalIds: IntArray get() = onlineMessageSource.internalIds - override val time: Int get() = onlineMessageSource.time - override val fromId: Long get() = onlineMessageSource.fromId - override val targetId: Long get() = onlineMessageSource.targetId - override val originalMessage: MessageChain get() = onlineMessageSource.originalMessage -} +} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/MiraiImpl.kt b/mirai-core/src/commonMain/kotlin/MiraiImpl.kt index c21b1836e..063add083 100644 --- a/mirai-core/src/commonMain/kotlin/MiraiImpl.kt +++ b/mirai-core/src/commonMain/kotlin/MiraiImpl.kt @@ -892,14 +892,14 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor { override fun constructMessageSource( botId: Long, kind: MessageSourceKind, - fromUin: Long, - targetUin: Long, + fromId: Long, + targetId: Long, ids: IntArray, time: Int, internalIds: IntArray, originalMessage: MessageChain ): OfflineMessageSource = OfflineMessageSourceImplData( - kind, ids, botId, time, fromUin, targetUin, originalMessage, internalIds + kind, ids, botId, time, fromId, targetId, originalMessage, internalIds ) } \ No newline at end of file