mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-12 05:50:27 +08:00
[core] Fix forward message seq-id; Fix ordering on iOS (#2191)
This commit is contained in:
parent
6b8c054948
commit
a3cb15f13a
@ -129,7 +129,18 @@ internal open class MultiMsgUploader(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val existsIds = mutableSetOf<Long>()
|
val existsIds = mutableSetOf<Long>()
|
||||||
|
val existsSeqs = mutableSetOf<Int>()
|
||||||
|
|
||||||
|
class PendingMessage(
|
||||||
|
var seq: Int, var uid: Int,
|
||||||
|
var convertedMessageChain: MessageChain,
|
||||||
|
val msg: ForwardMessage.INode,
|
||||||
|
)
|
||||||
|
|
||||||
|
val pendingMessages = mutableListOf<PendingMessage>()
|
||||||
|
var hasMsgSource = false
|
||||||
|
|
||||||
|
// Step1: Convert message & Get message ids
|
||||||
msgs.forEach { msg ->
|
msgs.forEach { msg ->
|
||||||
var msgChain = msg.messageChain
|
var msgChain = msg.messageChain
|
||||||
msgChain[ForwardMessage]?.let { nestedForward ->
|
msgChain[ForwardMessage]?.let { nestedForward ->
|
||||||
@ -142,27 +153,112 @@ internal open class MultiMsgUploader(
|
|||||||
var uid: Int = -1
|
var uid: Int = -1
|
||||||
msg.messageChain.sourceOrNull?.let { source ->
|
msg.messageChain.sourceOrNull?.let { source ->
|
||||||
source as MessageSourceInternal
|
source as MessageSourceInternal
|
||||||
|
hasMsgSource = true
|
||||||
|
|
||||||
seq = source.sequenceIds.first()
|
seq = source.sequenceIds.first()
|
||||||
uid = source.internalIds.first()
|
uid = source.internalIds.first()
|
||||||
}
|
}
|
||||||
while (true) {
|
|
||||||
if (seq != -1 && uid != -1) {
|
|
||||||
if (existsIds.add(seq.concatAsLong(uid))) break
|
|
||||||
}
|
|
||||||
seq = random.nextInt().absoluteValue
|
|
||||||
uid = random.nextInt().absoluteValue
|
|
||||||
}
|
|
||||||
|
|
||||||
|
pendingMessages.add(
|
||||||
|
PendingMessage(
|
||||||
|
seq = seq, uid = uid, convertedMessageChain = msgChain,
|
||||||
|
msg = msg
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// Step2: Fix duplicated messages
|
||||||
|
if (hasMsgSource) {
|
||||||
|
pendingMessages.forEach { pm ->
|
||||||
|
if (pm.seq == -1 && pm.uid == -1) return@forEach
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (existsSeqs.add(pm.seq)) return@forEach
|
||||||
|
|
||||||
|
pm.seq++
|
||||||
|
pm.uid = random.nextInt().absoluteValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step3: Fill custom messages.....
|
||||||
|
val randSeqStart = random.nextInt().absoluteValue.coerceAtMost(
|
||||||
|
Int.MAX_VALUE - pendingMessages.size - 15405
|
||||||
|
).coerceAtLeast(141225)
|
||||||
|
|
||||||
|
var seqStart = if (hasMsgSource) {
|
||||||
|
val idx = pendingMessages.indexOfFirst { it.seq != -1 }
|
||||||
|
// Assertion: idx != -1
|
||||||
|
pendingMessages[idx].seq - idx
|
||||||
|
} else randSeqStart
|
||||||
|
|
||||||
|
pendingMessages.forEach { pm ->
|
||||||
|
if (pm.seq != -1 && pm.uid != -1) {
|
||||||
|
seqStart = pm.seq + 1
|
||||||
|
} else {
|
||||||
|
pm.seq = seqStart
|
||||||
|
seqStart++
|
||||||
|
|
||||||
|
do { // For patch: no duplicated id
|
||||||
|
pm.uid = random.nextInt().absoluteValue
|
||||||
|
} while (!existsIds.add(pm.seq.concatAsLong(pm.uid)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step4: Verify sequence
|
||||||
|
existsSeqs.clear()
|
||||||
|
var lastSeq = 0
|
||||||
|
var needPatch = false
|
||||||
|
for (pm in pendingMessages) {
|
||||||
|
if (pm.seq <= lastSeq) {
|
||||||
|
needPatch = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
lastSeq = pm.seq
|
||||||
|
if (!existsSeqs.add(lastSeq)) {
|
||||||
|
needPatch = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Step 5: Patch
|
||||||
|
if (needPatch) {
|
||||||
|
existsIds.clear()
|
||||||
|
existsSeqs.clear()
|
||||||
|
|
||||||
|
var ranSeqStart = randSeqStart
|
||||||
|
for (pm in pendingMessages) {
|
||||||
|
val oldSeq = pm.seq
|
||||||
|
val oldUid = pm.uid
|
||||||
|
pm.seq = ranSeqStart
|
||||||
|
ranSeqStart++
|
||||||
|
pm.uid = random.nextInt().absoluteValue
|
||||||
|
|
||||||
|
for (otherpms in pendingMessages) {
|
||||||
|
val quoteReply = otherpms.convertedMessageChain[QuoteReply] ?: continue
|
||||||
|
val srco = quoteReply.source
|
||||||
|
val src = srco as? MessageSourceInternal ?: continue
|
||||||
|
if (src.sequenceIds.first() == oldSeq && src.internalIds.first() == oldUid) {
|
||||||
|
val newSrc = MessageSourceBuilder()
|
||||||
|
.allFrom(srco)
|
||||||
|
.id(pm.seq)
|
||||||
|
.internalId(pm.uid)
|
||||||
|
.time(srco.time)
|
||||||
|
.build(botId = client.uin, kind = srco.kind)
|
||||||
|
otherpms.convertedMessageChain = otherpms.convertedMessageChain + newSrc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Step6: Convert
|
||||||
|
pendingMessages.forEach { pm ->
|
||||||
val msg0 = MsgComm.Msg(
|
val msg0 = MsgComm.Msg(
|
||||||
msgHead = MsgComm.MsgHead(
|
msgHead = MsgComm.MsgHead(
|
||||||
fromUin = msg.senderId,
|
fromUin = pm.msg.senderId,
|
||||||
toUin = if (isLong) {
|
toUin = if (isLong) {
|
||||||
contact.userIdOrNull ?: 0
|
contact.userIdOrNull ?: 0
|
||||||
} else 0,
|
} else 0,
|
||||||
msgSeq = seq,
|
msgSeq = pm.seq,
|
||||||
msgTime = msg.time,
|
msgTime = pm.msg.time,
|
||||||
msgUid = 0x01000000000000000L or uid.toLongUnsigned(),
|
msgUid = 0x01000000000000000L or pm.uid.toLongUnsigned(),
|
||||||
mutiltransHead = MsgComm.MutilTransHead(
|
mutiltransHead = MsgComm.MutilTransHead(
|
||||||
status = 0,
|
status = 0,
|
||||||
msgId = 1,
|
msgId = 1,
|
||||||
@ -170,13 +266,14 @@ internal open class MultiMsgUploader(
|
|||||||
msgType = 82, // troop,
|
msgType = 82, // troop,
|
||||||
groupInfo = MsgComm.GroupInfo(
|
groupInfo = MsgComm.GroupInfo(
|
||||||
groupCode = if (contact is Group) contact.groupCode else 0L,
|
groupCode = if (contact is Group) contact.groupCode else 0L,
|
||||||
groupCard = msg.senderName, // Cinnamon
|
groupCard = pm.msg.senderName, // Cinnamon
|
||||||
),
|
),
|
||||||
isSrcMsg = false,
|
isSrcMsg = false,
|
||||||
), msgBody = ImMsgBody.MsgBody(
|
), msgBody = ImMsgBody.MsgBody(
|
||||||
richText = ImMsgBody.RichText(
|
richText = ImMsgBody.RichText(
|
||||||
elems = MessageProtocolFacade.encode(
|
elems = MessageProtocolFacade.encode(
|
||||||
msgChain, messageTarget = contact, withGeneralFlags = false, isForward = true
|
pm.convertedMessageChain,
|
||||||
|
messageTarget = contact, withGeneralFlags = false, isForward = true
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user