console login with BotAuthorization

This commit is contained in:
Karlatemp 2023-03-05 12:07:16 +08:00
parent 61318032f9
commit 8ea04dce3b
No known key found for this signature in database
GPG Key ID: BA173CA2B9956C59
5 changed files with 145 additions and 5 deletions

View File

@ -19,6 +19,7 @@ public abstract interface class net/mamoe/mirai/console/MiraiConsole : kotlinx/c
public final class net/mamoe/mirai/console/MiraiConsole$INSTANCE : net/mamoe/mirai/console/MiraiConsole { public final class net/mamoe/mirai/console/MiraiConsole$INSTANCE : net/mamoe/mirai/console/MiraiConsole {
public static synthetic fun addBot$default (Lnet/mamoe/mirai/console/MiraiConsole$INSTANCE;JLjava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lnet/mamoe/mirai/Bot; public static synthetic fun addBot$default (Lnet/mamoe/mirai/console/MiraiConsole$INSTANCE;JLjava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lnet/mamoe/mirai/Bot;
public static synthetic fun addBot$default (Lnet/mamoe/mirai/console/MiraiConsole$INSTANCE;JLnet/mamoe/mirai/auth/BotAuthorization;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lnet/mamoe/mirai/Bot;
public static synthetic fun addBot$default (Lnet/mamoe/mirai/console/MiraiConsole$INSTANCE;J[BLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lnet/mamoe/mirai/Bot; public static synthetic fun addBot$default (Lnet/mamoe/mirai/console/MiraiConsole$INSTANCE;J[BLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lnet/mamoe/mirai/Bot;
public fun getBuildDate ()Ljava/time/Instant; public fun getBuildDate ()Ljava/time/Instant;
public fun getBuiltInPluginLoaders ()Ljava/util/List; public fun getBuiltInPluginLoaders ()Ljava/util/List;

View File

@ -16,6 +16,7 @@ import kotlinx.coroutines.*
import me.him188.kotlin.dynamic.delegation.dynamicDelegation import me.him188.kotlin.dynamic.delegation.dynamicDelegation
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.BotFactory import net.mamoe.mirai.BotFactory
import net.mamoe.mirai.auth.BotAuthorization
import net.mamoe.mirai.console.MiraiConsole.INSTANCE import net.mamoe.mirai.console.MiraiConsole.INSTANCE
import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start
import net.mamoe.mirai.console.extensions.BotConfigurationAlterer import net.mamoe.mirai.console.extensions.BotConfigurationAlterer
@ -191,8 +192,31 @@ public interface MiraiConsole : CoroutineScope {
public fun addBot(id: Long, password: ByteArray, configuration: BotConfiguration.() -> Unit = {}): Bot = public fun addBot(id: Long, password: ByteArray, configuration: BotConfiguration.() -> Unit = {}): Bot =
addBotImpl(id, password, configuration) addBotImpl(id, password, configuration)
/**
* 添加一个 [Bot] 实例到全局 Bot 列表, 但不登录.
*
* 调用 [Bot.login] 可登录.
*
* @see Bot.instances 获取现有 [Bot] 实例列表
* @see BotConfigurationAlterer ExtensionPoint
*/
@ConsoleExperimentalApi("This is a low-level API and might be removed in the future.")
public fun addBot(
id: Long,
authorization: BotAuthorization,
configuration: BotConfiguration.() -> Unit = {}
): Bot = addBotImpl(id, authorization, configuration)
@Suppress("UNREACHABLE_CODE") @Suppress("UNREACHABLE_CODE")
private fun addBotImpl(id: Long, password: Any, configuration: BotConfiguration.() -> Unit = {}): Bot { private fun addBotImpl(id: Long, authorization: Any, configuration: BotConfiguration.() -> Unit = {}): Bot {
when (authorization) {
is String -> {}
is ByteArray -> {}
is BotAuthorization -> {}
else -> throw IllegalArgumentException("Bad authorization type: `${authorization.javaClass.name}`. Require String, ByteArray or BotAuthorization")
}
var config = BotConfiguration().apply { var config = BotConfiguration().apply {
workingDir = MiraiConsole.rootDir workingDir = MiraiConsole.rootDir
@ -239,10 +263,11 @@ public interface MiraiConsole : CoroutineScope {
extension.alterConfiguration(id, acc) extension.alterConfiguration(id, acc)
} }
return when (password) { return when (authorization) {
is ByteArray -> BotFactory.newBot(id, password, config) is ByteArray -> BotFactory.newBot(id, authorization, config) // pwd md5
is String -> BotFactory.newBot(id, password, config) is String -> BotFactory.newBot(id, authorization, config) // pwd
else -> throw IllegalArgumentException("Bad password type: `${password.javaClass.name}`. Require ByteArray or String") is BotAuthorization -> BotFactory.newBot(id, authorization, config) // authorization
else -> error("assert")
} }
} }

View File

@ -33,6 +33,7 @@ import net.mamoe.mirai.console.extensions.CommandCallParserProvider
import net.mamoe.mirai.console.extensions.CommandCallResolverProvider import net.mamoe.mirai.console.extensions.CommandCallResolverProvider
import net.mamoe.mirai.console.extensions.PermissionServiceProvider import net.mamoe.mirai.console.extensions.PermissionServiceProvider
import net.mamoe.mirai.console.extensions.PostStartupExtension import net.mamoe.mirai.console.extensions.PostStartupExtension
import net.mamoe.mirai.console.internal.auth.ConsoleSecretsCalculator
import net.mamoe.mirai.console.internal.command.CommandConfig import net.mamoe.mirai.console.internal.command.CommandConfig
import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig
import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig.Account.ConfigurationKey import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig.Account.ConfigurationKey
@ -100,6 +101,9 @@ internal class MiraiConsoleImplementationBridge(
@Volatile @Volatile
var permissionSeviceLoaded: Boolean = false var permissionSeviceLoaded: Boolean = false
// For protect account.secrets in console with non-password login
lateinit var consoleSecretsCalculator: ConsoleSecretsCalculator
// MiraiConsoleImplementation define: get() = LoggerControllerImpl() // MiraiConsoleImplementation define: get() = LoggerControllerImpl()
// Need to cache it or else created every call. // Need to cache it or else created every call.
// It caused config/Console/Logger.yml ignored. // It caused config/Console/Logger.yml ignored.
@ -290,6 +294,10 @@ ___ ____ _ _____ _
phase("initialize all plugins") { phase("initialize all plugins") {
pluginManager // init pluginManager // init
consoleSecretsCalculator = ConsoleSecretsCalculator(
pluginManager.pluginsDataPath.resolve("Console/console-secrets.key")
).also { it.consoleKey }
mainLogger.verbose { "Loading JVM plugins..." } mainLogger.verbose { "Loading JVM plugins..." }
pluginManager.loadAllPluginsUsingBuiltInLoaders() pluginManager.loadAllPluginsUsingBuiltInLoaders()
pluginManager.initExternalPluginLoaders().let { count -> pluginManager.initExternalPluginLoaders().let { count ->

View File

@ -0,0 +1,53 @@
/*
* 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.console.internal.auth
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.console.MiraiConsoleImplementation
import java.io.ByteArrayOutputStream
internal class ConsoleBotAuthorization(
private val delegate: suspend (BotAuthSession, BotAuthInfo) -> BotAuthResult,
) : BotAuthorization {
override suspend fun authorize(session: BotAuthSession, info: BotAuthInfo): BotAuthResult {
return delegate.invoke(session, info)
}
override fun calculateSecretsKey(bot: BotAuthInfo): ByteArray {
val calc = MiraiConsoleImplementation.getBridge().consoleSecretsCalculator
val writer = ByteArrayOutputStream()
writer += calc.consoleKey.asByteArray
writer += bot.deviceInfo.apn
writer += bot.deviceInfo.device
writer += bot.deviceInfo.bootId
writer += bot.deviceInfo.imsiMd5
return writer.toByteArray()
}
private operator fun ByteArrayOutputStream.plusAssign(data: ByteArray) {
write(data)
}
companion object {
fun byQRCode(): ConsoleBotAuthorization = ConsoleBotAuthorization { session, _ ->
session.authByQRCode()
}
}
}

View File

@ -0,0 +1,53 @@
/*
* 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.console.internal.auth
import net.mamoe.mirai.utils.SecretsProtection
import net.mamoe.mirai.utils.lateinitMutableProperty
import java.io.ByteArrayOutputStream
import java.io.DataOutputStream
import java.nio.file.Path
import java.util.*
import kotlin.io.path.createDirectories
import kotlin.io.path.isRegularFile
import kotlin.io.path.readBytes
import kotlin.io.path.writeBytes
internal class ConsoleSecretsCalculator(
private val file: Path,
) {
internal val consoleKey: SecretsProtection.EscapedByteBuffer get() = _consoleKey
private var _consoleKey: SecretsProtection.EscapedByteBuffer by lateinitMutableProperty {
loadOrCreate()
}
fun loadOrCreate(): SecretsProtection.EscapedByteBuffer {
if (file.isRegularFile()) {
return SecretsProtection.EscapedByteBuffer(file.readBytes())
}
file.parent?.createDirectories()
val dataStream = ByteArrayOutputStream()
val dataWriter = DataOutputStream(dataStream)
repeat(3) {
dataWriter.writeUTF(UUID.randomUUID().toString())
}
val data = dataStream.toByteArray()
file.writeBytes(data)
return SecretsProtection.EscapedByteBuffer(data)
}
fun reloadOrCreate() {
_consoleKey = loadOrCreate()
}
}