mirror of
https://github.com/mamoe/mirai.git
synced 2025-04-25 21:23:55 +08:00
[core] Provide isFirstLogin
and getReLoginCause
in BotAuthInfo
(#2664)
* [core] provide `isFirstLogin` and `getReLoginCause` in `BotAuthInfo` * [core] provide `reAuthCause` as sealed class * [core] add test * Update mirai-core-api/src/commonMain/kotlin/auth/BotAuthorization.kt 我觉得这个描述不太好,因为这里是 `authorize` 过程而不是 `login` 过程 Co-authored-by: Him188 <Him188@mamoe.net> * [core] optimize docs and rename * import * revert linebreak --------- Co-authored-by: Him188 <Him188@mamoe.net>
This commit is contained in:
parent
8ff64d4a7f
commit
545e5bb310
mirai-core-api
compatibility-validation
src/commonMain/kotlin/auth
mirai-core/src
commonMain/kotlin
commonTest/kotlin/network
auth
component
framework/components
@ -172,10 +172,48 @@ public final class net/mamoe/mirai/_MiraiInstance {
|
||||
public static final fun set (Lnet/mamoe/mirai/IMirai;)V
|
||||
}
|
||||
|
||||
public abstract class net/mamoe/mirai/auth/AuthReason {
|
||||
public abstract fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public abstract fun getMessage ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/auth/AuthReason$FastLoginError : net/mamoe/mirai/auth/AuthReason {
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public fun getMessage ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/auth/AuthReason$ForceOffline : net/mamoe/mirai/auth/AuthReason {
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public fun getMessage ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/auth/AuthReason$FreshLogin : net/mamoe/mirai/auth/AuthReason {
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public fun getMessage ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/auth/AuthReason$MsfOffline : net/mamoe/mirai/auth/AuthReason {
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public fun getMessage ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/auth/AuthReason$NetworkError : net/mamoe/mirai/auth/AuthReason {
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public fun getMessage ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/auth/AuthReason$Unknown : net/mamoe/mirai/auth/AuthReason {
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public final fun getCause ()Ljava/lang/Throwable;
|
||||
public fun getMessage ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/auth/BotAuthInfo {
|
||||
public abstract fun getConfiguration ()Lnet/mamoe/mirai/utils/BotConfiguration;
|
||||
public abstract fun getDeviceInfo ()Lnet/mamoe/mirai/utils/DeviceInfo;
|
||||
public abstract fun getId ()J
|
||||
public abstract fun getReason ()Lnet/mamoe/mirai/auth/AuthReason;
|
||||
public abstract fun isFirstLogin ()Z
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/auth/BotAuthResult {
|
||||
|
@ -172,10 +172,48 @@ public final class net/mamoe/mirai/_MiraiInstance {
|
||||
public static final fun set (Lnet/mamoe/mirai/IMirai;)V
|
||||
}
|
||||
|
||||
public abstract class net/mamoe/mirai/auth/AuthReason {
|
||||
public abstract fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public abstract fun getMessage ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/auth/AuthReason$FastLoginError : net/mamoe/mirai/auth/AuthReason {
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public fun getMessage ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/auth/AuthReason$ForceOffline : net/mamoe/mirai/auth/AuthReason {
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public fun getMessage ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/auth/AuthReason$FreshLogin : net/mamoe/mirai/auth/AuthReason {
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public fun getMessage ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/auth/AuthReason$MsfOffline : net/mamoe/mirai/auth/AuthReason {
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public fun getMessage ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/auth/AuthReason$NetworkError : net/mamoe/mirai/auth/AuthReason {
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public fun getMessage ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/auth/AuthReason$Unknown : net/mamoe/mirai/auth/AuthReason {
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public final fun getCause ()Ljava/lang/Throwable;
|
||||
public fun getMessage ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/auth/BotAuthInfo {
|
||||
public abstract fun getConfiguration ()Lnet/mamoe/mirai/utils/BotConfiguration;
|
||||
public abstract fun getDeviceInfo ()Lnet/mamoe/mirai/utils/DeviceInfo;
|
||||
public abstract fun getId ()J
|
||||
public abstract fun getReason ()Lnet/mamoe/mirai/auth/AuthReason;
|
||||
public abstract fun isFirstLogin ()Z
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/auth/BotAuthResult {
|
||||
|
@ -9,8 +9,10 @@
|
||||
|
||||
package net.mamoe.mirai.auth
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.BotFactory
|
||||
import net.mamoe.mirai.Mirai
|
||||
import net.mamoe.mirai.event.events.BotOfflineEvent
|
||||
import net.mamoe.mirai.network.LoginFailedException
|
||||
import net.mamoe.mirai.network.RetryLaterException
|
||||
import net.mamoe.mirai.utils.*
|
||||
@ -102,6 +104,114 @@ public interface BotAuthInfo {
|
||||
public val id: Long
|
||||
public val deviceInfo: DeviceInfo
|
||||
public val configuration: BotConfiguration
|
||||
|
||||
/**
|
||||
* 是否是首次登录
|
||||
*
|
||||
* 首次登录指的是首次调用 [Bot.login] 进行登录,直到登录成功的过程。
|
||||
*
|
||||
* 若在首次登录过程中多次进入[认证流程][BotAuthorization.authorize],则这流程些均被视为首次登录。
|
||||
*
|
||||
* @see Bot.login
|
||||
* @see BotAuthorization.authorize
|
||||
*/
|
||||
public val isFirstLogin: Boolean
|
||||
|
||||
/**
|
||||
* 导致进入[认证流程][BotAuthorization.authorize]的原因。
|
||||
*/
|
||||
public val reason: AuthReason
|
||||
}
|
||||
|
||||
/**
|
||||
* 导致进行[认证流程][BotAuthorization.authorize]的原因
|
||||
*/
|
||||
public sealed class AuthReason {
|
||||
public abstract val bot: Bot
|
||||
public abstract val message: String?
|
||||
|
||||
/**
|
||||
* Bot 全新[登录][Bot.login]
|
||||
*
|
||||
* 全新登录指登录前本地没有任何当前 Bot 的登录缓存信息而进行的登录。
|
||||
*
|
||||
* 全新登录时将会进入[认证流程][BotAuthorization.authorize]。
|
||||
*
|
||||
* @see Bot.login
|
||||
* @see FastLoginError
|
||||
*/
|
||||
public class FreshLogin @MiraiInternalApi constructor(
|
||||
override val bot: Bot,
|
||||
override val message: String?
|
||||
) : AuthReason()
|
||||
|
||||
/**
|
||||
* Bot 被挤下线
|
||||
*
|
||||
* 当 Bot 账号在其他客户端使用相同(或相似)协议登录时,Bot 会下线,
|
||||
* 被挤下线后当前的登录会话将失效。
|
||||
*
|
||||
* 当 [BotConfiguration.autoReconnectOnForceOffline] 为 `true` 时,
|
||||
* Bot 会尝试重新登录,并会以此原因进入[认证流程][BotAuthorization.authorize]。
|
||||
*
|
||||
* @see BotConfiguration.autoReconnectOnForceOffline
|
||||
* @see BotOfflineEvent.Force
|
||||
*/
|
||||
public class ForceOffline @MiraiInternalApi constructor(
|
||||
override val bot: Bot,
|
||||
override val message: String?
|
||||
) : AuthReason()
|
||||
|
||||
/**
|
||||
* Bot 被服务器断开
|
||||
*
|
||||
* 因其他原因导致 Bot 被服务器断开。这些原因包括账号被封禁、被其他客户端手动下线等,
|
||||
* 被服务器断开下线后当前的登录会话将失效。
|
||||
*
|
||||
* Bot 会尝试重新登录,并会以此原因进入[认证流程][BotAuthorization.authorize]。
|
||||
*
|
||||
* @see BotOfflineEvent.MsfOffline
|
||||
*/
|
||||
public class MsfOffline @MiraiInternalApi constructor(
|
||||
override val bot: Bot,
|
||||
override val message: String?
|
||||
) : AuthReason()
|
||||
|
||||
/**
|
||||
* 由网络原因引起的掉线
|
||||
*
|
||||
* 一般情况下,Bot 被服务器断开后会尝试重新登录。
|
||||
*
|
||||
* 由网络问题引起的掉线不一定会使当前的登录会话失效,
|
||||
* 仅登录会话失效时 Bot 会以此原因进入[认证流程][BotAuthorization.authorize]。
|
||||
*/
|
||||
public class NetworkError @MiraiInternalApi constructor(
|
||||
override val bot: Bot,
|
||||
override val message: String?
|
||||
) : AuthReason()
|
||||
|
||||
/**
|
||||
* 快速登录失败
|
||||
*
|
||||
* Bot 账号首次 [登录][Bot.login] 成功后,会保存登录缓存信息用于下次登录。
|
||||
*
|
||||
* 下次登录时,Bot 会首先使用登录缓存信息尝试快速登录,
|
||||
* 若快速登录失败,则会以此原因进入[认证流程][BotAuthorization.authorize]。
|
||||
*
|
||||
* @see BotAuthorization.authorize
|
||||
* @see Bot.login
|
||||
*/
|
||||
public class FastLoginError @MiraiInternalApi constructor(
|
||||
override val bot: Bot,
|
||||
override val message: String?
|
||||
) : AuthReason()
|
||||
|
||||
public class Unknown @MiraiInternalApi constructor(
|
||||
override val bot: Bot,
|
||||
public val cause: Throwable?
|
||||
) : AuthReason() {
|
||||
override val message: String? = cause?.message
|
||||
}
|
||||
}
|
||||
|
||||
@NotStableForInheritance
|
||||
|
@ -12,6 +12,7 @@ package net.mamoe.mirai.internal
|
||||
import kotlinx.atomicfu.atomic
|
||||
import kotlinx.coroutines.*
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.auth.AuthReason
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.BotOfflineEvent
|
||||
import net.mamoe.mirai.event.events.BotOnlineEvent
|
||||
@ -141,14 +142,18 @@ internal open class QQAndroidBot constructor(
|
||||
cause is ForceOfflineException -> {
|
||||
eventDispatcher.broadcastAsync(BotOfflineEvent.Force(bot, cause.title, cause.message))
|
||||
}
|
||||
|
||||
cause is StatSvc.ReqMSFOffline.MsfOfflineToken -> {
|
||||
eventDispatcher.broadcastAsync(BotOfflineEvent.MsfOffline(bot, cause))
|
||||
}
|
||||
|
||||
cause is NetworkException && cause.recoverable -> {
|
||||
eventDispatcher.broadcastAsync(BotOfflineEvent.Dropped(bot, cause))
|
||||
}
|
||||
|
||||
cause is BotClosedByEvent -> {
|
||||
}
|
||||
|
||||
else -> {
|
||||
// any other unexpected exceptions considered as an error
|
||||
|
||||
@ -165,6 +170,17 @@ internal open class QQAndroidBot constructor(
|
||||
}
|
||||
}
|
||||
},
|
||||
StateChangedObserver("ReLoginCauseCatcher", State.OK, State.CLOSED) { new ->
|
||||
get(SsoProcessor).authReason = when (val cause = new.getCause()) {
|
||||
is ForceOfflineException -> AuthReason.ForceOffline(bot, cause.message)
|
||||
is StatSvc.ReqMSFOffline.MsfOfflineToken -> AuthReason.MsfOffline(bot, cause.message)
|
||||
is NetworkException -> AuthReason.NetworkError(bot, cause.message)
|
||||
else -> AuthReason.Unknown(bot, cause)
|
||||
}
|
||||
},
|
||||
StateChangedObserver("FirstLoginObserver", State.OK) {
|
||||
get(SsoProcessor).isFirstLogin = false
|
||||
}
|
||||
).safe(logger.subLogger("StateObserver")) + LoggingStateObserver.createLoggingIfEnabled()
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ package net.mamoe.mirai.internal.network.components
|
||||
|
||||
import kotlinx.atomicfu.AtomicRef
|
||||
import kotlinx.atomicfu.atomic
|
||||
import net.mamoe.mirai.auth.AuthReason
|
||||
import net.mamoe.mirai.auth.BotAuthInfo
|
||||
import net.mamoe.mirai.auth.BotAuthorization
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
@ -58,6 +59,9 @@ internal interface SsoProcessor {
|
||||
val firstLoginSucceed: Boolean get() = firstLoginResult?.success ?: false
|
||||
val registerResp: StatSvc.Register.Response?
|
||||
|
||||
var isFirstLogin: Boolean
|
||||
var authReason: AuthReason
|
||||
|
||||
/**
|
||||
* Do login. Throws [LoginFailedException] if failed
|
||||
*/
|
||||
@ -147,6 +151,11 @@ internal open class SsoProcessorImpl(
|
||||
override val ssoSession: SsoSession get() = client
|
||||
private val components get() = ssoContext.bot.components
|
||||
|
||||
override var isFirstLogin: Boolean = true
|
||||
override var authReason: AuthReason by lateinitMutableProperty {
|
||||
AuthReason.FreshLogin(ssoContext.bot, null)
|
||||
}
|
||||
|
||||
private val botAuthInfo = object : BotAuthInfo {
|
||||
override val id: Long
|
||||
get() = ssoContext.bot.id
|
||||
@ -154,6 +163,10 @@ internal open class SsoProcessorImpl(
|
||||
get() = ssoContext.device
|
||||
override val configuration: BotConfiguration
|
||||
get() = ssoContext.bot.configuration
|
||||
override val isFirstLogin: Boolean
|
||||
get() = this@SsoProcessorImpl.isFirstLogin
|
||||
override val reason: AuthReason
|
||||
get() = this@SsoProcessorImpl.authReason
|
||||
}
|
||||
|
||||
protected open suspend fun doSlowLogin(
|
||||
@ -215,6 +228,11 @@ internal open class SsoProcessorImpl(
|
||||
kotlin.runCatching {
|
||||
doFastLogin(handler)
|
||||
}.onFailure { e ->
|
||||
// first fast-login exception should also be considered as re-auth cause.
|
||||
if (isFirstLogin) {
|
||||
authReason = AuthReason.FastLoginError(ssoContext.bot, e.message)
|
||||
}
|
||||
|
||||
initAndStartAuthControl()
|
||||
authControl!!.exceptionCollector.collect(e)
|
||||
|
||||
@ -224,6 +242,8 @@ internal open class SsoProcessorImpl(
|
||||
loginSuccess()
|
||||
|
||||
return
|
||||
} else if (isFirstLogin) {
|
||||
authReason = AuthReason.FreshLogin(ssoContext.bot, null)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ internal abstract class AbstractBotAuthTest : AbstractCommonNHTestWithSelector()
|
||||
overrideComponents[SsoProcessor] = SsoProcessorImpl(overrideComponents[SsoProcessorContext])
|
||||
}
|
||||
|
||||
protected fun setAuthorization(authorize: (session: BotAuthSession, info: BotAuthInfo) -> BotAuthResult) {
|
||||
protected fun setAuthorization(authorize: suspend (session: BotAuthSession, info: BotAuthInfo) -> BotAuthResult) {
|
||||
// Run a real SsoProcessor, just without sending packets
|
||||
bot.account.authorization = object : BotAuthorization {
|
||||
override suspend fun authorize(session: BotAuthSession, info: BotAuthInfo): BotAuthResult {
|
||||
|
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2019-2023 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/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.network.auth
|
||||
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import net.mamoe.mirai.auth.AuthReason
|
||||
import net.mamoe.mirai.auth.BotAuthResult
|
||||
import net.mamoe.mirai.internal.MockAccount
|
||||
import net.mamoe.mirai.internal.contact.uin
|
||||
import net.mamoe.mirai.internal.network.components.AccountSecretsManager
|
||||
import net.mamoe.mirai.internal.network.framework.createWLoginSigInfo
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushForceOffline
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.SvcRespRegister
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacket
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.MessageSvcPushForceOffline
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.login.WtLogin
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertIs
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
internal class AuthorizationReasonTest : AbstractBotAuthTest() {
|
||||
@Test
|
||||
fun `first login without fast login`() = runTest {
|
||||
var isFirstLogin: Boolean = false
|
||||
var authReason: AuthReason? = AuthReason.Unknown(bot, null)
|
||||
|
||||
setAuthorization { auth, info ->
|
||||
isFirstLogin = info.isFirstLogin
|
||||
authReason = info.reason
|
||||
|
||||
auth.authByPassword("")
|
||||
return@setAuthorization object : BotAuthResult {}
|
||||
}
|
||||
|
||||
usePacketReplierThroughout {
|
||||
expect(WtLogin.Login) reply {
|
||||
bot.components[AccountSecretsManager].getSecrets(MockAccount)
|
||||
?.wLoginSigInfo = createWLoginSigInfo(bot.id)
|
||||
|
||||
WtLogin.Login.LoginPacketResponse.Success(bot)
|
||||
}
|
||||
expect(StatSvc.Register) reply { StatSvc.Register.Response(SvcRespRegister()) }
|
||||
expect(StatSvc.Register) reply { StatSvc.Register.Response(SvcRespRegister()) }
|
||||
}
|
||||
|
||||
bot.components[AccountSecretsManager].getSecrets(MockAccount)?.wLoginSigInfoField = null
|
||||
bot.login()
|
||||
|
||||
assertTrue(isFirstLogin)
|
||||
assertIs<AuthReason.FreshLogin>(authReason)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `first login with fast login success`() = runTest {
|
||||
var authorizationCalled = false
|
||||
setAuthorization { auth, _ ->
|
||||
authorizationCalled = true
|
||||
|
||||
auth.authByPassword("")
|
||||
return@setAuthorization object : BotAuthResult {}
|
||||
}
|
||||
|
||||
usePacketReplierThroughout {
|
||||
expect(WtLogin.ExchangeEmp) reply { WtLogin.Login.LoginPacketResponse.Success(bot) }
|
||||
expect(StatSvc.Register) reply { StatSvc.Register.Response(SvcRespRegister()) }
|
||||
expect(StatSvc.Register) reply { StatSvc.Register.Response(SvcRespRegister()) }
|
||||
}
|
||||
|
||||
bot.login()
|
||||
|
||||
assertFalse(authorizationCalled)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `first login with fast login fail`() = runTest {
|
||||
var isFirstLogin: Boolean = false
|
||||
var authReason: AuthReason? = null
|
||||
|
||||
setAuthorization { auth, info ->
|
||||
isFirstLogin = info.isFirstLogin
|
||||
authReason = info.reason
|
||||
|
||||
auth.authByPassword("")
|
||||
return@setAuthorization object : BotAuthResult {}
|
||||
}
|
||||
|
||||
usePacketReplierThroughout {
|
||||
expect(WtLogin.ExchangeEmp) reply { WtLogin.Login.LoginPacketResponse.Error(bot, 1, "", "", ", ") }
|
||||
expect(WtLogin.Login) reply { WtLogin.Login.LoginPacketResponse.Success(bot) }
|
||||
expect(StatSvc.Register) reply { StatSvc.Register.Response(SvcRespRegister()) }
|
||||
expect(StatSvc.Register) reply { StatSvc.Register.Response(SvcRespRegister()) }
|
||||
}
|
||||
|
||||
bot.login()
|
||||
|
||||
assertTrue(isFirstLogin)
|
||||
assertIs<AuthReason.FastLoginError>(authReason)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `force offline`() = runTest {
|
||||
var isFirstLogin: Boolean = true
|
||||
var authReason: AuthReason? = null
|
||||
|
||||
setAuthorization { auth, info ->
|
||||
isFirstLogin = info.isFirstLogin
|
||||
authReason = info.reason
|
||||
|
||||
auth.authByPassword("")
|
||||
return@setAuthorization object : BotAuthResult {}
|
||||
}
|
||||
|
||||
usePacketReplierThroughout {
|
||||
expect(WtLogin.ExchangeEmp) reply { WtLogin.Login.LoginPacketResponse.Success(bot) }
|
||||
expect(StatSvc.Register) reply { StatSvc.Register.Response(SvcRespRegister()) }
|
||||
expect(WtLogin.Login) reply {
|
||||
bot.components[AccountSecretsManager].getSecrets(MockAccount)
|
||||
?.wLoginSigInfo = createWLoginSigInfo(bot.id)
|
||||
WtLogin.Login.LoginPacketResponse.Success(bot)
|
||||
}
|
||||
expect(StatSvc.Register) reply { StatSvc.Register.Response(SvcRespRegister()) }
|
||||
expect(StatSvc.Register) reply { StatSvc.Register.Response(SvcRespRegister()) }
|
||||
}
|
||||
|
||||
bot.configuration.autoReconnectOnForceOffline = true
|
||||
bot.login()
|
||||
|
||||
network.currentInstance().collectReceived(
|
||||
IncomingPacket(
|
||||
MessageSvcPushForceOffline.commandName,
|
||||
RequestPushForceOffline(bot.uin, tips = "force offline manually in test")
|
||||
)
|
||||
)
|
||||
|
||||
eventDispatcher.joinBroadcast() // why test finished before code reaches end??
|
||||
|
||||
assertFalse(isFirstLogin)
|
||||
assertIs<AuthReason.ForceOffline>(authReason)
|
||||
}
|
||||
}
|
@ -11,10 +11,7 @@ package net.mamoe.mirai.internal.network.component
|
||||
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlinx.coroutines.yield
|
||||
import net.mamoe.mirai.auth.BotAuthInfo
|
||||
import net.mamoe.mirai.auth.BotAuthResult
|
||||
import net.mamoe.mirai.auth.BotAuthSession
|
||||
import net.mamoe.mirai.auth.BotAuthorization
|
||||
import net.mamoe.mirai.auth.*
|
||||
import net.mamoe.mirai.internal.network.auth.AuthControl
|
||||
import net.mamoe.mirai.internal.network.components.SsoProcessorContext
|
||||
import net.mamoe.mirai.internal.network.components.SsoProcessorImpl
|
||||
@ -23,6 +20,7 @@ import net.mamoe.mirai.network.CustomLoginFailedException
|
||||
import net.mamoe.mirai.utils.BotConfiguration
|
||||
import net.mamoe.mirai.utils.DeviceInfo
|
||||
import net.mamoe.mirai.utils.EMPTY_BYTE_ARRAY
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertFailsWith
|
||||
@ -36,6 +34,11 @@ internal class BotAuthControlTest : AbstractCommonNHTest() {
|
||||
get() = bot.components[SsoProcessorContext].device
|
||||
override val configuration: BotConfiguration
|
||||
get() = bot.configuration
|
||||
|
||||
override val isFirstLogin: Boolean
|
||||
get() = false
|
||||
|
||||
override val reason: AuthReason by Delegates.notNull()
|
||||
}
|
||||
|
||||
private suspend fun AuthControl.assertRequire(exceptedType: KClass<*>) {
|
||||
|
@ -11,6 +11,7 @@ package net.mamoe.mirai.internal.network.framework.components
|
||||
|
||||
import kotlinx.atomicfu.AtomicRef
|
||||
import kotlinx.atomicfu.atomic
|
||||
import net.mamoe.mirai.auth.AuthReason
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.network.QQAndroidClient
|
||||
import net.mamoe.mirai.internal.network.components.*
|
||||
@ -21,6 +22,7 @@ import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
|
||||
import net.mamoe.mirai.utils.DeviceInfo
|
||||
import net.mamoe.mirai.utils.debug
|
||||
import net.mamoe.mirai.utils.lateinitMutableProperty
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.random.Random
|
||||
|
||||
internal open class TestSsoProcessor(private val bot: QQAndroidBot) : SsoProcessor {
|
||||
@ -47,6 +49,9 @@ internal open class TestSsoProcessor(private val bot: QQAndroidBot) : SsoProcess
|
||||
}
|
||||
|
||||
override var registerResp: StatSvc.Register.Response? = null
|
||||
|
||||
override var authReason: AuthReason by Delegates.notNull()
|
||||
override var isFirstLogin: Boolean = true
|
||||
override suspend fun login(handler: NetworkHandler) {
|
||||
bot.network.logger.debug { "SsoProcessor.login" }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user