diff --git a/mirai-core/src/commonMain/kotlin/network/auth/AuthControl.kt b/mirai-core/src/commonMain/kotlin/network/auth/AuthControl.kt index 215d91661..10eeea267 100644 --- a/mirai-core/src/commonMain/kotlin/network/auth/AuthControl.kt +++ b/mirai-core/src/commonMain/kotlin/network/auth/AuthControl.kt @@ -10,11 +10,13 @@ package net.mamoe.mirai.internal.network.auth import net.mamoe.mirai.auth.BotAuthInfo -import net.mamoe.mirai.auth.BotAuthResult import net.mamoe.mirai.auth.BotAuthorization import net.mamoe.mirai.internal.network.components.SsoProcessorImpl import net.mamoe.mirai.internal.utils.subLogger -import net.mamoe.mirai.utils.* +import net.mamoe.mirai.utils.ExceptionCollector +import net.mamoe.mirai.utils.MiraiLogger +import net.mamoe.mirai.utils.debug +import net.mamoe.mirai.utils.verbose import kotlin.coroutines.CoroutineContext import kotlin.coroutines.cancellation.CancellationException @@ -35,41 +37,7 @@ internal class AuthControl( private val userDecisions: OnDemandConsumer = CoroutineOnDemandValueScope(parentCoroutineContext, logger.subLogger("AuthControl/UserDecisions")) { _ -> - /** - * Implements [BotAuthSessionInternal] from API, to be called by the user, to receive user's decisions. - */ - val sessionImpl = object : BotAuthSessionInternal() { - private val authResultImpl = object : BotAuthResult {} - - override suspend fun authByPassword(passwordMd5: SecretsProtection.EscapedByteBuffer): BotAuthResult { - runWrapInternalException { - emit(SsoProcessorImpl.AuthMethod.Pwd(passwordMd5)) - }?.let { throw it } - return authResultImpl - } - - override suspend fun authByQRCode(): BotAuthResult { - runWrapInternalException { - emit(SsoProcessorImpl.AuthMethod.QRCode) - }?.let { throw it } - return authResultImpl - } - - private inline fun runWrapInternalException(block: () -> R): R { - try { - return block() - } catch (e: IllegalProducerStateException) { - if (e.lastStateWasSucceed) { - throw IllegalStateException( - "This login session has already completed. Please return the BotAuthResult you get from 'authBy*()' immediately", - e - ) - } else { - throw e // internal bug - } - } - } - } + val sessionImpl = SafeBotAuthSession(this) try { logger.verbose { "[AuthControl/auth] Authorization started" } diff --git a/mirai-core/src/commonMain/kotlin/network/auth/BotAuthSession.kt b/mirai-core/src/commonMain/kotlin/network/auth/BotAuthSessionInternal.kt similarity index 100% rename from mirai-core/src/commonMain/kotlin/network/auth/BotAuthSession.kt rename to mirai-core/src/commonMain/kotlin/network/auth/BotAuthSessionInternal.kt diff --git a/mirai-core/src/commonMain/kotlin/network/auth/SafeBotAuthSession.kt b/mirai-core/src/commonMain/kotlin/network/auth/SafeBotAuthSession.kt new file mode 100644 index 000000000..27e8a3d69 --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/network/auth/SafeBotAuthSession.kt @@ -0,0 +1,52 @@ +/* + * 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 net.mamoe.mirai.auth.BotAuthResult +import net.mamoe.mirai.internal.network.components.SsoProcessorImpl +import net.mamoe.mirai.utils.SecretsProtection + +/** + * Implements [BotAuthSessionInternal] from API, to be called by the user, to receive user's decisions. + */ +internal class SafeBotAuthSession( + private val producer: OnDemandProducerScope +) : BotAuthSessionInternal() { + private val authResultImpl = object : BotAuthResult {} + + override suspend fun authByPassword(passwordMd5: SecretsProtection.EscapedByteBuffer): BotAuthResult { + runWrapInternalException { + producer.emit(SsoProcessorImpl.AuthMethod.Pwd(passwordMd5)) + }?.let { throw it } + return authResultImpl + } + + override suspend fun authByQRCode(): BotAuthResult { + runWrapInternalException { + producer.emit(SsoProcessorImpl.AuthMethod.QRCode) + }?.let { throw it } + return authResultImpl + } + + private inline fun runWrapInternalException(block: () -> R): R { + try { + return block() + } catch (e: IllegalProducerStateException) { + if (e.lastStateWasSucceed) { + throw IllegalStateException( + "This login session has already completed. Please return the BotAuthResult you get from 'authBy*()' immediately", + e + ) + } else { + throw e // internal bug + } + } + } +}