demo plugin and read-only config

This commit is contained in:
jiahua.liu 2020-02-23 20:09:01 +08:00
parent 971d7e182f
commit 108183daad
3 changed files with 128 additions and 17 deletions

View File

@ -17,8 +17,11 @@ import com.moandjiezana.toml.Toml
import com.moandjiezana.toml.TomlWriter
import kotlinx.serialization.Serializable
import kotlinx.serialization.UnstableDefault
import net.mamoe.mirai.utils.io.encodeToString
import org.yaml.snakeyaml.Yaml
import tornadofx.c
import java.io.File
import java.io.InputStream
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import kotlin.collections.LinkedHashMap
@ -69,6 +72,9 @@ interface Config {
)
}
/**
* create a read-write config
* */
fun load(file: File): Config {
if (!file.exists()) {
file.createNewFile()
@ -86,6 +92,32 @@ interface Config {
else -> error("Unsupported file config type ${file.extension.toLowerCase()}")
}
}
/**
* create a read-only config
*/
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
*/
fun load(inputStream: InputStream, type: String): Config {
return load(inputStream.readBytes().encodeToString(), type)
}
}
}
@ -363,14 +395,23 @@ interface FileConfig : Config {
abstract class FileConfigImpl internal constructor(
private val file: File
private val rawContent: String
) : FileConfig,
ConfigSection {
private val content by lazy {
deserialize(file.readText())
internal var file: File? = null
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
@ -384,12 +425,17 @@ abstract class FileConfigImpl internal constructor(
override fun remove(key: String): Any? = content.remove(key)
override fun save() {
if (!file.exists()) {
file.createNewFile()
if (isReadOnly()) {
error("Config is readonly")
}
file.writeText(serialize(content))
if (!((file?.exists())!!)) {
file?.createNewFile()
}
file?.writeText(serialize(content))
}
fun isReadOnly() = file == null
override fun contains(key: String): Boolean {
return content.contains(key)
}
@ -409,8 +455,12 @@ abstract class FileConfigImpl internal constructor(
}
class JsonConfig internal constructor(
file: File
) : FileConfigImpl(file) {
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 == "{}") {
@ -429,7 +479,11 @@ class JsonConfig internal constructor(
}
}
class YamlConfig internal constructor(file: File) : FileConfigImpl(file) {
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()
@ -447,7 +501,11 @@ class YamlConfig internal constructor(file: File) : FileConfigImpl(file) {
}
class TomlConfig internal constructor(file: File) : FileConfigImpl(file) {
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()

View File

@ -17,6 +17,7 @@ import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.SimpleLogger
import net.mamoe.mirai.utils.io.encodeToString
import java.io.File
import java.io.InputStream
import java.net.URL
import java.net.URLClassLoader
import java.util.jar.JarFile
@ -91,6 +92,13 @@ abstract class PluginBase(coroutineContext: CoroutineContext) : CoroutineScope {
val logger: MiraiLogger by lazy {
DefaultLogger(pluginDescription.name)
}
fun getResources(fileName: String): InputStream? {
return PluginManager.getFileInJarByName(
this.pluginDescription.name,
fileName
)
}
}
class PluginDescription(
@ -325,6 +333,47 @@ object PluginManager {
it.disable(throwable)
}
}
/**
* 根据插件名字找Jar的文件
* null => 没找到
*/
fun getJarPath(pluginName: String): File? {
File(pluginsPath).listFiles()?.forEach { file ->
if (file != null && file.extension == "jar") {
val jar = JarFile(file)
val pluginYml =
jar.entries().asSequence().filter { it.name.toLowerCase().contains("plugin.yml") }.firstOrNull()
if (pluginYml != null) {
val description =
PluginDescription.readFromContent(
URL("jar:file:" + file.absoluteFile + "!/" + pluginYml.name).openConnection().inputStream.use {
it.readBytes().encodeToString()
})
if (description.name.toLowerCase() == pluginName.toLowerCase()) {
return file
}
}
}
}
return null
}
/**
* 根据插件名字找Jar resources中的文件
* null => 没找到
*/
fun getFileInJarByName(pluginName: String, toFind: String): InputStream? {
val jarFile = getJarPath(pluginName)
if (jarFile == null) {
return null
}
val jar = JarFile(jarFile)
val toFindFile =
jar.entries().asSequence().filter { it.name == toFind }.firstOrNull() ?: return null
return URL("jar:file:" + jarFile.absoluteFile + "!/" + toFindFile.name).openConnection().inputStream
}
}

View File

@ -12,17 +12,17 @@ package net.mamoe.mirai.imageplugin
import kotlinx.coroutines.*
import net.mamoe.mirai.console.plugins.Config
import net.mamoe.mirai.console.plugins.ConfigSection
import net.mamoe.mirai.console.plugins.PluginBase
import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.event.events.BotOnlineEvent
import net.mamoe.mirai.event.subscribeAlways
import net.mamoe.mirai.event.subscribeMessages
import net.mamoe.mirai.console.plugins.PluginBase
import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.uploadAsImage
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import org.jsoup.Jsoup
import java.io.File
import kotlin.random.Random
import java.net.URL
class ImageSenderMain : PluginBase() {
@ -60,7 +60,6 @@ class ImageSenderMain : PluginBase() {
reply(e.message ?: "unknown error")
}
}
}
}
}
@ -84,16 +83,21 @@ class ImageSenderMain : PluginBase() {
override fun onLoad() {
logger.info("loading local image data")
try {
images = Config.load(this.javaClass.classLoader.getResource("data.yml")!!.path!!)
images = Config.load(getResources(fileName = "data.yml")!!, "yml")
} catch (e: Exception) {
e.printStackTrace()
logger.info("无法加载本地图片")
}
logger.info("本地图片版本" + images.getString("version"))
logger.info("Normal * " + images.getList("normal").size)
logger.info("R18 * " + images.getList("R18").size)
r18 = images.getConfigSectionList("R18")
normal = images.getConfigSectionList("normal")
logger.info("Normal * " + normal.size)
logger.info("R18 * " + r18.size)
}
override fun onDisable() {
}