mirror of
https://github.com/mamoe/mirai.git
synced 2025-04-01 20:50:15 +08:00
Add BotOfflineEvent.reconnect
, support auto-reconnect control.
AbstractBot.offlineListener is now MONITOR
This commit is contained in:
parent
44053ae85f
commit
95e6ca4c7a
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||||
*
|
*
|
||||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
* 此源代码的使用受 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.
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
@ -34,6 +34,10 @@ public data class BotOnlineEvent internal constructor(
|
|||||||
* [Bot] 离线.
|
* [Bot] 离线.
|
||||||
*/
|
*/
|
||||||
public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
|
public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
|
||||||
|
/**
|
||||||
|
* 为 `true` 时会尝试重连. 仅 [BotOfflineEvent.Force] 默认为 `false`, 其他默认为 `true`.
|
||||||
|
*/
|
||||||
|
public open val reconnect: Boolean get() = true
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主动离线. 主动广播这个事件也可以让 [Bot] 关闭.
|
* 主动离线. 主动广播这个事件也可以让 [Bot] 关闭.
|
||||||
@ -41,16 +45,20 @@ public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
|
|||||||
public data class Active(
|
public data class Active(
|
||||||
public override val bot: Bot,
|
public override val bot: Bot,
|
||||||
public override val cause: Throwable?
|
public override val cause: Throwable?
|
||||||
) : BotOfflineEvent(), BotActiveEvent, CauseAware
|
) : BotOfflineEvent(), BotActiveEvent, CauseAware {
|
||||||
|
override val reconnect: Boolean get() = false
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 被挤下线
|
* 被挤下线. 默认不会自动重连. 可将 [reconnect] 改为 `true` 以重连.
|
||||||
*/
|
*/
|
||||||
public data class Force internal constructor(
|
public data class Force internal constructor(
|
||||||
public override val bot: Bot,
|
public override val bot: Bot,
|
||||||
public val title: String,
|
public val title: String,
|
||||||
public val message: String
|
public val message: String,
|
||||||
) : BotOfflineEvent(), Packet, BotPassiveEvent
|
) : BotOfflineEvent(), Packet, BotPassiveEvent {
|
||||||
|
override var reconnect: Boolean = false
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 被服务器断开
|
* 被服务器断开
|
||||||
@ -59,7 +67,9 @@ public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
|
|||||||
public data class MsfOffline internal constructor(
|
public data class MsfOffline internal constructor(
|
||||||
public override val bot: Bot,
|
public override val bot: Bot,
|
||||||
public override val cause: Throwable?
|
public override val cause: Throwable?
|
||||||
) : BotOfflineEvent(), Packet, BotPassiveEvent, CauseAware
|
) : BotOfflineEvent(), Packet, BotPassiveEvent, CauseAware {
|
||||||
|
override var reconnect: Boolean = true
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 因网络问题而掉线
|
* 因网络问题而掉线
|
||||||
@ -67,7 +77,9 @@ public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
|
|||||||
public data class Dropped internal constructor(
|
public data class Dropped internal constructor(
|
||||||
public override val bot: Bot,
|
public override val bot: Bot,
|
||||||
public override val cause: Throwable?
|
public override val cause: Throwable?
|
||||||
) : BotOfflineEvent(), Packet, BotPassiveEvent, CauseAware
|
) : BotOfflineEvent(), Packet, BotPassiveEvent, CauseAware {
|
||||||
|
override var reconnect: Boolean = true
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 因 returnCode = -10008 等原因掉线
|
* 因 returnCode = -10008 等原因掉线
|
||||||
@ -77,7 +89,9 @@ public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
|
|||||||
val returnCode: Int,
|
val returnCode: Int,
|
||||||
public override val bot: Bot,
|
public override val bot: Bot,
|
||||||
public override val cause: Throwable
|
public override val cause: Throwable
|
||||||
) : BotOfflineEvent(), Packet, BotPassiveEvent, CauseAware
|
) : BotOfflineEvent(), Packet, BotPassiveEvent, CauseAware {
|
||||||
|
override var reconnect: Boolean = true
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 服务器主动要求更换另一个服务器
|
* 服务器主动要求更换另一个服务器
|
||||||
@ -85,8 +99,9 @@ public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
|
|||||||
@MiraiInternalApi
|
@MiraiInternalApi
|
||||||
public data class RequireReconnect internal constructor(
|
public data class RequireReconnect internal constructor(
|
||||||
public override val bot: Bot
|
public override val bot: Bot
|
||||||
) : BotOfflineEvent(), Packet,
|
) : BotOfflineEvent(), Packet, BotPassiveEvent {
|
||||||
BotPassiveEvent
|
override var reconnect: Boolean = true
|
||||||
|
}
|
||||||
|
|
||||||
@MiraiExperimentalApi
|
@MiraiExperimentalApi
|
||||||
public interface CauseAware {
|
public interface CauseAware {
|
||||||
|
@ -23,6 +23,7 @@ import kotlinx.coroutines.sync.Mutex
|
|||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.contact.OtherClientList
|
import net.mamoe.mirai.contact.OtherClientList
|
||||||
import net.mamoe.mirai.event.*
|
import net.mamoe.mirai.event.*
|
||||||
|
import net.mamoe.mirai.event.Listener.EventPriority.MONITOR
|
||||||
import net.mamoe.mirai.event.events.BotEvent
|
import net.mamoe.mirai.event.events.BotEvent
|
||||||
import net.mamoe.mirai.event.events.BotOfflineEvent
|
import net.mamoe.mirai.event.events.BotOfflineEvent
|
||||||
import net.mamoe.mirai.event.events.BotReloginEvent
|
import net.mamoe.mirai.event.events.BotReloginEvent
|
||||||
@ -91,7 +92,10 @@ internal abstract class AbstractBot<N : BotNetworkHandler> constructor(
|
|||||||
@OptIn(ExperimentalTime::class)
|
@OptIn(ExperimentalTime::class)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
private val offlineListener: Listener<BotOfflineEvent> =
|
private val offlineListener: Listener<BotOfflineEvent> =
|
||||||
this@AbstractBot.eventChannel.subscribeAlways(concurrency = Listener.ConcurrencyKind.LOCKED) { event ->
|
this@AbstractBot.eventChannel.subscribeAlways(
|
||||||
|
priority = MONITOR,
|
||||||
|
concurrency = Listener.ConcurrencyKind.LOCKED
|
||||||
|
) { event ->
|
||||||
if (!event.bot.isActive) {
|
if (!event.bot.isActive) {
|
||||||
// bot closed
|
// bot closed
|
||||||
return@subscribeAlways
|
return@subscribeAlways
|
||||||
@ -110,30 +114,6 @@ internal abstract class AbstractBot<N : BotNetworkHandler> constructor(
|
|||||||
return@subscribeAlways
|
return@subscribeAlways
|
||||||
}*/
|
}*/
|
||||||
when (event) {
|
when (event) {
|
||||||
is BotOfflineEvent.MsfOffline,
|
|
||||||
is BotOfflineEvent.Dropped,
|
|
||||||
is BotOfflineEvent.RequireReconnect,
|
|
||||||
is BotOfflineEvent.PacketFactoryErrorCode
|
|
||||||
-> {
|
|
||||||
if (!_network.isActive) {
|
|
||||||
// normally closed
|
|
||||||
return@subscribeAlways
|
|
||||||
}
|
|
||||||
bot.logger.info { "Connection lost, retrying login" }
|
|
||||||
|
|
||||||
bot.asQQAndroidBot().client.run {
|
|
||||||
if (serverList.isEmpty()) {
|
|
||||||
serverList.addAll(DefaultServerList)
|
|
||||||
} else serverList.removeAt(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
val success: Boolean
|
|
||||||
val time = measureTime { success = Reconnect().reconnect(event) }
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
logger.info { "Reconnected successfully in ${time.toHumanReadableString()}" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is BotOfflineEvent.Active -> {
|
is BotOfflineEvent.Active -> {
|
||||||
val cause = event.cause
|
val cause = event.cause
|
||||||
val msg = if (cause == null) {
|
val msg = if (cause == null) {
|
||||||
@ -146,7 +126,37 @@ internal abstract class AbstractBot<N : BotNetworkHandler> constructor(
|
|||||||
}
|
}
|
||||||
is BotOfflineEvent.Force -> {
|
is BotOfflineEvent.Force -> {
|
||||||
bot.logger.info { "Connection occupied by another android device: ${event.message}" }
|
bot.logger.info { "Connection occupied by another android device: ${event.message}" }
|
||||||
bot.cancel(ForceOfflineException("Connection occupied by another android device: ${event.message}"))
|
if (!event.reconnect) {
|
||||||
|
bot.cancel(ForceOfflineException("Connection occupied by another android device: ${event.message}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is BotOfflineEvent.MsfOffline,
|
||||||
|
is BotOfflineEvent.Dropped,
|
||||||
|
is BotOfflineEvent.RequireReconnect,
|
||||||
|
is BotOfflineEvent.PacketFactoryErrorCode
|
||||||
|
-> {
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.reconnect) {
|
||||||
|
if (!_network.isActive) {
|
||||||
|
// normally closed
|
||||||
|
return@subscribeAlways
|
||||||
|
}
|
||||||
|
bot.logger.info { "Connection lost, retrying login" }
|
||||||
|
|
||||||
|
bot.asQQAndroidBot().client.run {
|
||||||
|
if (serverList.isEmpty()) {
|
||||||
|
serverList.addAll(DefaultServerList)
|
||||||
|
} else serverList.removeAt(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
val success: Boolean
|
||||||
|
val time = measureTime { success = Reconnect().reconnect(event) }
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
logger.info { "Reconnected successfully in ${time.toHumanReadableString()}" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user