Commit 66f46202 authored by Him188's avatar Him188

Add `MessageSource.internalId`, support `OfflineMessageSource` building

parent 6311c39c
......@@ -35,6 +35,7 @@ import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.MemberJoinRequestEvent
import net.mamoe.mirai.event.events.MessageRecallEvent
import net.mamoe.mirai.event.events.NewFriendRequestEvent
import net.mamoe.mirai.event.internal.MiraiAtomicBoolean
import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.network.LoginFailedException
......@@ -45,6 +46,7 @@ import net.mamoe.mirai.qqandroid.message.*
import net.mamoe.mirai.qqandroid.network.QQAndroidBotNetworkHandler
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.highway.HighwayHelper
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.LongMsg
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.*
import net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList
......@@ -321,7 +323,7 @@ internal abstract class QQAndroidBotBase constructor(
bot.asQQAndroidBot().client,
group.id,
source.sequenceId,
source.random
source.internalId
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
}
}
......@@ -335,7 +337,7 @@ internal abstract class QQAndroidBotBase constructor(
bot.client,
source.targetId,
source.sequenceId,
source.random,
source.internalId,
source.time
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
}
......@@ -351,7 +353,7 @@ internal abstract class QQAndroidBotBase constructor(
source.target.group.id,
source.targetId,
source.sequenceId,
source.random,
source.internalId,
source.time
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
}
......@@ -365,7 +367,7 @@ internal abstract class QQAndroidBotBase constructor(
bot.client,
source.targetId,
source.sequenceId,
source.random,
source.internalId,
source.time
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
}
......@@ -378,7 +380,7 @@ internal abstract class QQAndroidBotBase constructor(
source.targetId, // groupUin
source.targetId, // memberUin
source.sequenceId,
source.random,
source.internalId,
source.time
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
}
......@@ -387,7 +389,7 @@ internal abstract class QQAndroidBotBase constructor(
bot.client,
source.targetId,
source.sequenceId,
source.random
source.internalId
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
}
}
......@@ -658,6 +660,43 @@ internal abstract class QQAndroidBotBase constructor(
else -> error("unsupported image class: ${image::class.simpleName}")
}
override fun constructMessageSource(
kind: OfflineMessageSource.Kind,
fromUin: Long,
targetUin: Long,
id: Int,
time: Int,
internalId: Int,
originalMessage: MessageChain
): OfflineMessageSource {
return object : OfflineMessageSource(), MessageSourceInternal {
override val kind: Kind get() = kind
override val id: Int get() = id
override val bot: Bot get() = this@QQAndroidBotBase
override val time: Int get() = time
override val fromId: Long get() = fromUin
override val targetId: Long get() = targetUin
override val originalMessage: MessageChain get() = originalMessage
override val sequenceId: Int = id
override val internalId: Int = internalId
override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false)
override fun toJceData(): ImMsgBody.SourceMsg {
return ImMsgBody.SourceMsg(
origSeqs = listOf(sequenceId),
senderUin = fromUin,
toUin = 0,
flag = 1,
elems = originalMessage.toRichTextElems(forGroup = kind == Kind.GROUP, withGeneralFlags = false),
type = 0,
time = time,
pbReserve = EMPTY_BYTE_ARRAY,
srcMsg = EMPTY_BYTE_ARRAY
)
}
}
}
@Suppress("DeprecatedCallableAddReplaceWith")
@PlannedRemoval("1.0.0")
@Deprecated("use your own Http clients, this is going to be removed in 1.0.0", level = DeprecationLevel.WARNING)
......@@ -673,6 +712,8 @@ internal abstract class QQAndroidBotBase constructor(
.fold(5381) { acc: Int, b: Byte -> acc + acc.shl(5) + b.toInt() }
}
internal val EMPTY_BYTE_ARRAY = ByteArray(0)
@Suppress("DEPRECATION")
@OptIn(MiraiInternalAPI::class)
internal expect fun io.ktor.utils.io.ByteReadChannel.toKotlinByteReadChannel(): ByteReadChannel
......
......@@ -27,7 +27,7 @@ import net.mamoe.mirai.qqandroid.utils.io.serialization.toByteArray
internal interface MessageSourceInternal {
val sequenceId: Int
val random: Int
val internalId: Int // randomId
@Deprecated("don't use this internally. Use sequenceId or random instead.", level = DeprecationLevel.ERROR)
val id: Int
......@@ -54,12 +54,12 @@ internal class MessageSourceFromFriendImpl(
override val sequenceId: Int get() = msg.msgHead.msgSeq
override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false)
override val id: Int get() = sequenceId// msg.msgBody.richText.attr!!.random
override val random: Int get() = msg.msgBody.richText.attr!!.random
override val internalId: Int get() = msg.msgBody.richText.attr!!.random
override val time: Int get() = msg.msgHead.msgTime
override val originalMessage: MessageChain by lazy { msg.toMessageChain(bot, 0, false) }
override val sender: Friend get() = bot.getFriend(msg.msgHead.fromUin)
private val jceData by lazy { msg.toJceDataFriendOrTemp(random) }
private val jceData by lazy { msg.toJceDataFriendOrTemp(internalId) }
override fun toJceData(): ImMsgBody.SourceMsg = jceData
}
......@@ -105,14 +105,14 @@ internal class MessageSourceFromTempImpl(
private val msg: MsgComm.Msg
) : OnlineMessageSource.Incoming.FromTemp(), MessageSourceInternal {
override val sequenceId: Int get() = msg.msgHead.msgSeq
override val random: Int get() = msg.msgBody.richText.attr!!.random
override val internalId: Int get() = msg.msgBody.richText.attr!!.random
override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false)
override val id: Int get() = sequenceId//
override val time: Int get() = msg.msgHead.msgTime
override val originalMessage: MessageChain by lazy { msg.toMessageChain(bot, 0, false) }
override val sender: Member get() = with(msg.msgHead) { bot.getGroup(c2cTmpMsgHead!!.groupUin)[fromUin] }
private val jceData by lazy { msg.toJceDataFriendOrTemp(random) }
private val jceData by lazy { msg.toJceDataFriendOrTemp(internalId) }
override fun toJceData(): ImMsgBody.SourceMsg = jceData
}
......@@ -122,7 +122,7 @@ internal data class MessageSourceFromGroupImpl(
) : OnlineMessageSource.Incoming.FromGroup(), MessageSourceInternal {
override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false)
override val sequenceId: Int get() = msg.msgHead.msgSeq
override val random: Int get() = msg.msgBody.richText.attr!!.random
override val internalId: Int get() = msg.msgBody.richText.attr!!.random
override val id: Int get() = sequenceId
override val time: Int get() = msg.msgHead.msgTime
override val originalMessage: MessageChain by lazy {
......
......@@ -28,7 +28,7 @@ internal class OfflineMessageSourceImplByMsg(
) : OfflineMessageSource(), MessageSourceInternal {
override val kind: Kind = if (delegate.msgHead.groupInfo != null) Kind.GROUP else Kind.FRIEND
override val id: Int get() = sequenceId
override val random: Int
override val internalId: Int
get() = delegate.msgHead.msgUid.toInt()
override val time: Int
get() = delegate.msgHead.msgTime
......@@ -74,7 +74,7 @@ internal class OfflineMessageSourceImplBySourceMsg(
override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false)
override val sequenceId: Int
get() = delegate.origSeqs?.first() ?: error("cannot find sequenceId")
override val random: Int
override val internalId: Int
get() = delegate.pbReserve.loadAs(SourceMsg.ResvAttr.serializer()).origUids?.toInt() ?: 0
override val time: Int get() = delegate.time
override val originalMessage: MessageChain by lazy { delegate.toMessageChain(bot, groupIdOrZero) }
......
......@@ -33,7 +33,7 @@ private fun <T> T.toJceDataImpl(): ImMsgBody.SourceMsg
where T : MessageSourceInternal, T : MessageSource {
val elements = originalMessage.toRichTextElems(forGroup = false, withGeneralFlags = true)
val messageUid: Long = sequenceId.toLong().shl(32) or random.toLong().and(0xffFFffFF)
val messageUid: Long = sequenceId.toLong().shl(32) or internalId.toLong().and(0xffFFffFF)
return ImMsgBody.SourceMsg(
origSeqs = listOf(sequenceId),
senderUin = fromId,
......@@ -70,7 +70,7 @@ private fun <T> T.toJceDataImpl(): ImMsgBody.SourceMsg
internal class MessageSourceToFriendImpl(
override val sequenceId: Int,
override val random: Int,
override val internalId: Int,
override val time: Int,
override val originalMessage: MessageChain,
override val sender: Bot,
......@@ -87,7 +87,7 @@ internal class MessageSourceToFriendImpl(
internal class MessageSourceToTempImpl(
override val sequenceId: Int,
override val random: Int,
override val internalId: Int,
override val time: Int,
override val originalMessage: MessageChain,
override val sender: Bot,
......@@ -104,7 +104,7 @@ internal class MessageSourceToTempImpl(
internal class MessageSourceToGroupImpl(
coroutineScope: CoroutineScope,
override val random: Int,
override val internalId: Int,
override val time: Int,
override val originalMessage: MessageChain,
override val sender: Bot,
......@@ -120,7 +120,7 @@ internal class MessageSourceToGroupImpl(
coroutineScope.asyncFromEventOrNull<OnlinePush.PbPushGroupMsg.SendGroupMessageReceipt, Int>(
timeoutMillis = 3000
) {
if (it.messageRandom == this@MessageSourceToGroupImpl.random) {
if (it.messageRandom == this@MessageSourceToGroupImpl.internalId) {
it.sequenceId
} else null
}
......
......@@ -369,7 +369,7 @@ internal class MessageSvc {
): OutgoingPacket {
val rand = Random.nextInt().absoluteValue
val source = MessageSourceToFriendImpl(
random = rand,
internalId = rand,
sender = client.bot,
target = qq,
time = currentTimeSeconds.toInt(),
......@@ -403,7 +403,7 @@ internal class MessageSvc {
)
),
msgSeq = source.sequenceId,
msgRand = source.random,
msgRand = source.internalId,
syncCookie = SyncCookie(time = source.time.toLong()).toByteArray(SyncCookie.serializer())
// msgVia = 1
)
......@@ -418,7 +418,7 @@ internal class MessageSvc {
sourceCallback: (MessageSourceToTempImpl) -> Unit
): OutgoingPacket {
val source = MessageSourceToTempImpl(
random = Random.nextInt().absoluteValue,
internalId = Random.nextInt().absoluteValue,
sender = client.bot,
target = member,
time = currentTimeSeconds.toInt(),
......@@ -451,7 +451,7 @@ internal class MessageSvc {
)
),
msgSeq = source.sequenceId,
msgRand = source.random,
msgRand = source.internalId,
syncCookie = SyncCookie(time = source.time.toLong()).toByteArray(SyncCookie.serializer())
)
)
......@@ -467,7 +467,7 @@ internal class MessageSvc {
val source = MessageSourceToGroupImpl(
group,
random = Random.nextInt().absoluteValue,
internalId = Random.nextInt().absoluteValue,
sender = client.bot,
target = group,
time = currentTimeSeconds.toInt(),
......@@ -503,7 +503,7 @@ internal class MessageSvc {
)
),
msgSeq = client.atomicNextMessageSequenceId(),
msgRand = source.random,
msgRand = source.internalId,
syncCookie = EMPTY_BYTE_ARRAY,
msgVia = 1
)
......
......@@ -179,6 +179,24 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI(
@JvmSynthetic
abstract suspend fun queryImageUrl(image: Image): String
/**
* 构造一个 [OfflineMessageSource]
*
* @param id 即 [MessageSource.id]
* @param internalId 即 [MessageSource.internalId]
*
* @param fromUin 为用户时为 [Friend.id], 为群时需使用 [Group.calculateGroupUinByGroupCode] 计算
* @param targetUin 为用户时为 [Friend.id], 为群时需使用 [Group.calculateGroupUinByGroupCode] 计算
*/
@MiraiExperimentalAPI
@SinceMirai("0.39.0")
abstract fun constructMessageSource(
kind: OfflineMessageSource.Kind,
fromUin: Long, targetUin: Long,
id: Int, time: Int, internalId: Int,
originalMessage: MessageChain
): OfflineMessageSource
/**
* 获取图片下载链接并开始下载.
*
......@@ -281,6 +299,7 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI(
val selfQQDeprecated: QQ
get() = selfQQ
@PlannedRemoval("1.0.0.")
@JvmName("getFriend")
@Suppress("INAPPLICABLE_JVM_NAME", "DEPRECATION_ERROR")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
......
......@@ -28,11 +28,9 @@ import net.mamoe.mirai.utils.*
*
* 目前在回复时无法通过 [originalMessage] 获取自定义类型消息
*
* **实现方法**:
*
* @sample samples.CustomMessageIdentifier 实现示例
*
* @see CustomMessageMetadata
* @see CustomMessageMetadata 自定义消息元数据
*/
@SinceMirai("0.38.0")
@MiraiExperimentalAPI
......@@ -172,6 +170,11 @@ sealed class CustomMessage : SingleMessage {
/**
* 自定义消息元数据.
*
* **实现方法**:
* 1. 实现一个类继承 [CustomMessageMetadata], 添加 `@Serializable` (来自 `kotlinx.serialization`)
* 2. 添加伴生对象, 继承 [CustomMessage.ProtoBufSerializerFactory] 或 [CustomMessage.JsonSerializerFactory], 或 [CustomMessage.Factory]
* 3. 在需要解析消息前调用一次伴生对象以注册
*
* @see CustomMessage 查看更多信息
* @see ConstrainSingle 可实现此接口以保证消息链中只存在一个元素
*/
......@@ -191,8 +194,9 @@ abstract class CustomMessageMetadata : CustomMessage(), MessageMetadata {
}
@Suppress("NOTHING_TO_INLINE")
@OptIn(MiraiExperimentalAPI::class)
internal fun <T : CustomMessageMetadata> T.customToStringImpl(factory: CustomMessage.Factory<*>): ByteArray {
internal inline fun <T : CustomMessageMetadata> T.customToStringImpl(factory: CustomMessage.Factory<*>): ByteArray {
@Suppress("UNCHECKED_CAST")
return (factory as CustomMessage.Factory<T>).serialize(this)
}
\ No newline at end of file
......@@ -58,6 +58,7 @@ import kotlin.jvm.JvmSynthetic
* @see QuoteReply 一条消息的引用
* @see RichMessage 富文本消息, 如 [Xml][XmlMessage], [小程序][LightApp], [Json][JsonMessage]
* @see HummerMessage 一些特殊的消息, 如 [闪照][FlashImage], [戳一戳][PokeMessage]
* @see CustomMessage 自定义消息类型
*
* @see MessageChain 消息链(即 `List<Message>`)
* @see buildMessageChain 构造一个 [MessageChain]
......
......@@ -62,8 +62,11 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSo
/**
* 内部 id, 仅用于 [Bot.constructMessageSource]
* 可能为 0, 取决于服务器是否提供.
* 值没有顺序, 也可能为 0, 取决于服务器是否提供.
*
* 仅用于协议实现.
*/
@SinceMirai("0.39.0")
abstract val internalId: Int
/**
......@@ -94,7 +97,7 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSo
@LazyProperty
abstract val originalMessage: MessageChain
final override fun toString(): String = "[mirai:source:$id]"
final override fun toString(): String = "[mirai:source:$id,$internalId]"
final override fun contentToString(): String = ""
}
......
......@@ -13,13 +13,14 @@
package net.mamoe.mirai.message.data
import net.mamoe.mirai.BotImpl
import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.ContactOrBot
import net.mamoe.mirai.contact.Friend
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.SinceMirai
import net.mamoe.mirai.utils.asSequence
import net.mamoe.mirai.utils.currentTimeSeconds
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
......@@ -53,68 +54,231 @@ abstract class OfflineMessageSource : MessageSource() {
}
///////////////
//// AMEND ////
///////////////
/**
* 复制这个消息源, 并修改
* 复制这个消息源, 并以 [block] 修改
*
* @see buildMessageSource 查看更多说明
*/
@MiraiExperimentalAPI
@SinceMirai("0.39.0")
@JvmName("copySource")
inline fun MessageSource.copyAmend(
block: MessageSourceBuilder.() -> Unit
): OfflineMessageSource {
return constructMessageSource()
}
fun MessageSource.copyAmend(
block: MessageSourceAmender.() -> Unit
): OfflineMessageSource = toMutableOffline().apply(block)
@MiraiExperimentalAPI
/**
* 仅于 [copyAmend] 中修改 [MessageSource]
*/
@SinceMirai("0.39.0")
@OptIn(MiraiInternalAPI::class)
fun constructMessageSource(
kind: OfflineMessageSource.Kind,
fromUin: Long, targetUin: Long,
id: Int, time: Int, internalId: Int,
originalMessage: MessageChain
): OfflineMessageSource {
val bot = BotImpl.instances.asSequence().mapNotNull { it.get() }.firstOrNull()
?: error("no Bot instance available")
return bot.constructMessageSource(kind, fromUin, targetUin, id, time, internalId, originalMessage)
interface MessageSourceAmender {
var kind: OfflineMessageSource.Kind
var fromUin: Long
var targetUin: Long
var id: Int
var time: Int
var internalId: Int
var originalMessage: MessageChain
}
///////////////
//// BUILD ////
///////////////
/**
* 构建一个 [OfflineMessageSource]
*
* ### 参数
* 一个 [OfflineMessageSource] 须要以下参数:
* - 发送人和发送目标: 通过 [MessageSourceBuilder.sendTo] 设置
* - 消息元数据 (即 [MessageSource.id], [MessageSource.internalId], [MessageSource.time])
* 元数据用于 [撤回][MessageSource.recall], [引用回复][MessageSource.quote], 和官方客户端定位原消息.
* 可通过 [MessageSourceBuilder.id], [MessageSourceBuilder.time], [MessageSourceBuilder.internalId] 设置
* 可通过 [MessageSourceBuilder.metadata] 从另一个 [MessageSource] 复制
* - 消息内容: 通过 [MessageSourceBuilder.messages] 设置
*
* ### 性质
* - 当两个消息的元数据相同时, 他们在群中会是同一条消息. 可通过此特性决定官方客户端 "定位原消息" 的目标
* - 发送人的信息和消息内容会在官方客户端显示在引用回复中.
*/
@SinceMirai("0.39.0")
@JvmSynthetic
@MiraiExperimentalAPI
inline fun buildMessageSource(block: MessageSourceBuilder.() -> Unit): MessageSource {
val builder = MessageSourceBuilder().apply(block)
fun Bot.buildMessageSource(block: MessageSourceBuilder.() -> Unit): MessageSource {
val builder = MessageSourceBuilderImpl().apply(block)
return constructMessageSource(
builder.kind ?: error("found "),
block
builder.kind ?: error("You must call `Contact.sendTo(Contact)` when `buildMessageSource`"),
builder.fromUin,
builder.targetUin,
builder.id,
builder.time,
builder.internalId,
builder.originalMessages.build()
)
}
@DslMarker
annotation class SourceBuilderDsl
class MessageSourceBuilder(
source: OfflineMessageSource
) : MessageChainBuilder() {
var kind: OfflineMessageSource.Kind = source.kind
var fromUin: Long = source.fromId
var targetUin: Long = source.targetId
var id: Int = source.id
var time: Int = source.time
var internalId: Int = source.internalId
var originalMessage: MessageChain = source.originalMessage
fun from(sender: Contact): MessageSourceBuilder {
fromUin = if (sender is Group) {
Group.calculateGroupUinByGroupCode(sender.id)
} else sender.id
/**
* @see buildMessageSource
*/
abstract class MessageSourceBuilder {
internal abstract var kind: OfflineMessageSource.Kind?
internal abstract var fromUin: Long
internal abstract var targetUin: Long
internal abstract var id: Int
internal abstract var time: Int
internal abstract var internalId: Int
@PublishedApi
internal val originalMessages: MessageChainBuilder = MessageChainBuilder()
fun time(from: MessageSource): MessageSourceBuilder = apply { this.time = from.time }
val now: Int get() = currentTimeSeconds.toInt()
fun time(value: Int) = apply { this.time = value }
fun internalId(from: MessageSource): MessageSourceBuilder = apply { this.internalId = from.internalId }
fun internalId(value: Int): MessageSourceBuilder = apply { this.internalId = value }
fun id(from: MessageSource): MessageSourceBuilder = apply { this.id = from.id }
fun id(value: Int): MessageSourceBuilder = apply { this.id = value }
/**
* 从另一个 [MessageSource] 复制 [id], [time], [internalId].
* 这三个数据决定官方客户端能 "定位" 到的原消息
*/
fun metadata(from: MessageSource): MessageSourceBuilder = apply {
id(from)
internalId(from)
time(from)
}
/**
* 从另一个 [MessageSource] 复制所有信息, 包括消息内容. 不会清空已有消息.
*/
fun allFrom(source: MessageSource): MessageSourceBuilder {
this.kind = determineKind(source)
this.id = source.id
this.time = source.time
this.fromUin = source.fromId
this.targetUin = source.targetId
this.internalId = source.internalId
this.originalMessages.addAll(source.originalMessage)
return this
}
fun target(target: Contact): MessageSourceBuilder {
/**
* 从另一个 [MessageSource] 复制 [消息内容][MessageSource.originalMessage]. 不会清空已有消息.
*/
fun messagesFrom(source: MessageSource): MessageSourceBuilder = apply {
this.originalMessages.addAll(source.originalMessage)
}
fun messages(messages: Iterable<Message>): MessageSourceBuilder = apply {
this.originalMessages.addAll(messages)
}
fun messages(vararg message: Message): MessageSourceBuilder = apply {
for (it in message) {
this.originalMessages.add(it)
}
}
@JvmSynthetic
inline fun messages(block: MessageChainBuilder.() -> Unit): MessageSourceBuilder = apply {
this.originalMessages.apply(block)
}
fun clearMessages(): MessageSourceBuilder = apply { this.originalMessages.clear() }
/**
* 设置 [发送人][this] 和 [发送目标][target], 并自动判断 [kind]
*/
@JvmSynthetic
abstract infix fun ContactOrBot.sendTo(target: ContactOrBot): MessageSourceBuilder
fun setSenderAndTarget(sender: ContactOrBot, target: ContactOrBot) = sender sendTo target
}
//////////////////
//// INTERNAL ////
//////////////////
internal class MessageSourceBuilderImpl : MessageSourceBuilder() {
override var kind: OfflineMessageSource.Kind? = null
override var fromUin: Long = 0
override var targetUin: Long = 0
override var id: Int = 0
override var time: Int = currentTimeSeconds.toInt()
override var internalId: Int = 0
@JvmSynthetic
override fun ContactOrBot.sendTo(target: ContactOrBot): MessageSourceBuilder {
fromUin = if (this is Group) {
Group.calculateGroupUinByGroupCode(this.id)
} else this.id
targetUin = if (target is Group) {
Group.calculateGroupUinByGroupCode(target.id)
} else target.id
return this
check(this != target) { "sender and target mustn't be the same" }
kind = when {
this is Group || target is Group -> OfflineMessageSource.Kind.GROUP
this is Member || target is Member -> OfflineMessageSource.Kind.TEMP
this is Bot && target is Friend -> OfflineMessageSource.Kind.FRIEND
this is Friend && target is Bot -> OfflineMessageSource.Kind.FRIEND
else -> throw IllegalArgumentException("Cannot determine source kind for sender $this and target $target")
}
return this@MessageSourceBuilderImpl
}
}
@JvmSynthetic
internal fun MessageSource.toMutableOffline(): MutableOfflineMessageSourceByOnline =
MutableOfflineMessageSourceByOnline(this)
internal class MutableOfflineMessageSourceByOnline(
origin: MessageSource
) : OfflineMessageSource(), MessageSourceAmender {
override var kind: Kind = determineKind(origin)
override var fromUin: Long
get() = fromId
set(value) {
fromId = value
}
override var targetUin: Long
get() = targetId
set(value) {
targetId = value
}
override var bot: Bot = origin.bot
override var id: Int = origin.id
override var internalId: Int = origin.internalId
override var time: Int = origin.time
override var fromId: Long = origin.fromId
override var targetId: Long = origin.targetId
override var originalMessage: MessageChain = origin.originalMessage
}
fun
private fun determineKind(source: MessageSource): OfflineMessageSource.Kind {
return when {
source.isAboutGroup() -> OfflineMessageSource.Kind.GROUP
source.isAboutFriend() -> OfflineMessageSource.Kind.FRIEND
source.isAboutTemp() -> OfflineMessageSource.Kind.TEMP
else -> error("stub")
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment