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 com.moandjiezana.toml.TomlWriter
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UnstableDefault import kotlinx.serialization.UnstableDefault
import net.mamoe.mirai.utils.io.encodeToString
import org.yaml.snakeyaml.Yaml import org.yaml.snakeyaml.Yaml
import tornadofx.c
import java.io.File import java.io.File
import java.io.InputStream
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import kotlin.collections.LinkedHashMap import kotlin.collections.LinkedHashMap
@ -69,6 +72,9 @@ interface Config {
) )
} }
/**
* create a read-write config
* */
fun load(file: File): Config { fun load(file: File): Config {
if (!file.exists()) { if (!file.exists()) {
file.createNewFile() file.createNewFile()
@ -86,6 +92,32 @@ interface Config {
else -> error("Unsupported file config type ${file.extension.toLowerCase()}") 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( abstract class FileConfigImpl internal constructor(
private val file: File private val rawContent: String
) : FileConfig, ) : FileConfig,
ConfigSection { ConfigSection {
private val content by lazy { internal var file: File? = null
deserialize(file.readText())
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 size: Int get() = content.size
override val entries: MutableSet<MutableMap.MutableEntry<String, Any>> get() = content.entries override val entries: MutableSet<MutableMap.MutableEntry<String, Any>> get() = content.entries
override val keys: MutableSet<String> get() = content.keys override val keys: MutableSet<String> get() = content.keys
@ -384,11 +425,16 @@ abstract class FileConfigImpl internal constructor(
override fun remove(key: String): Any? = content.remove(key) override fun remove(key: String): Any? = content.remove(key)
override fun save() { override fun save() {
if (!file.exists()) { if (isReadOnly()) {
file.createNewFile() 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 { override fun contains(key: String): Boolean {
return content.contains(key) return content.contains(key)
@ -409,8 +455,12 @@ abstract class FileConfigImpl internal constructor(
} }
class JsonConfig internal constructor( class JsonConfig internal constructor(
file: File content: String
) : FileConfigImpl(file) { ) : FileConfigImpl(content) {
constructor(file: File) : this(file.readText()) {
this.file = file
}
@UnstableDefault @UnstableDefault
override fun deserialize(content: String): ConfigSection { override fun deserialize(content: String): ConfigSection {
if (content.isEmpty() || content.isBlank() || content == "{}") { 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 { override fun deserialize(content: String): ConfigSection {
if (content.isEmpty() || content.isBlank()) { if (content.isEmpty() || content.isBlank()) {
return ConfigSectionImpl() 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 { override fun deserialize(content: String): ConfigSection {
if (content.isEmpty() || content.isBlank()) { if (content.isEmpty() || content.isBlank()) {
return ConfigSectionImpl() 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.SimpleLogger
import net.mamoe.mirai.utils.io.encodeToString import net.mamoe.mirai.utils.io.encodeToString
import java.io.File import java.io.File
import java.io.InputStream
import java.net.URL import java.net.URL
import java.net.URLClassLoader import java.net.URLClassLoader
import java.util.jar.JarFile import java.util.jar.JarFile
@ -91,6 +92,13 @@ abstract class PluginBase(coroutineContext: CoroutineContext) : CoroutineScope {
val logger: MiraiLogger by lazy { val logger: MiraiLogger by lazy {
DefaultLogger(pluginDescription.name) DefaultLogger(pluginDescription.name)
} }
fun getResources(fileName: String): InputStream? {
return PluginManager.getFileInJarByName(
this.pluginDescription.name,
fileName
)
}
} }
class PluginDescription( class PluginDescription(
@ -325,6 +333,47 @@ object PluginManager {
it.disable(throwable) 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 kotlinx.coroutines.*
import net.mamoe.mirai.console.plugins.Config import net.mamoe.mirai.console.plugins.Config
import net.mamoe.mirai.console.plugins.ConfigSection 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.events.BotOnlineEvent
import net.mamoe.mirai.event.subscribeAlways import net.mamoe.mirai.event.subscribeAlways
import net.mamoe.mirai.event.subscribeMessages 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.data.Image
import net.mamoe.mirai.message.uploadAsImage import net.mamoe.mirai.message.uploadAsImage
import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.MiraiExperimentalAPI
import org.jsoup.Jsoup import org.jsoup.Jsoup
import java.io.File import java.io.File
import kotlin.random.Random import java.net.URL
class ImageSenderMain : PluginBase() { class ImageSenderMain : PluginBase() {
@ -60,7 +60,6 @@ class ImageSenderMain : PluginBase() {
reply(e.message ?: "unknown error") reply(e.message ?: "unknown error")
} }
} }
} }
} }
} }
@ -84,16 +83,21 @@ class ImageSenderMain : PluginBase() {
override fun onLoad() { override fun onLoad() {
logger.info("loading local image data") logger.info("loading local image data")
try { try {
images = Config.load(this.javaClass.classLoader.getResource("data.yml")!!.path!!) images = Config.load(getResources(fileName = "data.yml")!!, "yml")
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace()
logger.info("无法加载本地图片") logger.info("无法加载本地图片")
} }
logger.info("本地图片版本" + images.getString("version")) logger.info("本地图片版本" + images.getString("version"))
logger.info("Normal * " + images.getList("normal").size) r18 = images.getConfigSectionList("R18")
logger.info("R18 * " + images.getList("R18").size) normal = images.getConfigSectionList("normal")
logger.info("Normal * " + normal.size)
logger.info("R18 * " + r18.size)
} }
override fun onDisable() { override fun onDisable() {
} }