Commit 3a8b2dd6 authored by Him188's avatar Him188

Fix MessageSource.id from offline quotations

parent 7f498604
...@@ -255,6 +255,10 @@ internal class OfflineMessageSourceImplBySourceMsg( // from others' quotation ...@@ -255,6 +255,10 @@ internal class OfflineMessageSourceImplBySourceMsg( // from others' quotation
override val bot: Bot, override val bot: Bot,
groupIdOrZero: Long groupIdOrZero: Long
) : OfflineMessageSource(), MessageSourceImpl { ) : OfflineMessageSource(), MessageSourceImpl {
init {
println(delegate._miraiContentToString())
}
override val kind: Kind get() = if (delegate.srcMsg == null) Kind.GROUP else Kind.FRIEND override val kind: Kind get() = if (delegate.srcMsg == null) Kind.GROUP else Kind.FRIEND
private val isRecalled: AtomicBoolean = atomic(false) private val isRecalled: AtomicBoolean = atomic(false)
...@@ -276,7 +280,7 @@ internal class OfflineMessageSourceImplBySourceMsg( // from others' quotation ...@@ -276,7 +280,7 @@ internal class OfflineMessageSourceImplBySourceMsg( // from others' quotation
override val id: Int override val id: Int
get() = delegate.pbReserve.loadAs(SourceMsg.ResvAttr.serializer()).origUids?.toInt() get() = delegate.pbReserve.loadAs(SourceMsg.ResvAttr.serializer()).origUids?.toInt()
?: error("在读取 OfflineMessageSourceImplBySourceMsg.id 时找不到 origUids, delegate=${delegate._miraiContentToString()}") ?: 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
......
...@@ -30,6 +30,7 @@ import net.mamoe.mirai.qqandroid.contact.GroupImpl ...@@ -30,6 +30,7 @@ import net.mamoe.mirai.qqandroid.contact.GroupImpl
import net.mamoe.mirai.qqandroid.contact.QQImpl import net.mamoe.mirai.qqandroid.contact.QQImpl
import net.mamoe.mirai.qqandroid.contact.singleLine import net.mamoe.mirai.qqandroid.contact.singleLine
import net.mamoe.mirai.qqandroid.event.PacketReceivedEvent import net.mamoe.mirai.qqandroid.event.PacketReceivedEvent
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.StTroopNum
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgSvc import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgSvc
import net.mamoe.mirai.qqandroid.network.protocol.packet.* import net.mamoe.mirai.qqandroid.network.protocol.packet.*
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.GroupInfoImpl import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.GroupInfoImpl
...@@ -189,8 +190,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -189,8 +190,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
* Don't use concurrently * Don't use concurrently
*/ */
suspend fun reloadFriendList() { suspend fun reloadFriendList() {
// 不要用 fun, 不要 join declaration, 不要用 val, 编译失败警告 logger.info { "开始加载好友信息" }
logger.info("开始加载好友信息")
var currentFriendCount = 0 var currentFriendCount = 0
var totalFriendCount: Short var totalFriendCount: Short
while (true) { while (true) {
...@@ -221,107 +221,83 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -221,107 +221,83 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
logger.info { "好友列表加载完成, 共 ${currentFriendCount}个" } logger.info { "好友列表加载完成, 共 ${currentFriendCount}个" }
} }
@OptIn(MiraiExperimentalAPI::class, ExperimentalTime::class) suspend fun StTroopNum.reloadGroup() {
override suspend fun init(): Unit = coroutineScope {
check(bot.isActive) { "bot is dead therefore network can't init" }
check(this@QQAndroidBotNetworkHandler.isActive) { "network is dead therefore can't init" }
CancellationException("re-init").let { reInitCancellationException ->
bot.friends.delegate.clear { it.cancel(reInitCancellationException) }
bot.groups.delegate.clear { it.cancel(reInitCancellationException) }
}
if (!pendingEnabled) {
pendingIncomingPackets = LockFreeLinkedList()
_pendingEnabled.value = true
}
supervisorScope {
this.launch { reloadFriendList() }
launch {
try {
logger.info("开始加载群组列表与群成员列表")
val troopListData = FriendList.GetTroopListSimplify(bot.client)
.sendAndExpect<FriendList.GetTroopListSimplify.Response>(retry = 3)
troopListData.groups.chunked(50).forEach { chunk ->
supervisorScope {
chunk.forEach { troopNum ->
// 别用 fun, 别 val, 编译失败警告
lateinit var loadGroup: suspend () -> Unit
loadGroup = suspend {
retryCatching(3) { retryCatching(3) {
bot.groups.delegate.addLast( bot.groups.delegate.addLast(
@Suppress("DuplicatedCode") @Suppress("DuplicatedCode")
(GroupImpl( GroupImpl(
bot = bot, bot = bot,
coroutineContext = bot.coroutineContext, coroutineContext = bot.coroutineContext,
id = troopNum.groupCode, id = groupCode,
groupInfo = bot._lowLevelQueryGroupInfo(troopNum.groupCode).apply { groupInfo = bot._lowLevelQueryGroupInfo(groupCode).apply {
this as GroupInfoImpl this as GroupInfoImpl
if (this.delegate.groupName == null) { if (this.delegate.groupName == null) {
this.delegate.groupName = troopNum.groupName this.delegate.groupName = groupName
} }
if (this.delegate.groupMemo == null) { if (this.delegate.groupMemo == null) {
this.delegate.groupMemo = troopNum.groupMemo this.delegate.groupMemo = groupMemo
} }
if (this.delegate.groupUin == null) { if (this.delegate.groupUin == null) {
this.delegate.groupUin = troopNum.groupUin this.delegate.groupUin = groupUin
} }
this.delegate.groupCode = troopNum.groupCode this.delegate.groupCode = this@reloadGroup.groupCode
}, },
members = bot._lowLevelQueryGroupMemberList( members = bot._lowLevelQueryGroupMemberList(
troopNum.groupUin, groupUin,
troopNum.groupCode, groupCode,
troopNum.dwGroupOwnerUin dwGroupOwnerUin
) )
))
) )
}.exceptionOrNull()?.let { )
logger.error { "群${troopNum.groupCode}的列表拉取失败, 一段时间后将会重试" } }.getOrThrow()
logger.error(it)
this@QQAndroidBotNetworkHandler.launch {
delay(10_000)
loadGroup()
}
}
Unit // 别删, 编译失败警告
} }
suspend fun reloadGroupList() {
logger.info { "开始加载群组列表与群成员列表" }
val troopListData = FriendList.GetTroopListSimplify(bot.client)
.sendAndExpect<FriendList.GetTroopListSimplify.Response>(retry = 3)
troopListData.groups.chunked(50).forEach { chunk ->
coroutineScope {
chunk.forEach {
launch { launch {
loadGroup() retryCatching(3) { it.reloadGroup() }.getOrThrow()
} }
} }
} }
} }
logger.info { "群组列表与群成员加载完成, 共 ${troopListData.groups.size}个" } logger.info { "群组列表与群成员加载完成, 共 ${troopListData.groups.size}个" }
} catch (e: Exception) {
logger.error { "加载组信息失败|一般这是由于加载过于频繁导致/将以热加载方式加载群列表" }
logger.error(e)
}
} }
@OptIn(MiraiExperimentalAPI::class, ExperimentalTime::class)
override suspend fun init(): Unit = coroutineScope {
check(bot.isActive) { "bot is dead therefore network can't init" }
check(this@QQAndroidBotNetworkHandler.isActive) { "network is dead therefore can't init" }
CancellationException("re-init").let { reInitCancellationException ->
bot.friends.delegate.clear { it.cancel(reInitCancellationException) }
bot.groups.delegate.clear { it.cancel(reInitCancellationException) }
} }
runCatching { if (!pendingEnabled) {
withTimeoutOrNull(30000) { pendingIncomingPackets = LockFreeLinkedList()
lateinit var listener: Listener<PacketReceivedEvent> _pendingEnabled.value = true
listener = this.subscribeAlways {
if (it.packet is MessageSvc.PbGetMsg.GetMsgSuccess) {
listener.complete()
} }
coroutineScope {
launch { reloadFriendList() }
launch { reloadGroupList() }
} }
withTimeoutOrNull(30000) {
launch { subscribingGet<MessageSvc.PbGetMsg.GetMsgSuccess, Unit> { Unit } }
MessageSvc.PbGetMsg(bot.client, MsgSvc.SyncFlag.START, currentTimeSeconds).sendAndExpect<Packet>() MessageSvc.PbGetMsg(bot.client, MsgSvc.SyncFlag.START, currentTimeSeconds).sendAndExpect<Packet>()
} ?: error("timeout syncing friend message history") } ?: error("timeout syncing friend message history")
}.exceptionOrNull()?.let {
logger.error("exception while loading syncing friend message history: ${it.message}")
logger.error(it)
}
bot.firstLoginSucceed = true bot.firstLoginSucceed = true
_pendingEnabled.value = false _pendingEnabled.value = false
...@@ -568,11 +544,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -568,11 +544,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
check(bot.isActive) { "bot is dead therefore can't send any packet" } check(bot.isActive) { "bot is dead therefore can't send any packet" }
check(this@QQAndroidBotNetworkHandler.isActive) { "network is dead therefore can't send any packet" } check(this@QQAndroidBotNetworkHandler.isActive) { "network is dead therefore can't send any packet" }
logger.verbose("Send: ${this.commandName}") logger.verbose("Send: ${this.commandName}")
withContext(this@QQAndroidBotNetworkHandler.coroutineContext + CoroutineName("Packet sender")) {
PacketLogger.debug { "Channel sending: $commandName" }
channel.send(delegate) channel.send(delegate)
PacketLogger.debug { "Channel send done: $commandName" }
}
} }
class TimeoutException(override val message: String?) : Exception() class TimeoutException(override val message: String?) : Exception()
...@@ -588,19 +560,13 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -588,19 +560,13 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
check(this@QQAndroidBotNetworkHandler.isActive) { "network is dead therefore can't send any packet" } check(this@QQAndroidBotNetworkHandler.isActive) { "network is dead therefore can't send any packet" }
suspend fun doSendAndReceive(handler: PacketListener, data: Any, length: Int): E { suspend fun doSendAndReceive(handler: PacketListener, data: Any, length: Int): E {
withTimeoutOrNull(3000) {
withContext(this@QQAndroidBotNetworkHandler.coroutineContext + CoroutineName("Packet sender")) {
PacketLogger.debug { "Channel sending: $commandName" }
when (data) { when (data) {
is ByteArray -> channel.send(data, 0, length) is ByteArray -> channel.send(data, 0, length)
is ByteReadPacket -> channel.send(data) is ByteReadPacket -> channel.send(data)
else -> error("Internal error: unexpected data type: ${data::class.simpleName}") else -> error("Internal error: unexpected data type: ${data::class.simpleName}")
} }
PacketLogger.debug { "Channel send done: $commandName" }
}
} ?: throw TimeoutException("timeout sending packet $commandName")
logger.verbose("Send done: $commandName") logger.verbose { "Send done: $commandName" }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return withTimeoutOrNull(timeoutMillis) { return withTimeoutOrNull(timeoutMillis) {
......
...@@ -23,6 +23,7 @@ import net.mamoe.mirai.contact.Member ...@@ -23,6 +23,7 @@ import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.contact.QQ import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.data.MemberInfo import net.mamoe.mirai.data.MemberInfo
import net.mamoe.mirai.event.Event
import net.mamoe.mirai.event.events.BotJoinGroupEvent import net.mamoe.mirai.event.events.BotJoinGroupEvent
import net.mamoe.mirai.event.events.BotOfflineEvent import net.mamoe.mirai.event.events.BotOfflineEvent
import net.mamoe.mirai.event.events.MemberJoinEvent import net.mamoe.mirai.event.events.MemberJoinEvent
...@@ -116,7 +117,8 @@ internal class MessageSvc { ...@@ -116,7 +117,8 @@ internal class MessageSvc {
} }
@OptIn(MiraiInternalAPI::class) @OptIn(MiraiInternalAPI::class)
open class GetMsgSuccess(delegate: List<Packet>) : Response(MsgSvc.SyncFlag.STOP, delegate) { open class GetMsgSuccess(delegate: List<Packet>) : Response(MsgSvc.SyncFlag.STOP, delegate), Event,
Packet.NoLog {
override fun toString(): String = "MessageSvc.PbGetMsg.GetMsgSuccess(messages=<Iterable>))" override fun toString(): String = "MessageSvc.PbGetMsg.GetMsgSuccess(messages=<Iterable>))"
} }
......
...@@ -56,6 +56,8 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<OnlineMes ...@@ -56,6 +56,8 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<OnlineMes
/** /**
* 消息 id. * 消息 id.
* 当 [OnlineMessageSource] 时为随机数.
* 当 [OfflineMessageSource] 时可能为 0, 取决于服务器是否提供这个值.
*/ */
abstract val id: Int // random abstract val id: Int // random
...@@ -235,7 +237,7 @@ inline fun MessageSource.isAboutGroup(): Boolean { ...@@ -235,7 +237,7 @@ inline fun MessageSource.isAboutGroup(): Boolean {
} }
inline fun MessageSource.isAboutTemp(): Boolean { inline fun MessageSource.isAboutTemp(): Boolean {
return when(this) { return when (this) {
is OnlineMessageSource -> subject is Member is OnlineMessageSource -> subject is Member
is OfflineMessageSource -> kind == OfflineMessageSource.Kind.TEMP is OfflineMessageSource -> kind == OfflineMessageSource.Kind.TEMP
} }
...@@ -302,6 +304,12 @@ abstract class OfflineMessageSource : MessageSource() { ...@@ -302,6 +304,12 @@ 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