mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-10 18:40:15 +08:00
Support builtin settings; cleanup
This commit is contained in:
parent
58187f95f0
commit
b636ea9b31
@ -57,6 +57,7 @@ kotlin {
|
|||||||
getByName("main") {
|
getByName("main") {
|
||||||
languageSettings.apply {
|
languageSettings.apply {
|
||||||
languageVersion = "1.3"
|
languageVersion = "1.3"
|
||||||
|
apiVersion = "1.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,8 +102,8 @@ tasks {
|
|||||||
val compileKotlin by getting {}
|
val compileKotlin by getting {}
|
||||||
|
|
||||||
val fillBuildConstants by registering {
|
val fillBuildConstants by registering {
|
||||||
|
group = "mirai"
|
||||||
doLast {
|
doLast {
|
||||||
return@doLast //
|
|
||||||
(compileKotlin as KotlinCompile).source.filter { it.name == "MiraiConsole.kt" }.single().let { file ->
|
(compileKotlin as KotlinCompile).source.filter { it.name == "MiraiConsole.kt" }.single().let { file ->
|
||||||
file.writeText(file.readText()
|
file.writeText(file.readText()
|
||||||
.replace(Regex("""val buildDate: Date = Date\((.*)\) //(.*)""")) {
|
.replace(Regex("""val buildDate: Date = Date\((.*)\) //(.*)""")) {
|
||||||
@ -121,10 +122,6 @@ tasks {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"compileKotlin" {
|
|
||||||
dependsOn(fillBuildConstants)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// region PUBLISHING
|
// region PUBLISHING
|
||||||
|
@ -28,6 +28,7 @@ import net.mamoe.mirai.console.plugin.center.CuiPluginCenter
|
|||||||
import net.mamoe.mirai.console.plugin.center.PluginCenter
|
import net.mamoe.mirai.console.plugin.center.PluginCenter
|
||||||
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader
|
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader
|
||||||
import net.mamoe.mirai.console.setting.SettingStorage
|
import net.mamoe.mirai.console.setting.SettingStorage
|
||||||
|
import net.mamoe.mirai.console.utils.ConsoleBuiltInSettingStorage
|
||||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||||
import net.mamoe.mirai.console.utils.ConsoleInternalAPI
|
import net.mamoe.mirai.console.utils.ConsoleInternalAPI
|
||||||
import net.mamoe.mirai.utils.DefaultLogger
|
import net.mamoe.mirai.utils.DefaultLogger
|
||||||
@ -127,7 +128,8 @@ internal object MiraiConsoleInternal : CoroutineScope, IMiraiConsole, MiraiConso
|
|||||||
override val builtInPluginLoaders: List<PluginLoader<*, *>> get() = instance.builtInPluginLoaders
|
override val builtInPluginLoaders: List<PluginLoader<*, *>> get() = instance.builtInPluginLoaders
|
||||||
override val consoleCommandSender: ConsoleCommandSender get() = instance.consoleCommandSender
|
override val consoleCommandSender: ConsoleCommandSender get() = instance.consoleCommandSender
|
||||||
|
|
||||||
override val settingStorage: SettingStorage get() = instance.settingStorage
|
override val settingStorageForJarPluginLoader: SettingStorage get() = instance.settingStorageForJarPluginLoader
|
||||||
|
override val settingStorageForBuiltIns: SettingStorage get() = instance.settingStorageForBuiltIns
|
||||||
|
|
||||||
init {
|
init {
|
||||||
DefaultLogger = { identity -> this.newLogger(identity) }
|
DefaultLogger = { identity -> this.newLogger(identity) }
|
||||||
@ -157,6 +159,8 @@ internal object MiraiConsoleInternal : CoroutineScope, IMiraiConsole, MiraiConso
|
|||||||
PluginManagerImpl.loadEnablePlugins()
|
PluginManagerImpl.loadEnablePlugins()
|
||||||
mainLogger.info { "${PluginManager.plugins.size} plugin(s) loaded." }
|
mainLogger.info { "${PluginManager.plugins.size} plugin(s) loaded." }
|
||||||
mainLogger.info { "mirai-console started successfully." }
|
mainLogger.info { "mirai-console started successfully." }
|
||||||
|
|
||||||
|
ConsoleBuiltInSettingStorage // init
|
||||||
// Only for initialize
|
// Only for initialize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,7 +190,8 @@ internal interface IMiraiConsole : CoroutineScope {
|
|||||||
|
|
||||||
val consoleCommandSender: ConsoleCommandSender
|
val consoleCommandSender: ConsoleCommandSender
|
||||||
|
|
||||||
val settingStorage: SettingStorage
|
val settingStorageForJarPluginLoader: SettingStorage
|
||||||
|
val settingStorageForBuiltIns: SettingStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,7 +46,7 @@ internal object JarPluginLoaderImpl :
|
|||||||
|
|
||||||
@ConsoleExperimentalAPI
|
@ConsoleExperimentalAPI
|
||||||
override val settingStorage: SettingStorage
|
override val settingStorage: SettingStorage
|
||||||
get() = MiraiConsoleInternal.settingStorage
|
get() = MiraiConsoleInternal.settingStorageForJarPluginLoader
|
||||||
|
|
||||||
override val coroutineContext: CoroutineContext =
|
override val coroutineContext: CoroutineContext =
|
||||||
MiraiConsole.coroutineContext +
|
MiraiConsole.coroutineContext +
|
||||||
|
@ -23,6 +23,8 @@ import kotlin.reflect.full.findAnnotation
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* [Setting] 存储容器
|
* [Setting] 存储容器
|
||||||
|
*
|
||||||
|
* @see SettingHolder
|
||||||
*/
|
*/
|
||||||
public interface SettingStorage {
|
public interface SettingStorage {
|
||||||
/**
|
/**
|
||||||
@ -36,10 +38,35 @@ public interface SettingStorage {
|
|||||||
public fun store(holder: SettingHolder, setting: Setting)
|
public fun store(holder: SettingHolder, setting: Setting)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: 2020/7/11 document
|
||||||
|
public interface MemorySettingStorage : SettingStorage {
|
||||||
|
public companion object {
|
||||||
|
@JvmStatic
|
||||||
|
@JvmName("create")
|
||||||
|
public operator fun invoke(): MemorySettingStorage = MemorySettingStorageImpl()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: 2020/7/11 document
|
||||||
|
public interface MultiFileSettingStorage : SettingStorage {
|
||||||
|
public val directory: File
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
@JvmStatic
|
||||||
|
@JvmName("create")
|
||||||
|
public operator fun invoke(directory: File): MultiFileSettingStorage = MultiFileSettingStorageImpl(directory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: 2020/7/11 here or companion?
|
// TODO: 2020/7/11 here or companion?
|
||||||
public inline fun <T : Setting> SettingStorage.load(holder: SettingHolder, settingClass: KClass<T>): T =
|
public inline fun <T : Setting> SettingStorage.load(holder: SettingHolder, settingClass: KClass<T>): T =
|
||||||
this.load(holder, settingClass.java)
|
this.load(holder, settingClass.java)
|
||||||
|
|
||||||
|
// TODO: 2020/7/11 here or companion?
|
||||||
|
public inline fun <reified T : Setting> SettingStorage.load(holder: SettingHolder): T =
|
||||||
|
this.load(holder, T::class)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可以持有相关 [Setting] 的对象.
|
* 可以持有相关 [Setting] 的对象.
|
||||||
*
|
*
|
||||||
@ -119,26 +146,9 @@ public interface AutoSaveSettingHolder : SettingHolder, CoroutineScope {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 2020/7/11 document
|
|
||||||
public interface MemorySettingStorage : SettingStorage {
|
|
||||||
public companion object INSTANCE : MemorySettingStorage by MemorySettingStorageImpl
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: 2020/7/11 document
|
|
||||||
public interface MultiFileSettingStorage : SettingStorage {
|
|
||||||
public val directory: File
|
|
||||||
|
|
||||||
public companion object {
|
|
||||||
@JvmStatic
|
|
||||||
@JvmName("create")
|
|
||||||
public operator fun invoke(directory: File): MultiFileSettingStorage = MultiFileSettingStorageImpl(directory)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// internal
|
// internal
|
||||||
|
|
||||||
internal object MemorySettingStorageImpl : SettingStorage, MemorySettingStorage {
|
internal class MemorySettingStorageImpl : SettingStorage, MemorySettingStorage {
|
||||||
private val list = mutableMapOf<Class<out Setting>, Setting>()
|
private val list = mutableMapOf<Class<out Setting>, Setting>()
|
||||||
|
|
||||||
internal class MemorySettingImpl : AbstractSetting() {
|
internal class MemorySettingImpl : AbstractSetting() {
|
||||||
@ -173,34 +183,35 @@ internal object MemorySettingStorageImpl : SettingStorage, MemorySettingStorage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class MultiFileSettingStorageImpl(
|
public open class MultiFileSettingStorageImpl(
|
||||||
override val directory: File
|
public final override val directory: File
|
||||||
) : SettingStorage, MultiFileSettingStorage {
|
) : SettingStorage, MultiFileSettingStorage {
|
||||||
override fun <T : Setting> load(holder: SettingHolder, settingClass: Class<T>): T = with(settingClass.kotlin) {
|
public override fun <T : Setting> load(holder: SettingHolder, settingClass: Class<T>): T =
|
||||||
val file = settingFile(holder, settingClass::class)
|
with(settingClass.kotlin) {
|
||||||
|
val file = getSettingFile(holder, settingClass::class)
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val instance = objectInstance ?: this.createInstanceOrNull() ?: kotlin.run {
|
val instance = objectInstance ?: this.createInstanceOrNull() ?: kotlin.run {
|
||||||
if (settingClass != Setting::class.java) {
|
if (settingClass != Setting::class.java) {
|
||||||
throw IllegalArgumentException(
|
throw IllegalArgumentException(
|
||||||
"Cannot create Setting instance. Make sure settingClass is Setting::class.java or a Kotlin's object, " +
|
"Cannot create Setting instance. Make sure settingClass is Setting::class.java or a Kotlin's object, " +
|
||||||
"or has a constructor which either has no parameters or all parameters of which are optional"
|
"or has a constructor which either has no parameters or all parameters of which are optional"
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
if (holder is AutoSaveSettingHolder) {
|
||||||
|
AutoSaveSetting(holder, this@MultiFileSettingStorageImpl) as T?
|
||||||
|
} else null
|
||||||
|
} ?: throw IllegalArgumentException(
|
||||||
|
"Cannot create Setting instance. Make sure 'holder' is a AutoSaveSettingHolder, " +
|
||||||
|
"or 'setting' is an object or has a constructor which either has no parameters or all parameters of which are optional"
|
||||||
|
)
|
||||||
|
if (file.exists() && file.isFile && file.canRead()) {
|
||||||
|
Yaml.default.parse(instance.updaterSerializer, file.readText())
|
||||||
}
|
}
|
||||||
if (holder is AutoSaveSettingHolder) {
|
instance
|
||||||
AutoSaveSetting(holder, this@MultiFileSettingStorageImpl) as T?
|
|
||||||
} else null
|
|
||||||
} ?: throw IllegalArgumentException(
|
|
||||||
"Cannot create Setting instance. Make sure 'holder' is a AutoSaveSettingHolder, " +
|
|
||||||
"or 'setting' is an object or has a constructor which either has no parameters or all parameters of which are optional"
|
|
||||||
)
|
|
||||||
if (file.exists() && file.isFile && file.canRead()) {
|
|
||||||
Yaml.default.parse(instance.updaterSerializer, file.readText())
|
|
||||||
}
|
}
|
||||||
instance
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun settingFile(holder: SettingHolder, clazz: KClass<*>): File = with(clazz) {
|
protected open fun getSettingFile(holder: SettingHolder, clazz: KClass<*>): File = with(clazz) {
|
||||||
val name = findASerialName()
|
val name = findASerialName()
|
||||||
|
|
||||||
val dir = File(directory, holder.name)
|
val dir = File(directory, holder.name)
|
||||||
@ -216,8 +227,8 @@ internal class MultiFileSettingStorageImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ConsoleExperimentalAPI
|
@ConsoleExperimentalAPI
|
||||||
override fun store(holder: SettingHolder, setting: Setting): Unit = with(setting::class) {
|
public override fun store(holder: SettingHolder, setting: Setting): Unit = with(setting::class) {
|
||||||
val file = settingFile(holder, this)
|
val file = getSettingFile(holder, this)
|
||||||
|
|
||||||
if (file.exists() && file.isFile && file.canRead()) {
|
if (file.exists() && file.isFile && file.canRead()) {
|
||||||
file.writeText(Yaml.default.stringify(setting.updaterSerializer, Unit))
|
file.writeText(Yaml.default.stringify(setting.updaterSerializer, Unit))
|
||||||
@ -225,14 +236,14 @@ internal class MultiFileSettingStorageImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T : Any> KClass<T>.createInstanceOrNull(): T? {
|
internal fun <T : Any> KClass<T>.createInstanceOrNull(): T? {
|
||||||
val noArgsConstructor = constructors.singleOrNull { it.parameters.all(KParameter::isOptional) }
|
val noArgsConstructor = constructors.singleOrNull { it.parameters.all(KParameter::isOptional) }
|
||||||
?: return null
|
?: return null
|
||||||
|
|
||||||
return noArgsConstructor.callBy(emptyMap())
|
return noArgsConstructor.callBy(emptyMap())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KClass<*>.findASerialName(): String =
|
internal fun KClass<*>.findASerialName(): String =
|
||||||
findAnnotation<SerialName>()?.value
|
findAnnotation<SerialName>()?.value
|
||||||
?: qualifiedName
|
?: qualifiedName
|
||||||
?: throw IllegalArgumentException("Cannot find a serial name for $this")
|
?: throw IllegalArgumentException("Cannot find a serial name for $this")
|
@ -10,24 +10,49 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.utils
|
package net.mamoe.mirai.console.utils
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
|
import net.mamoe.mirai.console.MiraiConsole
|
||||||
|
import net.mamoe.mirai.console.MiraiConsoleInternal
|
||||||
|
import net.mamoe.mirai.console.setting.*
|
||||||
import net.mamoe.mirai.contact.User
|
import net.mamoe.mirai.contact.User
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断此用户是否为 console 管理员
|
* 判断此用户是否为 console 管理员
|
||||||
*/
|
*/
|
||||||
public val User.isManager: Boolean
|
public val User.isManager: Boolean get() = this.id in this.bot.managers
|
||||||
get() = this.bot.managers.contains(this.id)
|
|
||||||
|
|
||||||
internal fun Bot.addManager(long: Long): Boolean {
|
public fun Bot.removeManager(id: Long): Boolean {
|
||||||
TODO()
|
return ManagersConfig[this].remove(id)
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun Bot.removeManager(long: Long) {
|
|
||||||
TODO()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public val Bot.managers: List<Long>
|
public val Bot.managers: List<Long>
|
||||||
get() = TODO()
|
get() = ManagersConfig[this].toList()
|
||||||
|
|
||||||
|
internal fun Bot.addManager(id: Long): Boolean {
|
||||||
|
return ManagersConfig[this].add(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal object ManagersConfig : Setting by (ConsoleBuiltInSettingStorage.load(ConsoleBuiltInSettingHolder)) {
|
||||||
|
private val managers: MutableMap<Long, MutableSet<Long>> by value()
|
||||||
|
|
||||||
|
internal operator fun get(bot: Bot): MutableSet<Long> = managers.getOrPut(bot.id, ::mutableSetOf)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal fun CoroutineContext.overrideWithSupervisorJob(): CoroutineContext = this + SupervisorJob(this[Job])
|
||||||
|
internal fun CoroutineScope.childScope(context: CoroutineContext = EmptyCoroutineContext): CoroutineScope =
|
||||||
|
CoroutineScope(this.coroutineContext.overrideWithSupervisorJob() + context)
|
||||||
|
|
||||||
|
internal object ConsoleBuiltInSettingHolder : AutoSaveSettingHolder,
|
||||||
|
CoroutineScope by MiraiConsole.childScope() {
|
||||||
|
override val name: String get() = "ConsoleBuiltIns"
|
||||||
|
}
|
||||||
|
|
||||||
|
internal object ConsoleBuiltInSettingStorage : SettingStorage by MiraiConsoleInternal.settingStorageForJarPluginLoader
|
@ -49,7 +49,8 @@ fun initTestEnvironment() {
|
|||||||
override val consoleCommandSender: ConsoleCommandSender = object : ConsoleCommandSender() {
|
override val consoleCommandSender: ConsoleCommandSender = object : ConsoleCommandSender() {
|
||||||
override suspend fun sendMessage(message: Message) = println(message)
|
override suspend fun sendMessage(message: Message) = println(message)
|
||||||
}
|
}
|
||||||
override val settingStorage: SettingStorage get() = MemorySettingStorage
|
override val settingStorageForJarPluginLoader: SettingStorage get() = MemorySettingStorage()
|
||||||
|
override val settingStorageForBuiltIns: SettingStorage get() = MemorySettingStorage()
|
||||||
override val coroutineContext: CoroutineContext = SupervisorJob()
|
override val coroutineContext: CoroutineContext = SupervisorJob()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ dependencies {
|
|||||||
testApi(project(":mirai-console"))
|
testApi(project(":mirai-console"))
|
||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext.apply {
|
||||||
// 傻逼 compileAndRuntime 没 exclude 掉
|
// 傻逼 compileAndRuntime 没 exclude 掉
|
||||||
// 傻逼 gradle 第二次配置 task 会覆盖掉第一次的配置
|
// 傻逼 gradle 第二次配置 task 会覆盖掉第一次的配置
|
||||||
val x: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.() -> Unit = {
|
val x: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.() -> Unit = {
|
||||||
|
@ -50,18 +50,18 @@ class MiraiConsolePure @JvmOverloads constructor(
|
|||||||
override val frontEnd: MiraiConsoleFrontEnd = MiraiConsoleFrontEndPure,
|
override val frontEnd: MiraiConsoleFrontEnd = MiraiConsoleFrontEndPure,
|
||||||
override val mainLogger: MiraiLogger = frontEnd.loggerFor("main"),
|
override val mainLogger: MiraiLogger = frontEnd.loggerFor("main"),
|
||||||
override val consoleCommandSender: ConsoleCommandSender = ConsoleCommandSenderImpl,
|
override val consoleCommandSender: ConsoleCommandSender = ConsoleCommandSenderImpl,
|
||||||
override val settingStorage: SettingStorage = MultiFileSettingStorage(rootDir)
|
override val settingStorageForJarPluginLoader: SettingStorage = MultiFileSettingStorage(rootDir),
|
||||||
|
override val settingStorageForBuiltIns: SettingStorage = MultiFileSettingStorage(rootDir)
|
||||||
) : IMiraiConsole, CoroutineScope by CoroutineScope(SupervisorJob()) {
|
) : IMiraiConsole, CoroutineScope by CoroutineScope(SupervisorJob()) {
|
||||||
init {
|
init {
|
||||||
rootDir.mkdir()
|
rootDir.mkdir()
|
||||||
require(rootDir.isDirectory) { "rootDir ${rootDir.absolutePath} is not a directory" }
|
require(rootDir.isDirectory) { "rootDir ${rootDir.absolutePath} is not a directory" }
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
@JvmField
|
||||||
@Volatile
|
internal var started: Boolean = false
|
||||||
@JvmStatic
|
|
||||||
private var started: Boolean = false
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun MiraiConsolePure.start() = synchronized(this) {
|
fun MiraiConsolePure.start() = synchronized(this) {
|
||||||
check(!started) { "mirai-console is already started and can't be restarted." }
|
check(!started) { "mirai-console is already started and can't be restarted." }
|
||||||
|
Loading…
Reference in New Issue
Block a user