From ace117467837c4a995c3ec50e869d6aac4e3745b Mon Sep 17 00:00:00 2001 From: Him188 Date: Fri, 14 Feb 2020 21:54:03 +0800 Subject: [PATCH] Fix configuration --- .../mirai/utils/BotConfigurationAndroid.kt | 131 ++++++++++++++++++ .../mamoe/mirai/utils/defaultLoginSolver.kt | 30 ---- .../net.mamoe.mirai/utils/BotConfiguration.kt | 45 ++++-- ...chaSolverJvm.kt => BotConfigurationJvm.kt} | 97 +++++++++++++ .../net/mamoe/mirai/utils/SystemDeviceInfo.kt | 21 ++- 5 files changed, 274 insertions(+), 50 deletions(-) create mode 100644 mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/BotConfigurationAndroid.kt delete mode 100644 mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/defaultLoginSolver.kt rename mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/{DefaultCaptchaSolverJvm.kt => BotConfigurationJvm.kt} (67%) diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/BotConfigurationAndroid.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/BotConfigurationAndroid.kt new file mode 100644 index 000000000..611b8927d --- /dev/null +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/BotConfigurationAndroid.kt @@ -0,0 +1,131 @@ +/* + * Copyright 2020 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/master/LICENSE + */ + +package net.mamoe.mirai.utils + +import kotlinx.io.core.IoBuffer +import net.mamoe.mirai.Bot +import net.mamoe.mirai.network.BotNetworkHandler +import java.io.File +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext + +/** + * 在各平台实现的默认的验证码处理器. + */ +actual var defaultLoginSolver: LoginSolver = object : LoginSolver() { + override suspend fun onSolvePicCaptcha(bot: Bot, data: IoBuffer): String? { + error("should be implemented manually by you") + } + + override suspend fun onSolveSliderCaptcha(bot: Bot, url: String): String? { + error("should be implemented manually by you") + } + + override suspend fun onSolveUnsafeDeviceLoginVerify(bot: Bot, url: String): String? { + error("should be implemented manually by you") + } +} + +@Suppress("ClassName", "PropertyName") +actual open class BotConfiguration actual constructor() { + /** + * 日志记录器 + */ + actual var botLoggerSupplier: ((Bot) -> MiraiLogger) = { DefaultLogger("Bot(${it.uin})") } + /** + * 网络层日志构造器 + */ + actual var networkLoggerSupplier: ((BotNetworkHandler) -> MiraiLogger) = { DefaultLogger("Network(${it.bot.uin})") } + /** + * 设备信息覆盖. 默认使用随机的设备信息. + */ + actual var deviceInfo: ((Context) -> DeviceInfo)? = null + + /** + * 父 [CoroutineContext] + */ + actual var parentCoroutineContext: CoroutineContext = EmptyCoroutineContext + + /** + * 心跳周期. 过长会导致被服务器断开连接. + */ + actual var heartbeatPeriodMillis: Long = 60.secondsToMillis + /** + * 每次心跳时等待结果的时间. + * 一旦心跳超时, 整个网络服务将会重启 (将消耗约 5s). 除正在进行的任务 (如图片上传) 会被中断外, 事件和插件均不受影响. + */ + actual var heartbeatTimeoutMillis: Long = 2.secondsToMillis + /** + * 心跳失败后的第一次重连前的等待时间. + */ + actual var firstReconnectDelayMillis: Long = 5.secondsToMillis + /** + * 重连失败后, 继续尝试的每次等待时间 + */ + actual var reconnectPeriodMillis: Long = 60.secondsToMillis + /** + * 最多尝试多少次重连 + */ + actual var reconnectionRetryTimes: Int = 3 + /** + * 验证码处理器 + */ + actual var loginSolver: LoginSolver = defaultLoginSolver + + actual companion object { + /** + * 默认的配置实例 + */ + @JvmStatic + actual val Default = BotConfiguration() + } + + @Suppress("NOTHING_TO_INLINE") + @BotConfigurationDsl + inline operator fun FileBasedDeviceInfo.unaryPlus() { + deviceInfo = { File(filepath).loadAsDeviceInfo() } + } + + @Suppress("NOTHING_TO_INLINE") + @BotConfigurationDsl + inline operator fun FileBasedDeviceInfo.ByDeviceDotJson.unaryPlus() { + deviceInfo = { File("device.json").loadAsDeviceInfo() } + } + + actual operator fun _NoNetworkLog.unaryPlus() { + networkLoggerSupplier = supplier + } + + /** + * 不记录网络层的 log. + * 网络层 log 包含包接收, 包发送, 和一些调试用的记录. + */ + @BotConfigurationDsl + actual val NoNetworkLog: _NoNetworkLog + get() = _NoNetworkLog + + + @BotConfigurationDsl + actual object _NoNetworkLog { + internal val supplier = { _: BotNetworkHandler -> SilentLogger } + } +} + +/** + * 使用文件系统存储设备信息. + */ +@BotConfigurationDsl +inline class FileBasedDeviceInfo @BotConfigurationDsl constructor(val filepath: String) { + /** + * 使用 "device.json" 存储设备信息 + */ + @BotConfigurationDsl + companion object ByDeviceDotJson +} \ No newline at end of file diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/defaultLoginSolver.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/defaultLoginSolver.kt deleted file mode 100644 index ccd94b74c..000000000 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/defaultLoginSolver.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2020 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/master/LICENSE - */ - -package net.mamoe.mirai.utils - -import kotlinx.io.core.IoBuffer -import net.mamoe.mirai.Bot - -/** - * 在各平台实现的默认的验证码处理器. - */ -actual var defaultLoginSolver: LoginSolver = object : LoginSolver() { - override suspend fun onSolvePicCaptcha(bot: Bot, data: IoBuffer): String? { - error("should be implemented manually by you") - } - - override suspend fun onSolveSliderCaptcha(bot: Bot, url: String): String? { - error("should be implemented manually by you") - } - - override suspend fun onSolveUnsafeDeviceLoginVerify(bot: Bot, url: String): String? { - error("should be implemented manually by you") - } -} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt index b23e274d6..3ebb748ec 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt @@ -13,7 +13,6 @@ import kotlinx.io.core.IoBuffer import net.mamoe.mirai.Bot import net.mamoe.mirai.network.BotNetworkHandler import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext import kotlin.jvm.JvmStatic /** @@ -33,58 +32,74 @@ abstract class LoginSolver { expect var defaultLoginSolver: LoginSolver /** - * 网络和连接配置 + * [Bot] 配置 */ -class BotConfiguration { +@Suppress("PropertyName") +expect open class BotConfiguration() { /** * 日志记录器 */ - var botLoggerSupplier: ((Bot) -> MiraiLogger) = { DefaultLogger("Bot(${it.uin})") } + var botLoggerSupplier: ((Bot) -> MiraiLogger) /** * 网络层日志构造器 */ - var networkLoggerSupplier: ((BotNetworkHandler) -> MiraiLogger) = { DefaultLogger("Network(${it.bot.uin})") } + var networkLoggerSupplier: ((BotNetworkHandler) -> MiraiLogger) /** * 设备信息覆盖. 默认使用随机的设备信息. */ - var deviceInfo: ((Context) -> DeviceInfo)? = null + var deviceInfo: ((Context) -> DeviceInfo)? /** * 父 [CoroutineContext] */ - var parentCoroutineContext: CoroutineContext = EmptyCoroutineContext + var parentCoroutineContext: CoroutineContext /** * 心跳周期. 过长会导致被服务器断开连接. */ - var heartbeatPeriodMillis: Long = 60.secondsToMillis + var heartbeatPeriodMillis: Long /** * 每次心跳时等待结果的时间. * 一旦心跳超时, 整个网络服务将会重启 (将消耗约 5s). 除正在进行的任务 (如图片上传) 会被中断外, 事件和插件均不受影响. */ - var heartbeatTimeoutMillis: Long = 2.secondsToMillis + var heartbeatTimeoutMillis: Long /** * 心跳失败后的第一次重连前的等待时间. */ - var firstReconnectDelayMillis: Long = 5.secondsToMillis + var firstReconnectDelayMillis: Long /** * 重连失败后, 继续尝试的每次等待时间 */ - var reconnectPeriodMillis: Long = 60.secondsToMillis + var reconnectPeriodMillis: Long /** * 最多尝试多少次重连 */ - var reconnectionRetryTimes: Int = 3 + var reconnectionRetryTimes: Int /** * 验证码处理器 */ - var loginSolver: LoginSolver = defaultLoginSolver + var loginSolver: LoginSolver companion object { /** * 默认的配置实例 */ @JvmStatic - val Default = BotConfiguration() + val Default: BotConfiguration } -} \ No newline at end of file + + operator fun _NoNetworkLog.unaryPlus() + + /** + * 不记录网络层的 log. + * 网络层 log 包含包接收, 包发送, 和一些调试用的记录. + */ + @BotConfigurationDsl + val NoNetworkLog: _NoNetworkLog + + @Suppress("ClassName") + object _NoNetworkLog +} + +@DslMarker +annotation class BotConfigurationDsl \ No newline at end of file diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/DefaultCaptchaSolverJvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/BotConfigurationJvm.kt similarity index 67% rename from mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/DefaultCaptchaSolverJvm.kt rename to mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/BotConfigurationJvm.kt index ec265bd0e..a136328e3 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/DefaultCaptchaSolverJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/BotConfigurationJvm.kt @@ -22,12 +22,14 @@ import kotlinx.coroutines.withContext import kotlinx.io.core.IoBuffer import kotlinx.io.core.use import net.mamoe.mirai.Bot +import net.mamoe.mirai.network.BotNetworkHandler import java.awt.Image import java.awt.image.BufferedImage import java.io.File import java.io.RandomAccessFile import javax.imageio.ImageIO import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext /** * 平台默认的验证码识别器. @@ -157,3 +159,98 @@ private fun BufferedImage.createCharImg(outputWidth: Int = 100, ignoreRate: Doub } } +@Suppress("ClassName", "PropertyName") +actual open class BotConfiguration actual constructor() { + /** + * 日志记录器 + */ + actual var botLoggerSupplier: ((Bot) -> MiraiLogger) = { DefaultLogger("Bot(${it.uin})") } + /** + * 网络层日志构造器 + */ + actual var networkLoggerSupplier: ((BotNetworkHandler) -> MiraiLogger) = { DefaultLogger("Network(${it.bot.uin})") } + /** + * 设备信息覆盖. 默认使用随机的设备信息. + */ + actual var deviceInfo: ((Context) -> DeviceInfo)? = null + + /** + * 父 [CoroutineContext] + */ + actual var parentCoroutineContext: CoroutineContext = EmptyCoroutineContext + + /** + * 心跳周期. 过长会导致被服务器断开连接. + */ + actual var heartbeatPeriodMillis: Long = 60.secondsToMillis + /** + * 每次心跳时等待结果的时间. + * 一旦心跳超时, 整个网络服务将会重启 (将消耗约 5s). 除正在进行的任务 (如图片上传) 会被中断外, 事件和插件均不受影响. + */ + actual var heartbeatTimeoutMillis: Long = 2.secondsToMillis + /** + * 心跳失败后的第一次重连前的等待时间. + */ + actual var firstReconnectDelayMillis: Long = 5.secondsToMillis + /** + * 重连失败后, 继续尝试的每次等待时间 + */ + actual var reconnectPeriodMillis: Long = 60.secondsToMillis + /** + * 最多尝试多少次重连 + */ + actual var reconnectionRetryTimes: Int = 3 + /** + * 验证码处理器 + */ + actual var loginSolver: LoginSolver = defaultLoginSolver + + actual companion object { + /** + * 默认的配置实例 + */ + @JvmStatic + actual val Default = BotConfiguration() + } + + @Suppress("NOTHING_TO_INLINE") + @BotConfigurationDsl + inline operator fun FileBasedDeviceInfo.unaryPlus() { + deviceInfo = { File(filepath).loadAsDeviceInfo() } + } + + @Suppress("NOTHING_TO_INLINE") + @BotConfigurationDsl + inline operator fun FileBasedDeviceInfo.ByDeviceDotJson.unaryPlus() { + deviceInfo = { File("device.json").loadAsDeviceInfo() } + } + + actual operator fun _NoNetworkLog.unaryPlus() { + networkLoggerSupplier = supplier + } + + /** + * 不记录网络层的 log. + * 网络层 log 包含包接收, 包发送, 和一些调试用的记录. + */ + @BotConfigurationDsl + actual val NoNetworkLog: _NoNetworkLog + get() = _NoNetworkLog + + @BotConfigurationDsl + actual object _NoNetworkLog { + internal val supplier = { _: BotNetworkHandler -> SilentLogger } + } +} + +/** + * 使用文件系统存储设备信息. + */ +@BotConfigurationDsl +inline class FileBasedDeviceInfo @BotConfigurationDsl constructor(val filepath: String) { + /** + * 使用 "device.json" 存储设备信息 + */ + @BotConfigurationDsl + companion object ByDeviceDotJson +} \ No newline at end of file diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt index b1274bdaf..c1176eabf 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt @@ -19,7 +19,7 @@ import net.mamoe.mirai.utils.io.getRandomString import java.io.File /** - * 加载或创建一个设备信息. + * 加载一个设备信息. 若文件不存在或为空则随机并创建一个设备信息保存. */ @UseExperimental(UnstableDefault::class) fun File.loadAsDeviceInfo(context: Context = ContextImpl()): DeviceInfo { @@ -55,7 +55,7 @@ actual open class SystemDeviceInfo actual constructor() : DeviceInfo() { override val bootId: ByteArray = ExternalImage.generateUUID(md5(getRandomByteArray(16))).toByteArray() override val procVersion: ByteArray = "Linux version 3.0.31-${getRandomString(8)} (android-build@xxx.xxx.xxx.xxx.com)".toByteArray() override val baseBand: ByteArray = byteArrayOf() - override val version: DeviceInfo.Version get() = Version + override val version: Version = Version override val simInfo: ByteArray = "T-Mobile".toByteArray() override val osType: ByteArray = "android".toByteArray() override val macAddress: ByteArray = "02:00:00:00:00:00".toByteArray() @@ -89,7 +89,7 @@ class DeviceInfoData( override val bootId: ByteArray, override val procVersion: ByteArray, override val baseBand: ByteArray, - override val version: Version, + override val version: VersionData, override val simInfo: ByteArray, override val osType: ByteArray, override val macAddress: ByteArray, @@ -97,10 +97,21 @@ class DeviceInfoData( override val wifiSSID: ByteArray?, override val imsiMd5: ByteArray, override val imei: String, - override val ipAddress: ByteArray, - override val androidId: ByteArray, override val apn: ByteArray ) : DeviceInfo() { @Transient override lateinit var context: Context + + @UseExperimental(ExperimentalUnsignedTypes::class) + override val ipAddress: ByteArray + get() = localIpAddress().split(".").map { it.toUByte().toByte() }.takeIf { it.size == 4 }?.toByteArray() ?: byteArrayOf() + override val androidId: ByteArray get() = display + + @Serializable + class VersionData( + override val incremental: ByteArray, + override val release: ByteArray, + override val codename: ByteArray, + override val sdk: Int + ) : Version } \ No newline at end of file