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 @@
*
* 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
......@@ -17,7 +17,6 @@ import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.coroutineContext
import kotlin.jvm.JvmField
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmStatic
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")
open class BotConfiguration {
@SinceMirai("1.1.0")
internal open class BotConfigurationBase internal constructor() {
/**
* 日志记录器
*
......@@ -61,13 +86,6 @@ open class BotConfiguration {
*/
var networkLoggerSupplier: ((Bot) -> MiraiLogger) = { DefaultLogger("Net ${it.id}") }
/**
* 设备信息覆盖. 在没有手动指定时将会通过日志警告, 并使用随机设备信息.
* @see fileBasedDeviceInfo 使用指定文件存储设备信息
* @see randomDeviceInfo 使用随机设备信息
*/
var deviceInfo: ((Context) -> DeviceInfo)? = deviceInfoStub
/** 父 [CoroutineContext]. [Bot] 创建后会使用 [SupervisorJob] 覆盖其 [Job], 但会将这个 [Job] 作为父 [Job] */
var parentCoroutineContext: CoroutineContext = EmptyCoroutineContext
......@@ -121,12 +139,6 @@ open class BotConfiguration {
ANDROID_PAD(537062409)
}
companion object {
/** 默认的配置实例. 可以进行修改 */
@JvmStatic
val Default = BotConfiguration()
}
/**
* 不显示网络日志. 不推荐.
* @see networkLoggerSupplier 更多日志处理方式
......@@ -145,29 +157,6 @@ open class BotConfiguration {
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].
*
......@@ -230,32 +219,12 @@ open class BotConfiguration {
@Target(AnnotationTarget.FUNCTION)
@DslMarker
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")
MiraiLogger.warning("未指定设备信息, 已使用随机设备信息. 请查看 BotConfiguration.deviceInfo 以获取更多信息.")
@Suppress("DEPRECATION")
MiraiLogger.warning("Device info isn't specified. Please refer to BotConfiguration.deviceInfo for more information")
SystemDeviceInfo()
}
@OptIn(ExperimentalMultiplatform::class)
internal expect fun getFileBasedDeviceInfoSupplier(filename: String): ((Context) -> DeviceInfo)?
\ No newline at end of file
}
\ 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 {
//////////////// internal
///////////////////////////////
internal actual fun getFileBasedDeviceInfoSupplier(filename: String): ((Context) -> DeviceInfo)? {
internal fun getFileBasedDeviceInfoSupplier(filename: String): ((Context) -> DeviceInfo)? {
return {
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