mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-31 19:40:24 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
fcc6100cb6
@ -8,12 +8,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.serialization.UnstableDefault
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.alsoLogin
|
import net.mamoe.mirai.alsoLogin
|
||||||
import net.mamoe.mirai.api.http.generateSessionKey
|
import net.mamoe.mirai.api.http.generateSessionKey
|
||||||
import net.mamoe.mirai.plugin.JsonConfig
|
import net.mamoe.mirai.plugin.*
|
||||||
import net.mamoe.mirai.plugin.PluginBase
|
|
||||||
import net.mamoe.mirai.plugin.PluginManager
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
@ -112,24 +111,13 @@ object MiraiConsole {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UnstableDefault
|
||||||
object MiraiProperties {
|
object MiraiProperties {
|
||||||
var HTTP_API_ENABLE: Boolean = true
|
var config = Config.load("$path/mirai.json")
|
||||||
var HTTP_API_PORT: Short = 8080
|
|
||||||
var HTTP_API_AUTH_KEY: String = ""
|
|
||||||
private val file = File(path + "/mirai.json".replace("//", "/"))
|
|
||||||
private lateinit var config: JsonConfig
|
|
||||||
fun load() {
|
|
||||||
if (!file.exists()) {
|
|
||||||
HTTP_API_AUTH_KEY = "INITKEY" + generateSessionKey()
|
|
||||||
save()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
config = PluginBase
|
|
||||||
}
|
|
||||||
|
|
||||||
fun save() {
|
var HTTP_API_ENABLE: Boolean by config.withDefault { true }
|
||||||
|
var HTTP_API_PORT: Int by config.withDefault { 8080 }
|
||||||
}
|
var HTTP_API_AUTH_KEY: String by config.withDefault { "INITKEY" + generateSessionKey() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,20 +9,19 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.plugin
|
package net.mamoe.mirai.plugin
|
||||||
|
|
||||||
import kotlinx.serialization.KSerializer
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.Transient
|
|
||||||
import kotlinx.serialization.UnstableDefault
|
import kotlinx.serialization.UnstableDefault
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import kotlin.properties.Delegates
|
|
||||||
import kotlin.properties.ReadWriteProperty
|
import kotlin.properties.ReadWriteProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
import kotlin.reflect.full.isSubclassOf
|
import kotlin.reflect.full.isSubclassOf
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: support all config types
|
* TODO: support all config types
|
||||||
|
* only JSON is now supported
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
interface Config {
|
interface Config {
|
||||||
@ -42,9 +41,29 @@ interface Config {
|
|||||||
operator fun get(key: String): Any?
|
operator fun get(key: String): Any?
|
||||||
fun exist(key: String): Boolean
|
fun exist(key: String): Boolean
|
||||||
fun asMap(): Map<String, Any>
|
fun asMap(): Map<String, Any>
|
||||||
|
fun save()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun load(fileName: String): Config {
|
||||||
|
return load(File(fileName.replace("//", "/")))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun load(file: File): Config {
|
||||||
|
if (!file.exists()) {
|
||||||
|
file.createNewFile()
|
||||||
|
}
|
||||||
|
return when (file.extension.toLowerCase()) {
|
||||||
|
"json" -> JsonConfig(file)
|
||||||
|
else -> error("Unsupported file config type ${file.extension.toLowerCase()}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : Any> Config.withDefault(crossinline defaultValue: () -> T): ReadWriteProperty<Any, T> {
|
inline fun <reified T : Any> Config.withDefault(
|
||||||
|
autoSave: Boolean = true,
|
||||||
|
crossinline defaultValue: () -> T
|
||||||
|
): ReadWriteProperty<Any, T> {
|
||||||
return object : ReadWriteProperty<Any, T> {
|
return object : ReadWriteProperty<Any, T> {
|
||||||
override fun getValue(thisRef: Any, property: KProperty<*>): T {
|
override fun getValue(thisRef: Any, property: KProperty<*>): T {
|
||||||
if (!this@withDefault.exist(property.name)) {
|
if (!this@withDefault.exist(property.name)) {
|
||||||
@ -55,12 +74,13 @@ inline fun <reified T : Any> Config.withDefault(crossinline defaultValue: () ->
|
|||||||
|
|
||||||
override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
|
override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
|
||||||
this@withDefault[property.name] = value
|
this@withDefault[property.name] = value
|
||||||
|
if (autoSave) save()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("IMPLICIT_CAST_TO_ANY")
|
@Suppress("IMPLICIT_CAST_TO_ANY")
|
||||||
inline operator fun <reified T> ConfigSection.getValue(thisRef: Any?, property: KProperty<*>): T {
|
inline operator fun <reified T> Config.getValue(thisRef: Any?, property: KProperty<*>): T {
|
||||||
return when (T::class) {
|
return when (T::class) {
|
||||||
String::class -> this.getString(property.name)
|
String::class -> this.getString(property.name)
|
||||||
Int::class -> this.getInt(property.name)
|
Int::class -> this.getInt(property.name)
|
||||||
@ -93,7 +113,7 @@ inline operator fun <reified T> ConfigSection.getValue(thisRef: Any?, property:
|
|||||||
} as T
|
} as T
|
||||||
}
|
}
|
||||||
|
|
||||||
inline operator fun <reified T> ConfigSection.setValue(thisRef: Any?, property: KProperty<*>, value: T) {
|
inline operator fun <reified T> Config.setValue(thisRef: Any?, property: KProperty<*>, value: T) {
|
||||||
this[property.name] = value!!
|
this[property.name] = value!!
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,14 +167,17 @@ interface ConfigSection : Config {
|
|||||||
return ((get(key) ?: error("ConfigSection does not contain $key ")) as List<*>).map { it.toString().toLong() }
|
return ((get(key) ?: error("ConfigSection does not contain $key ")) as List<*>).map { it.toString().toLong() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override operator fun set(key: String, value: Any) {
|
override fun exist(key: String): Boolean {
|
||||||
this[key] = value
|
return get(key) != null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
open class ConfigSectionImpl() : ConcurrentHashMap<String, Any>(), ConfigSection {
|
open class ConfigSectionImpl() : ConcurrentHashMap<String, Any>(), ConfigSection {
|
||||||
|
override fun set(key: String, value: Any) {
|
||||||
|
this[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
override operator fun get(key: String): Any? {
|
override operator fun get(key: String): Any? {
|
||||||
return super.get(key)
|
return super.get(key)
|
||||||
}
|
}
|
||||||
@ -166,48 +189,66 @@ open class ConfigSectionImpl() : ConcurrentHashMap<String, Any>(), ConfigSection
|
|||||||
override fun asMap(): Map<String, Any> {
|
override fun asMap(): Map<String, Any> {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
override fun save() {
|
||||||
|
|
||||||
interface FileConfig {
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Serializable
|
interface FileConfig : Config {
|
||||||
abstract class FileConfigImpl internal constructor() : ConfigSectionImpl(), FileConfig {
|
fun deserialize(content: String): ConfigSectionImpl
|
||||||
|
|
||||||
}
|
fun serialize(config: ConfigSectionImpl): String
|
||||||
|
}
|
||||||
@Serializable
|
|
||||||
class JsonConfig internal constructor() : FileConfigImpl() {
|
|
||||||
|
abstract class FileConfigImpl internal constructor(
|
||||||
companion object {
|
private val file: File
|
||||||
@UnstableDefault
|
) : FileConfig, ConfigSection {
|
||||||
fun load(file: File): Config {
|
|
||||||
require(file.extension.toLowerCase() == "json")
|
private val content by lazy {
|
||||||
val content = file.apply {
|
deserialize(file.readText())
|
||||||
if (!this.exists()) this.createNewFile()
|
}
|
||||||
}.readText()
|
|
||||||
|
override fun save() {
|
||||||
if (content.isEmpty() || content.isBlank()) {
|
if (!file.exists()) {
|
||||||
return JsonConfig()
|
file.createNewFile()
|
||||||
}
|
}
|
||||||
return Json.parse(
|
file.writeText(serialize(content))
|
||||||
JsonConfig.serializer(),
|
}
|
||||||
content
|
|
||||||
)
|
override fun get(key: String): Any? {
|
||||||
}
|
return content[key]
|
||||||
|
}
|
||||||
@UnstableDefault
|
|
||||||
fun save(file: File, config: JsonConfig) {
|
override fun set(key: String, value: Any) {
|
||||||
require(file.extension.toLowerCase() == "json")
|
content[key] = value
|
||||||
val content = Json.stringify(
|
}
|
||||||
JsonConfig.serializer(),
|
|
||||||
config
|
override fun asMap(): Map<String, Any> {
|
||||||
)
|
return content
|
||||||
file.apply {
|
}
|
||||||
if (!this.exists()) this.createNewFile()
|
|
||||||
}.writeText(content)
|
}
|
||||||
}
|
|
||||||
|
class JsonConfig internal constructor(file: File) : FileConfigImpl(file) {
|
||||||
|
@UnstableDefault
|
||||||
|
override fun deserialize(content: String): ConfigSectionImpl {
|
||||||
|
if (content.isEmpty() || content.isBlank() || content == "{}") {
|
||||||
|
return ConfigSectionImpl()
|
||||||
|
}
|
||||||
|
return Json.parse(
|
||||||
|
ConfigSectionImpl.serializer(),
|
||||||
|
content
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@UnstableDefault
|
||||||
|
override fun serialize(config: ConfigSectionImpl): String {
|
||||||
|
if (config.isEmpty()) {
|
||||||
|
return "{}"
|
||||||
|
}
|
||||||
|
return Json.stringify(ConfigSectionImpl.serializer(), config)
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user