Commit f175d07c authored by Him188's avatar Him188

Introduce multi-platform BotConfiguration structure; Add...

Introduce multi-platform BotConfiguration structure; Add `redirectNetworkLogToDirectory` functions, fix #371
parent 5e7beddf
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:Suppress("unused", "DEPRECATION_ERROR") @file:Suppress("unused", "DEPRECATION_ERROR", "EXPOSED_SUPER_CLASS")
package net.mamoe.mirai.utils package net.mamoe.mirai.utils
...@@ -17,7 +17,6 @@ import kotlin.coroutines.CoroutineContext ...@@ -17,7 +17,6 @@ import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.coroutineContext import kotlin.coroutines.coroutineContext
import kotlin.jvm.JvmField import kotlin.jvm.JvmField
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmStatic import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmSynthetic import kotlin.jvm.JvmSynthetic
...@@ -35,8 +34,34 @@ import kotlin.jvm.JvmSynthetic ...@@ -35,8 +34,34 @@ import kotlin.jvm.JvmSynthetic
* } * }
* ``` * ```
*/ */
expect open class BotConfiguration() : BotConfigurationBase {
/**
* 设备信息覆盖. 在没有手动指定时将会通过日志警告, 并使用随机设备信息.
* @see randomDeviceInfo 使用随机设备信息
*/
var deviceInfo: ((Context) -> DeviceInfo)?
/**
* 使用随机设备信息.
*
* @see deviceInfo
*/
@ConfigurationDsl
fun randomDeviceInfo()
companion object {
/** 默认的配置实例. 可以进行修改 */
@JvmStatic
val Default: BotConfiguration
}
fun copy(): BotConfiguration
}
@MiraiInternalAPI
@Suppress("PropertyName") @Suppress("PropertyName")
open class BotConfiguration { @SinceMirai("1.1.0")
internal open class BotConfigurationBase internal constructor() {
/** /**
* 日志记录器 * 日志记录器
* *
...@@ -61,13 +86,6 @@ open class BotConfiguration { ...@@ -61,13 +86,6 @@ open class BotConfiguration {
*/ */
var networkLoggerSupplier: ((Bot) -> MiraiLogger) = { DefaultLogger("Net ${it.id}") } var networkLoggerSupplier: ((Bot) -> MiraiLogger) = { DefaultLogger("Net ${it.id}") }
/**
* 设备信息覆盖. 在没有手动指定时将会通过日志警告, 并使用随机设备信息.
* @see fileBasedDeviceInfo 使用指定文件存储设备信息
* @see randomDeviceInfo 使用随机设备信息
*/
var deviceInfo: ((Context) -> DeviceInfo)? = deviceInfoStub
/** 父 [CoroutineContext]. [Bot] 创建后会使用 [SupervisorJob] 覆盖其 [Job], 但会将这个 [Job] 作为父 [Job] */ /** 父 [CoroutineContext]. [Bot] 创建后会使用 [SupervisorJob] 覆盖其 [Job], 但会将这个 [Job] 作为父 [Job] */
var parentCoroutineContext: CoroutineContext = EmptyCoroutineContext var parentCoroutineContext: CoroutineContext = EmptyCoroutineContext
...@@ -121,12 +139,6 @@ open class BotConfiguration { ...@@ -121,12 +139,6 @@ open class BotConfiguration {
ANDROID_PAD(537062409) ANDROID_PAD(537062409)
} }
companion object {
/** 默认的配置实例. 可以进行修改 */
@JvmStatic
val Default = BotConfiguration()
}
/** /**
* 不显示网络日志. 不推荐. * 不显示网络日志. 不推荐.
* @see networkLoggerSupplier 更多日志处理方式 * @see networkLoggerSupplier 更多日志处理方式
...@@ -145,29 +157,6 @@ open class BotConfiguration { ...@@ -145,29 +157,6 @@ open class BotConfiguration {
botLoggerSupplier = { _ -> SilentLogger } botLoggerSupplier = { _ -> SilentLogger }
} }
/**
* 使用文件存储设备信息.
*
* 此函数只在 JVM 和 Android 有效. 在其他平台将会抛出异常.
* @param filepath 文件路径. 可相对于程序运行路径 (`user.dir`), 也可以是绝对路径.
* @see deviceInfo
*/
@JvmOverloads
@ConfigurationDsl
fun fileBasedDeviceInfo(filepath: String = "device.json") {
deviceInfo = getFileBasedDeviceInfoSupplier(filepath)
}
/**
* 使用随机设备信息.
*
* @see deviceInfo
*/
@ConfigurationDsl
fun randomDeviceInfo() {
deviceInfo = null
}
/** /**
* 使用当前协程的 [coroutineContext] 作为 [parentCoroutineContext]. * 使用当前协程的 [coroutineContext] 作为 [parentCoroutineContext].
* *
...@@ -230,32 +219,12 @@ open class BotConfiguration { ...@@ -230,32 +219,12 @@ open class BotConfiguration {
@Target(AnnotationTarget.FUNCTION) @Target(AnnotationTarget.FUNCTION)
@DslMarker @DslMarker
annotation class ConfigurationDsl annotation class ConfigurationDsl
fun copy(): BotConfiguration {
return BotConfiguration().also { new ->
new.botLoggerSupplier = botLoggerSupplier
new.networkLoggerSupplier = networkLoggerSupplier
new.deviceInfo = deviceInfo
new.parentCoroutineContext = parentCoroutineContext
new.heartbeatPeriodMillis = heartbeatPeriodMillis
new.heartbeatTimeoutMillis = heartbeatTimeoutMillis
new.firstReconnectDelayMillis = firstReconnectDelayMillis
new.reconnectPeriodMillis = reconnectPeriodMillis
new.reconnectionRetryTimes = reconnectionRetryTimes
new.loginSolver = loginSolver
new.protocol = protocol
new.fileCacheStrategy = fileCacheStrategy
}
}
} }
private val deviceInfoStub: (Context) -> DeviceInfo = { internal val deviceInfoStub: (Context) -> DeviceInfo = {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
MiraiLogger.warning("未指定设备信息, 已使用随机设备信息. 请查看 BotConfiguration.deviceInfo 以获取更多信息.") MiraiLogger.warning("未指定设备信息, 已使用随机设备信息. 请查看 BotConfiguration.deviceInfo 以获取更多信息.")
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
MiraiLogger.warning("Device info isn't specified. Please refer to BotConfiguration.deviceInfo for more information") MiraiLogger.warning("Device info isn't specified. Please refer to BotConfiguration.deviceInfo for more information")
SystemDeviceInfo() SystemDeviceInfo()
} }
\ No newline at end of file
@OptIn(ExperimentalMultiplatform::class)
internal expect fun getFileBasedDeviceInfoSupplier(filename: String): ((Context) -> DeviceInfo)?
\ No newline at end of file
/*
* 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
*/
@file:Suppress("unused", "DEPRECATION_ERROR", "EXPOSED_SUPER_CLASS")
package net.mamoe.mirai.utils
import net.mamoe.mirai.Bot
import java.io.File
/**
* [Bot] 配置.
*
* Kotlin 使用方法:
* ```
* val bot = Bot(...) {
* // 在这里配置 Bot
*
* bogLoggerSupplier = { bot -> ... }
* fileBasedDeviceInfo()
* inheritCoroutineContext() // 使用 `coroutineScope` 的 Job 作为父 Job
* }
* ```
*
* Java 使用方法:
* ```java
* Bot bot = BotFactory.newBot(..., new BotConfiguration() {{
* setBogLoggerSupplier((Bot bot) -> { ... })
* fileBasedDeviceInfo()
* ...
* }})
* ```
*/
@Suppress("PropertyName")
actual open class BotConfiguration : BotConfigurationBase() { // open for Java
/**
* 设备信息覆盖. 在没有手动指定时将会通过日志警告, 并使用随机设备信息.
* @see fileBasedDeviceInfo 使用指定文件存储设备信息
* @see randomDeviceInfo 使用随机设备信息
*/
actual var deviceInfo: ((Context) -> DeviceInfo)? = deviceInfoStub
/**
* 使用随机设备信息.
*
* @see deviceInfo
*/
@ConfigurationDsl
actual fun randomDeviceInfo() {
deviceInfo = null
}
/**
* 重定向 [网络日志][networkLoggerSupplier] 到指定目录. 若目录不存在将会自动创建 ([File.mkdirs])
* @see DirectoryLogger
* @see redirectNetworkLogToDirectory
*/
@JvmOverloads
@ConfigurationDsl
@SinceMirai("1.1.0")
fun redirectNetworkLogToDirectory(
dir: File = File("logs"),
retain: Long = 1.weeksToMillis,
identity: (bot: Bot) -> String = { "Net ${it.id}" }
) {
require(!dir.isFile) { "dir must not be a file" }
dir.mkdirs()
networkLoggerSupplier = { DirectoryLogger(identity(it), dir, retain) }
}
/**
* 重定向 [网络日志][networkLoggerSupplier] 到指定文件.
* 日志将会逐行追加到此文件. 若文件不存在将会自动创建 ([File.createNewFile])
* @see SingleFileLogger
* @see redirectNetworkLogToDirectory
*/
@JvmOverloads
@SinceMirai("1.1.0")
@ConfigurationDsl
fun redirectNetworkLogToFile(
file: File = File("mirai.log"),
identity: (bot: Bot) -> String = { "Net ${it.id}" }
) {
require(!file.isFile) { "file must not be a dir" }
file.createNewFile()
networkLoggerSupplier = { SingleFileLogger(identity(it), file) }
}
/**
* 重定向 [Bot 日志][botLoggerSupplier] 到指定目录. 若目录不存在将会自动创建 ([File.mkdirs])
* @see DirectoryLogger
* @see redirectBotLogToFile
*/
@JvmOverloads
@ConfigurationDsl
@SinceMirai("1.1.0")
fun redirectBotLogToDirectory(
dir: File,
retain: Long = 1.weeksToMillis,
identity: (bot: Bot) -> String = { "Net ${it.id}" }
) {
require(!dir.isFile) { "dir must not be a file" }
dir.mkdirs()
botLoggerSupplier = { DirectoryLogger(identity(it), dir, retain) }
}
/**
* 重定向 [Bot 日志][botLoggerSupplier] 到指定文件.
* 日志将会逐行追加到此文件. 若文件不存在将会自动创建 ([File.createNewFile])
* @see SingleFileLogger
* @see redirectBotLogToDirectory
*/
@JvmOverloads
@ConfigurationDsl
@SinceMirai("1.1.0")
fun redirectBotLogToFile(
file: File,
identity: (bot: Bot) -> String = { "Net ${it.id}" }
) {
require(!file.isFile) { "file must not be a dir" }
file.createNewFile()
botLoggerSupplier = { SingleFileLogger(identity(it), file) }
}
actual companion object {
/** 默认的配置实例. 可以进行修改 */
@JvmStatic
actual val Default = BotConfiguration()
}
/**
* 使用文件存储设备信息.
*
* 此函数只在 JVM 和 Android 有效. 在其他平台将会抛出异常.
* @param filepath 文件路径. 可相对于程序运行路径 (`user.dir`), 也可以是绝对路径.
* @see deviceInfo
*/
@JvmOverloads
@ConfigurationDsl
fun fileBasedDeviceInfo(filepath: String = "device.json") {
deviceInfo = getFileBasedDeviceInfoSupplier(filepath)
}
actual fun copy(): BotConfiguration {
return BotConfiguration().also { new ->
new.botLoggerSupplier = botLoggerSupplier
new.networkLoggerSupplier = networkLoggerSupplier
new.deviceInfo = deviceInfo
new.parentCoroutineContext = parentCoroutineContext
new.heartbeatPeriodMillis = heartbeatPeriodMillis
new.heartbeatTimeoutMillis = heartbeatTimeoutMillis
new.firstReconnectDelayMillis = firstReconnectDelayMillis
new.reconnectPeriodMillis = reconnectPeriodMillis
new.reconnectionRetryTimes = reconnectionRetryTimes
new.loginSolver = loginSolver
new.protocol = protocol
new.fileCacheStrategy = fileCacheStrategy
}
}
}
...@@ -154,7 +154,7 @@ actual abstract class LoginSolver { ...@@ -154,7 +154,7 @@ actual abstract class LoginSolver {
//////////////// internal //////////////// internal
/////////////////////////////// ///////////////////////////////
internal actual fun getFileBasedDeviceInfoSupplier(filename: String): ((Context) -> DeviceInfo)? { internal fun getFileBasedDeviceInfoSupplier(filename: String): ((Context) -> DeviceInfo)? {
return { return {
File(filename).loadAsDeviceInfo(it) File(filename).loadAsDeviceInfo(it)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment