Multiple MessageSource.id and MessageSource.internalId for split sources now, and split messages in the future. Close #618

This commit is contained in:
Him188 2020-12-02 10:46:06 +08:00
parent 8fdfe830fe
commit 64bd63d7a0
19 changed files with 370 additions and 256 deletions

View File

@ -107,8 +107,8 @@ public interface IMirai : LowLevelApiAccessor {
/**
* 构造一个 [OfflineMessageSource]
*
* @param id [MessageSource.id]
* @param internalId [MessageSource.internalId]
* @param ids [MessageSource.ids]
* @param internalIds [MessageSource.internalIds]
*
* @param fromUin 为用户时为 [Friend.id], 为群时需使用 [Group.calculateGroupUinByGroupCode] 计算
* @param targetUin 为用户时为 [Friend.id], 为群时需使用 [Group.calculateGroupUinByGroupCode] 计算
@ -118,7 +118,7 @@ public interface IMirai : LowLevelApiAccessor {
bot: Bot,
kind: OfflineMessageSource.Kind,
fromUin: Long, targetUin: Long,
id: Int, time: Int, internalId: Int,
ids: IntArray, time: Int, internalIds: IntArray,
originalMessage: MessageChain
): OfflineMessageSource

View File

@ -259,16 +259,16 @@ public sealed class MessageRecallEvent : BotEvent, AbstractEvent() {
public abstract val authorId: Long
/**
* 消息 id.
* @see MessageSource.id
* 消息 ids.
* @see MessageSource.ids
*/
public abstract val messageId: Int
public abstract val messageIds: IntArray
/**
* 消息内部 id.
* @see MessageSource.id
* 消息内部 ids.
* @see MessageSource.ids
*/
public abstract val messageInternalId: Int
public abstract val messageInternalIds: IntArray
/**
* 原发送时间
@ -280,8 +280,8 @@ public sealed class MessageRecallEvent : BotEvent, AbstractEvent() {
*/
public data class FriendRecall internal constructor(
public override val bot: Bot,
public override val messageId: Int,
public override val messageInternalId: Int,
public override val messageIds: IntArray,
public override val messageInternalIds: IntArray,
public override val messageTime: Int,
/**
* 撤回操作人, 好友的 [User.id]
@ -290,6 +290,30 @@ public sealed class MessageRecallEvent : BotEvent, AbstractEvent() {
) : MessageRecallEvent(), Packet {
public override val authorId: Long
get() = bot.id
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as FriendRecall
if (bot != other.bot) return false
if (!messageIds.contentEquals(other.messageIds)) return false
if (!messageInternalIds.contentEquals(other.messageInternalIds)) return false
if (messageTime != other.messageTime) return false
if (operator != other.operator) return false
return true
}
override fun hashCode(): Int {
var result = bot.hashCode()
result = 31 * result + messageIds.contentHashCode()
result = 31 * result + messageInternalIds.contentHashCode()
result = 31 * result + messageTime
result = 31 * result + operator.hashCode()
return result
}
}
/**
@ -298,15 +322,43 @@ public sealed class MessageRecallEvent : BotEvent, AbstractEvent() {
public data class GroupRecall @PublishedApi internal constructor(
public override val bot: Bot,
public override val authorId: Long,
public override val messageId: Int,
public override val messageInternalId: Int,
public override val messageIds: IntArray,
public override val messageInternalIds: IntArray,
public override val messageTime: Int,
/**
* 操作人. null 时则为 [Bot] 操作.
*/
public override val operator: Member?,
public override val group: Group
) : MessageRecallEvent(), GroupOperableEvent, Packet
) : MessageRecallEvent(), GroupOperableEvent, Packet {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as GroupRecall
if (bot != other.bot) return false
if (authorId != other.authorId) return false
if (!messageIds.contentEquals(other.messageIds)) return false
if (!messageInternalIds.contentEquals(other.messageInternalIds)) return false
if (messageTime != other.messageTime) return false
if (operator != other.operator) return false
if (group != other.group) return false
return true
}
override fun hashCode(): Int {
var result = bot.hashCode()
result = 31 * result + authorId.hashCode()
result = 31 * result + messageIds.contentHashCode()
result = 31 * result + messageInternalIds.contentHashCode()
result = 31 * result + messageTime
result = 31 * result + (operator?.hashCode() ?: 0)
result = 31 * result + group.hashCode()
return result
}
}
}
public val MessageRecallEvent.GroupRecall.author: Member

View File

@ -78,7 +78,7 @@ public abstract class MessageEvent : ContactMessage(),
/**
* 消息内容.
*
* 第一个元素一定为 [MessageSource], 存储此消息的发送人, 发送时间, 收信人, 消息 id 等数据.
* 第一个元素一定为 [MessageSource], 存储此消息的发送人, 发送时间, 收信人, 消息 ids 等数据.
* 随后的元素为拥有顺序的真实消息内容.
*/
public abstract override val message: MessageChain

View File

@ -16,7 +16,6 @@ import net.mamoe.mirai.Mirai
import net.mamoe.mirai.contact.*
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.utils.MiraiExperimentalApi
import kotlin.jvm.JvmSynthetic
/**
* 发送消息后得到的回执. 可用于撤回, 引用回复等.
@ -32,7 +31,7 @@ import kotlin.jvm.JvmSynthetic
* @see User.sendMessage 发送群消息, 返回回执此对象
* @see Member.sendMessage 发送临时消息, 返回回执此对象
*
* @see MessageReceipt.sourceId id
* @see MessageReceipt.sourceIds ids
* @see MessageReceipt.sourceTime 源时间
*/
public open class MessageReceipt<out C : Contact> @MiraiExperimentalApi("The constructor is subject to change.") constructor(
@ -95,23 +94,23 @@ public suspend inline fun <C : Contact> MessageReceipt<C>.quoteReply(message: St
/**
* 获取源消息 [MessageSource.id]
* 获取源消息 [MessageSource.ids]
*
* @see MessageSource.id
* @see MessageSource.ids
*/
@get:JvmSynthetic
public inline val MessageReceipt<*>.sourceId: Int
get() = this.source.id
public inline val MessageReceipt<*>.sourceIds: IntArray
get() = this.source.ids
/**
* 获取源消息 [MessageSource.internalId]
* 获取源消息 [MessageSource.internalIds]
*
* @see MessageSource.id
* @see MessageSource.ids
*/
@get:JvmSynthetic
public inline val MessageReceipt<*>.sourceInternalId: Int
get() = this.source.internalId
public inline val MessageReceipt<*>.sourceInternalIds: IntArray
get() = this.source.internalIds
/**
* 获取源消息 [MessageSource.time]

View File

@ -22,9 +22,6 @@ import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.quote
import net.mamoe.mirai.message.recall
import net.mamoe.mirai.utils.LazyProperty
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**
* 消息源. 消息源存在于 [MessageChain] , 用于表示这个消息的来源, 也可以用来分辨 [MessageChain].
@ -36,8 +33,8 @@ import kotlin.jvm.JvmSynthetic
* [MessageSource] metadata (元数据), form & target, content 组成
*
* #### metadata
* - [id] 消息 id (序列号)
* - [internalId] 消息内部 id
* - [ids] 消息 ids (序列号)
* - [internalIds] 消息内部 ids
* - [time] 时间
*
* 官方客户端通过 metadata 这三个数据定位消息, 撤回和引用回复都是如此.
@ -51,9 +48,9 @@ import kotlin.jvm.JvmSynthetic
*
* ### 使用
*
* 消息源可用于 [引用回复][QuoteReply] [撤回][Bot.recall].
* 消息源可用于 [引用回复][QuoteReply] [撤回][IMirai.recall].
*
* @see Bot.recall 撤回一条消息
* @see IMirai.recall 撤回一条消息
* @see MessageSource.quote 引用这条消息, 创建 [MessageChain]
*
* @see OnlineMessageSource 在线消息的 [MessageSource]
@ -74,28 +71,28 @@ public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<Me
public abstract val bot: Bot
/**
* 消息 id (序列号). 在获取失败时 (概率很低) `-1`.
* 消息 ids (序列号). 在获取失败时 (概率很低) `-1`.
**
* #### 值域
* 值的范围约为 [UShort] 的范围.
*
* #### 顺序
* 群消息的 id 由服务器维护. 好友消息的 id mirai 维护.
* id 不一定从 0 开始.
* 群消息的 ids 由服务器维护. 好友消息的 ids mirai 维护.
* ids 不一定从 0 开始.
*
* - 在同一个群的消息中此值随每条消息递增 1, 但此行为由服务器决定, mirai 不保证自增顺序.
* - 在好友消息中无法保证每次都递增 1. 也可能会产生大幅跳过的情况.
*/
public abstract val id: Int
public abstract val ids: IntArray
/**
* 内部 id. **仅用于协议模块使用**
* 内部 ids. **仅用于协议模块使用**
*
* 值没有顺序, 也可能为 0, 取决于服务器是否提供.
*
* 在事件中和在引用中无法保证同一条消息的 [internalId] 相同.
* 在事件中和在引用中无法保证同一条消息的 [internalIds] 相同.
*/
public abstract val internalId: Int
public abstract val internalIds: IntArray
/**
* 发送时间时间戳, 单位为秒.
@ -131,9 +128,9 @@ public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<Me
public abstract val originalMessage: MessageChain
/**
* 返回 `"[mirai:source:$id,$internalId]"`
* 返回 `"[mirai:source:$ids,$internalIds]"`
*/
public final override fun toString(): String = "[mirai:source:$id,$internalId]"
public final override fun toString(): String = "[mirai:source:$ids,$internalIds]"
}
@ -206,7 +203,7 @@ public sealed class OnlineMessageSource : MessageSource() {
public abstract override val target: Friend
public final override val subject: Friend get() = target
// final override fun toString(): String = "OnlineMessageSource.ToFriend(target=${target.id})"
// final override fun toString(): String = "OnlineMessageSource.ToFriend(target=${target.ids})"
}
public abstract class ToTemp : Outgoing() {
@ -250,7 +247,7 @@ public sealed class OnlineMessageSource : MessageSource() {
public abstract override val sender: Friend
public final override val subject: Friend get() = sender
public final override val target: Bot get() = sender.bot
// final override fun toString(): String = "OnlineMessageSource.FromFriend(from=${sender.id})"
// final override fun toString(): String = "OnlineMessageSource.FromFriend(from=${sender.ids})"
}
public abstract class FromTemp : Incoming() {
@ -367,44 +364,44 @@ public suspend inline fun MessageSource.recall(): Unit = Mirai.recall(bot, this)
// For MessageChain
/**
* 消息 id.
* 消息 ids.
*
* 仅从服务器接收的消息 (即来自 [MessageEvent.message]), 或手动添加了 [MessageSource] 元素的 [MessageChain] 才可以获取消息源.
*
* @see MessageSource.id
* @see MessageSource.ids
*/
@get:JvmSynthetic
public val MessageChain.id: Int
get() = this.source.id
public val MessageChain.ids: IntArray
get() = this.source.ids
/**
* 消息内部 id.
* 消息内部 ids.
*
* 仅从服务器接收的消息 (即来自 [MessageEvent.message]), 或手动添加了 [MessageSource] 元素的 [MessageChain] 才可以获取消息源.
*
* @see MessageSource.id
* @see MessageSource.ids
*/
@get:JvmSynthetic
public val MessageChain.internalId: Int
get() = this.source.internalId
public val MessageChain.internalId: IntArray
get() = this.source.internalIds
/**
* 消息时间.
*
* 仅从服务器接收的消息 (即来自 [MessageEvent.message]), 或手动添加了 [MessageSource] 元素的 [MessageChain] 才可以获取消息源.
*
* @see MessageSource.id
* @see MessageSource.ids
*/
@get:JvmSynthetic
public val MessageChain.time: Int
get() = this.source.time
/**
* 消息内部 id.
* 消息内部 ids.
*
* 仅从服务器接收的消息 (即来自 [MessageEvent.message]), 或手动添加了 [MessageSource] 元素的 [MessageChain] 才可以获取. 否则将抛出异常 [NoSuchElementException]
*
* @see MessageSource.id
* @see MessageSource.ids
*/
@get:JvmSynthetic
public val MessageChain.bot: Bot
@ -414,11 +411,24 @@ public val MessageChain.bot: Bot
* 获取这条消息的 [消息源][MessageSource].
*
* 仅从服务器接收的消息 (即来自 [MessageEvent.message]), 或手动添加了 [MessageSource] 元素的 [MessageChain] 才可以获取消息源, 否则将抛出异常 [NoSuchElementException]
*
* @see sourceOrNull
*/
@get:JvmSynthetic
public val MessageChain.source: MessageSource
get() = this.getOrFail(MessageSource)
/**
* 获取这条消息的 [消息源][MessageSource].
*
* 仅从服务器接收的消息 (即来自 [MessageEvent.message]), 或手动添加了 [MessageSource] 元素的 [MessageChain] 才可以获取消息源, 否则返回 `null`
*
* @see source
*/
@get:JvmSynthetic
public val MessageChain.sourceOrNull: MessageSource?
get() = this[MessageSource]
/**
* 撤回这条消息. 可撤回自己 2 分钟内发出的消息, 和任意时间的群成员的消息.
*

View File

@ -52,16 +52,16 @@ public interface MessageSourceAmender {
public var kind: OfflineMessageSource.Kind
public var fromUin: Long
public var targetUin: Long
public var id: Int
public var ids: IntArray
public var time: Int
public var internalId: Int
public var internalIds: IntArray
public var originalMessage: MessageChain
/** 从另一个 [MessageSource] 中复制 [id], [internalId], [time]*/
/** 从另一个 [MessageSource] 中复制 [ids], [internalIds], [time]*/
public fun metadataFrom(another: MessageSource) {
this.id = another.id
this.internalId = another.internalId
this.ids = another.ids
this.internalIds = another.internalIds
this.time = another.time
}
}
@ -78,9 +78,9 @@ public interface MessageSourceAmender {
* ### 参数
* 一个 [OfflineMessageSource] 须要以下参数:
* - 发送人和发送目标: 通过 [MessageSourceBuilder.sendTo] 设置
* - 消息元数据 ( [MessageSource.id], [MessageSource.internalId], [MessageSource.time])
* - 消息元数据 ( [MessageSource.ids], [MessageSource.internalIds], [MessageSource.time])
* 元数据用于 [撤回][MessageSource.recall], [引用回复][MessageSource.quote], 和官方客户端定位原消息.
* 可通过 [MessageSourceBuilder.id], [MessageSourceBuilder.time], [MessageSourceBuilder.internalId] 设置
* 可通过 [MessageSourceBuilder.ids], [MessageSourceBuilder.time], [MessageSourceBuilder.internalIds] 设置
* 可通过 [MessageSourceBuilder.metadata] 从另一个 [MessageSource] 复制
* - 消息内容: 通过 [MessageSourceBuilder.messages] 设置
*
@ -92,7 +92,7 @@ public interface MessageSourceAmender {
* ```
* bot.buildMessageSource {
* bot sendTo target // 指定发送人和发送目标
* metadata(source) // 从另一个消息源复制 id, internalId, time
* metadata(source) // 从另一个消息源复制 ids, internalIds, time
*
* messages { // 指定消息内容
* +"hi"
@ -109,9 +109,9 @@ public fun Bot.buildMessageSource(block: MessageSourceBuilder.() -> Unit): Messa
builder.kind ?: error("You must call `Contact.sendTo(Contact)` when `buildMessageSource`"),
builder.fromUin,
builder.targetUin,
builder.id,
builder.ids,
builder.time,
builder.internalId,
builder.internalIds,
builder.originalMessages.build()
)
}
@ -124,9 +124,9 @@ public abstract class MessageSourceBuilder {
internal abstract var fromUin: Long
internal abstract var targetUin: Long
internal abstract var id: Int
internal abstract var ids: IntArray
internal abstract var time: Int
internal abstract var internalId: Int
internal abstract var internalIds: IntArray
@PublishedApi
internal val originalMessages: MessageChainBuilder = MessageChainBuilder()
@ -135,15 +135,15 @@ public abstract class MessageSourceBuilder {
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.internalId = from.internalId }
public fun internalId(value: Int): MessageSourceBuilder = apply { this.internalId = value }
public fun internalId(from: MessageSource): MessageSourceBuilder = apply { this.internalIds = from.internalIds }
public fun internalId(vararg value: Int): MessageSourceBuilder = apply { this.internalIds = value }
public fun id(from: MessageSource): MessageSourceBuilder = apply { this.id = from.id }
public fun id(value: Int): MessageSourceBuilder = apply { this.id = value }
public fun id(from: MessageSource): MessageSourceBuilder = apply { this.ids = from.ids }
public fun id(vararg value: Int): MessageSourceBuilder = apply { this.ids = value }
/**
* 从另一个 [MessageSource] 复制 [id], [time], [internalId].
* 从另一个 [MessageSource] 复制 [ids], [time], [internalIds].
* 这三个数据决定官方客户端能 "定位" 到的原消息
*/
public fun metadata(from: MessageSource): MessageSourceBuilder = apply {
@ -157,11 +157,11 @@ public abstract class MessageSourceBuilder {
*/
public fun allFrom(source: MessageSource): MessageSourceBuilder {
this.kind = determineKind(source)
this.id = source.id
this.ids = source.ids
this.time = source.time
this.fromUin = source.fromId
this.targetUin = source.targetId
this.internalId = source.internalId
this.internalIds = source.internalIds
this.originalMessages.addAll(source.originalMessage)
return this
}
@ -212,9 +212,9 @@ internal class MessageSourceBuilderImpl : MessageSourceBuilder() {
override var fromUin: Long = 0
override var targetUin: Long = 0
override var id: Int = 0
override var ids: IntArray = intArrayOf()
override var time: Int = currentTimeSeconds.toInt()
override var internalId: Int = 0
override var internalIds: IntArray = intArrayOf()
@JvmSynthetic
override fun ContactOrBot.sendTo(target: ContactOrBot): MessageSourceBuilder {
@ -259,8 +259,8 @@ internal class MutableOfflineMessageSourceByOnline(
targetId = value
}
override var bot: Bot = origin.bot
override var id: Int = origin.id
override var internalId: Int = origin.internalId
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
@ -287,8 +287,8 @@ internal class OfflineMessageSourceByOnline(
else -> error("stub")
}
override val bot: Bot get() = onlineMessageSource.bot
override val id: Int get() = onlineMessageSource.id
override val internalId: Int get() = onlineMessageSource.internalId
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

View File

@ -14,9 +14,6 @@
package net.mamoe.mirai.message.data
import net.mamoe.mirai.Bot
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**
@ -35,7 +32,7 @@ import kotlin.jvm.JvmSynthetic
* 引用回复的原消息内容完全由 [source] [MessageSource.originalMessage] 控制, 客户端不会自行寻找原消息.
*
* #### 客户端内跳转
* 客户端在跳转原消息时, 会通过 [MessageSource.id] metadata
* 客户端在跳转原消息时, 会通过 [MessageSource.ids] metadata
*
* @see MessageSource 获取有关消息源的更多信息
*/
@ -47,7 +44,8 @@ public class QuoteReply(public val source: MessageSource) : Message, MessageMeta
public override val key: Message.Key<QuoteReply> get() = Key
public override fun toString(): String = "[mirai:quote:${source.id},${source.internalId}]"
// TODO: 2020/12/2 QuoteReply.toString
public override fun toString(): String = "[mirai:quote:${source.ids},${source.internalIds}]"
public override fun equals(other: Any?): Boolean = other is QuoteReply && other.source == this.source
public override fun hashCode(): Int = source.hashCode()
}

View File

@ -7,7 +7,31 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:JvmMultifileClass
@file:JvmName("MiraiUtils")
package net.mamoe.mirai.utils
public inline fun <A, reified B> Array<A>.mapToArray(block: (element: A) -> B): Array<B> {
val result = arrayOfNulls<B>(size)
this.forEachIndexed { index, element ->
result[index] = block(element)
}
return result.cast()
}
public inline fun <A, reified B> Collection<A>.mapToArray(block: (element: A) -> B): Array<B> {
val result = arrayOfNulls<B>(size)
this.forEachIndexed { index, element ->
result[index] = block(element)
}
return result.cast()
}
public inline fun <A> Collection<A>.mapToIntArray(block: (element: A) -> Int): IntArray {
val result = IntArray(size)
this.forEachIndexed { index, element ->
result[index] = block(element)
}
return result.cast()
}

View File

@ -0,0 +1,15 @@
/*
* 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:JvmMultifileClass
@file:JvmName("MiraiUtils")
package net.mamoe.mirai.utils
public fun Int.toLongUnsigned(): Long = this.toLong().and(0xFFFF_FFFF)

View File

@ -7,12 +7,13 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:JvmMultifileClass
@file:JvmName("MiraiUtils")
package net.mamoe.mirai.utils
inline fun <reified T> Any?.cast(): T = this as T
public inline fun <reified T> Any?.cast(): T = this as T
inline fun <reified T> Any?.safeCast(): T? = this as? T
public inline fun <reified T> Any?.safeCast(): T? = this as? T
inline fun <reified T> Any?.castOrNull(): T? = this as? T
public inline fun <reified T> Any?.castOrNull(): T? = this as? T

View File

@ -280,8 +280,8 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
MessageRecallEvent.GroupRecall(
bot,
source.fromId,
source.id,
source.internalId,
source.ids,
source.internalIds,
source.time,
null,
group
@ -291,8 +291,8 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
PbMessageSvc.PbMsgWithDraw.createForGroupMessage(
bot.asQQAndroidBot().client,
group.id,
source.sequenceId,
source.internalId
source.sequenceIds,
source.internalIds
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
}
}
@ -305,8 +305,8 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
PbMessageSvc.PbMsgWithDraw.createForFriendMessage(
bot.client,
source.targetId,
source.sequenceId,
source.internalId,
source.sequenceIds,
source.internalIds,
source.time
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
}
@ -321,8 +321,8 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
bot.client,
(source.target.group as GroupImpl).uin,
source.targetId,
source.sequenceId,
source.internalId,
source.sequenceIds,
source.internalIds,
source.time
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
}
@ -335,8 +335,8 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
PbMessageSvc.PbMsgWithDraw.createForFriendMessage(
bot.client,
source.targetId,
source.sequenceId,
source.internalId,
source.sequenceIds,
source.internalIds,
source.time
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
}
@ -348,8 +348,8 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
bot.client,
source.targetId, // groupUin
source.targetId, // memberUin
source.sequenceId,
source.internalId,
source.sequenceIds,
source.internalIds,
source.time
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
}
@ -357,8 +357,8 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
PbMessageSvc.PbMsgWithDraw.createForGroupMessage(
bot.client,
source.targetId,
source.sequenceId,
source.internalId
source.sequenceIds,
source.internalIds
).sendAndExpect<PbMessageSvc.PbMsgWithDraw.Response>()
}
}
@ -370,7 +370,7 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
// 1001: No message meets the requirements (实际上是没权限, 管理员在尝试撤回群主的消息)
// 154: timeout
// 3: <no message>
check(response is PbMessageSvc.PbMsgWithDraw.Response.Success) { "Failed to recall message #${source.id}: $response" }
check(response is PbMessageSvc.PbMsgWithDraw.Response.Success) { "Failed to recall message #${source.ids}: $response" }
}
@LowLevelApi
@ -813,28 +813,28 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
kind: OfflineMessageSource.Kind,
fromUin: Long,
targetUin: Long,
id: Int,
ids: IntArray,
time: Int,
internalId: Int,
internalIds: IntArray,
originalMessage: MessageChain
): OfflineMessageSource {
return object : OfflineMessageSource(), MessageSourceInternal {
override val kind: Kind get() = kind
override val id: Int get() = id
override val ids: IntArray get() = ids
override val bot: Bot get() = bot
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 val sequenceIds: IntArray = ids
override val internalIds: IntArray = internalIds
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
override fun toJceData(): ImMsgBody.SourceMsg {
return ImMsgBody.SourceMsg(
origSeqs = listOf(sequenceId),
origSeqs = sequenceIds,
senderUin = fromUin,
toUin = 0,
flag = 1,

View File

@ -29,11 +29,11 @@ import net.mamoe.mirai.message.data.OnlineMessageSource
import java.util.concurrent.atomic.AtomicBoolean
internal interface MessageSourceInternal {
val sequenceId: Int
val internalId: Int // randomId
val sequenceIds: IntArray
val internalIds: IntArray // randomId
@Deprecated("don't use this internally. Use sequenceId or random instead.", level = DeprecationLevel.ERROR)
val id: Int
val ids: IntArray
val isRecalledOrPlanned: AtomicBoolean
@ -66,25 +66,25 @@ internal class MessageSourceFromFriendImpl(
override val bot: Bot,
val msg: MsgComm.Msg
) : OnlineMessageSource.Incoming.FromFriend(), MessageSourceInternal {
override val sequenceId: Int get() = msg.msgHead.msgSeq
override val sequenceIds: IntArray get() = intArrayOf(msg.msgHead.msgSeq)
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
override val id: Int get() = sequenceId// msg.msgBody.richText.attr!!.random
override val internalId: Int get() = msg.msgBody.richText.attr!!.random
override val ids: IntArray get() = sequenceIds// msg.msgBody.richText.attr!!.random
override val internalIds: IntArray get() = intArrayOf(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(internalId) }
private val jceData by lazy { msg.toJceDataFriendOrTemp(internalIds) }
override fun toJceData(): ImMsgBody.SourceMsg = jceData
}
private fun MsgComm.Msg.toJceDataFriendOrTemp(id: Int): ImMsgBody.SourceMsg {
private fun MsgComm.Msg.toJceDataFriendOrTemp(ids: IntArray): ImMsgBody.SourceMsg {
val elements = msgBody.richText.elems.toMutableList().also {
if (it.last().elemFlags2 == null) it.add(ImMsgBody.Elem(elemFlags2 = ImMsgBody.ElemFlags2()))
}
return ImMsgBody.SourceMsg(
origSeqs = listOf(this.msgHead.msgSeq),
origSeqs = intArrayOf(this.msgHead.msgSeq),
senderUin = this.msgHead.fromUin,
toUin = this.msgHead.toUin,
flag = 1,
@ -92,7 +92,7 @@ private fun MsgComm.Msg.toJceDataFriendOrTemp(id: Int): ImMsgBody.SourceMsg {
type = 0,
time = this.msgHead.msgTime,
pbReserve = SourceMsg.ResvAttr(
origUids = id.toLong() and 0xFFFF_FFFF
origUids = ids.map { it.toLong() and 0xFFFF_FFFF }
).toByteArray(SourceMsg.ResvAttr.serializer()),
srcMsg = MsgComm.Msg(
msgHead = MsgComm.MsgHead(
@ -102,7 +102,7 @@ private fun MsgComm.Msg.toJceDataFriendOrTemp(id: Int): ImMsgBody.SourceMsg {
c2cCmd = this.msgHead.c2cCmd,
msgSeq = this.msgHead.msgSeq,
msgTime = this.msgHead.msgTime,
msgUid = id.toLong() and 0xFFFF_FFFF, // ok
msgUid = ids.single().toLong() and 0xFFFF_FFFF, // ok
// groupInfo = MsgComm.GroupInfo(groupCode = this.msgHead.groupInfo.groupCode),
isSrcMsg = true
),
@ -119,15 +119,15 @@ internal class MessageSourceFromTempImpl(
override val bot: Bot,
private val msg: MsgComm.Msg
) : OnlineMessageSource.Incoming.FromTemp(), MessageSourceInternal {
override val sequenceId: Int get() = msg.msgHead.msgSeq
override val internalId: Int get() = msg.msgBody.richText.attr!!.random
override val sequenceIds: IntArray get() = intArrayOf(msg.msgHead.msgSeq)
override val internalIds: IntArray get() = intArrayOf(msg.msgBody.richText.attr!!.random)
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
override val id: Int get() = sequenceId//
override val ids: IntArray get() = sequenceIds//
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(internalId) }
private val jceData by lazy { msg.toJceDataFriendOrTemp(internalIds) }
override fun toJceData(): ImMsgBody.SourceMsg = jceData
}
@ -136,9 +136,9 @@ internal data class MessageSourceFromGroupImpl(
private val msg: MsgComm.Msg
) : OnlineMessageSource.Incoming.FromGroup(), MessageSourceInternal {
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
override val sequenceId: Int get() = msg.msgHead.msgSeq
override val internalId: Int get() = msg.msgBody.richText.attr!!.random
override val id: Int get() = sequenceId
override val sequenceIds: IntArray get() = intArrayOf(msg.msgHead.msgSeq)
override val internalIds: IntArray get() = intArrayOf(msg.msgBody.richText.attr!!.random)
override val ids: IntArray get() = sequenceIds
override val time: Int get() = msg.msgHead.msgTime
override val originalMessage: MessageChain by lazy {
msg.toMessageChain(bot, groupIdOrZero = group.id, onlineSource = false)
@ -159,7 +159,7 @@ internal data class MessageSourceFromGroupImpl(
override fun toJceData(): ImMsgBody.SourceMsg {
return ImMsgBody.SourceMsg(
origSeqs = listOf(msg.msgHead.msgSeq),
origSeqs = intArrayOf(msg.msgHead.msgSeq),
senderUin = msg.msgHead.fromUin,
toUin = 0,
flag = 1,

View File

@ -19,6 +19,7 @@ import net.mamoe.mirai.internal.network.protocol.packet.EMPTY_BYTE_ARRAY
import net.mamoe.mirai.internal.utils.io.serialization.loadAs
import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.OfflineMessageSource
import net.mamoe.mirai.utils.mapToIntArray
import java.util.concurrent.atomic.AtomicBoolean
@ -28,9 +29,8 @@ internal class OfflineMessageSourceImplByMsg(
override val bot: Bot
) : OfflineMessageSource(), MessageSourceInternal {
override val kind: Kind = if (delegate.msgHead.groupInfo != null) Kind.GROUP else Kind.FRIEND
override val id: Int get() = sequenceId
override val internalId: Int
get() = delegate.msgHead.msgUid.toInt()
override val ids: IntArray get() = sequenceIds
override val internalIds: IntArray = intArrayOf(delegate.msgHead.msgUid.toInt())
override val time: Int
get() = delegate.msgHead.msgTime
override val fromId: Long
@ -38,20 +38,20 @@ internal class OfflineMessageSourceImplByMsg(
override val targetId: Long
get() = delegate.msgHead.groupInfo?.groupCode ?: delegate.msgHead.toUin
override val originalMessage: MessageChain by lazy {
delegate.toMessageChain(bot,
delegate.toMessageChain(
bot,
groupIdOrZero = delegate.msgHead.groupInfo?.groupCode ?: 0,
onlineSource = false,
isTemp = delegate.msgHead.c2cTmpMsgHead != null
)
}
override val sequenceId: Int
get() = delegate.msgHead.msgSeq
override val sequenceIds: IntArray = intArrayOf(delegate.msgHead.msgSeq)
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
override fun toJceData(): ImMsgBody.SourceMsg {
return ImMsgBody.SourceMsg(
origSeqs = listOf(delegate.msgHead.msgSeq),
origSeqs = intArrayOf(delegate.msgHead.msgSeq),
senderUin = delegate.msgHead.fromUin,
toUin = 0,
flag = 1,
@ -73,20 +73,19 @@ internal class OfflineMessageSourceImplBySourceMsg(
override val kind: Kind get() = if (delegate.srcMsg == null) Kind.GROUP else Kind.FRIEND
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
override val sequenceId: Int
get() = delegate.origSeqs.firstOrNull() ?: error("cannot find sequenceId")
override val internalId: Int
get() = delegate.pbReserve.loadAs(SourceMsg.ResvAttr.serializer()).origUids?.toInt() ?: 0
override val sequenceIds: IntArray = delegate.origSeqs
override val internalIds: IntArray = delegate.pbReserve.loadAs(SourceMsg.ResvAttr.serializer())
.origUids?.mapToIntArray { it.toInt() } ?: intArrayOf()
override val time: Int get() = delegate.time
override val originalMessage: MessageChain by lazy { delegate.toMessageChain(bot, groupIdOrZero) }
/*
override val id: Long
override val ids: Long
get() = (delegate.origSeqs?.firstOrNull()
?: error("cannot find sequenceId from ImMsgBody.SourceMsg")).toLong().shl(32) or
delegate.pbReserve.loadAs(SourceMsg.ResvAttr.serializer()).origUids!!.and(0xFFFFFFFF)
*/
override val id: Int get() = sequenceId
override val ids: IntArray get() = sequenceIds
// delegate.pbReserve.loadAs(SourceMsg.ResvAttr.serializer()).origUids?.toInt()
// ?: 0

View File

@ -24,6 +24,7 @@ import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
import net.mamoe.mirai.internal.network.protocol.data.proto.SourceMsg
import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.OnlinePushPbPushGroupMsg.SendGroupMessageReceipt
import net.mamoe.mirai.internal.network.protocol.packet.chat.toLongUnsigned
import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.MessageSource
@ -35,27 +36,30 @@ 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 internalId.toLong().and(0xffFFffFF)
val pdReserve = SourceMsg.ResvAttr(
origUids = sequenceIds.zip(internalIds)
.map { (seq, internal) -> seq.toLong().shl(32) or internal.toLongUnsigned() }
)
return ImMsgBody.SourceMsg(
origSeqs = listOf(sequenceId),
origSeqs = sequenceIds,
senderUin = fromId,
toUin = targetId,
flag = 1,
elems = elements,
type = 0,
time = time,
pbReserve = SourceMsg.ResvAttr(
origUids = messageUid
).toByteArray(SourceMsg.ResvAttr.serializer()),
pbReserve = pdReserve.toByteArray(SourceMsg.ResvAttr.serializer()),
srcMsg = MsgComm.Msg(
msgHead = MsgComm.MsgHead(
fromUin = fromId, // qq
toUin = targetId, // group
msgType = 9, // 82?
c2cCmd = 11,
msgSeq = sequenceId,
msgSeq = sequenceIds.single(), // TODO !!
msgTime = time,
msgUid = messageUid, // ok
msgUid = pdReserve.origUids!!.single(), // TODO !!
// groupInfo = MsgComm.GroupInfo(groupCode = delegate.msgHead.groupInfo.groupCode),
isSrcMsg = true
),
@ -71,8 +75,8 @@ private fun <T> T.toJceDataImpl(): ImMsgBody.SourceMsg
}
internal class MessageSourceToFriendImpl(
override val sequenceId: Int,
override val internalId: Int,
override val sequenceIds: IntArray,
override val internalIds: IntArray,
override val time: Int,
override val originalMessage: MessageChain,
override val sender: Bot,
@ -80,16 +84,16 @@ internal class MessageSourceToFriendImpl(
) : OnlineMessageSource.Outgoing.ToFriend(), MessageSourceInternal {
override val bot: Bot
get() = sender
override val id: Int
get() = sequenceId
override val ids: IntArray
get() = sequenceIds
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
private val jceData by lazy { toJceDataImpl() }
override fun toJceData(): ImMsgBody.SourceMsg = jceData
}
internal class MessageSourceToTempImpl(
override val sequenceId: Int,
override val internalId: Int,
override val sequenceIds: IntArray,
override val internalIds: IntArray,
override val time: Int,
override val originalMessage: MessageChain,
override val sender: Bot,
@ -97,8 +101,8 @@ internal class MessageSourceToTempImpl(
) : OnlineMessageSource.Outgoing.ToTemp(), MessageSourceInternal {
override val bot: Bot
get() = sender
override val id: Int
get() = sequenceId
override val ids: IntArray
get() = sequenceIds
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
private val jceData by lazy { toJceDataImpl() }
override fun toJceData(): ImMsgBody.SourceMsg = jceData
@ -106,14 +110,14 @@ internal class MessageSourceToTempImpl(
internal class MessageSourceToGroupImpl(
coroutineScope: CoroutineScope,
override val internalId: Int,
override val internalIds: IntArray,
override val time: Int,
override val originalMessage: MessageChain,
override val sender: Bot,
override val target: Group
) : OnlineMessageSource.Outgoing.ToGroup(), MessageSourceInternal {
override val id: Int
get() = sequenceId
override val ids: IntArray
get() = sequenceIds
override val bot: Bot
get() = sender
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
@ -122,25 +126,27 @@ internal class MessageSourceToGroupImpl(
coroutineScope.asyncFromEventOrNull<SendGroupMessageReceipt, Int>(
timeoutMillis = 3000
) {
if (it.messageRandom == this@MessageSourceToGroupImpl.internalId) {
if (it.messageRandom in this@MessageSourceToGroupImpl.internalIds) {
it.sequenceId
} else null
}
@OptIn(ExperimentalCoroutinesApi::class)
override val sequenceId: Int
get() = when {
sequenceIdDeferred.isCompleted -> sequenceIdDeferred.getCompleted() ?: -1
!sequenceIdDeferred.isActive -> -1
else -> error("sequenceId not yet available")
}
override val sequenceIds: IntArray
get() = intArrayOf(
when {
sequenceIdDeferred.isCompleted -> sequenceIdDeferred.getCompleted() ?: -1
!sequenceIdDeferred.isActive -> -1
else -> error("sequenceIds not yet available")
}
)
suspend fun ensureSequenceIdAvailable() = kotlin.run { sequenceIdDeferred.await() }
private val jceData by lazy {
val elements = originalMessage.toRichTextElems(forGroup = false, withGeneralFlags = true)
ImMsgBody.SourceMsg(
origSeqs = listOf(sequenceId),
origSeqs = sequenceIds,
senderUin = fromId,
toUin = Mirai.calculateGroupUinByGroupCode(targetId),
flag = 1,
@ -148,7 +154,7 @@ internal class MessageSourceToGroupImpl(
type = 0,
time = time,
pbReserve = SourceMsg.ResvAttr(
origUids = internalId.toLong() and 0xffFFffFF // id is actually messageRandom
origUids = internalIds.map { it.toLongUnsigned() } // ids is actually messageRandom
).toByteArray(SourceMsg.ResvAttr.serializer()),
srcMsg = MsgComm.Msg(
msgHead = MsgComm.MsgHead(
@ -156,9 +162,9 @@ internal class MessageSourceToGroupImpl(
toUin = Mirai.calculateGroupUinByGroupCode(targetId), // group
msgType = 82, // 82?
c2cCmd = 1,
msgSeq = sequenceId,
msgSeq = sequenceIds.single(), // TODO !!
msgTime = time,
msgUid = internalId.toLong() and 0xffFFffFF, // ok
msgUid = internalIds.single().toLongUnsigned(), // TODO !!
groupInfo = MsgComm.GroupInfo(groupCode = targetId),
isSrcMsg = true
),

View File

@ -16,7 +16,6 @@ import kotlinx.serialization.protobuf.ProtoType
import net.mamoe.mirai.internal.network.protocol.packet.EMPTY_BYTE_ARRAY
import net.mamoe.mirai.internal.utils.io.ProtoBuf
import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
import kotlin.jvm.JvmField
@Serializable
internal class ImCommon : ProtoBuf {
@ -879,7 +878,7 @@ internal class ImMsgBody : ProtoBuf {
@Serializable
internal class SourceMsg(
@ProtoNumber(1) @JvmField val origSeqs: List<Int> = emptyList(),
@ProtoNumber(1) @JvmField val origSeqs: IntArray = intArrayOf(),
@ProtoNumber(2) @JvmField val senderUin: Long = 0L,
@ProtoNumber(3) @JvmField val time: Int = 0,
@ProtoNumber(4) @JvmField val flag: Int = 0,

View File

@ -13,7 +13,6 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import net.mamoe.mirai.internal.network.protocol.packet.EMPTY_BYTE_ARRAY
import net.mamoe.mirai.internal.utils.io.ProtoBuf
import kotlin.jvm.JvmField
internal class Generalflags : ProtoBuf {
@Serializable
@ -117,7 +116,7 @@ internal class SourceMsg : ProtoBuf {
internal class ResvAttr(
@ProtoNumber(1) @JvmField val richMsg2: ByteArray? = null,
@ProtoNumber(2) @JvmField val oriMsgtype: Int? = null,
@ProtoNumber(3) @JvmField val origUids: Long? = null // 原来是 list
@ProtoNumber(3) @JvmField val origUids: List<Long>? = null
) : ProtoBuf
}

View File

@ -46,66 +46,74 @@ internal class PbMessageSvc {
fun createForGroupMessage(
client: QQAndroidClient,
groupCode: Long,
messageSequenceId: Int, // 56639
messageRandom: Int, // 921878719
messageSequenceId: IntArray, // 56639
messageRandom: IntArray, // 921878719
messageType: Int = 0
): OutgoingPacket = buildOutgoingUniPacket(client) {
writeProtoBuf(
MsgSvc.PbMsgWithDrawReq.serializer(),
MsgSvc.PbMsgWithDrawReq(
groupWithDraw = listOf(
MsgSvc.PbGroupMsgWithDrawReq(
subCmd = 1,
groupType = 0, // 普通群
groupCode = groupCode,
msgList = listOf(
MsgSvc.PbGroupMsgWithDrawReq.MessageInfo(
msgSeq = messageSequenceId,
msgRandom = messageRandom,
msgType = messageType
)
),
userdef = MsgRevokeUserDef.MsgInfoUserDef(
longMessageFlag = 0
).toByteArray(MsgRevokeUserDef.MsgInfoUserDef.serializer())
): OutgoingPacket {
require(messageSequenceId.size == messageRandom.size)
return buildOutgoingUniPacket(client) {
writeProtoBuf(
MsgSvc.PbMsgWithDrawReq.serializer(),
MsgSvc.PbMsgWithDrawReq(
groupWithDraw = listOf(
MsgSvc.PbGroupMsgWithDrawReq(
subCmd = 1,
groupType = 0, // 普通群
groupCode = groupCode,
msgList = messageSequenceId.zip(messageRandom).map { (seq, random) ->
MsgSvc.PbGroupMsgWithDrawReq.MessageInfo(
msgSeq = seq,
msgRandom = random,
msgType = messageType
)
},
userdef = MsgRevokeUserDef.MsgInfoUserDef(
longMessageFlag = 0
).toByteArray(MsgRevokeUserDef.MsgInfoUserDef.serializer())
)
)
)
)
)
}
}
fun createForTempMessage(
client: QQAndroidClient,
groupUin: Long,
toUin: Long,
messageSequenceId: Int, // 56639
messageRandom: Int, // 921878719
messageSequenceId: IntArray, // 56639
messageRandom: IntArray, // 921878719
time: Int
): OutgoingPacket = buildOutgoingUniPacket(client) {
writeProtoBuf(
MsgSvc.PbMsgWithDrawReq.serializer(),
MsgSvc.PbMsgWithDrawReq(
c2cWithDraw = listOf(
MsgSvc.PbC2CMsgWithDrawReq(
subCmd = 1,
msgInfo = listOf(
MsgSvc.PbC2CMsgWithDrawReq.MsgInfo(
fromUin = client.bot.id,
toUin = toUin,
msgSeq = messageSequenceId,
msgRandom = messageRandom,
msgUid = 0x0100000000000000 or (messageRandom.toLong() and 0xFFFFFFFF),
msgTime = time.toLong(),
routingHead = MsgSvc.RoutingHead(
grpTmp = MsgSvc.GrpTmp(groupUin, toUin)
): OutgoingPacket {
require(messageSequenceId.size == messageRandom.size)
return buildOutgoingUniPacket(client) {
writeProtoBuf(
MsgSvc.PbMsgWithDrawReq.serializer(),
MsgSvc.PbMsgWithDrawReq(
c2cWithDraw = listOf(
MsgSvc.PbC2CMsgWithDrawReq(
subCmd = 1,
msgInfo = messageSequenceId.zip(messageRandom).map { (seq, random) ->
MsgSvc.PbC2CMsgWithDrawReq.MsgInfo(
fromUin = client.bot.id,
toUin = toUin,
msgSeq = seq,
msgRandom = random,
msgUid = 0x0100000000000000 or random.toLongUnsigned(),
msgTime = time.toLong(),
routingHead = MsgSvc.RoutingHead(
grpTmp = MsgSvc.GrpTmp(groupUin, toUin)
)
)
)
),
reserved = RESERVED_TEMP
},
reserved = RESERVED_TEMP
)
)
)
)
)
}
}
private val RESERVED_TEMP = "08 01 10 E3 E9 D6 80 02".hexToBytes()
@ -113,36 +121,40 @@ internal class PbMessageSvc {
fun createForFriendMessage(
client: QQAndroidClient,
toUin: Long,
messageSequenceId: Int, // 56639
messageRandom: Int, // 921878719
messageSequenceId: IntArray, // 56639
messageRandom: IntArray, // 921878719
time: Int
): OutgoingPacket = buildOutgoingUniPacket(client) {
writeProtoBuf(
MsgSvc.PbMsgWithDrawReq.serializer(),
MsgSvc.PbMsgWithDrawReq(
c2cWithDraw = listOf(
MsgSvc.PbC2CMsgWithDrawReq(
subCmd = 1,
msgInfo = listOf(
MsgSvc.PbC2CMsgWithDrawReq.MsgInfo(
fromUin = client.bot.id,
toUin = toUin,
msgSeq = messageSequenceId,
msgRandom = messageRandom,
msgUid = 0x0100000000000000 or (messageRandom.toLong() and 0xFFFFFFFF),
msgTime = time.toLong(),
routingHead = MsgSvc.RoutingHead(
c2c = MsgSvc.C2C(
toUin = toUin
): OutgoingPacket {
require(messageSequenceId.size == messageRandom.size)
return buildOutgoingUniPacket(client) {
writeProtoBuf(
MsgSvc.PbMsgWithDrawReq.serializer(),
MsgSvc.PbMsgWithDrawReq(
c2cWithDraw = listOf(
MsgSvc.PbC2CMsgWithDrawReq(
subCmd = 1,
msgInfo = messageSequenceId.zip(messageRandom).map { (seq, random) ->
MsgSvc.PbC2CMsgWithDrawReq.MsgInfo(
fromUin = client.bot.id,
toUin = toUin,
msgSeq = seq,
msgRandom = random,
msgUid = 0x0100000000000000 or random.toLongUnsigned(),
msgTime = time.toLong(),
routingHead = MsgSvc.RoutingHead(
c2c = MsgSvc.C2C(
toUin = toUin
)
)
)
)
),
reserved = byteArrayOf(0x08, 0x00)
},
reserved = byteArrayOf(0x08, 0x00)
)
)
)
)
)
}
}
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {

View File

@ -78,8 +78,8 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
elems = message.toRichTextElems(forGroup = false, withGeneralFlags = true)
)
),
msgSeq = source.sequenceId,
msgRand = source.internalId,
msgSeq = source.sequenceIds.single(),
msgRand = source.internalIds.single(),
syncCookie = client.syncingController.syncCookie ?: byteArrayOf()
// msgVia = 1
)
@ -108,8 +108,8 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
elems = message.toRichTextElems(forGroup = false, withGeneralFlags = true)
)
),
msgSeq = source.sequenceId,
msgRand = source.internalId,
msgSeq = source.sequenceIds.single(),
msgRand = source.internalIds.single(),
syncCookie = client.syncingController.syncCookie ?: byteArrayOf()
)
)
@ -152,7 +152,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
)
),
msgSeq = client.atomicNextMessageSequenceId(),
msgRand = source.internalId,
msgRand = source.internalIds.single(),
syncCookie = EMPTY_BYTE_ARRAY,
msgVia = 1,
msgCtrl = if (isForward) MsgCtrl.MsgCtrl(
@ -186,11 +186,11 @@ internal inline fun MessageSvcPbSendMsg.createToTemp(
callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE)
}
val source = MessageSourceToTempImpl(
internalId = Random.nextInt().absoluteValue,
internalIds = intArrayOf(Random.nextInt().absoluteValue),
sender = client.bot,
target = member,
time = currentTimeSeconds.toInt(),
sequenceId = client.atomicNextMessageSequenceId(),
sequenceIds = intArrayOf(client.atomicNextMessageSequenceId()),
originalMessage = message
)
sourceCallback(source)
@ -214,11 +214,11 @@ internal inline fun MessageSvcPbSendMsg.createToFriend(
}
val rand = Random.nextInt().absoluteValue
val source = MessageSourceToFriendImpl(
internalId = rand,
internalIds = intArrayOf(rand),
sender = client.bot,
target = qq,
time = currentTimeSeconds.toInt(),
sequenceId = client.nextFriendSeq(),
sequenceIds = intArrayOf(client.nextFriendSeq()),
originalMessage = message
)
sourceCallback(source)
@ -242,7 +242,7 @@ internal inline fun MessageSvcPbSendMsg.createToGroup(
}
val source = MessageSourceToGroupImpl(
group,
internalId = Random.nextInt().absoluteValue,
internalIds = intArrayOf(Random.nextInt().absoluteValue),
sender = client.bot,
target = group,
time = currentTimeSeconds.toInt(),

View File

@ -367,8 +367,8 @@ private object Transformers732 : Map<Int, Lambda732> by mapOf(
MessageRecallEvent.GroupRecall(
bot,
pkg.authorUin,
pkg.seq,
pkg.msgRandom,
intArrayOf(pkg.seq),
intArrayOf(pkg.msgRandom),
pkg.time,
operator,
group
@ -440,8 +440,8 @@ internal object Transformers528 : Map<Long, Lambda528> by mapOf(
.filter { it.botUin == bot.id }.map {
MessageRecallEvent.FriendRecall(
bot = bot,
messageId = it.srcId,
messageInternalId = it.srcInternalId,
messageIds = intArrayOf(it.srcId),
messageInternalIds = intArrayOf(it.srcInternalId),
messageTime = it.time,
operator = it.fromUin
)