mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-04 00:14:36 +08:00
demo plugin and read-only config
This commit is contained in:
parent
971d7e182f
commit
108183daad
@ -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()
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user