diff --git a/mirai-core-api/src/commonMain/kotlin/event/events/group.kt b/mirai-core-api/src/commonMain/kotlin/event/events/group.kt index 20b1c544c..7566e4d8c 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/events/group.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/events/group.kt @@ -9,7 +9,9 @@ @file:JvmMultifileClass @file:JvmName("BotEventsKt") -@file:Suppress("unused", "FunctionName", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "DEPRECATION_ERROR") +@file:Suppress("unused", "FunctionName", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "DEPRECATION_ERROR", + "MemberVisibilityCanBePrivate" +) package net.mamoe.mirai.event.events @@ -28,8 +30,8 @@ import java.util.concurrent.atomic.AtomicBoolean /** * 机器人被踢出群或在其他客户端主动退出一个群. 在事件广播前 [Bot.groups] 就已删除这个群. */ -public sealed class BotLeaveEvent : BotEvent, Packet, AbstractEvent() { - public abstract val group: Group +public sealed class BotLeaveEvent : BotEvent, Packet, AbstractEvent(), GroupMemberInfoChangeEvent { + public abstract override val group: Group /** * 机器人主动退出一个群. @@ -64,7 +66,7 @@ public data class BotGroupPermissionChangeEvent @MiraiInternalApi constructor( public override val group: Group, public val origin: MemberPermission, public val new: MemberPermission -) : BotPassiveEvent, GroupEvent, Packet, AbstractEvent() +) : BotPassiveEvent, GroupEvent, Packet, AbstractEvent(), GroupMemberInfoChangeEvent /** * Bot 被禁言 @@ -75,7 +77,7 @@ public data class BotMuteEvent @MiraiInternalApi constructor( * 操作人. */ public val operator: NormalMember -) : GroupEvent, Packet, BotPassiveEvent, AbstractEvent() { +) : GroupEvent, Packet, BotPassiveEvent, AbstractEvent(), GroupMemberInfoChangeEvent { public override val group: Group get() = operator.group } @@ -88,7 +90,7 @@ public data class BotUnmuteEvent @MiraiInternalApi constructor( * 操作人. */ public val operator: NormalMember -) : GroupEvent, Packet, BotPassiveEvent, AbstractEvent() { +) : GroupEvent, Packet, BotPassiveEvent, AbstractEvent(), GroupMemberInfoChangeEvent { public override val group: Group get() = operator.group } @@ -96,7 +98,7 @@ public data class BotUnmuteEvent @MiraiInternalApi constructor( /** * Bot 成功加入了一个新群 */ -public sealed class BotJoinGroupEvent : GroupEvent, BotPassiveEvent, Packet, AbstractEvent() { +public sealed class BotJoinGroupEvent : GroupEvent, BotPassiveEvent, Packet, AbstractEvent(), GroupMemberInfoChangeEvent { public abstract override val group: Group /** @@ -164,7 +166,7 @@ public data class GroupNameChangeEvent @MiraiInternalApi constructor( * 操作人. 为 null 时则是机器人操作 */ public override val operator: NormalMember? -) : GroupSettingChangeEvent, Packet, GroupOperableEvent, AbstractEvent() +) : GroupSettingChangeEvent, Packet, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent /** * 入群公告改变. 此事件广播前修改就已经完成. @@ -177,7 +179,7 @@ public data class GroupEntranceAnnouncementChangeEvent @MiraiInternalApi constru * 操作人. 为 null 时则是机器人操作 */ public override val operator: NormalMember? -) : GroupSettingChangeEvent, Packet, GroupOperableEvent, AbstractEvent() +) : GroupSettingChangeEvent, Packet, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent /** @@ -191,7 +193,7 @@ public data class GroupMuteAllEvent @MiraiInternalApi constructor( * 操作人. 为 null 时则是机器人操作 */ public override val operator: NormalMember? -) : GroupSettingChangeEvent, Packet, GroupOperableEvent, AbstractEvent() +) : GroupSettingChangeEvent, Packet, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent /** @@ -205,7 +207,7 @@ public data class GroupAllowAnonymousChatEvent @MiraiInternalApi constructor( * 操作人. 为 null 时则是机器人操作 */ public override val operator: NormalMember? -) : GroupSettingChangeEvent, Packet, GroupOperableEvent, AbstractEvent() +) : GroupSettingChangeEvent, Packet, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent /** @@ -216,7 +218,7 @@ public data class GroupAllowConfessTalkEvent @MiraiInternalApi constructor( public override val new: Boolean, public override val group: Group, public val isByBot: Boolean // 无法获取操作人 -) : GroupSettingChangeEvent, Packet, AbstractEvent() +) : GroupSettingChangeEvent, Packet, AbstractEvent(), GroupMemberInfoChangeEvent /** * 群 "允许群员邀请好友加群" 功能状态改变. 此事件广播前修改就已经完成. @@ -229,7 +231,7 @@ public data class GroupAllowMemberInviteEvent @MiraiInternalApi constructor( * 操作人. 为 null 时则是机器人操作 */ public override val operator: NormalMember? -) : GroupSettingChangeEvent, Packet, GroupOperableEvent, AbstractEvent() +) : GroupSettingChangeEvent, Packet, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent // endregion @@ -245,7 +247,7 @@ public data class GroupAllowMemberInviteEvent @MiraiInternalApi constructor( public sealed class MemberJoinEvent( public override val member: NormalMember ) : GroupMemberEvent, BotPassiveEvent, Packet, - AbstractEvent() { + AbstractEvent(), GroupMemberInfoChangeEvent { /** * 被邀请加入群 */ @@ -282,7 +284,7 @@ public sealed class MemberJoinEvent( /** * 成员已经离开群的事件. 在事件广播前成员就已经从 [Group.members] 中删除 */ -public sealed class MemberLeaveEvent : GroupMemberEvent, AbstractEvent() { +public sealed class MemberLeaveEvent : GroupMemberEvent, AbstractEvent(), GroupMemberInfoChangeEvent { /** * 成员被踢出群. 成员不可能是机器人自己. */ @@ -320,13 +322,13 @@ public data class BotInvitedJoinGroupRequestEvent @MiraiInternalApi constructor( * 邀请入群的账号的 id */ public val invitorId: Long, - public val groupId: Long, + public override val groupId: Long, public val groupName: String, /** * 邀请人昵称 */ public val invitorNick: String -) : BotEvent, Packet, AbstractEvent() { +) : BotEvent, Packet, AbstractEvent(), BaseGroupMemberInfoChangeEvent { /** * 邀请人. 若在事件发生后邀请人已经被删除好友, [invitor] 为 `null`. */ @@ -360,7 +362,7 @@ public data class MemberJoinRequestEvent @MiraiInternalApi constructor( * 申请入群的账号的 id */ val fromId: Long, - val groupId: Long, + override val groupId: Long, val groupName: String, /** * 申请人昵称 @@ -370,7 +372,7 @@ public data class MemberJoinRequestEvent @MiraiInternalApi constructor( * 邀请人 id(如果是邀请入群) */ val invitorId: Long? = null -) : BotEvent, Packet, AbstractEvent() { +) : BotEvent, Packet, AbstractEvent(), BaseGroupMemberInfoChangeEvent { /** * 相关群. 若在事件发生后机器人退出这个群, [group] 为 `null`. */ @@ -471,7 +473,7 @@ public data class MemberCardChangeEvent @MiraiInternalApi constructor( public val new: String, public override val member: NormalMember -) : GroupMemberEvent, Packet, AbstractEvent() +) : GroupMemberEvent, Packet, AbstractEvent(), GroupMemberInfoChangeEvent /** * 成员群头衔改动. 一定为群主操作 @@ -495,7 +497,7 @@ public data class MemberSpecialTitleChangeEvent @MiraiInternalApi constructor( * 为 null 时则是机器人操作. */ public override val operator: NormalMember? -) : GroupMemberEvent, GroupOperableEvent, AbstractEvent() +) : GroupMemberEvent, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent // endregion @@ -509,7 +511,7 @@ public data class MemberPermissionChangeEvent @MiraiInternalApi constructor( public override val member: NormalMember, public val origin: MemberPermission, public val new: MemberPermission -) : GroupMemberEvent, BotPassiveEvent, Packet, AbstractEvent() +) : GroupMemberEvent, BotPassiveEvent, Packet, AbstractEvent(), GroupMemberInfoChangeEvent // endregion @@ -528,7 +530,7 @@ public data class MemberMuteEvent @MiraiInternalApi constructor( * 操作人. 为 null 则为机器人操作 */ public override val operator: Member? -) : GroupMemberEvent, Packet, GroupOperableEvent, AbstractEvent() +) : GroupMemberEvent, Packet, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent /** * 群成员被取消禁言事件. 被禁言的成员都不可能是机器人本人 @@ -541,7 +543,7 @@ public data class MemberUnmuteEvent @MiraiInternalApi constructor( * 操作人. 为 null 则为机器人操作 */ public override val operator: Member? -) : GroupMemberEvent, Packet, GroupOperableEvent, AbstractEvent() +) : GroupMemberEvent, Packet, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent // endregion diff --git a/mirai-core-api/src/commonMain/kotlin/event/events/types.kt b/mirai-core-api/src/commonMain/kotlin/event/events/types.kt index 9e90afb58..aa2b25f4b 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/events/types.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/events/types.kt @@ -16,6 +16,7 @@ import net.mamoe.mirai.Bot import net.mamoe.mirai.contact.* import net.mamoe.mirai.event.Event import net.mamoe.mirai.internal.network.Packet +import net.mamoe.mirai.utils.MiraiInternalApi /** * 有关一个 [Bot] 的事件 @@ -110,6 +111,19 @@ public interface GroupMemberEvent : GroupEvent, UserEvent { override val user: Member get() = member } +/** + * 用于更新缓存, 请勿使用. + */ +@MiraiInternalApi +internal interface BaseGroupMemberInfoChangeEvent : BotEvent { + val groupId: Long +} // for cache + +@MiraiInternalApi +internal interface GroupMemberInfoChangeEvent : BotEvent, GroupEvent, BaseGroupMemberInfoChangeEvent { + override val groupId: Long get() = group.id +} // for cache + public interface OtherClientEvent : BotEvent, Packet { public val client: OtherClient override val bot: Bot get() = client.bot diff --git a/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt b/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt index 806fb727b..10a5d1cbf 100644 --- a/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt +++ b/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt @@ -347,6 +347,39 @@ public open class BotConfiguration { // open for Java } + /** + * 非 `null` 时启用群成员列表缓存, 加快初始化速度. 在启用后将会在下载群成员列表后保存到文件, 并在修改时自动保存. + * @since 2.4 + * @see enableGroupMemberListCache + */ + public var groupMemberListCache: GroupMemberListCache? = GroupMemberListCache() + + /** + * 群成员列表缓存设置. + * @since 2.4 + * @see groupMemberListCache + */ + public class GroupMemberListCache @JvmOverloads constructor( + /** + * 缓存文件位置, 相对于 [workingDir] 的路径. + */ + public val cacheDir: File = File("cache"), + /** + * 在有好友列表修改是 + */ + public val saveIntervalMillis: Long = 60_000, + ) + + /** + * 启用群成员列表缓存. + * @since 2.4 + * @see BotConfiguration.enableGroupMemberListCache + */ + public fun enableGroupMemberListCache() { + friendListCache = FriendListCache() + } + + /** * 使用当前协程的 [coroutineContext] 作为 [parentCoroutineContext]. * diff --git a/mirai-core/src/commonMain/kotlin/MiraiImpl.kt b/mirai-core/src/commonMain/kotlin/MiraiImpl.kt index 71d91a3c0..6babe0880 100644 --- a/mirai-core/src/commonMain/kotlin/MiraiImpl.kt +++ b/mirai-core/src/commonMain/kotlin/MiraiImpl.kt @@ -20,6 +20,7 @@ import kotlinx.coroutines.withContext import kotlinx.io.core.discardExact import kotlinx.io.core.readBytes import kotlinx.serialization.json.* +import net.mamoe.kjbb.JvmBlockingBridge import net.mamoe.mirai.* import net.mamoe.mirai.contact.* import net.mamoe.mirai.data.* diff --git a/mirai-core/src/commonMain/kotlin/QQAndroidBot.kt b/mirai-core/src/commonMain/kotlin/QQAndroidBot.kt index 57d5eef1d..fd1ed3cee 100644 --- a/mirai-core/src/commonMain/kotlin/QQAndroidBot.kt +++ b/mirai-core/src/commonMain/kotlin/QQAndroidBot.kt @@ -78,19 +78,24 @@ internal class QQAndroidBot constructor( override val friends: ContactList = ContactList() val friendListCache: FriendListCache? by lazy { - configuration.friendListCache?.cacheFile?.run { - val ret = loadAs(FriendListCache.serializer(), JsonForCache) ?: FriendListCache() + configuration.friendListCache?.cacheFile?.let { cacheFile -> + val ret = configuration.workingDir.resolve(cacheFile).loadAs(FriendListCache.serializer(), JsonForCache) ?: FriendListCache() @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") bot.eventChannel.parentScope(this@QQAndroidBot) .subscribeAlways { friendListSaver?.notice() } - ret } } + val groupMemberListCaches: GroupMemberListCaches? by lazy { + if (configuration.groupMemberListCache!= null) { + GroupMemberListCaches(this) + } else null + } + private val friendListSaver by lazy { configuration.friendListCache?.let { friendListCache: BotConfiguration.FriendListCache -> @@ -99,11 +104,10 @@ internal class QQAndroidBot constructor( } } } - fun saveFriendCache() { val friendListCache = friendListCache if (friendListCache != null) { - configuration.friendListCache?.cacheFile?.run { + configuration.friendListCache?.cacheFile?.let { configuration.workingDir.resolve(it) }?.run { createFileIfNotExists() writeText(JsonForCache.encodeToString(FriendListCache.serializer(), friendListCache)) bot.network.logger.info { "Saved ${friendListCache.list.size} friends to local cache." } diff --git a/mirai-core/src/commonMain/kotlin/network/ContactListCache.kt b/mirai-core/src/commonMain/kotlin/network/ContactListCache.kt new file mode 100644 index 000000000..f5fde74c8 --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/network/ContactListCache.kt @@ -0,0 +1,126 @@ +/* + * Copyright 2019-2021 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + +package net.mamoe.mirai.internal.network + +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json +import net.mamoe.mirai.internal.QQAndroidBot +import net.mamoe.mirai.internal.contact.info.FriendInfoImpl +import net.mamoe.mirai.internal.contact.info.MemberInfoImpl +import net.mamoe.mirai.internal.network.protocol.data.jce.StTroopNum +import net.mamoe.mirai.internal.utils.ScheduledJob +import net.mamoe.mirai.utils.createFileIfNotExists +import net.mamoe.mirai.utils.info +import net.mamoe.mirai.utils.runBIO +import java.io.File +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ConcurrentLinkedQueue +import kotlin.time.milliseconds + +internal val JsonForCache = Json { + encodeDefaults = true + ignoreUnknownKeys = true + isLenient = true +} + +@Serializable +internal data class FriendListCache( + var friendListSeq: Long = 0, + /** + * 实际上是个序列号, 不是时间 + */ + var timeStamp: Long = 0, + var list: List = emptyList(), +) + +@Serializable +internal data class GroupMemberListCache( + var troopMemberNumSeq: Long, + var list: List = emptyList(), +) + +internal fun GroupMemberListCache.isValid(stTroopNum: StTroopNum): Boolean { + return this.list.size == stTroopNum.dwMemberNum?.toInt() && this.troopMemberNumSeq == stTroopNum.dwMemberNumSeq +} + +internal class GroupMemberListCaches( + private val bot: QQAndroidBot, +) { + init { + @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") + bot.eventChannel.parentScope(bot) + .subscribeAlways { + groupListSaver.notice() + } + + } + + private val changedGroups: MutableCollection = ConcurrentLinkedQueue() + private val groupListSaver by lazy { + ScheduledJob(bot.coroutineContext, bot.configuration.groupMemberListCache!!.saveIntervalMillis.milliseconds) { + runBIO { saveGroupCaches() } + } + } + + fun reportChanged(groupCode: Long) { + changedGroups.add(groupCode) + groupListSaver.notice() + } + + private fun takeCurrentChangedGroups(): Map { + val ret = HashMap() + changedGroups.removeIf { + ret[it] = get(it) + true + } + return ret + } + + private val cacheDir by lazy { + bot.configuration.groupMemberListCache!!.cacheDir.let { bot.configuration.workingDir.resolve(it) } + } + + private fun resolveCacheFile(groupCode: Long): File { + cacheDir.mkdirs() + return cacheDir.resolve("$groupCode.json") + } + + fun saveGroupCaches() { + val currentChanged = takeCurrentChangedGroups() + if (currentChanged.isNotEmpty()) { + for ((id, cache) in currentChanged) { + val file = resolveCacheFile(id) + file.createFileIfNotExists() + file.writeText(JsonForCache.encodeToString(GroupMemberListCache.serializer(), cache)) + } + bot.network.logger.info { "Saved ${currentChanged.size} groups to local cache." } + } + } + + val map: MutableMap = ConcurrentHashMap() + + fun retainAll(list: Collection) { + this.map.keys.retainAll(list) + } + + operator fun get(id: Long): GroupMemberListCache { + return map.getOrPut(id) { + val file = resolveCacheFile(id) + if (file.exists() && file.isFile) { + val text = file.readText() + if (text.isNotBlank()) { + return JsonForCache.decodeFromString(GroupMemberListCache.serializer(), text) + } + } + + GroupMemberListCache(0, emptyList()) + } + } +} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/network/ContactUpdater.kt b/mirai-core/src/commonMain/kotlin/network/ContactUpdater.kt index 2d50bdf06..e60e883e3 100644 --- a/mirai-core/src/commonMain/kotlin/network/ContactUpdater.kt +++ b/mirai-core/src/commonMain/kotlin/network/ContactUpdater.kt @@ -18,11 +18,13 @@ import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit import net.mamoe.mirai.Mirai import net.mamoe.mirai.data.FriendInfo +import net.mamoe.mirai.data.MemberInfo import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.contact.FriendImpl import net.mamoe.mirai.internal.contact.GroupImpl import net.mamoe.mirai.internal.contact.info.FriendInfoImpl import net.mamoe.mirai.internal.contact.info.GroupInfoImpl +import net.mamoe.mirai.internal.contact.info.MemberInfoImpl import net.mamoe.mirai.internal.contact.info.StrangerInfoImpl import net.mamoe.mirai.internal.contact.toMiraiFriendInfo import net.mamoe.mirai.internal.network.protocol.data.jce.StTroopNum @@ -141,19 +143,38 @@ internal class ContactUpdaterImpl( private fun addFriendToBot(it: FriendInfo) = bot.friends.delegate.add(FriendImpl(bot, bot.coroutineContext, it)) - private suspend fun addGroupToBot(stTroopNum: StTroopNum) { + private suspend fun addGroupToBot(stTroopNum: StTroopNum) = stTroopNum.run { + suspend fun refreshGroupMemberList(): Sequence { + return Mirai.getRawGroupMemberList( + bot, + groupUin, + groupCode, + dwGroupOwnerUin + ) + } + + val cache = bot.groupMemberListCaches?.get(groupCode) + val members = if (cache != null) { + if (cache.isValid(stTroopNum)) { + cache.list.asSequence().also { + bot.network.logger.info { "Loaded ${cache.list.size} members from local cache for group ${groupName} (${groupCode})" } + } + } else refreshGroupMemberList().also { sequence -> + cache.troopMemberNumSeq = dwMemberNumSeq ?: 0 + cache.list = sequence.mapTo(ArrayList()) { it as MemberInfoImpl } + bot.groupMemberListCaches!!.reportChanged(groupCode) + } + } else { + refreshGroupMemberList() + } + bot.groups.delegate.add( GroupImpl( bot = bot, coroutineContext = bot.coroutineContext, - id = stTroopNum.groupCode, + id = groupCode, groupInfo = GroupInfoImpl(stTroopNum), - members = Mirai.getRawGroupMemberList( - bot, - stTroopNum.groupUin, - stTroopNum.groupCode, - stTroopNum.dwGroupOwnerUin - ) + members = members ) ) } @@ -184,9 +205,7 @@ internal class ContactUpdaterImpl( if (initGroupOk) { return } - logger.info { "Start syncing group config..." } TroopManagement.GetTroopConfig(bot.client).sendAndExpect() - logger.info { "Successfully synced group config." } logger.info { "Start loading group list..." } val troopListData = FriendList.GetTroopListSimplify(bot.client) @@ -203,7 +222,9 @@ internal class ContactUpdaterImpl( } } } + logger.info { "Successfully loaded group list: ${troopListData.groups.size} in total." } + bot.groupMemberListCaches?.saveGroupCaches() initGroupOk = true } diff --git a/mirai-core/src/commonMain/kotlin/network/FriendListCache.kt b/mirai-core/src/commonMain/kotlin/network/FriendListCache.kt deleted file mode 100644 index b4786c15d..000000000 --- a/mirai-core/src/commonMain/kotlin/network/FriendListCache.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2019-2021 Mamoe Technologies and contributors. - * - * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. - * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. - * - * https://github.com/mamoe/mirai/blob/master/LICENSE - */ - -package net.mamoe.mirai.internal.network - -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json -import net.mamoe.mirai.internal.contact.info.FriendInfoImpl - -internal val JsonForCache = Json { - encodeDefaults = true - ignoreUnknownKeys = true - isLenient = true -} - -@Serializable -internal data class FriendListCache( - var friendListSeq: Long = 0, - /** - * 实际上是个序列号, 不是时间 - */ - var timeStamp: Long = 0, - var list: List = emptyList(), -) \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/list/StrangerList.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/list/StrangerList.kt index f1a0f6b95..44af3e529 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/list/StrangerList.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/list/StrangerList.kt @@ -30,7 +30,7 @@ import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf internal class StrangerList { object GetStrangerList : OutgoingPacketFactory("OidbSvc.0x5d2_0") { - class Response(val result: Int, val strangerList: List) : Packet { + class Response(val result: Int, val strangerList: List, val origin: Oidb0x5d2.RspGetList?) : Packet { override fun toString(): String { return "StrangerList.GetStrangerList.Response(result=$result)" } @@ -61,10 +61,10 @@ internal class StrangerList { if (pkg.result == 0) { pkg.bodybuffer.loadAs(Oidb0x5d2.RspBody.serializer()).rspGetList!!.let { bot.client.strangerSeq = it.seq - return Response(pkg.result, it.list) + return Response(pkg.result, it.list, it) } } - return Response(pkg.result, emptyList()) + return Response(pkg.result, emptyList(), null) } }