mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-11 04:24:48 +08:00
Close bot if first login failed
This commit is contained in:
parent
35a6d12dde
commit
95d634233c
@ -165,6 +165,9 @@ public inline fun <E> MutableList<E>.replaceAllKotlin(operator: (E) -> E) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun systemProp(name: String, default: String): String =
|
||||||
|
System.getProperty(name, default) ?: default
|
||||||
|
|
||||||
public fun systemProp(name: String, default: Boolean): Boolean =
|
public fun systemProp(name: String, default: Boolean): Boolean =
|
||||||
System.getProperty(name, default.toString())?.toBoolean() ?: default
|
System.getProperty(name, default.toString())?.toBoolean() ?: default
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import net.mamoe.mirai.internal.contact.info.FriendInfoImpl
|
|||||||
import net.mamoe.mirai.internal.contact.info.StrangerInfoImpl
|
import net.mamoe.mirai.internal.contact.info.StrangerInfoImpl
|
||||||
import net.mamoe.mirai.internal.contact.uin
|
import net.mamoe.mirai.internal.contact.uin
|
||||||
import net.mamoe.mirai.internal.network.component.ConcurrentComponentStorage
|
import net.mamoe.mirai.internal.network.component.ConcurrentComponentStorage
|
||||||
|
import net.mamoe.mirai.internal.network.components.SsoProcessor
|
||||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler
|
import net.mamoe.mirai.internal.network.handler.NetworkHandler
|
||||||
import net.mamoe.mirai.internal.network.impl.netty.asCoroutineExceptionHandler
|
import net.mamoe.mirai.internal.network.impl.netty.asCoroutineExceptionHandler
|
||||||
import net.mamoe.mirai.supervisorJob
|
import net.mamoe.mirai.supervisorJob
|
||||||
@ -110,11 +111,18 @@ internal abstract class AbstractBot constructor(
|
|||||||
// network
|
// network
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
val network: NetworkHandler by lazy { createNetworkHandler() }
|
val network: NetworkHandler by lazy { createNetworkHandler() } // the selector handles renewal of [NetworkHandler]
|
||||||
|
|
||||||
final override suspend fun login() {
|
final override suspend fun login() {
|
||||||
if (!isActive) error("Bot is already closed and cannot relogin. Please create a new Bot instance then do login.")
|
if (!isActive) error("Bot is already closed and cannot relogin. Please create a new Bot instance then do login.")
|
||||||
|
try {
|
||||||
network.resumeConnection()
|
network.resumeConnection()
|
||||||
|
} catch (e: Throwable) { // failed to init
|
||||||
|
if (!components[SsoProcessor].firstLoginSucceed) {
|
||||||
|
this.close() // failed to do first login.
|
||||||
|
}
|
||||||
|
throw e
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun createNetworkHandler(): NetworkHandler
|
protected abstract fun createNetworkHandler(): NetworkHandler
|
||||||
|
@ -51,12 +51,25 @@ internal fun Bot.asQQAndroidBot(): QQAndroidBot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal class BotDebugConfiguration(
|
internal class BotDebugConfiguration(
|
||||||
var stateObserver: StateObserver? = when {
|
var stateObserver: StateObserver? = when (systemProp(
|
||||||
systemProp("mirai.debug.network.state.observer.logging", false) ->
|
"mirai.debug.network.state.observer.logging",
|
||||||
|
"off"
|
||||||
|
).toLowerCase()) {
|
||||||
|
"full" -> {
|
||||||
SafeStateObserver(
|
SafeStateObserver(
|
||||||
LoggingStateObserver(MiraiLogger.create("States")),
|
LoggingStateObserver(MiraiLogger.create("States"), true),
|
||||||
MiraiLogger.create("LoggingStateObserver errors")
|
MiraiLogger.create("LoggingStateObserver errors")
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
"off", "false" -> {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
"on", "true" -> {
|
||||||
|
SafeStateObserver(
|
||||||
|
LoggingStateObserver(MiraiLogger.create("States"), false),
|
||||||
|
MiraiLogger.create("LoggingStateObserver errors")
|
||||||
|
)
|
||||||
|
}
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -69,6 +82,14 @@ internal open class QQAndroidBot constructor(
|
|||||||
) : AbstractBot(configuration, account.id) {
|
) : AbstractBot(configuration, account.id) {
|
||||||
override val bot: QQAndroidBot get() = this
|
override val bot: QQAndroidBot get() = this
|
||||||
|
|
||||||
|
|
||||||
|
@Deprecated(
|
||||||
|
"",
|
||||||
|
replaceWith = ReplaceWith(
|
||||||
|
"this.components[SsoProcessor].firstLoginSucceed",
|
||||||
|
"net.mamoe.mirai.internal.network.components.SsoProcessor"
|
||||||
|
)
|
||||||
|
)
|
||||||
internal var firstLoginSucceed: Boolean = false
|
internal var firstLoginSucceed: Boolean = false
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
@ -85,7 +106,7 @@ internal open class QQAndroidBot constructor(
|
|||||||
StateChangedObserver(to = State.OK) { new ->
|
StateChangedObserver(to = State.OK) { new ->
|
||||||
bot.launch(logger.asCoroutineExceptionHandler()) {
|
bot.launch(logger.asCoroutineExceptionHandler()) {
|
||||||
BotOnlineEvent(bot).broadcast()
|
BotOnlineEvent(bot).broadcast()
|
||||||
if (bot.firstLoginSucceed) { // TODO: 2021/4/21 actually no use
|
if (bot.components[SsoProcessor].firstLoginSucceed) { // TODO: 2021/4/21 actually no use
|
||||||
BotReloginEvent(bot, new.getCause()).broadcast()
|
BotReloginEvent(bot, new.getCause()).broadcast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ internal class BotInitProcessorImpl(
|
|||||||
launch { context[ContactUpdater].loadAll(registerResp.origin) }
|
launch { context[ContactUpdater].loadAll(registerResp.origin) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bot.firstLoginSucceed = true
|
bot.components[SsoProcessor].firstLoginSucceed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun registerClientOnline(): StatSvc.Register.Response {
|
private suspend fun registerClientOnline(): StatSvc.Register.Response {
|
||||||
|
@ -10,8 +10,10 @@
|
|||||||
package net.mamoe.mirai.internal.network.components
|
package net.mamoe.mirai.internal.network.components
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.coroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.selects.select
|
||||||
|
import kotlinx.coroutines.yield
|
||||||
import net.mamoe.mirai.event.ConcurrencyKind
|
import net.mamoe.mirai.event.ConcurrencyKind
|
||||||
import net.mamoe.mirai.event.EventPriority
|
import net.mamoe.mirai.event.EventPriority
|
||||||
import net.mamoe.mirai.event.events.BotOfflineEvent
|
import net.mamoe.mirai.event.events.BotOfflineEvent
|
||||||
@ -19,17 +21,27 @@ import net.mamoe.mirai.event.subscribeAlways
|
|||||||
import net.mamoe.mirai.internal.QQAndroidBot
|
import net.mamoe.mirai.internal.QQAndroidBot
|
||||||
import net.mamoe.mirai.internal.asQQAndroidBot
|
import net.mamoe.mirai.internal.asQQAndroidBot
|
||||||
import net.mamoe.mirai.internal.network.component.ComponentKey
|
import net.mamoe.mirai.internal.network.component.ComponentKey
|
||||||
|
import net.mamoe.mirai.internal.network.handler.NetworkHandler
|
||||||
|
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State
|
||||||
import net.mamoe.mirai.utils.castOrNull
|
import net.mamoe.mirai.utils.castOrNull
|
||||||
import net.mamoe.mirai.utils.info
|
import net.mamoe.mirai.utils.info
|
||||||
import net.mamoe.mirai.utils.toHumanReadableString
|
import net.mamoe.mirai.utils.toHumanReadableString
|
||||||
import kotlin.time.measureTime
|
import kotlin.time.measureTime
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles [BotOfflineEvent]
|
||||||
|
*/
|
||||||
internal interface BotOfflineEventMonitor {
|
internal interface BotOfflineEventMonitor {
|
||||||
companion object : ComponentKey<BotOfflineEventMonitor>
|
companion object : ComponentKey<BotOfflineEventMonitor>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach a listener to the [scope]. [scope] is usually the scope of [NetworkHandler.State.OK].
|
||||||
|
*/
|
||||||
fun attachJob(bot: QQAndroidBot, scope: CoroutineScope)
|
fun attachJob(bot: QQAndroidBot, scope: CoroutineScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private data class BotClosedByEvent(val event: BotOfflineEvent) : RuntimeException("Bot is closed by event '$event'.")
|
||||||
|
|
||||||
internal class BotOfflineEventMonitorImpl : BotOfflineEventMonitor {
|
internal class BotOfflineEventMonitorImpl : BotOfflineEventMonitor {
|
||||||
override fun attachJob(bot: QQAndroidBot, scope: CoroutineScope) {
|
override fun attachJob(bot: QQAndroidBot, scope: CoroutineScope) {
|
||||||
bot.eventChannel.parentScope(scope).subscribeAlways(
|
bot.eventChannel.parentScope(scope).subscribeAlways(
|
||||||
@ -39,38 +51,37 @@ internal class BotOfflineEventMonitorImpl : BotOfflineEventMonitor {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 2021/4/25 Review BotOfflineEventMonitor
|
private suspend fun onEvent(event: BotOfflineEvent) = coroutineScope {
|
||||||
private suspend fun onEvent(event: BotOfflineEvent) {
|
|
||||||
val bot = event.bot.asQQAndroidBot()
|
val bot = event.bot.asQQAndroidBot()
|
||||||
val network = bot.network
|
val network = bot.network
|
||||||
if (
|
|
||||||
!event.bot.isActive // bot closed
|
fun closeNetwork() {
|
||||||
// || _isConnecting // bot 还在登入 // TODO: 2021/4/14 处理还在登入?
|
if (network.state == State.CLOSED) return // avoid recursive calls.
|
||||||
) {
|
launch {
|
||||||
// Close network to avoid endless reconnection while network is ok
|
// suspend until state becomes CLOSED to hang [onEvent] for synchronization.
|
||||||
// https://github.com/mamoe/mirai/issues/894
|
while (select { network.onStateChanged { it != State.CLOSED } }) yield()
|
||||||
kotlin.runCatching { network.close(null) }
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
/*
|
bot.launch { network.close(BotClosedByEvent(event)) }
|
||||||
if (network.areYouOk() && event !is BotOfflineEvent.Force && event !is BotOfflineEvent.MsfOffline) {
|
}
|
||||||
// network 运行正常
|
|
||||||
return@subscribeAlways
|
|
||||||
}*/
|
|
||||||
when (event) {
|
when (event) {
|
||||||
is BotOfflineEvent.Active -> {
|
is BotOfflineEvent.Active -> {
|
||||||
|
// This event might also be broadcast by the network handler by a state observer.
|
||||||
|
// In that case, `network.state` will be `CLOSED` then `closeNetwork` returns immediately.
|
||||||
|
// So there won't be recursive calls.
|
||||||
|
|
||||||
val cause = event.cause
|
val cause = event.cause
|
||||||
val msg = if (cause == null) "" else " with exception: $cause"
|
val msg = if (cause == null) "" else " with exception: $cause"
|
||||||
bot.logger.info("Bot is closed manually $msg", cause)
|
bot.logger.info("Bot is closed manually $msg", cause)
|
||||||
network.close(null)
|
|
||||||
|
closeNetwork()
|
||||||
}
|
}
|
||||||
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}" }
|
||||||
|
closeNetwork()
|
||||||
if (event.reconnect) {
|
if (event.reconnect) {
|
||||||
bot.logger.info { "Reconnecting..." }
|
bot.logger.info { "Reconnecting..." }
|
||||||
// delay(3000)
|
|
||||||
} else {
|
} else {
|
||||||
network.close(null)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is BotOfflineEvent.MsfOffline,
|
is BotOfflineEvent.MsfOffline,
|
||||||
@ -82,11 +93,6 @@ internal class BotOfflineEventMonitorImpl : BotOfflineEventMonitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event.reconnect) {
|
if (event.reconnect) {
|
||||||
if (!network.isOk()) {
|
|
||||||
// normally closed
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val causeMessage = event.castOrNull<BotOfflineEvent.CauseAware>()?.cause?.toString() ?: event.toString()
|
val causeMessage = event.castOrNull<BotOfflineEvent.CauseAware>()?.cause?.toString() ?: event.toString()
|
||||||
bot.logger.info { "Connection lost, retrying login ($causeMessage)." }
|
bot.logger.info { "Connection lost, retrying login ($causeMessage)." }
|
||||||
|
|
||||||
@ -94,8 +100,8 @@ internal class BotOfflineEventMonitorImpl : BotOfflineEventMonitor {
|
|||||||
val success: Boolean
|
val success: Boolean
|
||||||
val time = measureTime {
|
val time = measureTime {
|
||||||
success = kotlin.runCatching {
|
success = kotlin.runCatching {
|
||||||
bot.login()
|
bot.login() // selector will create new NH to replace the old, closed one, with some further comprehensive considerations. For example, limitation for attempts.
|
||||||
}.isSuccess // resume connection
|
}.isSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
|
@ -45,6 +45,8 @@ internal interface SsoProcessor {
|
|||||||
val client: QQAndroidClient
|
val client: QQAndroidClient
|
||||||
val ssoSession: SsoSession
|
val ssoSession: SsoSession
|
||||||
|
|
||||||
|
var firstLoginSucceed: Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The observers to launch jobs for states.
|
* The observers to launch jobs for states.
|
||||||
*
|
*
|
||||||
@ -78,6 +80,8 @@ internal class SsoProcessorImpl(
|
|||||||
// public
|
// public
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
override var firstLoginSucceed: Boolean = false
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
override var client = createClient(ssoContext.bot)
|
override var client = createClient(ssoContext.bot)
|
||||||
|
|
||||||
@ -111,6 +115,7 @@ internal class SsoProcessorImpl(
|
|||||||
SlowLoginImpl(handler).doLogin()
|
SlowLoginImpl(handler).doLogin()
|
||||||
}
|
}
|
||||||
ssoContext.accountSecretsManager.saveSecrets(ssoContext.account, AccountSecretsImpl(client))
|
ssoContext.accountSecretsManager.saveSecrets(ssoContext.account, AccountSecretsImpl(client))
|
||||||
|
ssoContext.bot.logger.info { "Login successful." }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun logout(handler: NetworkHandler) {
|
override suspend fun logout(handler: NetworkHandler) {
|
||||||
|
@ -98,9 +98,10 @@ internal interface NetworkHandler {
|
|||||||
OK,
|
OK,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The terminal state. Cannot resume anymore. Both [resumeConnection] and [sendAndExpect] throw a [IllegalStateException].
|
* The terminal state. Both [resumeConnection] and [sendAndExpect] throw a [IllegalStateException].
|
||||||
*
|
*
|
||||||
* When a handler reached [CLOSED] state, it is finalized and cannot be restored to any other states.
|
* **Important nodes**: if [NetworkHandler] is [SelectorNetworkHandler], it might return to a normal state e.g. [INITIALIZED] if new instance of [NetworkHandler] is created.
|
||||||
|
* However callers usually do not need to pay extra attention on this behavior. Everything will just work fine if you consider [CLOSED] as a final, non-recoverable state.
|
||||||
*
|
*
|
||||||
* At this state [resumeConnection] throws the exception caught from underlying socket implementation (i.e netty).
|
* At this state [resumeConnection] throws the exception caught from underlying socket implementation (i.e netty).
|
||||||
* [sendAndExpect] throws [IllegalStateException].
|
* [sendAndExpect] throws [IllegalStateException].
|
||||||
|
@ -15,7 +15,8 @@ import net.mamoe.mirai.utils.MiraiLogger
|
|||||||
import net.mamoe.mirai.utils.debug
|
import net.mamoe.mirai.utils.debug
|
||||||
|
|
||||||
internal class LoggingStateObserver(
|
internal class LoggingStateObserver(
|
||||||
val logger: MiraiLogger
|
val logger: MiraiLogger,
|
||||||
|
private val showStacktrace: Boolean = false
|
||||||
) : StateObserver {
|
) : StateObserver {
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "LoggingStateObserver"
|
return "LoggingStateObserver"
|
||||||
@ -26,7 +27,10 @@ internal class LoggingStateObserver(
|
|||||||
previous: NetworkHandlerSupport.BaseStateImpl,
|
previous: NetworkHandlerSupport.BaseStateImpl,
|
||||||
new: NetworkHandlerSupport.BaseStateImpl
|
new: NetworkHandlerSupport.BaseStateImpl
|
||||||
) {
|
) {
|
||||||
logger.debug { "State changed: ${previous.correspondingState} -> ${new.correspondingState}" }
|
logger.debug(
|
||||||
|
{ "State changed: ${previous.correspondingState} -> ${new.correspondingState}" },
|
||||||
|
if (showStacktrace) Exception("Show stacktrace") else null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun exceptionOnCreatingNewState(
|
override fun exceptionOnCreatingNewState(
|
||||||
@ -34,7 +38,7 @@ internal class LoggingStateObserver(
|
|||||||
previousState: NetworkHandlerSupport.BaseStateImpl,
|
previousState: NetworkHandlerSupport.BaseStateImpl,
|
||||||
exception: Throwable
|
exception: Throwable
|
||||||
) {
|
) {
|
||||||
logger.debug({ "State changed: ${previousState.correspondingState} -> $exception" }, exception)
|
logger.debug { "State changed: ${previousState.correspondingState} -> $exception" }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun beforeStateResume(networkHandler: NetworkHandler, state: NetworkHandlerSupport.BaseStateImpl) {
|
override fun beforeStateResume(networkHandler: NetworkHandler, state: NetworkHandlerSupport.BaseStateImpl) {
|
||||||
|
@ -36,6 +36,7 @@ import net.mamoe.mirai.internal.message.toMessageChainOnline
|
|||||||
import net.mamoe.mirai.internal.network.MultiPacket
|
import net.mamoe.mirai.internal.network.MultiPacket
|
||||||
import net.mamoe.mirai.internal.network.Packet
|
import net.mamoe.mirai.internal.network.Packet
|
||||||
import net.mamoe.mirai.internal.network.QQAndroidClient
|
import net.mamoe.mirai.internal.network.QQAndroidClient
|
||||||
|
import net.mamoe.mirai.internal.network.components.SsoProcessor
|
||||||
import net.mamoe.mirai.internal.network.handler.logger
|
import net.mamoe.mirai.internal.network.handler.logger
|
||||||
import net.mamoe.mirai.internal.network.protocol.data.proto.FrdSysMsg
|
import net.mamoe.mirai.internal.network.protocol.data.proto.FrdSysMsg
|
||||||
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
|
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
|
||||||
@ -378,7 +379,7 @@ internal suspend fun MsgComm.Msg.transform(bot: QQAndroidBot, fromSync: Boolean
|
|||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
if (!bot.firstLoginSucceed) {
|
if (!bot.components[SsoProcessor].firstLoginSucceed) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val fromUin = if (fromSync) {
|
val fromUin = if (fromSync) {
|
||||||
@ -483,7 +484,7 @@ internal suspend fun MsgComm.Msg.transform(bot: QQAndroidBot, fromSync: Boolean
|
|||||||
}
|
}
|
||||||
141 -> {
|
141 -> {
|
||||||
|
|
||||||
if (!bot.firstLoginSucceed || msgHead.fromUin == bot.id && !fromSync) {
|
if (!bot.components[SsoProcessor].firstLoginSucceed || msgHead.fromUin == bot.id && !fromSync) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val tmpHead = msgHead.c2cTmpMsgHead ?: return null
|
val tmpHead = msgHead.c2cTmpMsgHead ?: return null
|
||||||
|
@ -26,6 +26,7 @@ import net.mamoe.mirai.internal.contact.info.MemberInfoImpl
|
|||||||
import net.mamoe.mirai.internal.contact.newAnonymous
|
import net.mamoe.mirai.internal.contact.newAnonymous
|
||||||
import net.mamoe.mirai.internal.message.toMessageChainOnline
|
import net.mamoe.mirai.internal.message.toMessageChainOnline
|
||||||
import net.mamoe.mirai.internal.network.Packet
|
import net.mamoe.mirai.internal.network.Packet
|
||||||
|
import net.mamoe.mirai.internal.network.components.SsoProcessor
|
||||||
import net.mamoe.mirai.internal.network.handler.logger
|
import net.mamoe.mirai.internal.network.handler.logger
|
||||||
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
|
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.MsgComm
|
||||||
@ -70,7 +71,7 @@ internal object OnlinePushPbPushGroupMsg : IncomingPacketFactory<Packet?>("Onlin
|
|||||||
@OptIn(ExperimentalStdlibApi::class)
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet? {
|
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet? {
|
||||||
// 00 00 02 E4 0A D5 05 0A 4F 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 52 20 00 28 BC 3D 30 8C 82 AB F1 05 38 D2 80 E0 8C 80 80 80 80 02 4A 21 08 E7 C1 AD B8 02 10 01 18 BA 05 22 09 48 69 6D 31 38 38 6D 6F 65 30 06 38 02 42 05 4D 69 72 61 69 50 01 58 01 60 00 88 01 08 12 06 08 01 10 00 18 00 1A F9 04 0A F6 04 0A 26 08 00 10 87 82 AB F1 05 18 B7 B4 BF 30 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 E6 03 42 E3 03 12 2A 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 22 00 2A 04 03 00 00 00 32 60 15 36 20 39 36 6B 45 31 41 38 35 32 32 39 64 63 36 39 38 34 37 39 37 37 62 20 20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 31 32 31 32 41 38 C6 BB 8A A9 08 40 FB AE 9E C2 09 48 50 50 41 5A 00 60 01 6A 10 4E 18 58 22 0E 7B F8 0F C5 B1 34 48 83 74 D3 9C 72 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 31 39 38 3F 74 65 72 6D 3D 32 82 01 57 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 30 3F 74 65 72 6D 3D 32 B0 01 4D B8 01 2E C8 01 FF 05 D8 01 4D E0 01 2E FA 01 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 34 30 30 3F 74 65 72 6D 3D 32 80 02 4D 88 02 2E 12 45 AA 02 42 50 03 60 00 68 00 9A 01 39 08 09 20 BF 50 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 04 08 02 08 01 90 04 80 80 80 10 B8 04 00 C0 04 00 12 06 4A 04 08 00 40 01 12 14 82 01 11 0A 09 48 69 6D 31 38 38 6D 6F 65 18 06 20 08 28 03 10 8A CA 9D A1 07 1A 00
|
// 00 00 02 E4 0A D5 05 0A 4F 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 52 20 00 28 BC 3D 30 8C 82 AB F1 05 38 D2 80 E0 8C 80 80 80 80 02 4A 21 08 E7 C1 AD B8 02 10 01 18 BA 05 22 09 48 69 6D 31 38 38 6D 6F 65 30 06 38 02 42 05 4D 69 72 61 69 50 01 58 01 60 00 88 01 08 12 06 08 01 10 00 18 00 1A F9 04 0A F6 04 0A 26 08 00 10 87 82 AB F1 05 18 B7 B4 BF 30 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 E6 03 42 E3 03 12 2A 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 22 00 2A 04 03 00 00 00 32 60 15 36 20 39 36 6B 45 31 41 38 35 32 32 39 64 63 36 39 38 34 37 39 37 37 62 20 20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 31 32 31 32 41 38 C6 BB 8A A9 08 40 FB AE 9E C2 09 48 50 50 41 5A 00 60 01 6A 10 4E 18 58 22 0E 7B F8 0F C5 B1 34 48 83 74 D3 9C 72 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 31 39 38 3F 74 65 72 6D 3D 32 82 01 57 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 30 3F 74 65 72 6D 3D 32 B0 01 4D B8 01 2E C8 01 FF 05 D8 01 4D E0 01 2E FA 01 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 34 30 30 3F 74 65 72 6D 3D 32 80 02 4D 88 02 2E 12 45 AA 02 42 50 03 60 00 68 00 9A 01 39 08 09 20 BF 50 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 04 08 02 08 01 90 04 80 80 80 10 B8 04 00 C0 04 00 12 06 4A 04 08 00 40 01 12 14 82 01 11 0A 09 48 69 6D 31 38 38 6D 6F 65 18 06 20 08 28 03 10 8A CA 9D A1 07 1A 00
|
||||||
if (!bot.firstLoginSucceed) return null
|
if (!bot.components[SsoProcessor].firstLoginSucceed) return null
|
||||||
val pbPushMsg = readProtoBuf(MsgOnlinePush.PbPushMsg.serializer())
|
val pbPushMsg = readProtoBuf(MsgOnlinePush.PbPushMsg.serializer())
|
||||||
|
|
||||||
val msgHead = pbPushMsg.msg.msgHead
|
val msgHead = pbPushMsg.msg.msgHead
|
||||||
|
@ -71,6 +71,7 @@ internal abstract class AbstractRealNetworkHandlerTest<H : NetworkHandler> : Abs
|
|||||||
set(SsoProcessor, object : SsoProcessor {
|
set(SsoProcessor, object : SsoProcessor {
|
||||||
override val client: QQAndroidClient get() = bot.client
|
override val client: QQAndroidClient get() = bot.client
|
||||||
override val ssoSession: SsoSession get() = bot.client
|
override val ssoSession: SsoSession get() = bot.client
|
||||||
|
override var firstLoginSucceed: Boolean = false
|
||||||
override fun createObserverChain(): StateObserver = get(StateObserver)
|
override fun createObserverChain(): StateObserver = get(StateObserver)
|
||||||
override suspend fun login(handler: NetworkHandler) {
|
override suspend fun login(handler: NetworkHandler) {
|
||||||
nhEvents.add(NHEvent.Login)
|
nhEvents.add(NHEvent.Login)
|
||||||
|
@ -13,7 +13,11 @@ import kotlinx.coroutines.CoroutineName
|
|||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
|
import net.mamoe.mirai.event.broadcast
|
||||||
|
import net.mamoe.mirai.event.events.BotOfflineEvent
|
||||||
import net.mamoe.mirai.internal.MockBot
|
import net.mamoe.mirai.internal.MockBot
|
||||||
|
import net.mamoe.mirai.internal.network.components.BotOfflineEventMonitor
|
||||||
|
import net.mamoe.mirai.internal.network.components.BotOfflineEventMonitorImpl
|
||||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State.*
|
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State.*
|
||||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||||
import net.mamoe.mirai.supervisorJob
|
import net.mamoe.mirai.supervisorJob
|
||||||
@ -24,6 +28,29 @@ import kotlin.test.assertTrue
|
|||||||
|
|
||||||
internal class NettyBotLifecycleTest : AbstractNettyNHTest() {
|
internal class NettyBotLifecycleTest : AbstractNettyNHTest() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `closed on Force offline with BotOfflineEventMonitor`() = runBlockingUnit {
|
||||||
|
defaultComponents[BotOfflineEventMonitor] = BotOfflineEventMonitorImpl()
|
||||||
|
bot.login()
|
||||||
|
assertState(OK)
|
||||||
|
BotOfflineEvent.Force(bot, "test", "test").broadcast()
|
||||||
|
assertState(CLOSED)
|
||||||
|
assertFalse { network.isActive }
|
||||||
|
assertTrue { bot.isActive }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `closed on Active offline with BotOfflineEventMonitor`() = runBlockingUnit {
|
||||||
|
defaultComponents[BotOfflineEventMonitor] = BotOfflineEventMonitorImpl()
|
||||||
|
bot.login()
|
||||||
|
assertState(OK)
|
||||||
|
BotOfflineEvent.Active(bot, null).broadcast()
|
||||||
|
assertState(CLOSED)
|
||||||
|
assertFalse { network.isActive }
|
||||||
|
assertTrue { bot.isActive }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `send logout on exit`() = runBlockingUnit {
|
fun `send logout on exit`() = runBlockingUnit {
|
||||||
assertState(INITIALIZED)
|
assertState(INITIALIZED)
|
||||||
|
@ -14,6 +14,7 @@ import net.mamoe.mirai.event.Event
|
|||||||
import net.mamoe.mirai.event.events.BotOfflineEvent
|
import net.mamoe.mirai.event.events.BotOfflineEvent
|
||||||
import net.mamoe.mirai.event.events.BotOnlineEvent
|
import net.mamoe.mirai.event.events.BotOnlineEvent
|
||||||
import net.mamoe.mirai.event.events.BotReloginEvent
|
import net.mamoe.mirai.event.events.BotReloginEvent
|
||||||
|
import net.mamoe.mirai.internal.network.components.SsoProcessor
|
||||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State
|
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State
|
||||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State.INITIALIZED
|
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State.INITIALIZED
|
||||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State.OK
|
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State.OK
|
||||||
@ -40,7 +41,7 @@ internal class NettyHandlerEventTest : AbstractNettyNHTest() {
|
|||||||
assertEventBroadcasts<BotReloginEvent> {
|
assertEventBroadcasts<BotReloginEvent> {
|
||||||
assertEquals(INITIALIZED, network.state)
|
assertEquals(INITIALIZED, network.state)
|
||||||
bot.login()
|
bot.login()
|
||||||
bot.firstLoginSucceed = true
|
bot.components[SsoProcessor].firstLoginSucceed = true
|
||||||
network.setStateConnecting()
|
network.setStateConnecting()
|
||||||
network.resumeConnection()
|
network.resumeConnection()
|
||||||
delay(3.seconds) // `login` launches a job which broadcasts the event
|
delay(3.seconds) // `login` launches a job which broadcasts the event
|
||||||
@ -52,7 +53,7 @@ internal class NettyHandlerEventTest : AbstractNettyNHTest() {
|
|||||||
fun `BotOnlineEvent after successful reconnection`() = runBlockingUnit {
|
fun `BotOnlineEvent after successful reconnection`() = runBlockingUnit {
|
||||||
assertEquals(INITIALIZED, network.state)
|
assertEquals(INITIALIZED, network.state)
|
||||||
bot.login()
|
bot.login()
|
||||||
bot.firstLoginSucceed = true
|
bot.components[SsoProcessor].firstLoginSucceed = true
|
||||||
assertEquals(OK, network.state)
|
assertEquals(OK, network.state)
|
||||||
delay(3.seconds) // `login` launches a job which broadcasts the event
|
delay(3.seconds) // `login` launches a job which broadcasts the event
|
||||||
assertEventBroadcasts<BotOnlineEvent>(1) {
|
assertEventBroadcasts<BotOnlineEvent>(1) {
|
||||||
@ -67,7 +68,7 @@ internal class NettyHandlerEventTest : AbstractNettyNHTest() {
|
|||||||
fun `BotOfflineEvent after successful reconnection`() = runBlockingUnit {
|
fun `BotOfflineEvent after successful reconnection`() = runBlockingUnit {
|
||||||
assertEquals(INITIALIZED, network.state)
|
assertEquals(INITIALIZED, network.state)
|
||||||
bot.login()
|
bot.login()
|
||||||
bot.firstLoginSucceed = true
|
bot.components[SsoProcessor].firstLoginSucceed = true
|
||||||
assertEquals(OK, network.state)
|
assertEquals(OK, network.state)
|
||||||
delay(3.seconds) // `login` launches a job which broadcasts the event
|
delay(3.seconds) // `login` launches a job which broadcasts the event
|
||||||
assertEventBroadcasts<BotOfflineEvent>(1) {
|
assertEventBroadcasts<BotOfflineEvent>(1) {
|
||||||
@ -81,7 +82,7 @@ internal class NettyHandlerEventTest : AbstractNettyNHTest() {
|
|||||||
private fun noEventOn(setState: () -> Unit) = runBlockingUnit {
|
private fun noEventOn(setState: () -> Unit) = runBlockingUnit {
|
||||||
assertState(INITIALIZED)
|
assertState(INITIALIZED)
|
||||||
bot.login()
|
bot.login()
|
||||||
bot.firstLoginSucceed = true
|
bot.components[SsoProcessor].firstLoginSucceed = true
|
||||||
assertState(OK)
|
assertState(OK)
|
||||||
network.setStateConnecting()
|
network.setStateConnecting()
|
||||||
delay(3.seconds) // `login` launches a job which broadcasts the event
|
delay(3.seconds) // `login` launches a job which broadcasts the event
|
||||||
|
Loading…
Reference in New Issue
Block a user