Commit 405696d9 authored by Him188's avatar Him188

Use sequenceId as `MessageSource.id`, await sequenceId on `Group.sendMessage`

parent c695f2cd
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:Suppress("EXPERIMENTAL_API_USAGE", "DEPRECATION_ERROR", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") @file:Suppress("EXPERIMENTAL_API_USAGE", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
package net.mamoe.mirai.qqandroid package net.mamoe.mirai.qqandroid
...@@ -322,7 +322,7 @@ internal abstract class QQAndroidBotBase constructor( ...@@ -322,7 +322,7 @@ internal abstract class QQAndroidBotBase constructor(
bot.asQQAndroidBot().client, bot.asQQAndroidBot().client,
group.id, group.id,
source.sequenceId, source.sequenceId,
source.id source.random
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>() ).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
} }
} }
...@@ -336,7 +336,7 @@ internal abstract class QQAndroidBotBase constructor( ...@@ -336,7 +336,7 @@ internal abstract class QQAndroidBotBase constructor(
bot.client, bot.client,
source.targetId, source.targetId,
source.sequenceId, source.sequenceId,
source.id, source.random,
source.time source.time
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>() ).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
} }
...@@ -352,7 +352,7 @@ internal abstract class QQAndroidBotBase constructor( ...@@ -352,7 +352,7 @@ internal abstract class QQAndroidBotBase constructor(
source.target.group.id, source.target.group.id,
source.targetId, source.targetId,
source.sequenceId, source.sequenceId,
source.id, source.random,
source.time source.time
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>() ).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
} }
...@@ -366,7 +366,7 @@ internal abstract class QQAndroidBotBase constructor( ...@@ -366,7 +366,7 @@ internal abstract class QQAndroidBotBase constructor(
bot.client, bot.client,
source.targetId, source.targetId,
source.sequenceId, source.sequenceId,
source.id, source.random,
source.time source.time
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>() ).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
} }
...@@ -379,7 +379,7 @@ internal abstract class QQAndroidBotBase constructor( ...@@ -379,7 +379,7 @@ internal abstract class QQAndroidBotBase constructor(
source.targetId, // groupUin source.targetId, // groupUin
source.targetId, // memberUin source.targetId, // memberUin
source.sequenceId, source.sequenceId,
source.id, source.random,
source.time source.time
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>() ).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
} }
...@@ -388,7 +388,7 @@ internal abstract class QQAndroidBotBase constructor( ...@@ -388,7 +388,7 @@ internal abstract class QQAndroidBotBase constructor(
bot.client, bot.client,
source.targetId, source.targetId,
source.sequenceId, source.sequenceId,
source.id source.random
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>() ).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
} }
} }
......
...@@ -345,6 +345,15 @@ internal class GroupImpl( ...@@ -345,6 +345,15 @@ internal class GroupImpl(
} }
} }
try {
source.ensureSequenceIdAvailable()
} catch (e: Exception) {
bot.network.logger.warning {
"Timeout awaiting sequenceId for group message(${message.contentToString()
.take(10)}). Some features may not work properly"
}
}
return MessageReceipt(source, this, botAsMember) return MessageReceipt(source, this, botAsMember)
} }
......
...@@ -27,16 +27,24 @@ import net.mamoe.mirai.qqandroid.utils.io.serialization.toByteArray ...@@ -27,16 +27,24 @@ import net.mamoe.mirai.qqandroid.utils.io.serialization.toByteArray
internal interface MessageSourceInternal { internal interface MessageSourceInternal {
val sequenceId: Int val sequenceId: Int
val random: Int
@Deprecated("don't use this internally. Use sequenceId or random instead.", level = DeprecationLevel.ERROR)
val id: Int
val isRecalledOrPlanned: MiraiAtomicBoolean val isRecalledOrPlanned: MiraiAtomicBoolean
fun toJceData(): ImMsgBody.SourceMsg fun toJceData(): ImMsgBody.SourceMsg
} }
@Suppress("RedundantSuspendModifier", "unused")
internal suspend inline fun MessageSource.ensureSequenceIdAvailable() { internal suspend inline fun MessageSource.ensureSequenceIdAvailable() {
// obsolete but keep for future
return
/*
if (this is MessageSourceToGroupImpl) { if (this is MessageSourceToGroupImpl) {
this.ensureSequenceIdAvailable() this.ensureSequenceIdAvailable()
} }*/
} }
internal class MessageSourceFromFriendImpl( internal class MessageSourceFromFriendImpl(
...@@ -45,12 +53,13 @@ internal class MessageSourceFromFriendImpl( ...@@ -45,12 +53,13 @@ internal class MessageSourceFromFriendImpl(
) : OnlineMessageSource.Incoming.FromFriend(), MessageSourceInternal { ) : OnlineMessageSource.Incoming.FromFriend(), MessageSourceInternal {
override val sequenceId: Int get() = msg.msgHead.msgSeq override val sequenceId: Int get() = msg.msgHead.msgSeq
override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false) override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false)
override val id: Int get() = msg.msgBody.richText.attr!!.random override val id: Int get() = sequenceId// msg.msgBody.richText.attr!!.random
override val random: Int get() = msg.msgBody.richText.attr!!.random
override val time: Int get() = msg.msgHead.msgTime override val time: Int get() = msg.msgHead.msgTime
override val originalMessage: MessageChain by lazy { msg.toMessageChain(bot, 0, false) } override val originalMessage: MessageChain by lazy { msg.toMessageChain(bot, 0, false) }
override val sender: QQ get() = bot.getFriend(msg.msgHead.fromUin) override val sender: QQ get() = bot.getFriend(msg.msgHead.fromUin)
private val jceData by lazy { msg.toJceDataFriendOrTemp(id) } private val jceData by lazy { msg.toJceDataFriendOrTemp(random) }
override fun toJceData(): ImMsgBody.SourceMsg = jceData override fun toJceData(): ImMsgBody.SourceMsg = jceData
} }
...@@ -96,13 +105,14 @@ internal class MessageSourceFromTempImpl( ...@@ -96,13 +105,14 @@ internal class MessageSourceFromTempImpl(
private val msg: MsgComm.Msg private val msg: MsgComm.Msg
) : OnlineMessageSource.Incoming.FromTemp(), MessageSourceInternal { ) : OnlineMessageSource.Incoming.FromTemp(), MessageSourceInternal {
override val sequenceId: Int get() = msg.msgHead.msgSeq override val sequenceId: Int get() = msg.msgHead.msgSeq
override val random: Int get() = msg.msgBody.richText.attr!!.random
override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false) override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false)
override val id: Int get() = msg.msgBody.richText.attr!!.random override val id: Int get() = sequenceId//
override val time: Int get() = msg.msgHead.msgTime override val time: Int get() = msg.msgHead.msgTime
override val originalMessage: MessageChain by lazy { msg.toMessageChain(bot, 0, false) } override val originalMessage: MessageChain by lazy { msg.toMessageChain(bot, 0, false) }
override val sender: Member get() = with(msg.msgHead) { bot.getGroup(c2cTmpMsgHead!!.groupUin)[fromUin] } override val sender: Member get() = with(msg.msgHead) { bot.getGroup(c2cTmpMsgHead!!.groupUin)[fromUin] }
private val jceData by lazy { msg.toJceDataFriendOrTemp(id) } private val jceData by lazy { msg.toJceDataFriendOrTemp(random) }
override fun toJceData(): ImMsgBody.SourceMsg = jceData override fun toJceData(): ImMsgBody.SourceMsg = jceData
} }
...@@ -112,7 +122,8 @@ internal data class MessageSourceFromGroupImpl( ...@@ -112,7 +122,8 @@ internal data class MessageSourceFromGroupImpl(
) : OnlineMessageSource.Incoming.FromGroup(), MessageSourceInternal { ) : OnlineMessageSource.Incoming.FromGroup(), MessageSourceInternal {
override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false) override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false)
override val sequenceId: Int get() = msg.msgHead.msgSeq override val sequenceId: Int get() = msg.msgHead.msgSeq
override val id: Int get() = msg.msgBody.richText.attr!!.random override val random: Int get() = msg.msgBody.richText.attr!!.random
override val id: Int get() = sequenceId
override val time: Int get() = msg.msgHead.msgTime override val time: Int get() = msg.msgHead.msgTime
override val originalMessage: MessageChain by lazy { override val originalMessage: MessageChain by lazy {
msg.toMessageChain(bot, groupIdOrZero = group.id, onlineSource = false) msg.toMessageChain(bot, groupIdOrZero = group.id, onlineSource = false)
......
...@@ -27,7 +27,8 @@ internal class OfflineMessageSourceImplByMsg( ...@@ -27,7 +27,8 @@ internal class OfflineMessageSourceImplByMsg(
override val bot: Bot override val bot: Bot
) : OfflineMessageSource(), MessageSourceInternal { ) : OfflineMessageSource(), MessageSourceInternal {
override val kind: Kind = if (delegate.msgHead.groupInfo != null) Kind.GROUP else Kind.FRIEND override val kind: Kind = if (delegate.msgHead.groupInfo != null) Kind.GROUP else Kind.FRIEND
override val id: Int override val id: Int get() = sequenceId
override val random: Int
get() = delegate.msgHead.msgUid.toInt() get() = delegate.msgHead.msgUid.toInt()
override val time: Int override val time: Int
get() = delegate.msgHead.msgTime get() = delegate.msgHead.msgTime
...@@ -73,6 +74,8 @@ internal class OfflineMessageSourceImplBySourceMsg( ...@@ -73,6 +74,8 @@ internal class OfflineMessageSourceImplBySourceMsg(
override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false) override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false)
override val sequenceId: Int override val sequenceId: Int
get() = delegate.origSeqs?.first() ?: error("cannot find sequenceId") get() = delegate.origSeqs?.first() ?: error("cannot find sequenceId")
override val random: Int
get() = delegate.pbReserve.loadAs(SourceMsg.ResvAttr.serializer()).origUids?.toInt() ?: 0
override val time: Int get() = delegate.time override val time: Int get() = delegate.time
override val originalMessage: MessageChain by lazy { delegate.toMessageChain(bot, groupIdOrZero) } override val originalMessage: MessageChain by lazy { delegate.toMessageChain(bot, groupIdOrZero) }
/* /*
...@@ -82,9 +85,9 @@ internal class OfflineMessageSourceImplBySourceMsg( ...@@ -82,9 +85,9 @@ internal class OfflineMessageSourceImplBySourceMsg(
delegate.pbReserve.loadAs(SourceMsg.ResvAttr.serializer()).origUids!!.and(0xFFFFFFFF) delegate.pbReserve.loadAs(SourceMsg.ResvAttr.serializer()).origUids!!.and(0xFFFFFFFF)
*/ */
override val id: Int override val id: Int get() = sequenceId
get() = delegate.pbReserve.loadAs(SourceMsg.ResvAttr.serializer()).origUids?.toInt() // delegate.pbReserve.loadAs(SourceMsg.ResvAttr.serializer()).origUids?.toInt()
?: 0 // ?: 0
// override val sourceMessage: MessageChain get() = delegate.toMessageChain() // override val sourceMessage: MessageChain get() = delegate.toMessageChain()
override val fromId: Long get() = delegate.senderUin override val fromId: Long get() = delegate.senderUin
......
...@@ -34,7 +34,7 @@ private fun <T> T.toJceDataImpl(): ImMsgBody.SourceMsg ...@@ -34,7 +34,7 @@ private fun <T> T.toJceDataImpl(): ImMsgBody.SourceMsg
where T : MessageSourceInternal, T : MessageSource { where T : MessageSourceInternal, T : MessageSource {
val elements = originalMessage.toRichTextElems(forGroup = false, withGeneralFlags = true) val elements = originalMessage.toRichTextElems(forGroup = false, withGeneralFlags = true)
val messageUid: Long = sequenceId.toLong().shl(32) or id.toLong().and(0xffFFffFF) val messageUid: Long = sequenceId.toLong().shl(32) or random.toLong().and(0xffFFffFF)
return ImMsgBody.SourceMsg( return ImMsgBody.SourceMsg(
origSeqs = listOf(sequenceId), origSeqs = listOf(sequenceId),
senderUin = fromId, senderUin = fromId,
...@@ -71,7 +71,7 @@ private fun <T> T.toJceDataImpl(): ImMsgBody.SourceMsg ...@@ -71,7 +71,7 @@ private fun <T> T.toJceDataImpl(): ImMsgBody.SourceMsg
internal class MessageSourceToFriendImpl( internal class MessageSourceToFriendImpl(
override val sequenceId: Int, override val sequenceId: Int,
override val id: Int, override val random: Int,
override val time: Int, override val time: Int,
override val originalMessage: MessageChain, override val originalMessage: MessageChain,
override val sender: Bot, override val sender: Bot,
...@@ -79,6 +79,8 @@ internal class MessageSourceToFriendImpl( ...@@ -79,6 +79,8 @@ internal class MessageSourceToFriendImpl(
) : OnlineMessageSource.Outgoing.ToFriend(), MessageSourceInternal { ) : OnlineMessageSource.Outgoing.ToFriend(), MessageSourceInternal {
override val bot: Bot override val bot: Bot
get() = sender get() = sender
override val id: Int
get() = sequenceId
override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false) override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false)
private val jceData by lazy { toJceDataImpl() } private val jceData by lazy { toJceDataImpl() }
override fun toJceData(): ImMsgBody.SourceMsg = jceData override fun toJceData(): ImMsgBody.SourceMsg = jceData
...@@ -86,7 +88,7 @@ internal class MessageSourceToFriendImpl( ...@@ -86,7 +88,7 @@ internal class MessageSourceToFriendImpl(
internal class MessageSourceToTempImpl( internal class MessageSourceToTempImpl(
override val sequenceId: Int, override val sequenceId: Int,
override val id: Int, override val random: Int,
override val time: Int, override val time: Int,
override val originalMessage: MessageChain, override val originalMessage: MessageChain,
override val sender: Bot, override val sender: Bot,
...@@ -94,18 +96,22 @@ internal class MessageSourceToTempImpl( ...@@ -94,18 +96,22 @@ internal class MessageSourceToTempImpl(
) : OnlineMessageSource.Outgoing.ToTemp(), MessageSourceInternal { ) : OnlineMessageSource.Outgoing.ToTemp(), MessageSourceInternal {
override val bot: Bot override val bot: Bot
get() = sender get() = sender
override val id: Int
get() = sequenceId
override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false) override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false)
private val jceData by lazy { toJceDataImpl() } private val jceData by lazy { toJceDataImpl() }
override fun toJceData(): ImMsgBody.SourceMsg = jceData override fun toJceData(): ImMsgBody.SourceMsg = jceData
} }
internal class MessageSourceToGroupImpl( internal class MessageSourceToGroupImpl(
override val id: Int, override val random: Int,
override val time: Int, override val time: Int,
override val originalMessage: MessageChain, override val originalMessage: MessageChain,
override val sender: Bot, override val sender: Bot,
override val target: Group override val target: Group
) : OnlineMessageSource.Outgoing.ToGroup(), MessageSourceInternal { ) : OnlineMessageSource.Outgoing.ToGroup(), MessageSourceInternal {
override val id: Int
get() = sequenceId
override val bot: Bot override val bot: Bot
get() = sender get() = sender
override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false) override var isRecalledOrPlanned: MiraiAtomicBoolean = MiraiAtomicBoolean(false)
...@@ -113,7 +119,11 @@ internal class MessageSourceToGroupImpl( ...@@ -113,7 +119,11 @@ internal class MessageSourceToGroupImpl(
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
override val sequenceId: Int override val sequenceId: Int
get() = sequenceIdDeferred.getCompleted() get() = when {
sequenceIdDeferred.isCompleted -> sequenceIdDeferred.getCompleted()
!sequenceIdDeferred.isActive -> 0
else -> error("sequenceId not yet available")
}
@OptIn(MiraiExperimentalAPI::class) @OptIn(MiraiExperimentalAPI::class)
internal fun startWaitingSequenceId(coroutineScope: CoroutineScope) { internal fun startWaitingSequenceId(coroutineScope: CoroutineScope) {
......
...@@ -371,7 +371,7 @@ internal class MessageSvc { ...@@ -371,7 +371,7 @@ internal class MessageSvc {
): OutgoingPacket { ): OutgoingPacket {
val rand = Random.nextInt().absoluteValue val rand = Random.nextInt().absoluteValue
val source = MessageSourceToFriendImpl( val source = MessageSourceToFriendImpl(
id = rand, random = rand,
sender = client.bot, sender = client.bot,
target = qq, target = qq,
time = currentTimeSeconds.toInt(), time = currentTimeSeconds.toInt(),
...@@ -405,7 +405,7 @@ internal class MessageSvc { ...@@ -405,7 +405,7 @@ internal class MessageSvc {
) )
), ),
msgSeq = source.sequenceId, msgSeq = source.sequenceId,
msgRand = source.id, msgRand = source.random,
syncCookie = SyncCookie(time = source.time.toLong()).toByteArray(SyncCookie.serializer()) syncCookie = SyncCookie(time = source.time.toLong()).toByteArray(SyncCookie.serializer())
// msgVia = 1 // msgVia = 1
) )
...@@ -420,7 +420,7 @@ internal class MessageSvc { ...@@ -420,7 +420,7 @@ internal class MessageSvc {
sourceCallback: (MessageSourceToTempImpl) -> Unit sourceCallback: (MessageSourceToTempImpl) -> Unit
): OutgoingPacket { ): OutgoingPacket {
val source = MessageSourceToTempImpl( val source = MessageSourceToTempImpl(
id = Random.nextInt().absoluteValue, random = Random.nextInt().absoluteValue,
sender = client.bot, sender = client.bot,
target = member, target = member,
time = currentTimeSeconds.toInt(), time = currentTimeSeconds.toInt(),
...@@ -453,7 +453,7 @@ internal class MessageSvc { ...@@ -453,7 +453,7 @@ internal class MessageSvc {
) )
), ),
msgSeq = source.sequenceId, msgSeq = source.sequenceId,
msgRand = source.id, msgRand = source.random,
syncCookie = SyncCookie(time = source.time.toLong()).toByteArray(SyncCookie.serializer()) syncCookie = SyncCookie(time = source.time.toLong()).toByteArray(SyncCookie.serializer())
) )
) )
...@@ -468,7 +468,7 @@ internal class MessageSvc { ...@@ -468,7 +468,7 @@ internal class MessageSvc {
): OutgoingPacket { ): OutgoingPacket {
val source = MessageSourceToGroupImpl( val source = MessageSourceToGroupImpl(
id = Random.nextInt().absoluteValue, random = Random.nextInt().absoluteValue,
sender = client.bot, sender = client.bot,
target = group, target = group,
time = currentTimeSeconds.toInt(), time = currentTimeSeconds.toInt(),
...@@ -504,7 +504,7 @@ internal class MessageSvc { ...@@ -504,7 +504,7 @@ internal class MessageSvc {
) )
), ),
msgSeq = client.atomicNextMessageSequenceId(), msgSeq = client.atomicNextMessageSequenceId(),
msgRand = source.id, msgRand = source.random,
syncCookie = EMPTY_BYTE_ARRAY, syncCookie = EMPTY_BYTE_ARRAY,
msgVia = 1 msgVia = 1
) )
......
...@@ -53,10 +53,9 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSo ...@@ -53,10 +53,9 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSo
/** /**
* 消息 id. * 消息 id.
* 当 [OnlineMessageSource] 时为随机数. * 此值在同一会话中唯一且有顺序.
* 当 [OfflineMessageSource] 时可能为 0, 取决于服务器是否提供这个值.
*/ */
abstract val id: Int // random abstract val id: Int
/** /**
* 发送时间时间戳, 单位为秒. * 发送时间时间戳, 单位为秒.
...@@ -335,12 +334,6 @@ abstract class OfflineMessageSource : MessageSource() { ...@@ -335,12 +334,6 @@ abstract class OfflineMessageSource : MessageSource() {
*/ */
abstract val kind: Kind abstract val kind: Kind
/**
* 消息 id.
* 服务器不一定提供 id. 因此此值可能为 0
*/
abstract override val id: Int
// final override fun toString(): String = "OfflineMessageSource(sender=$senderId, target=$targetId)" // final override fun toString(): String = "OfflineMessageSource(sender=$senderId, target=$targetId)"
} }
......
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