Fix configuration

This commit is contained in:
Him188 2020-02-14 21:54:03 +08:00
parent 32e854db29
commit ace1174678
5 changed files with 274 additions and 50 deletions

View File

@ -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
}

View File

@ -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")
}
}

View File

@ -13,7 +13,6 @@ import kotlinx.io.core.IoBuffer
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.network.BotNetworkHandler
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.jvm.JvmStatic import kotlin.jvm.JvmStatic
/** /**
@ -33,58 +32,74 @@ abstract class LoginSolver {
expect var defaultLoginSolver: 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] * [CoroutineContext]
*/ */
var parentCoroutineContext: CoroutineContext = EmptyCoroutineContext var parentCoroutineContext: CoroutineContext
/** /**
* 心跳周期. 过长会导致被服务器断开连接. * 心跳周期. 过长会导致被服务器断开连接.
*/ */
var heartbeatPeriodMillis: Long = 60.secondsToMillis var heartbeatPeriodMillis: Long
/** /**
* 每次心跳时等待结果的时间. * 每次心跳时等待结果的时间.
* 一旦心跳超时, 整个网络服务将会重启 (将消耗约 5s). 除正在进行的任务 (如图片上传) 会被中断外, 事件和插件均不受影响. * 一旦心跳超时, 整个网络服务将会重启 (将消耗约 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 { companion object {
/** /**
* 默认的配置实例 * 默认的配置实例
*/ */
@JvmStatic @JvmStatic
val Default = BotConfiguration() val Default: BotConfiguration
} }
operator fun _NoNetworkLog.unaryPlus()
/**
* 不记录网络层的 log.
* 网络层 log 包含包接收, 包发送, 和一些调试用的记录.
*/
@BotConfigurationDsl
val NoNetworkLog: _NoNetworkLog
@Suppress("ClassName")
object _NoNetworkLog
} }
@DslMarker
annotation class BotConfigurationDsl

View File

@ -22,12 +22,14 @@ import kotlinx.coroutines.withContext
import kotlinx.io.core.IoBuffer import kotlinx.io.core.IoBuffer
import kotlinx.io.core.use import kotlinx.io.core.use
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.network.BotNetworkHandler
import java.awt.Image import java.awt.Image
import java.awt.image.BufferedImage import java.awt.image.BufferedImage
import java.io.File import java.io.File
import java.io.RandomAccessFile import java.io.RandomAccessFile
import javax.imageio.ImageIO import javax.imageio.ImageIO
import kotlin.coroutines.CoroutineContext 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
}

View File

@ -19,7 +19,7 @@ import net.mamoe.mirai.utils.io.getRandomString
import java.io.File import java.io.File
/** /**
* 加载或创建一个设备信息. * 加载一个设备信息. 若文件不存在为空则随机并创建一个设备信息保存.
*/ */
@UseExperimental(UnstableDefault::class) @UseExperimental(UnstableDefault::class)
fun File.loadAsDeviceInfo(context: Context = ContextImpl()): DeviceInfo { 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 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 procVersion: ByteArray = "Linux version 3.0.31-${getRandomString(8)} (android-build@xxx.xxx.xxx.xxx.com)".toByteArray()
override val baseBand: ByteArray = byteArrayOf() 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 simInfo: ByteArray = "T-Mobile".toByteArray()
override val osType: ByteArray = "android".toByteArray() override val osType: ByteArray = "android".toByteArray()
override val macAddress: ByteArray = "02:00:00:00:00:00".toByteArray() override val macAddress: ByteArray = "02:00:00:00:00:00".toByteArray()
@ -89,7 +89,7 @@ class DeviceInfoData(
override val bootId: ByteArray, override val bootId: ByteArray,
override val procVersion: ByteArray, override val procVersion: ByteArray,
override val baseBand: ByteArray, override val baseBand: ByteArray,
override val version: Version, override val version: VersionData,
override val simInfo: ByteArray, override val simInfo: ByteArray,
override val osType: ByteArray, override val osType: ByteArray,
override val macAddress: ByteArray, override val macAddress: ByteArray,
@ -97,10 +97,21 @@ class DeviceInfoData(
override val wifiSSID: ByteArray?, override val wifiSSID: ByteArray?,
override val imsiMd5: ByteArray, override val imsiMd5: ByteArray,
override val imei: String, override val imei: String,
override val ipAddress: ByteArray,
override val androidId: ByteArray,
override val apn: ByteArray override val apn: ByteArray
) : DeviceInfo() { ) : DeviceInfo() {
@Transient @Transient
override lateinit var context: Context 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
} }