Settings infrastructure:

Primitive Value codegen, use-site codegen, value impl codegen;
Settings serializers;
Values;
Settings property delegation.
This commit is contained in:
Him188 2020-05-15 14:44:39 +08:00
parent fdf12d024f
commit ef17e23a03
17 changed files with 1488 additions and 697 deletions

87
backend/codegen/README.MD Normal file
View 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>

View 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"
}

View File

@ -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()

View File

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

View File

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

View File

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

View File

@ -1,9 +0,0 @@
package net.mamoe.mirai.console.plugins;
public class ConfigSectionFactory {
public static ConfigSection create(){
return ConfigSection.Companion.create();
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -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
*/

View File

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

View File

@ -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>()

View File

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

View File

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

View File

@ -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) {