diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/BotImpl.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/BotImpl.kt index 55bd650b8..371627b97 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/BotImpl.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/BotImpl.kt @@ -74,11 +74,13 @@ internal abstract class BotImpl constructor( // bot 还未登录就被 close return@subscribeAlways } - if (network.areYouOk() && event !is BotOfflineEvent.Force) { + /* + if (network.areYouOk() && event !is BotOfflineEvent.Force && event !is BotOfflineEvent.MsfOffline) { // network 运行正常 return@subscribeAlways - } + }*/ when (event) { + is BotOfflineEvent.MsfOffline, is BotOfflineEvent.Dropped, is BotOfflineEvent.RequireReconnect -> { @@ -105,7 +107,12 @@ internal abstract class BotImpl constructor( @OptIn(ThisApiMustBeUsedInWithConnectionLockBlock::class) relogin((event as? BotOfflineEvent.Dropped)?.cause) } - launch { BotReloginEvent(bot, (event as? BotOfflineEvent.Dropped)?.cause).broadcast() } + launch { + BotReloginEvent( + bot, + (event as? BotOfflineEvent.CauseAware)?.cause + ).broadcast() + } return }.getOrElse { if (it is LoginFailedException && !it.killBot) { diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt index cad9f7eb1..c15a278d6 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt @@ -96,14 +96,17 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo private fun startHeartbeatJobOrKill(cancelCause: CancellationException? = null): Job { heartbeatJob?.cancel(cancelCause) - return this@QQAndroidBotNetworkHandler.launch(CoroutineName("Heartbeat")) { + return this@QQAndroidBotNetworkHandler.launch(CoroutineName("Heartbeat")) heartBeatJob@{ while (this.isActive) { delay(bot.configuration.heartbeatPeriodMillis) val failException = doHeartBeat() if (failException != null) { delay(bot.configuration.firstReconnectDelayMillis) - bot.launch { BotOfflineEvent.Dropped(bot, failException).broadcast() } - return@launch + + bot.launch { + BotOfflineEvent.Dropped(bot, failException).broadcast() + } + return@heartBeatJob } } }.also { heartbeatJob = it } diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/StatSvc.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/StatSvc.kt index 7242eb1fa..c0834831a 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/StatSvc.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/StatSvc.kt @@ -182,7 +182,7 @@ internal class StatSvc { } internal object ReqMSFOffline : - IncomingPacketFactory("StatSvc.ReqMSFOffline", "StatSvc.RspMSFForceOffline") { + IncomingPacketFactory("StatSvc.ReqMSFOffline", "StatSvc.RspMSFForceOffline") { internal data class MsfOfflineToken( val uin: Long, @@ -190,13 +190,13 @@ internal class StatSvc { val const: Byte ) : Packet, RuntimeException("dropped by StatSvc.ReqMSFOffline") - override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): BotOfflineEvent.Dropped { + override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): BotOfflineEvent.MsfOffline { val decodeUniPacket = readUniPacket(RequestMSFForceOffline.serializer()) @Suppress("INVISIBLE_MEMBER") - return BotOfflineEvent.Dropped(bot, MsfOfflineToken(decodeUniPacket.uin, decodeUniPacket.iSeqno, 0)) + return BotOfflineEvent.MsfOffline(bot, MsfOfflineToken(decodeUniPacket.uin, decodeUniPacket.iSeqno, 0)) } - override suspend fun QQAndroidBot.handle(packet: BotOfflineEvent.Dropped, sequenceId: Int): OutgoingPacket? { + override suspend fun QQAndroidBot.handle(packet: BotOfflineEvent.MsfOffline, sequenceId: Int): OutgoingPacket? { val cause = packet.cause check(cause is MsfOfflineToken) { "internal error: handling $packet in StatSvc.ReqMSFOffline" } return buildResponseUniPacket(client) { diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/bot.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/bot.kt index 41603de9f..ef61904d8 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/bot.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/bot.kt @@ -16,6 +16,9 @@ package net.mamoe.mirai.event.events import net.mamoe.mirai.Bot import net.mamoe.mirai.event.AbstractEvent import net.mamoe.mirai.qqandroid.network.Packet +import net.mamoe.mirai.utils.MiraiExperimentalAPI +import net.mamoe.mirai.utils.MiraiInternalAPI +import net.mamoe.mirai.utils.SinceMirai import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName @@ -35,7 +38,8 @@ sealed class BotOfflineEvent : BotEvent, AbstractEvent() { /** * 主动离线. 主动广播这个事件也可以让 [Bot] 关闭. */ - data class Active(override val bot: Bot, val cause: Throwable?) : BotOfflineEvent(), BotActiveEvent + data class Active(override val bot: Bot, override val cause: Throwable?) : BotOfflineEvent(), BotActiveEvent, + CauseAware /** * 被挤下线 @@ -45,15 +49,31 @@ sealed class BotOfflineEvent : BotEvent, AbstractEvent() { BotPassiveEvent /** - * 被服务器断开或因网络问题而掉线 + * 被服务器断开 */ - data class Dropped internal constructor(override val bot: Bot, val cause: Throwable?) : BotOfflineEvent(), Packet, - BotPassiveEvent + @SinceMirai("1.1.0") + @MiraiInternalAPI("This is very experimental and might be changed") + data class MsfOffline internal constructor(override val bot: Bot, override val cause: Throwable?) : + BotOfflineEvent(), Packet, + BotPassiveEvent, CauseAware + + /** + * 因网络问题而掉线 + */ + data class Dropped internal constructor(override val bot: Bot, override val cause: Throwable?) : BotOfflineEvent(), + Packet, + BotPassiveEvent, CauseAware /** * 服务器主动要求更换另一个服务器 */ + @MiraiInternalAPI data class RequireReconnect internal constructor(override val bot: Bot) : BotOfflineEvent(), Packet, BotPassiveEvent + + @MiraiExperimentalAPI + interface CauseAware { + val cause: Throwable? + } } /**