Commit 108183da authored by jiahua.liu's avatar jiahua.liu

demo plugin and read-only config

parent 971d7e18
...@@ -17,8 +17,11 @@ import com.moandjiezana.toml.Toml ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 {
internal var file: File? = null
constructor(file: File) : this(file.readText()) {
this.file = file
}
private val content by lazy { private val content by lazy {
deserialize(file.readText()) 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,12 +425,17 @@ abstract class FileConfigImpl internal constructor( ...@@ -384,12 +425,17 @@ 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")
}
if (!((file?.exists())!!)) {
file?.createNewFile()
} }
file.writeText(serialize(content)) 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( ...@@ -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( ...@@ -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) { ...@@ -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()
......
...@@ -17,6 +17,7 @@ import net.mamoe.mirai.utils.MiraiLogger ...@@ -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 { ...@@ -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 { ...@@ -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
}
} }
......
...@@ -12,17 +12,17 @@ package net.mamoe.mirai.imageplugin ...@@ -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() { ...@@ -60,7 +60,6 @@ class ImageSenderMain : PluginBase() {
reply(e.message ?: "unknown error") reply(e.message ?: "unknown error")
} }
} }
} }
} }
} }
...@@ -84,16 +83,21 @@ class ImageSenderMain : PluginBase() { ...@@ -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() {
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment