mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-25 15:40:28 +08:00
Settings infrastructure:
Primitive Value codegen, use-site codegen, value impl codegen; Settings serializers; Values; Settings property delegation.
This commit is contained in:
parent
fdf12d024f
commit
ef17e23a03
87
backend/codegen/README.MD
Normal file
87
backend/codegen/README.MD
Normal file
@ -0,0 +1,87 @@
|
||||
# Mirai Console
|
||||
你可以在全平台运行Mirai高效率机器人框架
|
||||
### Mirai Console提供了6个版本以满足各种需要
|
||||
#### 所有版本的Mirai Console API相同 插件系统相同
|
||||
|
||||
| 名字 | 介绍 |
|
||||
|:------------------------|:------------------------------|
|
||||
| Mirai-Console-Pure | 最纯净版, CLI环境, 通过标准输入与标准输出 交互 |
|
||||
| Mirai-Console-Terminal | (UNIX)Terminal环境 提供简洁的富文本控制台 |
|
||||
| Mirai-Console-Android | 安卓APP (TODO) |
|
||||
| Mirai-Console-Graphical | JavaFX的图形化界面 (.jar/.exe/.dmg) |
|
||||
| Mirai-Console-WebPanel | Web Panel操作(TODO) |
|
||||
| Mirai-Console-Ios | IOS APP (TODO) |
|
||||
|
||||
|
||||
### 如何选择版本
|
||||
1: Mirai-Console-Pure 兼容性最高, 在其他都表现不佳的时候请使用</br>
|
||||
2: 以系统区分
|
||||
```kotlin
|
||||
return when(operatingSystem){
|
||||
WINDOWS -> listOf("Graphical","WebPanel","Pure")
|
||||
MAC_OS -> listOf("Graphical","Terminal","WebPanel","Pure")
|
||||
LINUX -> listOf("Terminal","Pure")
|
||||
ANDROID -> listOf("Android","Pure","WebPanel")
|
||||
IOS -> listOf("Ios")
|
||||
else -> listOf("Pure")
|
||||
}
|
||||
```
|
||||
3: 以策略区分
|
||||
```kotlin
|
||||
return when(task){
|
||||
体验 -> listOf("Graphical","Terminal","WebPanel","Android","Pure")
|
||||
测试插件 -> listOf("Pure")
|
||||
调试插件 -> byOperatingSystem()
|
||||
稳定挂机 -> listOf("Terminal","Pure")
|
||||
else -> listOf("Pure")
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### More Importantly, Mirai Console support <b>Plugins</b>, tells the bot what to do
|
||||
#### Mirai Console 支持插件系统, 你可以自己开发或使用公开的插件来逻辑化机器人, 如群管
|
||||
<br>
|
||||
|
||||
#### download 下载
|
||||
#### how to get/write plugins 如何获取/写插件
|
||||
<br>
|
||||
<br>
|
||||
|
||||
### how to use(如何使用)
|
||||
#### how to run Mirai Console
|
||||
<ul>
|
||||
<li>download mirai-console.jar</li>
|
||||
<li>open command line/terminal</li>
|
||||
<li>create a folder and put mirai-console.jar in</li>
|
||||
<li>cd that folder</li>
|
||||
<li>"java -jar mirai-console.jar"</li>
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li>下载mirai-console.jar</li>
|
||||
<li>打开终端</li>
|
||||
<li>在任何地方创建一个文件夹, 并放入mirai-console.jar</li>
|
||||
<li>在终端中打开该文件夹"cd"</li>
|
||||
<li>输入"java -jar mirai-console.jar"</li>
|
||||
</ul>
|
||||
|
||||
#### how to add plugins
|
||||
<ul>
|
||||
<li>After first time of running mirai console</li>
|
||||
<li>/plugins/folder will be created next to mirai-console.jar</li>
|
||||
<li>put plugin(.jar) into /plugins/</li>
|
||||
<li>restart mirai console</li>
|
||||
<li>checking logger and check if the plugin is loaded successfully</li>
|
||||
<li>if the plugin has it own Config file, it normally appears in /plugins/{pluginName}/</li>
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li>在首次运行mirai console后</li>
|
||||
<li>mirai-console.jar 的同级会出现/plugins/文件夹</li>
|
||||
<li>将插件(.jar)放入/plugins/文件夹</li>
|
||||
<li>重启mirai console</li>
|
||||
<li>在开启后检查日志, 是否成功加载</li>
|
||||
<li>如该插件有配置文件, 配置文件一般会创建在/plugins/插件名字/ 文件夹下</li>
|
||||
</ul>
|
||||
|
||||
|
41
backend/codegen/build.gradle.kts
Normal file
41
backend/codegen/build.gradle.kts
Normal file
@ -0,0 +1,41 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
id("kotlin")
|
||||
kotlin("plugin.serialization")
|
||||
id("java")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
sourceSets {
|
||||
all {
|
||||
languageSettings.useExperimentalAnnotation("kotlin.Experimental")
|
||||
languageSettings.useExperimentalAnnotation("kotlin.OptIn")
|
||||
languageSettings.progressiveMode = true
|
||||
languageSettings.useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiInternalAPI")
|
||||
languageSettings.useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
|
||||
languageSettings.useExperimentalAnnotation("kotlin.experimental.ExperimentalTypeInference")
|
||||
languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(kotlin("stdlib"))
|
||||
}
|
||||
|
||||
val compileKotlin: KotlinCompile by tasks
|
||||
compileKotlin.kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
val compileTestKotlin: KotlinCompile by tasks
|
||||
compileTestKotlin.kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
tasks.withType(JavaCompile::class.java) {
|
||||
options.encoding = "UTF8"
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.console.codegen
|
||||
|
||||
import java.io.File
|
||||
|
||||
|
||||
fun main() {
|
||||
println(File("").absolutePath) // default project base dir
|
||||
|
||||
File("backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/_Setting.kt").apply {
|
||||
createNewFile()
|
||||
}.writeText(buildString {
|
||||
appendln(COPYRIGHT)
|
||||
appendln()
|
||||
appendln(PACKAGE)
|
||||
appendln()
|
||||
// appendln(IMPORTS)
|
||||
// appendln()
|
||||
// appendln()
|
||||
appendln(DO_NOT_MODIFY)
|
||||
appendln()
|
||||
appendln()
|
||||
appendln(genAllValueUseSite())
|
||||
})
|
||||
}
|
||||
|
||||
private val DO_NOT_MODIFY = """
|
||||
/**
|
||||
* !!! This file is auto-generated by backend/codegen/src/kotlin/net.mamoe.mirai.console.codegen.SettingValueUseSiteCodegen.kt
|
||||
* !!! DO NOT MODIFY THIS FILE MANUALLY
|
||||
*/
|
||||
""".trimIndent()
|
||||
|
||||
private val PACKAGE = """
|
||||
package net.mamoe.mirai.console.setting
|
||||
""".trimIndent()
|
||||
|
||||
private val IMPORTS = """
|
||||
import kotlinx.serialization.builtins.*
|
||||
""".trimIndent()
|
||||
|
||||
fun genAllValueUseSite(): String = buildString {
|
||||
// PRIMITIVE
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES) {
|
||||
appendln(genValueUseSite(number, number))
|
||||
}
|
||||
|
||||
// PRIMITIVE ARRAYS
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES.filterNot { it == "String" }) {
|
||||
appendln(genValueUseSite("${number}Array", "${number}Array"))
|
||||
}
|
||||
|
||||
// TYPED ARRAYS
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES) {
|
||||
appendln(genValueUseSite("Array<${number}>", "Typed${number}Array"))
|
||||
}
|
||||
|
||||
// PRIMITIVE LISTS
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES) {
|
||||
appendln(genValueUseSite("List<${number}>", "${number}List"))
|
||||
}
|
||||
}
|
||||
|
||||
fun genValueUseSite(kotlinTypeName: String, miraiValueName: String): String =
|
||||
"""
|
||||
fun Setting.value(default: $kotlinTypeName): ${miraiValueName}Value = valueImpl(default)
|
||||
""".trimIndent()
|
||||
|
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.console.codegen
|
||||
|
||||
import java.io.File
|
||||
|
||||
|
||||
fun main() {
|
||||
println(File("").absolutePath) // default project base dir
|
||||
|
||||
File("backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/_ValueImpl.kt").apply {
|
||||
createNewFile()
|
||||
}.writeText(buildString {
|
||||
appendln(COPYRIGHT)
|
||||
appendln()
|
||||
appendln(PACKAGE)
|
||||
appendln()
|
||||
appendln(IMPORTS)
|
||||
appendln()
|
||||
appendln()
|
||||
appendln(DO_NOT_MODIFY)
|
||||
appendln()
|
||||
appendln()
|
||||
appendln(genAllValueImpl())
|
||||
})
|
||||
}
|
||||
|
||||
private val DO_NOT_MODIFY = """
|
||||
/**
|
||||
* !!! This file is auto-generated by backend/codegen/src/kotlin/net.mamoe.mirai.console.codegen.ValueImplCodegen.kt
|
||||
* !!! DO NOT MODIFY THIS FILE MANUALLY
|
||||
*/
|
||||
""".trimIndent()
|
||||
|
||||
private val PACKAGE = """
|
||||
package net.mamoe.mirai.console.setting
|
||||
""".trimIndent()
|
||||
|
||||
private val IMPORTS = """
|
||||
import kotlinx.serialization.builtins.*
|
||||
""".trimIndent()
|
||||
|
||||
fun genAllValueImpl(): String = buildString {
|
||||
// PRIMITIVE
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES) {
|
||||
appendln(genValueImpl(number, number, "$number.serializer()", false))
|
||||
}
|
||||
|
||||
// PRIMITIVE ARRAYS
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES.filterNot { it == "String" }) {
|
||||
appendln(genValueImpl("${number}Array", "${number}Array", "${number}ArraySerializer()", true))
|
||||
}
|
||||
|
||||
// TYPED ARRAYS
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES) {
|
||||
appendln(genValueImpl("Array<${number}>", "Typed${number}Array", "ArraySerializer(${number}.serializer())", true))
|
||||
}
|
||||
|
||||
// PRIMITIVE LISTS
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES) {
|
||||
appendln(genValueImpl("List<${number}>", "${number}List", "ListSerializer(${number}.serializer())", false))
|
||||
}
|
||||
}
|
||||
|
||||
fun genValueImpl(kotlinTypeName: String, miraiValueName: String, serializer: String, isArray: Boolean): String =
|
||||
"""
|
||||
internal fun Setting.valueImpl(default: ${kotlinTypeName}): ${miraiValueName}Value {
|
||||
return object : ${miraiValueName}Value() {
|
||||
private var internalValue: $kotlinTypeName = default
|
||||
override var value: $kotlinTypeName
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
${
|
||||
if (isArray) """
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
""".trim()
|
||||
else """
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
""".trim()
|
||||
}
|
||||
}
|
||||
override val serializer = ${serializer}.bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
""".trimIndent() + "\n"
|
||||
|
@ -0,0 +1,199 @@
|
||||
/*
|
||||
* 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("ClassName")
|
||||
|
||||
package net.mamoe.mirai.console.codegen
|
||||
|
||||
import org.intellij.lang.annotations.Language
|
||||
import java.io.File
|
||||
|
||||
fun main() {
|
||||
println(File("").absolutePath) // default project base dir
|
||||
|
||||
File("backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/_Value.kt").apply {
|
||||
createNewFile()
|
||||
}.writeText(genPublicApi())
|
||||
}
|
||||
|
||||
internal const val COPYRIGHT = """
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
"""
|
||||
|
||||
internal val NUMBERS = listOf(
|
||||
"Int",
|
||||
"Short",
|
||||
"Byte",
|
||||
"Long",
|
||||
"Float",
|
||||
"Double"
|
||||
)
|
||||
|
||||
internal val UNSIGNED_NUMBERS = listOf(
|
||||
"UInt",
|
||||
"UShort",
|
||||
"UByte",
|
||||
"ULong"
|
||||
)
|
||||
|
||||
internal val OTHER_PRIMITIVES = listOf(
|
||||
"Boolean",
|
||||
"Char",
|
||||
"String"
|
||||
)
|
||||
|
||||
fun genPublicApi() = buildString {
|
||||
fun appendln(@Language("kt") code: String){
|
||||
this.appendln(code.trimIndent())
|
||||
}
|
||||
|
||||
appendln(COPYRIGHT.trim())
|
||||
appendln()
|
||||
appendln(
|
||||
"""
|
||||
package net.mamoe.mirai.console.setting
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
"""
|
||||
)
|
||||
appendln()
|
||||
appendln(
|
||||
"""
|
||||
/**
|
||||
* !!! These primitive types are auto-generated by backend/codegen/src/main/kotlin/net.mamoe.mirai.console.codegen.ValuesCodegen.kt
|
||||
* !!! for better performance
|
||||
* !!! DO NOT MODIFY THIS FILE MANUALLY
|
||||
*/
|
||||
"""
|
||||
)
|
||||
appendln()
|
||||
|
||||
appendln(
|
||||
"""
|
||||
sealed class Value<T : Any> : ReadWriteProperty<Setting, T> {
|
||||
abstract var value: T
|
||||
|
||||
abstract val serializer: KSerializer<T>
|
||||
override fun getValue(thisRef: Setting, property: KProperty<*>): T = value
|
||||
override fun setValue(thisRef: Setting, property: KProperty<*>, value: T) {
|
||||
this.value = value
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
appendln()
|
||||
|
||||
// PRIMITIVES
|
||||
|
||||
appendln(
|
||||
"""
|
||||
sealed class PrimitiveValue<T : Any> : Value<T>()
|
||||
|
||||
sealed class NumberValue<T : Number> : Value<T>()
|
||||
"""
|
||||
)
|
||||
|
||||
for (number in NUMBERS) {
|
||||
val template = """
|
||||
abstract class ${number}Value internal constructor() : NumberValue<${number}>()
|
||||
"""
|
||||
|
||||
appendln(template)
|
||||
}
|
||||
|
||||
appendln()
|
||||
|
||||
for (number in OTHER_PRIMITIVES) {
|
||||
val template = """
|
||||
abstract class ${number}Value internal constructor() : PrimitiveValue<${number}>()
|
||||
"""
|
||||
|
||||
appendln(template)
|
||||
}
|
||||
|
||||
appendln()
|
||||
|
||||
// ARRAYS
|
||||
|
||||
appendln(
|
||||
"""
|
||||
// T can be primitive array or typed Array
|
||||
sealed class ArrayValue<T : Any> : Value<T>()
|
||||
"""
|
||||
)
|
||||
|
||||
// PRIMITIVE ARRAYS
|
||||
appendln(
|
||||
"""
|
||||
sealed class PrimitiveArrayValue<T : Any> : ArrayValue<T>()
|
||||
"""
|
||||
)
|
||||
appendln()
|
||||
|
||||
for (number in (NUMBERS + OTHER_PRIMITIVES).filterNot { it == "String" }) {
|
||||
val template = """
|
||||
abstract class ${number}ArrayValue internal constructor() : PrimitiveArrayValue<${number}Array>(), Iterable<${number}> {
|
||||
override fun iterator(): Iterator<${number}> = this.value.iterator()
|
||||
}
|
||||
"""
|
||||
|
||||
appendln(template)
|
||||
}
|
||||
|
||||
appendln()
|
||||
|
||||
// TYPED ARRAYS
|
||||
|
||||
appendln(
|
||||
"""
|
||||
sealed class TypedPrimitiveArrayValue<E> : ArrayValue<Array<E>>() , Iterable<E>{
|
||||
override fun iterator() = this.value.iterator()
|
||||
}
|
||||
"""
|
||||
)
|
||||
appendln()
|
||||
|
||||
for (number in (NUMBERS + OTHER_PRIMITIVES)) {
|
||||
val template = """
|
||||
abstract class Typed${number}ArrayValue internal constructor() : TypedPrimitiveArrayValue<${number}>()
|
||||
"""
|
||||
|
||||
appendln(template)
|
||||
}
|
||||
|
||||
appendln()
|
||||
|
||||
// TYPED LISTS
|
||||
|
||||
appendln(
|
||||
"""
|
||||
sealed class ListValue<E> : Value<List<E>>(), Iterable<E>{
|
||||
override fun iterator() = this.value.iterator()
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
for (number in (NUMBERS + OTHER_PRIMITIVES)) {
|
||||
val template = """
|
||||
abstract class ${number}ListValue internal constructor() : ListValue<${number}>()
|
||||
"""
|
||||
|
||||
appendln(template)
|
||||
}
|
||||
|
||||
appendln()
|
||||
}
|
@ -32,7 +32,7 @@ dependencies {
|
||||
compileAndRuntime("net.mamoe:mirai-core:${Versions.Mirai.core}")
|
||||
compileAndRuntime(kotlin("stdlib"))
|
||||
|
||||
api("moe.him188.yamlkt:yamlkt:0.2.0")
|
||||
api("net.mamoe.yamlkt:yamlkt:0.2.0")
|
||||
|
||||
api("org.jsoup:jsoup:1.12.1")
|
||||
|
||||
|
@ -1,9 +0,0 @@
|
||||
package net.mamoe.mirai.console.plugins;
|
||||
|
||||
public class ConfigSectionFactory {
|
||||
|
||||
public static ConfigSection create(){
|
||||
return ConfigSection.Companion.create();
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +1,10 @@
|
||||
package net.mamoe.mirai.console.center
|
||||
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParser
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.cio.CIO
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.util.KtorExperimentalAPI
|
||||
import kotlinx.serialization.json.*
|
||||
import net.mamoe.mirai.console.utils.retryCatching
|
||||
import java.io.File
|
||||
|
||||
@ -26,20 +24,20 @@ internal object CuiPluginCenter : PluginCenter {
|
||||
if (plugins == null) {
|
||||
refresh()
|
||||
}
|
||||
if (it >= plugins!!.size()) {
|
||||
if (it >= plugins!!.size) {
|
||||
return@forEach
|
||||
}
|
||||
val info = plugins!![it]
|
||||
with(info.asJsonObject) {
|
||||
map[this.get("name").asString] = PluginCenter.PluginInsight(
|
||||
this.get("name")?.asString ?: "",
|
||||
this.get("version")?.asString ?: "",
|
||||
this.get("core")?.asString ?: "",
|
||||
this.get("console")?.asString ?: "",
|
||||
this.get("author")?.asString ?: "",
|
||||
this.get("description")?.asString ?: "",
|
||||
this.get("tags")?.asJsonArray?.map { it.asString } ?: arrayListOf(),
|
||||
this.get("commands")?.asJsonArray?.map { it.asString } ?: arrayListOf()
|
||||
with(info.jsonObject) {
|
||||
map[this["name"]!!.toString()] = PluginCenter.PluginInsight(
|
||||
this["name"]?.primitive?.content ?: "",
|
||||
this["version"]?.primitive?.content ?: "",
|
||||
this["core"]?.primitive?.content ?: "",
|
||||
this["console"]?.primitive?.content ?: "",
|
||||
this["author"]?.primitive?.content ?: "",
|
||||
this["description"]?.primitive?.content ?: "",
|
||||
this["tags"]?.jsonArray?.map { it.primitive.content } ?: arrayListOf(),
|
||||
this["commands"]?.jsonArray?.map { it.primitive.content } ?: arrayListOf()
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -62,18 +60,18 @@ internal object CuiPluginCenter : PluginCenter {
|
||||
|
||||
return result.asJson().run {
|
||||
PluginCenter.PluginInfo(
|
||||
this.get("name")?.asString ?: "",
|
||||
this.get("version")?.asString ?: "",
|
||||
this.get("core")?.asString ?: "",
|
||||
this.get("console")?.asString ?: "",
|
||||
this.get("tags")?.asJsonArray?.map { it.asString } ?: arrayListOf(),
|
||||
this.get("author")?.asString ?: "",
|
||||
this.get("contact")?.asString ?: "",
|
||||
this.get("description")?.asString ?: "",
|
||||
this.get("usage")?.asString ?: "",
|
||||
this.get("vsc")?.asString ?: "",
|
||||
this.get("commands")?.asJsonArray?.map { it.asString } ?: arrayListOf(),
|
||||
this.get("changeLog")?.asJsonArray?.map { it.asString } ?: arrayListOf()
|
||||
this["name"]?.primitive?.content ?: "",
|
||||
this["version"]?.primitive?.content ?: "",
|
||||
this["core"]?.primitive?.content ?: "",
|
||||
this["console"]?.primitive?.content ?: "",
|
||||
this["tags"]?.jsonArray?.map { it.primitive.content } ?: arrayListOf(),
|
||||
this["author"]?.primitive?.content ?: "",
|
||||
this["contact"]?.primitive?.content ?: "",
|
||||
this["description"]?.primitive?.content ?: "",
|
||||
this["usage"]?.primitive?.content ?: "",
|
||||
this["vsc"]?.primitive?.content ?: "",
|
||||
this["commands"]?.jsonArray?.map { it.primitive.content } ?: arrayListOf(),
|
||||
this["changeLog"]?.jsonArray?.map { it.primitive.content } ?: arrayListOf()
|
||||
)
|
||||
}
|
||||
|
||||
@ -82,10 +80,10 @@ internal object CuiPluginCenter : PluginCenter {
|
||||
override suspend fun refresh() {
|
||||
val results = Http.get<String>("https://miraiapi.jasonczc.cn/getPluginList").asJson()
|
||||
|
||||
if (!(results.has("success") && results["success"].asBoolean)) {
|
||||
if (!(results.containsKey("success") && results["success"]?.boolean == true)) {
|
||||
error("Failed to fetch plugin list from Cui Cloud")
|
||||
}
|
||||
plugins = results.get("result").asJsonArray//先不解析
|
||||
plugins = results["result"]?.jsonArray//先不解析
|
||||
}
|
||||
|
||||
override suspend fun <T : Any> T.downloadPlugin(name: String, progressListener: T.(Float) -> Unit): File {
|
||||
@ -118,8 +116,10 @@ internal object CuiPluginCenter : PluginCenter {
|
||||
get() = "崔云"
|
||||
|
||||
|
||||
private val json = Json(JsonConfiguration.Stable)
|
||||
|
||||
private fun String.asJson(): JsonObject {
|
||||
return JsonParser.parseString(this).asJsonObject
|
||||
return json.parseJson(this).jsonObject
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,617 +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
|
||||
*/
|
||||
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
package net.mamoe.mirai.console.plugins
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.moandjiezana.toml.Toml
|
||||
import com.moandjiezana.toml.TomlWriter
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.UnstableDefault
|
||||
import net.mamoe.mirai.console.encodeToString
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import org.yaml.snakeyaml.Yaml
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import kotlin.NoSuchElementException
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.full.isSubclassOf
|
||||
|
||||
|
||||
/**
|
||||
* 标注一个即将在将来版本删除的 API
|
||||
*
|
||||
* 目前 [Config] 的读写设计语义不明, list 和 map 读取效率低, 属性委托写入语义不明
|
||||
* 将在未来重写并变为 `ReadOnlyConfig` 和 `ReadWriteConfig`.
|
||||
* 并计划添加图形端配置绑定, 和带注释的序列化, 自动保存的配置文件, 与指令绑定的属性.
|
||||
*/
|
||||
@RequiresOptIn("将在未来进行不兼容的修改", RequiresOptIn.Level.WARNING)
|
||||
annotation class ToBeRemoved
|
||||
|
||||
/**
|
||||
* 可读可写配置文件.
|
||||
*
|
||||
* @suppress 注意: 配置文件正在进行不兼容的修改
|
||||
*/
|
||||
interface Config {
|
||||
@ToBeRemoved
|
||||
fun getConfigSection(key: String): ConfigSection
|
||||
|
||||
fun getString(key: String): String
|
||||
fun getInt(key: String): Int
|
||||
fun getFloat(key: String): Float
|
||||
fun getDouble(key: String): Double
|
||||
fun getLong(key: String): Long
|
||||
fun getBoolean(key: String): Boolean
|
||||
|
||||
@ToBeRemoved
|
||||
fun getList(key: String): List<*>
|
||||
|
||||
|
||||
@ToBeRemoved
|
||||
fun getStringList(key: String): List<String>
|
||||
|
||||
@ToBeRemoved
|
||||
fun getIntList(key: String): List<Int>
|
||||
|
||||
@ToBeRemoved
|
||||
fun getFloatList(key: String): List<Float>
|
||||
|
||||
@ToBeRemoved
|
||||
fun getDoubleList(key: String): List<Double>
|
||||
|
||||
@ToBeRemoved
|
||||
fun getLongList(key: String): List<Long>
|
||||
|
||||
@ToBeRemoved
|
||||
fun getConfigSectionList(key: String): List<ConfigSection>
|
||||
|
||||
operator fun set(key: String, value: Any)
|
||||
operator fun get(key: String): Any?
|
||||
operator fun contains(key: String): Boolean
|
||||
|
||||
@ToBeRemoved
|
||||
fun exist(key: String): Boolean
|
||||
|
||||
/**
|
||||
* 设置 key = value (如果value不存在则valueInitializer会被调用)
|
||||
* 之后返回当前key对应的值
|
||||
* */
|
||||
@ToBeRemoved
|
||||
fun <T : Any> setIfAbsent(key: String, value: T)
|
||||
|
||||
@ToBeRemoved
|
||||
fun <T : Any> setIfAbsent(key: String, valueInitializer: Config.() -> T)
|
||||
|
||||
@ToBeRemoved
|
||||
fun asMap(): Map<String, Any>
|
||||
|
||||
@ToBeRemoved
|
||||
fun save()
|
||||
|
||||
companion object {
|
||||
@ToBeRemoved
|
||||
fun load(fileName: String): Config {
|
||||
return load(
|
||||
File(
|
||||
fileName.replace(
|
||||
"//",
|
||||
"/"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* create a read-write config
|
||||
* */
|
||||
@ToBeRemoved
|
||||
fun load(file: File): Config {
|
||||
if (!file.exists()) {
|
||||
file.createNewFile()
|
||||
}
|
||||
return when (file.extension.toLowerCase()) {
|
||||
"json" -> JsonConfig(file)
|
||||
"yml" -> YamlConfig(file)
|
||||
"yaml" -> YamlConfig(file)
|
||||
"mirai" -> YamlConfig(file)
|
||||
"ini" -> TomlConfig(file)
|
||||
"toml" -> TomlConfig(file)
|
||||
"properties" -> TomlConfig(file)
|
||||
"property" -> TomlConfig(file)
|
||||
"data" -> TomlConfig(file)
|
||||
else -> error("Unsupported file config type ${file.extension.toLowerCase()}")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create a read-only config
|
||||
*/
|
||||
@ToBeRemoved
|
||||
fun load(content: String, type: String): Config {
|
||||
return when (type.toLowerCase()) {
|
||||
"json" -> JsonConfig(content)
|
||||
"yml" -> YamlConfig(content)
|
||||
"yaml" -> YamlConfig(content)
|
||||
"mirai" -> YamlConfig(content)
|
||||
"ini" -> TomlConfig(content)
|
||||
"toml" -> TomlConfig(content)
|
||||
"properties" -> TomlConfig(content)
|
||||
"property" -> TomlConfig(content)
|
||||
"data" -> TomlConfig(content)
|
||||
else -> error("Unsupported file config type $content")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create a read-only config
|
||||
*/
|
||||
@ToBeRemoved
|
||||
fun load(inputStream: InputStream, type: String): Config {
|
||||
return load(inputStream.readBytes().encodeToString(), type)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ToBeRemoved
|
||||
fun File.loadAsConfig(): Config {
|
||||
return Config.load(this)
|
||||
}
|
||||
|
||||
/* 最简单的代理 */
|
||||
@ToBeRemoved
|
||||
inline operator fun <reified T : Any> Config.getValue(thisRef: Any?, property: KProperty<*>): T {
|
||||
return smartCast(property)
|
||||
}
|
||||
|
||||
@ToBeRemoved
|
||||
inline operator fun <reified T : Any> Config.setValue(thisRef: Any?, property: KProperty<*>, value: T) {
|
||||
this[property.name] = value
|
||||
}
|
||||
|
||||
/* 带有默认值的代理 */
|
||||
@Suppress("unused")
|
||||
@ToBeRemoved
|
||||
inline fun <reified T : Any> Config.withDefault(
|
||||
crossinline defaultValue: () -> T
|
||||
): ReadWriteProperty<Any, T> {
|
||||
return object : ReadWriteProperty<Any, T> {
|
||||
override fun getValue(thisRef: Any, property: KProperty<*>): T {
|
||||
if (this@withDefault.exist(property.name)) {//unsafe
|
||||
return this@withDefault.smartCast(property)
|
||||
}
|
||||
return defaultValue()
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
|
||||
this@withDefault[property.name] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 带有默认值且如果为空会写入的代理 */
|
||||
@Suppress("unused")
|
||||
@ToBeRemoved
|
||||
inline fun <reified T : Any> Config.withDefaultWrite(
|
||||
noinline defaultValue: () -> T
|
||||
): WithDefaultWriteLoader<T> {
|
||||
return WithDefaultWriteLoader(
|
||||
T::class,
|
||||
this,
|
||||
defaultValue,
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
/* 带有默认值且如果为空会写入保存的代理 */
|
||||
@ToBeRemoved
|
||||
inline fun <reified T : Any> Config.withDefaultWriteSave(
|
||||
noinline defaultValue: () -> T
|
||||
): WithDefaultWriteLoader<T> {
|
||||
return WithDefaultWriteLoader(T::class, this, defaultValue, true)
|
||||
}
|
||||
|
||||
@ToBeRemoved
|
||||
class WithDefaultWriteLoader<T : Any>(
|
||||
private val _class: KClass<T>,
|
||||
private val config: Config,
|
||||
private val defaultValue: () -> T,
|
||||
private val save: Boolean
|
||||
) {
|
||||
operator fun provideDelegate(
|
||||
thisRef: Any,
|
||||
prop: KProperty<*>
|
||||
): ReadWriteProperty<Any, T> {
|
||||
val defaultValue by lazy { defaultValue.invoke() }
|
||||
if (!config.contains(prop.name)) {
|
||||
config[prop.name] = defaultValue
|
||||
if (save) {
|
||||
config.save()
|
||||
}
|
||||
}
|
||||
return object : ReadWriteProperty<Any, T> {
|
||||
override fun getValue(thisRef: Any, property: KProperty<*>): T {
|
||||
if (config.exist(property.name)) {//unsafe
|
||||
return config.smartCastInternal(property.name, _class)
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
|
||||
config[property.name] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal inline fun <reified T : Any> Config.smartCast(property: KProperty<*>): T {
|
||||
return smartCastInternal(property.name, T::class)
|
||||
}
|
||||
|
||||
@OptIn(ToBeRemoved::class)
|
||||
@PublishedApi
|
||||
@Suppress("IMPLICIT_CAST_TO_ANY", "UNCHECKED_CAST")
|
||||
internal fun <T : Any> Config.smartCastInternal(propertyName: String, _class: KClass<T>): T {
|
||||
return when (_class) {
|
||||
String::class -> this.getString(propertyName)
|
||||
Int::class -> this.getInt(propertyName)
|
||||
Float::class -> this.getFloat(propertyName)
|
||||
Double::class -> this.getDouble(propertyName)
|
||||
Long::class -> this.getLong(propertyName)
|
||||
Boolean::class -> this.getBoolean(propertyName)
|
||||
else -> when {
|
||||
_class.isSubclassOf(ConfigSection::class) -> this.getConfigSection(propertyName)
|
||||
_class == List::class || _class == MutableList::class -> {
|
||||
val list = this.getList(propertyName)
|
||||
return if (list.isEmpty()) {
|
||||
list
|
||||
} else {
|
||||
when (list[0]!!::class) {
|
||||
String::class -> getStringList(propertyName)
|
||||
Int::class -> getIntList(propertyName)
|
||||
Float::class -> getFloatList(propertyName)
|
||||
Double::class -> getDoubleList(propertyName)
|
||||
Long::class -> getLongList(propertyName)
|
||||
//不去支持getConfigSectionList(propertyName)
|
||||
// LinkedHashMap::class -> getConfigSectionList(propertyName)//faster approach
|
||||
else -> {
|
||||
//if(list[0]!! is ConfigSection || list[0]!! is Map<*,*>){
|
||||
// getConfigSectionList(propertyName)
|
||||
//}else {
|
||||
error("unsupported type" + list[0]!!::class)
|
||||
//}
|
||||
}
|
||||
}
|
||||
} as T
|
||||
}
|
||||
else -> {
|
||||
error("unsupported type")
|
||||
}
|
||||
}
|
||||
} as T
|
||||
}
|
||||
|
||||
|
||||
@ToBeRemoved
|
||||
interface ConfigSection : Config, MutableMap<String, Any> {
|
||||
companion object {
|
||||
fun create(): ConfigSection {
|
||||
return ConfigSectionImpl()
|
||||
}
|
||||
|
||||
fun new(): ConfigSection {
|
||||
return this.create()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getConfigSection(key: String): ConfigSection {
|
||||
val content = get(key) ?: throw NoSuchElementException(key)
|
||||
if (content is ConfigSection) {
|
||||
return content
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return ConfigSectionDelegation(
|
||||
Collections.synchronizedMap(
|
||||
(get(key) ?: throw NoSuchElementException(key)) as LinkedHashMap<String, Any>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun getString(key: String): String {
|
||||
return (get(key) ?: throw NoSuchElementException(key)).toString()
|
||||
}
|
||||
|
||||
override fun getInt(key: String): Int {
|
||||
return (get(key) ?: throw NoSuchElementException(key)).toString().toInt()
|
||||
}
|
||||
|
||||
override fun getFloat(key: String): Float {
|
||||
return (get(key) ?: throw NoSuchElementException(key)).toString().toFloat()
|
||||
}
|
||||
|
||||
override fun getBoolean(key: String): Boolean {
|
||||
return (get(key) ?: throw NoSuchElementException(key)).toString().toBoolean()
|
||||
}
|
||||
|
||||
override fun getDouble(key: String): Double {
|
||||
return (get(key) ?: throw NoSuchElementException(key)).toString().toDouble()
|
||||
}
|
||||
|
||||
override fun getLong(key: String): Long {
|
||||
return (get(key) ?: throw NoSuchElementException(key)).toString().toLong()
|
||||
}
|
||||
|
||||
override fun getList(key: String): List<*> {
|
||||
return ((get(key) ?: throw NoSuchElementException(key)) as List<*>)
|
||||
}
|
||||
|
||||
override fun getStringList(key: String): List<String> {
|
||||
return ((get(key) ?: throw NoSuchElementException(key)) as List<*>).filterNotNull().map { it.toString() }
|
||||
}
|
||||
|
||||
override fun getIntList(key: String): List<Int> {
|
||||
return ((get(key) ?: throw NoSuchElementException(key)) as List<*>).map { it.toString().toInt() }
|
||||
}
|
||||
|
||||
override fun getFloatList(key: String): List<Float> {
|
||||
return ((get(key) ?: throw NoSuchElementException(key)) as List<*>).map { it.toString().toFloat() }
|
||||
}
|
||||
|
||||
override fun getDoubleList(key: String): List<Double> {
|
||||
return ((get(key) ?: throw NoSuchElementException(key)) as List<*>).map { it.toString().toDouble() }
|
||||
}
|
||||
|
||||
override fun getLongList(key: String): List<Long> {
|
||||
return ((get(key) ?: throw NoSuchElementException(key)) as List<*>).map { it.toString().toLong() }
|
||||
}
|
||||
|
||||
override fun getConfigSectionList(key: String): List<ConfigSection> {
|
||||
return ((get(key) ?: throw NoSuchElementException(key)) as List<*>).map {
|
||||
if (it is ConfigSection) {
|
||||
it
|
||||
} else {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
ConfigSectionDelegation(
|
||||
Collections.synchronizedMap(
|
||||
it as MutableMap<String, Any>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun exist(key: String): Boolean {
|
||||
return get(key) != null
|
||||
}
|
||||
|
||||
override fun <T : Any> setIfAbsent(key: String, value: T) {
|
||||
putIfAbsent(key, value)
|
||||
}
|
||||
|
||||
override fun <T : Any> setIfAbsent(key: String, valueInitializer: Config.() -> T) {
|
||||
if (this.exist(key)) {
|
||||
put(key, valueInitializer.invoke(this))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ToBeRemoved::class)
|
||||
internal inline fun <reified T : Any> ConfigSection.smartGet(key: String): T {
|
||||
return this.smartCastInternal(key, T::class)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@ToBeRemoved
|
||||
open class ConfigSectionImpl : ConcurrentHashMap<String, Any>(),
|
||||
|
||||
ConfigSection {
|
||||
override fun set(key: String, value: Any) {
|
||||
super.put(key, value)
|
||||
}
|
||||
|
||||
override operator fun get(key: String): Any? {
|
||||
return super.get(key)
|
||||
}
|
||||
|
||||
@Suppress("RedundantOverride")
|
||||
override fun contains(key: String): Boolean {
|
||||
return super.contains(key)
|
||||
}
|
||||
|
||||
override fun exist(key: String): Boolean {
|
||||
return containsKey(key)
|
||||
}
|
||||
|
||||
override fun asMap(): Map<String, Any> {
|
||||
return this
|
||||
}
|
||||
|
||||
override fun save() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ToBeRemoved
|
||||
open class ConfigSectionDelegation(
|
||||
private val delegate: MutableMap<String, Any>
|
||||
) : ConfigSection, MutableMap<String, Any> by delegate {
|
||||
override fun set(key: String, value: Any) {
|
||||
delegate[key] = value
|
||||
}
|
||||
|
||||
override fun contains(key: String): Boolean {
|
||||
return delegate.containsKey(key)
|
||||
}
|
||||
|
||||
override fun asMap(): Map<String, Any> {
|
||||
return delegate
|
||||
}
|
||||
|
||||
override fun save() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ToBeRemoved
|
||||
interface FileConfig : Config {
|
||||
fun deserialize(content: String): ConfigSection
|
||||
|
||||
fun serialize(config: ConfigSection): String
|
||||
}
|
||||
|
||||
|
||||
@MiraiInternalAPI
|
||||
@ToBeRemoved
|
||||
abstract class FileConfigImpl internal constructor(
|
||||
private val rawContent: String
|
||||
) : FileConfig,
|
||||
ConfigSection {
|
||||
|
||||
internal var file: File? = null
|
||||
|
||||
|
||||
@Suppress("unused")
|
||||
constructor(file: File) : this(file.readText()) {
|
||||
this.file = file
|
||||
}
|
||||
|
||||
|
||||
private val content by lazy {
|
||||
deserialize(rawContent)
|
||||
}
|
||||
|
||||
|
||||
override val size: Int get() = content.size
|
||||
override val entries: MutableSet<MutableMap.MutableEntry<String, Any>> get() = content.entries
|
||||
override val keys: MutableSet<String> get() = content.keys
|
||||
override val values: MutableCollection<Any> get() = content.values
|
||||
override fun containsKey(key: String): Boolean = content.containsKey(key)
|
||||
override fun containsValue(value: Any): Boolean = content.containsValue(value)
|
||||
override fun put(key: String, value: Any): Any? = content.put(key, value)
|
||||
override fun isEmpty(): Boolean = content.isEmpty()
|
||||
override fun putAll(from: Map<out String, Any>) = content.putAll(from)
|
||||
override fun clear() = content.clear()
|
||||
override fun remove(key: String): Any? = content.remove(key)
|
||||
|
||||
override fun save() {
|
||||
if (isReadOnly) {
|
||||
error("Config is readonly")
|
||||
}
|
||||
if (!((file?.exists())!!)) {
|
||||
file?.createNewFile()
|
||||
}
|
||||
file?.writeText(serialize(content))
|
||||
}
|
||||
|
||||
val isReadOnly: Boolean get() = file == null
|
||||
|
||||
override fun contains(key: String): Boolean {
|
||||
return content.contains(key)
|
||||
}
|
||||
|
||||
override fun get(key: String): Any? {
|
||||
return content[key]
|
||||
}
|
||||
|
||||
override fun set(key: String, value: Any) {
|
||||
content[key] = value
|
||||
}
|
||||
|
||||
override fun asMap(): Map<String, Any> {
|
||||
return content.asMap()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ToBeRemoved
|
||||
@OptIn(MiraiInternalAPI::class)
|
||||
class JsonConfig internal constructor(
|
||||
content: String
|
||||
) : FileConfigImpl(content) {
|
||||
constructor(file: File) : this(file.readText()) {
|
||||
this.file = file
|
||||
}
|
||||
|
||||
@UnstableDefault
|
||||
override fun deserialize(content: String): ConfigSection {
|
||||
if (content.isEmpty() || content.isBlank() || content == "{}") {
|
||||
return ConfigSectionImpl()
|
||||
}
|
||||
val gson = Gson()
|
||||
val typeRef = object : TypeToken<Map<String, Any>>() {}.type
|
||||
return ConfigSectionDelegation(
|
||||
gson.fromJson(content, typeRef)
|
||||
)
|
||||
}
|
||||
|
||||
@UnstableDefault
|
||||
override fun serialize(config: ConfigSection): String {
|
||||
val gson = Gson()
|
||||
return gson.toJson(config.toMap())
|
||||
}
|
||||
}
|
||||
|
||||
@ToBeRemoved
|
||||
@OptIn(MiraiInternalAPI::class)
|
||||
class YamlConfig internal constructor(content: String) : FileConfigImpl(content) {
|
||||
constructor(file: File) : this(file.readText()) {
|
||||
this.file = file
|
||||
}
|
||||
|
||||
override fun deserialize(content: String): ConfigSection {
|
||||
if (content.isEmpty() || content.isBlank()) {
|
||||
return ConfigSectionImpl()
|
||||
}
|
||||
return ConfigSectionDelegation(
|
||||
Collections.synchronizedMap(
|
||||
Yaml().load(content) as LinkedHashMap<String, Any>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun serialize(config: ConfigSection): String {
|
||||
return Yaml().dumpAsMap(config)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ToBeRemoved
|
||||
@OptIn(MiraiInternalAPI::class)
|
||||
class TomlConfig internal constructor(content: String) : FileConfigImpl(content) {
|
||||
constructor(file: File) : this(file.readText()) {
|
||||
this.file = file
|
||||
}
|
||||
|
||||
override fun deserialize(content: String): ConfigSection {
|
||||
if (content.isEmpty() || content.isBlank()) {
|
||||
return ConfigSectionImpl()
|
||||
}
|
||||
return ConfigSectionDelegation(
|
||||
Collections.synchronizedMap(
|
||||
Toml().read(content).toMap()
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
override fun serialize(config: ConfigSection): String {
|
||||
return TomlWriter().write(config)
|
||||
}
|
||||
}
|
@ -70,14 +70,6 @@ abstract class PluginBase
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载一个 [dataFolder] 中的 [Config]
|
||||
*/
|
||||
fun loadConfig(fileName: String): Config {
|
||||
@OptIn(ToBeRemoved::class)
|
||||
return Config.load(dataFolder.absolutePath + "/" + fileName)
|
||||
}
|
||||
|
||||
/**
|
||||
* 插件的日志
|
||||
*/
|
||||
@ -110,16 +102,6 @@ abstract class PluginBase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载 resource 中的 [Config]
|
||||
* 这个 [Config] 是只读的
|
||||
*/
|
||||
@ToBeRemoved
|
||||
fun getResourcesConfig(fileName: String): Config {
|
||||
require(fileName.contains(".")) { "Unknown Config Type" }
|
||||
@OptIn(ToBeRemoved::class)
|
||||
return Config.load(getResources(fileName) ?: error("No such file: $fileName"), fileName.substringAfter('.'))
|
||||
}
|
||||
|
||||
/**
|
||||
* Java API Scheduler
|
||||
|
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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("NOTHING_TO_INLINE")
|
||||
|
||||
package net.mamoe.mirai.console.setting
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import net.mamoe.yamlkt.Yaml
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
|
||||
internal inline fun <E> KSerializer<E>.bind(
|
||||
crossinline setter: (E) -> Unit,
|
||||
crossinline getter: () -> E
|
||||
): KSerializer<E> {
|
||||
return object : KSerializer<E> {
|
||||
override val descriptor: SerialDescriptor get() = this@bind.descriptor
|
||||
override fun deserialize(decoder: Decoder): E = this@bind.deserialize(decoder).also { setter(it) }
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun serialize(encoder: Encoder, value: E) =
|
||||
this@bind.serialize(encoder, getter())
|
||||
}
|
||||
}
|
||||
|
||||
typealias SerialName = kotlinx.serialization.SerialName
|
||||
|
||||
/**
|
||||
* 配置的基类
|
||||
*/
|
||||
abstract class Setting {
|
||||
open val serialName: String
|
||||
get() = this::class.findAnnotation<SerialName>()?.value
|
||||
?: this::class.qualifiedName
|
||||
?: error("Names should be assigned to anonymous classes manually by overriding serialName")
|
||||
|
||||
|
||||
@JvmSynthetic
|
||||
operator fun <T : Any> Value<T>.provideDelegate(
|
||||
thisRef: Setting,
|
||||
property: KProperty<*>
|
||||
): ReadWriteProperty<Setting, T> {
|
||||
if (built) error("The Setting is already serialized so it's structure is immutable.")
|
||||
valueList.add(this to property)
|
||||
return this
|
||||
}
|
||||
|
||||
@JvmField
|
||||
internal var valueList: MutableList<Pair<Value<*>, KProperty<*>>> = mutableListOf()
|
||||
private var built: Boolean = false
|
||||
|
||||
internal val serializer: KSerializer<SettingSerializerMark> by lazy {
|
||||
built = true
|
||||
SettingSerializer(this)
|
||||
}
|
||||
|
||||
internal fun onElementChanged(value: Value<*>) {
|
||||
println("my value changed!")
|
||||
}
|
||||
}
|
||||
|
||||
internal class SettingSerializer(
|
||||
private val instance: Setting
|
||||
) : KSerializer<SettingSerializerMark> {
|
||||
override val descriptor: SerialDescriptor by lazy {
|
||||
SerialDescriptor(instance.serialName) {
|
||||
for ((value, property) in instance.valueList) {
|
||||
element(property.serialNameOrPropertyName, value.serializer.descriptor, annotations, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST") // erased, no problem.
|
||||
override fun deserialize(decoder: Decoder): SettingSerializerMark = decoder.decodeStructure(descriptor) {
|
||||
if (this.decodeSequentially()) {
|
||||
instance.valueList.forEachIndexed { index, (value, _) ->
|
||||
this.decodeSerializableElement(
|
||||
value.serializer.descriptor,
|
||||
index,
|
||||
value.serializer as KSerializer<Any>
|
||||
)
|
||||
}
|
||||
} else {
|
||||
while (true) {
|
||||
val index = this.decodeElementIndex(descriptor)
|
||||
if (index == CompositeDecoder.READ_DONE) return@decodeStructure SettingSerializerMark
|
||||
val value = instance.valueList[index].first
|
||||
|
||||
this.decodeSerializableElement(
|
||||
descriptor,
|
||||
index,
|
||||
value.serializer
|
||||
)
|
||||
}
|
||||
}
|
||||
SettingSerializerMark
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: SettingSerializerMark) = encoder.encodeStructure(descriptor) {
|
||||
instance.valueList.forEachIndexed { index, (value, _) ->
|
||||
@Suppress("UNCHECKED_CAST") // erased, no problem.
|
||||
this.encodeSerializableElement(
|
||||
descriptor,
|
||||
index,
|
||||
value.serializer as KSerializer<Any>,
|
||||
value.value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal object SettingSerializerMark
|
||||
|
||||
internal val KProperty<*>.serialNameOrPropertyName: String get() = this.findAnnotation<SerialName>()?.value ?: this.name
|
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* 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.console.setting
|
||||
|
||||
object ValueSerializerMark
|
||||
|
||||
/*
|
||||
* More generic ones
|
||||
*/
|
@ -0,0 +1,55 @@
|
||||
|
||||
/*
|
||||
* 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.console.setting
|
||||
|
||||
/**
|
||||
* !!! This file is auto-generated by backend/codegen/src/kotlin/net.mamoe.mirai.console.codegen.SettingValueUseSiteCodegen.kt
|
||||
* !!! DO NOT MODIFY THIS FILE MANUALLY
|
||||
*/
|
||||
|
||||
|
||||
fun Setting.value(default: Int): IntValue = valueImpl(default)
|
||||
fun Setting.value(default: Short): ShortValue = valueImpl(default)
|
||||
fun Setting.value(default: Byte): ByteValue = valueImpl(default)
|
||||
fun Setting.value(default: Long): LongValue = valueImpl(default)
|
||||
fun Setting.value(default: Float): FloatValue = valueImpl(default)
|
||||
fun Setting.value(default: Double): DoubleValue = valueImpl(default)
|
||||
fun Setting.value(default: Boolean): BooleanValue = valueImpl(default)
|
||||
fun Setting.value(default: Char): CharValue = valueImpl(default)
|
||||
fun Setting.value(default: String): StringValue = valueImpl(default)
|
||||
fun Setting.value(default: IntArray): IntArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: ShortArray): ShortArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: ByteArray): ByteArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: LongArray): LongArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: FloatArray): FloatArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: DoubleArray): DoubleArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: BooleanArray): BooleanArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: CharArray): CharArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Int>): TypedIntArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Short>): TypedShortArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Byte>): TypedByteArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Long>): TypedLongArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Float>): TypedFloatArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Double>): TypedDoubleArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Boolean>): TypedBooleanArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<Char>): TypedCharArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: Array<String>): TypedStringArrayValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Int>): IntListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Short>): ShortListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Byte>): ByteListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Long>): LongListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Float>): FloatListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Double>): DoubleListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Boolean>): BooleanListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Char>): CharListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<String>): StringListValue = valueImpl(default)
|
||||
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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.console.setting
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/**
|
||||
* !!! These primitive types are auto-generated by backend/codegen/src/main/kotlin/net.mamoe.mirai.console.ValuesCodegen.kt
|
||||
* !!! for better performance
|
||||
* !!! DO NOT MODIFY THIS FILE MANUALLY
|
||||
*/
|
||||
|
||||
sealed class Value<T : Any> : ReadWriteProperty<Setting, T> {
|
||||
abstract var value: T
|
||||
|
||||
abstract val serializer: KSerializer<T>
|
||||
override fun getValue(thisRef: Setting, property: KProperty<*>): T = value
|
||||
override fun setValue(thisRef: Setting, property: KProperty<*>, value: T) {
|
||||
this.value = value
|
||||
}
|
||||
}
|
||||
|
||||
sealed class PrimitiveValue<T : Any> : Value<T>()
|
||||
|
||||
sealed class NumberValue<T : Number> : Value<T>()
|
||||
abstract class IntValue internal constructor() : NumberValue<Int>()
|
||||
abstract class ShortValue internal constructor() : NumberValue<Short>()
|
||||
abstract class ByteValue internal constructor() : NumberValue<Byte>()
|
||||
abstract class LongValue internal constructor() : NumberValue<Long>()
|
||||
abstract class FloatValue internal constructor() : NumberValue<Float>()
|
||||
abstract class DoubleValue internal constructor() : NumberValue<Double>()
|
||||
|
||||
abstract class BooleanValue internal constructor() : PrimitiveValue<Boolean>()
|
||||
abstract class CharValue internal constructor() : PrimitiveValue<Char>()
|
||||
abstract class StringValue internal constructor() : PrimitiveValue<String>()
|
||||
|
||||
// T can be primitive array or typed Array
|
||||
sealed class ArrayValue<T : Any> : Value<T>()
|
||||
sealed class PrimitiveArrayValue<T : Any> : ArrayValue<T>()
|
||||
|
||||
abstract class IntArrayValue internal constructor() : PrimitiveArrayValue<IntArray>(), Iterable<Int> {
|
||||
override fun iterator(): Iterator<Int> = this.value.iterator()
|
||||
}
|
||||
abstract class ShortArrayValue internal constructor() : PrimitiveArrayValue<ShortArray>(), Iterable<Short> {
|
||||
override fun iterator(): Iterator<Short> = this.value.iterator()
|
||||
}
|
||||
abstract class ByteArrayValue internal constructor() : PrimitiveArrayValue<ByteArray>(), Iterable<Byte> {
|
||||
override fun iterator(): Iterator<Byte> = this.value.iterator()
|
||||
}
|
||||
abstract class LongArrayValue internal constructor() : PrimitiveArrayValue<LongArray>(), Iterable<Long> {
|
||||
override fun iterator(): Iterator<Long> = this.value.iterator()
|
||||
}
|
||||
abstract class FloatArrayValue internal constructor() : PrimitiveArrayValue<FloatArray>(), Iterable<Float> {
|
||||
override fun iterator(): Iterator<Float> = this.value.iterator()
|
||||
}
|
||||
abstract class DoubleArrayValue internal constructor() : PrimitiveArrayValue<DoubleArray>(), Iterable<Double> {
|
||||
override fun iterator(): Iterator<Double> = this.value.iterator()
|
||||
}
|
||||
abstract class BooleanArrayValue internal constructor() : PrimitiveArrayValue<BooleanArray>(), Iterable<Boolean> {
|
||||
override fun iterator(): Iterator<Boolean> = this.value.iterator()
|
||||
}
|
||||
abstract class CharArrayValue internal constructor() : PrimitiveArrayValue<CharArray>(), Iterable<Char> {
|
||||
override fun iterator(): Iterator<Char> = this.value.iterator()
|
||||
}
|
||||
|
||||
sealed class TypedPrimitiveArrayValue<E> : ArrayValue<Array<E>>() , Iterable<E>{
|
||||
override fun iterator() = this.value.iterator()
|
||||
}
|
||||
|
||||
abstract class TypedIntArrayValue internal constructor() : TypedPrimitiveArrayValue<Int>()
|
||||
abstract class TypedShortArrayValue internal constructor() : TypedPrimitiveArrayValue<Short>()
|
||||
abstract class TypedByteArrayValue internal constructor() : TypedPrimitiveArrayValue<Byte>()
|
||||
abstract class TypedLongArrayValue internal constructor() : TypedPrimitiveArrayValue<Long>()
|
||||
abstract class TypedFloatArrayValue internal constructor() : TypedPrimitiveArrayValue<Float>()
|
||||
abstract class TypedDoubleArrayValue internal constructor() : TypedPrimitiveArrayValue<Double>()
|
||||
abstract class TypedBooleanArrayValue internal constructor() : TypedPrimitiveArrayValue<Boolean>()
|
||||
abstract class TypedCharArrayValue internal constructor() : TypedPrimitiveArrayValue<Char>()
|
||||
abstract class TypedStringArrayValue internal constructor() : TypedPrimitiveArrayValue<String>()
|
||||
|
||||
sealed class ListValue<E> : Value<List<E>>(), Iterable<E>{
|
||||
override fun iterator() = this.value.iterator()
|
||||
}
|
||||
abstract class IntListValue internal constructor() : ListValue<Int>()
|
||||
abstract class ShortListValue internal constructor() : ListValue<Short>()
|
||||
abstract class ByteListValue internal constructor() : ListValue<Byte>()
|
||||
abstract class LongListValue internal constructor() : ListValue<Long>()
|
||||
abstract class FloatListValue internal constructor() : ListValue<Float>()
|
||||
abstract class DoubleListValue internal constructor() : ListValue<Double>()
|
||||
abstract class BooleanListValue internal constructor() : ListValue<Boolean>()
|
||||
abstract class CharListValue internal constructor() : ListValue<Char>()
|
||||
abstract class StringListValue internal constructor() : ListValue<String>()
|
||||
|
@ -0,0 +1,652 @@
|
||||
/*
|
||||
* 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.console.setting
|
||||
|
||||
import kotlinx.serialization.builtins.*
|
||||
|
||||
|
||||
/**
|
||||
* !!! This file is auto-generated by test/kotlin/net.mamoe.mirai.console.SettingsCodegen.kt
|
||||
* !!! DO NOT MODIFY THIS FILE MANUALLY
|
||||
*/
|
||||
|
||||
|
||||
internal fun Setting.valueImpl(default: Int): IntValue {
|
||||
return object : IntValue() {
|
||||
private var internalValue: Int = default
|
||||
override var value: Int
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = Int.serializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Short): ShortValue {
|
||||
return object : ShortValue() {
|
||||
private var internalValue: Short = default
|
||||
override var value: Short
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = Short.serializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Byte): ByteValue {
|
||||
return object : ByteValue() {
|
||||
private var internalValue: Byte = default
|
||||
override var value: Byte
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = Byte.serializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Long): LongValue {
|
||||
return object : LongValue() {
|
||||
private var internalValue: Long = default
|
||||
override var value: Long
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = Long.serializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Float): FloatValue {
|
||||
return object : FloatValue() {
|
||||
private var internalValue: Float = default
|
||||
override var value: Float
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = Float.serializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Double): DoubleValue {
|
||||
return object : DoubleValue() {
|
||||
private var internalValue: Double = default
|
||||
override var value: Double
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = Double.serializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Boolean): BooleanValue {
|
||||
return object : BooleanValue() {
|
||||
private var internalValue: Boolean = default
|
||||
override var value: Boolean
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = Boolean.serializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Char): CharValue {
|
||||
return object : CharValue() {
|
||||
private var internalValue: Char = default
|
||||
override var value: Char
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = Char.serializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: String): StringValue {
|
||||
return object : StringValue() {
|
||||
private var internalValue: String = default
|
||||
override var value: String
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = String.serializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: IntArray): IntArrayValue {
|
||||
return object : IntArrayValue() {
|
||||
private var internalValue: IntArray = default
|
||||
override var value: IntArray
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = IntArraySerializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: ShortArray): ShortArrayValue {
|
||||
return object : ShortArrayValue() {
|
||||
private var internalValue: ShortArray = default
|
||||
override var value: ShortArray
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ShortArraySerializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: ByteArray): ByteArrayValue {
|
||||
return object : ByteArrayValue() {
|
||||
private var internalValue: ByteArray = default
|
||||
override var value: ByteArray
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ByteArraySerializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: LongArray): LongArrayValue {
|
||||
return object : LongArrayValue() {
|
||||
private var internalValue: LongArray = default
|
||||
override var value: LongArray
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = LongArraySerializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: FloatArray): FloatArrayValue {
|
||||
return object : FloatArrayValue() {
|
||||
private var internalValue: FloatArray = default
|
||||
override var value: FloatArray
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = FloatArraySerializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: DoubleArray): DoubleArrayValue {
|
||||
return object : DoubleArrayValue() {
|
||||
private var internalValue: DoubleArray = default
|
||||
override var value: DoubleArray
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = DoubleArraySerializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: BooleanArray): BooleanArrayValue {
|
||||
return object : BooleanArrayValue() {
|
||||
private var internalValue: BooleanArray = default
|
||||
override var value: BooleanArray
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = BooleanArraySerializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: CharArray): CharArrayValue {
|
||||
return object : CharArrayValue() {
|
||||
private var internalValue: CharArray = default
|
||||
override var value: CharArray
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = CharArraySerializer().bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Array<Int>): TypedIntArrayValue {
|
||||
return object : TypedIntArrayValue() {
|
||||
private var internalValue: Array<Int> = default
|
||||
override var value: Array<Int>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ArraySerializer(Int.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Array<Short>): TypedShortArrayValue {
|
||||
return object : TypedShortArrayValue() {
|
||||
private var internalValue: Array<Short> = default
|
||||
override var value: Array<Short>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ArraySerializer(Short.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Array<Byte>): TypedByteArrayValue {
|
||||
return object : TypedByteArrayValue() {
|
||||
private var internalValue: Array<Byte> = default
|
||||
override var value: Array<Byte>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ArraySerializer(Byte.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Array<Long>): TypedLongArrayValue {
|
||||
return object : TypedLongArrayValue() {
|
||||
private var internalValue: Array<Long> = default
|
||||
override var value: Array<Long>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ArraySerializer(Long.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Array<Float>): TypedFloatArrayValue {
|
||||
return object : TypedFloatArrayValue() {
|
||||
private var internalValue: Array<Float> = default
|
||||
override var value: Array<Float>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ArraySerializer(Float.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Array<Double>): TypedDoubleArrayValue {
|
||||
return object : TypedDoubleArrayValue() {
|
||||
private var internalValue: Array<Double> = default
|
||||
override var value: Array<Double>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ArraySerializer(Double.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Array<Boolean>): TypedBooleanArrayValue {
|
||||
return object : TypedBooleanArrayValue() {
|
||||
private var internalValue: Array<Boolean> = default
|
||||
override var value: Array<Boolean>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ArraySerializer(Boolean.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Array<Char>): TypedCharArrayValue {
|
||||
return object : TypedCharArrayValue() {
|
||||
private var internalValue: Array<Char> = default
|
||||
override var value: Array<Char>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ArraySerializer(Char.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Array<String>): TypedStringArrayValue {
|
||||
return object : TypedStringArrayValue() {
|
||||
private var internalValue: Array<String> = default
|
||||
override var value: Array<String>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (!new.contentEquals(internalValue)) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ArraySerializer(String.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: List<Int>): IntListValue {
|
||||
return object : IntListValue() {
|
||||
private var internalValue: List<Int> = default
|
||||
override var value: List<Int>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ListSerializer(Int.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: List<Short>): ShortListValue {
|
||||
return object : ShortListValue() {
|
||||
private var internalValue: List<Short> = default
|
||||
override var value: List<Short>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ListSerializer(Short.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: List<Byte>): ByteListValue {
|
||||
return object : ByteListValue() {
|
||||
private var internalValue: List<Byte> = default
|
||||
override var value: List<Byte>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ListSerializer(Byte.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: List<Long>): LongListValue {
|
||||
return object : LongListValue() {
|
||||
private var internalValue: List<Long> = default
|
||||
override var value: List<Long>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ListSerializer(Long.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: List<Float>): FloatListValue {
|
||||
return object : FloatListValue() {
|
||||
private var internalValue: List<Float> = default
|
||||
override var value: List<Float>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ListSerializer(Float.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: List<Double>): DoubleListValue {
|
||||
return object : DoubleListValue() {
|
||||
private var internalValue: List<Double> = default
|
||||
override var value: List<Double>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ListSerializer(Double.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: List<Boolean>): BooleanListValue {
|
||||
return object : BooleanListValue() {
|
||||
private var internalValue: List<Boolean> = default
|
||||
override var value: List<Boolean>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ListSerializer(Boolean.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: List<Char>): CharListValue {
|
||||
return object : CharListValue() {
|
||||
private var internalValue: List<Char> = default
|
||||
override var value: List<Char>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ListSerializer(Char.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: List<String>): StringListValue {
|
||||
return object : StringListValue() {
|
||||
private var internalValue: List<String> = default
|
||||
override var value: List<String>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = ListSerializer(String.serializer()).bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@ package net.mamoe.mirai.console.utils
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.plugins.*
|
||||
import net.mamoe.mirai.console.utils.BotManagers.BOT_MANAGERS
|
||||
import net.mamoe.mirai.contact.User
|
||||
import java.io.File
|
||||
|
||||
@ -23,12 +22,6 @@ import java.io.File
|
||||
val User.isManager: Boolean
|
||||
get() = this.bot.managers.contains(this.id)
|
||||
|
||||
@OptIn(ToBeRemoved::class)
|
||||
internal object BotManagers {
|
||||
val config = File("${MiraiConsole.path}/bot.yml").loadAsConfig()
|
||||
val BOT_MANAGERS: ConfigSection by config.withDefaultWriteSave { ConfigSectionImpl() }
|
||||
}
|
||||
|
||||
@JvmName("addManager")
|
||||
@JvmSynthetic
|
||||
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
|
||||
@ -36,31 +29,18 @@ fun Bot.addManagerDeprecated(long: Long) {
|
||||
addManager(long)
|
||||
}
|
||||
|
||||
@OptIn(ToBeRemoved::class)
|
||||
internal fun Bot.addManager(long: Long): Boolean {
|
||||
BOT_MANAGERS.putIfAbsent(this.id.toString(), mutableListOf<Long>())
|
||||
BOT_MANAGERS[this.id.toString()] =
|
||||
(BOT_MANAGERS.getLongList(this.id.toString()) as MutableList<Long>).apply {
|
||||
if (contains(long)) return@addManager false
|
||||
add(long)
|
||||
}
|
||||
BotManagers.config.save()
|
||||
TODO()
|
||||
return true
|
||||
}
|
||||
|
||||
@OptIn(ToBeRemoved::class)
|
||||
fun Bot.removeManager(long: Long) {
|
||||
BOT_MANAGERS.putIfAbsent(this.id.toString(), mutableListOf<Long>())
|
||||
BOT_MANAGERS[this.id.toString()] =
|
||||
(BOT_MANAGERS.getLongList(this.id.toString()) as MutableList<Long>).apply { remove(long) }
|
||||
BotManagers.config.save()
|
||||
TODO()
|
||||
}
|
||||
|
||||
val Bot.managers: List<Long>
|
||||
@OptIn(ToBeRemoved::class)
|
||||
get() {
|
||||
BOT_MANAGERS.putIfAbsent(this.id.toString(), mutableListOf<Long>())
|
||||
return BOT_MANAGERS.getLongList(this.id.toString())
|
||||
TODO()
|
||||
}
|
||||
|
||||
fun Bot.checkManager(long: Long): Boolean {
|
||||
|
@ -28,6 +28,9 @@ def onlyBackEnd = true
|
||||
include(':mirai-console')
|
||||
project(':mirai-console').dir = file("backend/mirai-console")
|
||||
|
||||
include(':codegen')
|
||||
project(':codegen').dir = file("backend/codegen")
|
||||
|
||||
|
||||
if (!onlyBackEnd) {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user