From 988ed191ec63a424e819043951c333806f913225 Mon Sep 17 00:00:00 2001 From: 3944Realms Date: Sat, 7 Feb 2026 19:29:07 +0800 Subject: [PATCH] =?UTF-8?q?refactor(=E4=BD=BF=E7=94=A8=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E6=A8=A1=E5=9D=97=E8=80=8C=E9=9D=9E=E7=A1=AC?= =?UTF-8?q?=E7=BC=96=E7=A0=81=E5=9C=A8=E4=B8=BB=E7=B1=BB=E4=B8=AD):=20?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=8A=A0=E8=BD=BD=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle.properties | 2 +- .../r3944realms/ltdmanager/GlobalManager.kt | 2 +- .../core/config/BlessingSkinServerConfig.kt | 2 +- .../ltdmanager/core/config/DatabaseConfig.kt | 2 +- .../ltdmanager/core/config/DgLabConfig.kt | 2 +- .../ltdmanager/core/config/HttpConfig.kt | 2 +- .../ltdmanager/core/config/ImgTuConfig.kt | 2 +- .../ltdmanager/core/config/MailConfig.kt | 2 +- .../ltdmanager/core/config/McsmConfig.kt | 2 +- .../ltdmanager/core/config/ModuleConfig.kt | 246 +++++++++++++++ .../ltdmanager/core/config/ToolConfig.kt | 2 +- .../ltdmanager/core/config/WebsocketConfig.kt | 2 +- .../core/config/YamlConfigLoader.kt | 74 +++-- .../core/init/DependencyResolver.kt | 4 - .../ltdmanager/core/init/ModuleConfig.kt | 149 --------- .../ltdmanager/core/init/ModuleFactory.kt | 32 -- .../ltdmanager/core/init/ModuleLoader.kt | 10 - .../ltdmanager/core/init/ModuleRegistry.kt | 15 - .../kotlin/top/r3944realms/ltdmanager/main.kt | 283 +++++++++--------- .../module/GroupRequestHandlerModule.kt | 2 +- .../ltdmanager/module/ModuleFactory.kt | 193 ++++++++++++ .../ltdmanager/module/ModuleManager.kt | 43 ++- src/main/resources/module.yaml | 2 + .../ltdmanagertest/help/helpTest.kt | 12 +- .../ltdmanagertest/mail/MailTest.kt | 4 +- .../r394realms/ltdmanagertest/mod/ModTest.kt | 9 +- .../top/r394realms/ltdmanagertest/test.kt | 5 +- 27 files changed, 690 insertions(+), 415 deletions(-) create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/core/config/ModuleConfig.kt delete mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/core/init/DependencyResolver.kt delete mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleConfig.kt delete mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleFactory.kt delete mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleLoader.kt delete mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleRegistry.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/module/ModuleFactory.kt create mode 100644 src/main/resources/module.yaml diff --git a/gradle.properties b/gradle.properties index 9ae7e09..733ecee 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,5 +3,5 @@ org.gradle.downloadSources=false org.gradle.parallel=true org.gradle.degree_of_parallelism=16 project_group=top.r3944realms.ltdmanager -project_version=1.14-SNAPSHOT +project_version=1.15-SNAPSHOT dg_lab_version=4.4.14.18 diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/GlobalManager.kt b/src/main/kotlin/top/r3944realms/ltdmanager/GlobalManager.kt index 73e9a19..23d571e 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/GlobalManager.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/GlobalManager.kt @@ -22,7 +22,7 @@ object GlobalManager { } fun initApplication() { - + moduleManager.loadConfig() } // NapCat 客户端 diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/BlessingSkinServerConfig.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/BlessingSkinServerConfig.kt index 3fba758..93935c9 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/BlessingSkinServerConfig.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/BlessingSkinServerConfig.kt @@ -38,7 +38,7 @@ data class BlessingSkinServerConfig( try { encryptedToken = "ENC(${CryptoUtil.encrypt(encryptedToken!!)})" YamlUpdater.updateYaml( - YamlConfigLoader.configFilePath.toString(), + YamlConfigLoader.appConfigFilePath.toString(), "blessing-skin-server.invitation-api.encrypted-token", encryptedToken!! ) diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/DatabaseConfig.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/DatabaseConfig.kt index f42d0f0..f4302a7 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/DatabaseConfig.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/DatabaseConfig.kt @@ -37,7 +37,7 @@ data class DatabaseConfig( try { encryptedPassword = "ENC(${CryptoUtil.encrypt(encryptedPassword!!)})" YamlUpdater.updateYaml( - YamlConfigLoader.configFilePath.toString(), + YamlConfigLoader.appConfigFilePath.toString(), "database.encrypted-password", this.encryptedPassword!! ) diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/DgLabConfig.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/DgLabConfig.kt index add2ff5..7bebb90 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/DgLabConfig.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/DgLabConfig.kt @@ -38,7 +38,7 @@ data class DgLabConfig( try { encryptedLocalServerSslPassword = "ENC(${CryptoUtil.encrypt(encryptedLocalServerSslPassword!!)})" YamlUpdater.updateYaml( - YamlConfigLoader.configFilePath.toString(), + YamlConfigLoader.appConfigFilePath.toString(), "dg-lab.ws-server.encrypted-local-server-ssl-password", encryptedLocalServerSslPassword!! ) diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/HttpConfig.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/HttpConfig.kt index 7da0152..da0fd2a 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/HttpConfig.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/HttpConfig.kt @@ -36,7 +36,7 @@ data class HttpConfig( try { encryptedToken = "ENC(${CryptoUtil.encrypt(encryptedToken!!)})" YamlUpdater.updateYaml( - YamlConfigLoader.configFilePath.toString(), + YamlConfigLoader.appConfigFilePath.toString(), "http.encrypted-token", this.encryptedToken!! ) diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/ImgTuConfig.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/ImgTuConfig.kt index 0b72651..c548df2 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/ImgTuConfig.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/ImgTuConfig.kt @@ -36,7 +36,7 @@ data class ImgTuConfig( try { encryptedPassword = "ENC(${CryptoUtil.encrypt(encryptedPassword!!)})" YamlUpdater.updateYaml( - YamlConfigLoader.configFilePath.toString(), + YamlConfigLoader.appConfigFilePath.toString(), "img-tu.encrypted-password", this.encryptedPassword!! ) diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/MailConfig.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/MailConfig.kt index ac43b10..789f26f 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/MailConfig.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/MailConfig.kt @@ -34,7 +34,7 @@ data class MailConfig( try { encryptedPassword = "ENC(${CryptoUtil.encrypt(encryptedPassword!!)})" YamlUpdater.updateYaml( - YamlConfigLoader.configFilePath.toString(), + YamlConfigLoader.appConfigFilePath.toString(), "mail.encrypted-password", this.encryptedPassword!! ) diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/McsmConfig.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/McsmConfig.kt index b79df43..e576910 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/McsmConfig.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/McsmConfig.kt @@ -30,7 +30,7 @@ data class McsmConfig( try { encryptedApiKey = "ENC(${CryptoUtil.encrypt(encryptedApiKey!!)})" YamlUpdater.updateYaml( - YamlConfigLoader.configFilePath.toString(), + YamlConfigLoader.appConfigFilePath.toString(), "mcsm.encrypted-api-key", this.encryptedApiKey!! ) diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/ModuleConfig.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/ModuleConfig.kt new file mode 100644 index 0000000..a330a49 --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/ModuleConfig.kt @@ -0,0 +1,246 @@ +package top.r3944realms.ltdmanager.core.config + +import top.r3944realms.ltdmanager.module.Modules +import top.r3944realms.ltdmanager.module.exception.ConfigError + +data class ModuleConfig( + var modules: List? = emptyList() +) { + data class Module( + var name: String = "default", + var type: ModuleType = ModuleType.HELP_MODULE, + var enabled: Boolean = true, + var dependencies: List = emptyList(), + var config: Map = emptyMap() + ) { + data class Dependency( + var name: String, + var type: ModuleType + ) { + private val dependencyName: String = "${type.modName}-$name" + + fun getDepName() :String = dependencyName + + } + + fun findDependency(type: ModuleType): Dependency? { + return dependencies.find { it.type == type } + } + inline fun typedList(paramName: String): List { + val list = anyList(paramName) + return list.map { element -> + when (T::class) { + String::class -> element.toString() as T + Int::class -> convertToInt(element, "$paramName.list.element") as T + Long::class -> convertToLong(element, "$paramName.list.element") as T + Boolean::class -> convertToBoolean(element, "$paramName.list.element") as T + else -> { + if (element is T) element + else throw ConfigError( + ConfigError.Type.NOT_EXPECTED_VALUE, + name, + "$paramName.list", + T::class.simpleName ?: T::class.java.simpleName, + element::class.simpleName ?: element::class.java.simpleName + ) + } + } + } + } + // 特定类型的 List 方法 + fun list(paramName: String): List = get>(paramName) + + // 特定类型的 Map 方法 + fun map(paramName: String): Map = get>(paramName) + + // 泛型 List 获取(返回 List) + fun anyList(paramName: String): List = get>(paramName) + + // 泛型 Map 获取(返回 Map) + fun anyMap(paramName: String): Map = get>(paramName) + + // String List 的便捷方法 + fun stringList(paramName: String): List { + val list = anyList(paramName) + return list.map { it.toString() } + } + + // Int List 的便捷方法 + fun intList(paramName: String): List { + val list = anyList(paramName) + return list.map { value -> + when (value) { + is Int -> value + is Number -> value.toInt() + is String -> value.toIntOrNull() + ?: throw ConfigError( + ConfigError.Type.NOT_EXPECTED_VALUE, + name, + paramName, + "List", + "元素类型: ${value::class.simpleName}" + ) + else -> throw ConfigError( + ConfigError.Type.NOT_EXPECTED_VALUE, + name, + paramName, + "List", + "元素类型: ${value::class.simpleName}" + ) + } + } + } + + // 获取特定类型的 Map + inline fun typedMap(paramName: String): Map { + val map = anyMap(paramName) + return map.mapValues { (key, value) -> + when (V::class) { + String::class -> value.toString() as V + Int::class -> convertToInt(value, "$paramName.$key") as V + Long::class -> convertToLong(value, "$paramName.$key") as V + Boolean::class -> convertToBoolean(value, "$paramName.$key") as V + else -> { + if (value is V) value + else throw ConfigError( + ConfigError.Type.NOT_EXPECTED_VALUE, + name, + "$paramName.$key", + V::class.simpleName ?: V::class.java.simpleName, + value::class.simpleName ?: value::class.java.simpleName + ) + } + } + } + } + + enum class ModuleType(val modName: String) { + GROUP_MESSAGE_POLLING_MODULE(Modules.GROUP_MESSAGE_POLLING), + GROUP_REQUEST_HANDLER_MODULE(Modules.GROUP_REQUEST_HANDLER), + MAIL_MODULE(Modules.MAIL), + BAN_MODULE(Modules.BAN), + DG_LAB_MODULE(Modules.DG_LAB), + INVITE_MODULE(Modules.INVITATION_CODE), + MC_SERVER_STATUS_MODULE(Modules.MC_SERVER_STATUS), + MOD_GROUP_HANDLER_MODULE(Modules.MOD_GROUP_HANDLER), + RCON_PLAYER_LIST_MODULE(Modules.RCON_PLAYER_LIST), + STATE_MODULE(Modules.STATE), + HELP_MODULE(Modules.HELP),; + } + // 基础获取方法 + fun value(paramName: String): Any = + config[paramName] ?: throw ConfigError( + ConfigError.Type.MISSING_PARAMETER, + name, + paramName + ) + + // 泛型获取方法 + private inline fun get(paramName: String): T { + val value = value(paramName) + return when (T::class) { + Long::class -> convertToLong(value, paramName) as T + Int::class -> convertToInt(value, paramName) as T + String::class -> value.toString() as T + Boolean::class -> convertToBoolean(value, paramName) as T + Double::class -> convertToDouble(value, paramName) as T + Float::class -> convertToFloat(value, paramName) as T + else -> { + if (value is T) value + else throw typeMismatchError(value, paramName) + } + } + } + + // 特定类型方法(向后兼容) + fun long(paramName: String): Long = get(paramName) + fun int(paramName: String): Int = get(paramName) + fun string(paramName: String): String = get(paramName) + fun boolean(paramName: String): Boolean = get(paramName) + fun double(paramName: String): Double = get(paramName) + fun float(paramName: String): Float = get(paramName) + + // 可选值方法 + inline fun getOrNull(paramName: String): T? = + config[paramName] as? T ?: run { + val value = config[paramName] + if (value == null) null + else if (value is T) value + else null + } + + inline fun getOrDefault(paramName: String, defaultValue: T): T = + getOrNull(paramName) ?: defaultValue + + // 类型转换辅助方法 + fun convertToLong(value: Any, paramName: String): Long = when (value) { + is Long -> value + is Number -> value.toLong() + is String -> try { + value.toLong() + } catch (e: NumberFormatException) { + throw typeMismatchError(value, paramName) + } + else -> throw typeMismatchError(value, paramName) + } + + fun convertToInt(value: Any, paramName: String): Int = when (value) { + is Int -> value + is Number -> value.toInt() + is String -> try { + value.toInt() + } catch (e: NumberFormatException) { + throw typeMismatchError(value, paramName) + } + else -> throw typeMismatchError(value, paramName) + } + + fun convertToBoolean(value: Any, paramName: String): Boolean = when (value) { + is Boolean -> value + is String -> when (value.lowercase()) { + "true", "yes", "1" -> true + "false", "no", "0" -> false + else -> throw typeMismatchError(value, paramName) + } + is Number -> value.toInt() != 0 + else -> throw typeMismatchError(value, paramName) + } + + private fun convertToDouble(value: Any, paramName: String): Double = when (value) { + is Double -> value + is Number -> value.toDouble() + is String -> try { + value.toDouble() + } catch (e: NumberFormatException) { + throw typeMismatchError(value, paramName) + } + else -> throw typeMismatchError(value, paramName) + } + + private fun convertToFloat(value: Any, paramName: String): Float = when (value) { + is Float -> value + is Number -> value.toFloat() + is String -> try { + value.toFloat() + } catch (e: NumberFormatException) { + throw typeMismatchError(value, paramName) + } + else -> throw typeMismatchError(value, paramName) + } + + // 错误处理辅助方法 + private inline fun typeMismatchError( + actualValue: Any, + paramName: String + ): Nothing { + throw ConfigError( + ConfigError.Type.NOT_EXPECTED_VALUE, + paramName, + T::class.simpleName ?: T::class.java.simpleName, + actualValue::class.simpleName ?: actualValue::class.java.simpleName + ) + } + } +} + + diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/ToolConfig.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/ToolConfig.kt index 2bbb5dc..7cf77e7 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/ToolConfig.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/ToolConfig.kt @@ -38,7 +38,7 @@ data class ToolConfig( try { rconPassword = "ENC(${CryptoUtil.encrypt(rconPassword!!)})" YamlUpdater.updateYaml( - YamlConfigLoader.configFilePath.toString(), + YamlConfigLoader.appConfigFilePath.toString(), "tools.rcon.rcon-password", rconPassword!! ) diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/WebsocketConfig.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/WebsocketConfig.kt index 00224d2..c02e032 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/WebsocketConfig.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/WebsocketConfig.kt @@ -36,7 +36,7 @@ data class WebsocketConfig( try { encryptedToken = "ENC(${CryptoUtil.encrypt(encryptedToken!!)})" YamlUpdater.updateYaml( - YamlConfigLoader.configFilePath.toString(), + YamlConfigLoader.appConfigFilePath.toString(), "websocket.encrypted-token", this.encryptedToken!! ) diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/YamlConfigLoader.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/YamlConfigLoader.kt index f764df4..b52a276 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/YamlConfigLoader.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/YamlConfigLoader.kt @@ -8,26 +8,30 @@ import org.yaml.snakeyaml.introspector.PropertyUtils import top.r3944realms.ltdmanager.utils.ConfigInitializer import top.r3944realms.ltdmanager.utils.NamingConventionUtil import java.nio.file.Files +import java.nio.file.Path import java.nio.file.Paths object YamlConfigLoader { - val configFilePath = Paths.get("config/application.yaml") // 配置文件路径 - private val _config by lazy { loadConfig() } // 延迟初始化 - val config: ConfigWrapper get() = _config + val appConfigFilePath: Path = Paths.get("config/application.yaml") // 配置文件路径 + val moduleConfigFilePath: Path = Paths.get("config/module.yaml") // 配置文件路径 + private val _app_config by lazy { loadAppConfigWrapper() } // 延迟初始化 + val appConfig: AppConfigWrapper get() = _app_config + private val _module_config by lazy { loadModuleConfigWrapper() } // 延迟初始化 + val moduleConfig: ModuleConfigWrapper get() = _module_config init { // 第一次启动确保配置文件存在 + ConfigInitializer.initConfig("module.yaml", "config", false) ConfigInitializer.initConfig("application.yaml", "config") - // 初始化后加密(确保只执行一次) runCatching { - ensureConfigEncrypted(_config) + ensureConfigEncrypted(_app_config) }.onFailure { e -> println("初始化加密失败: ${e.message}") e.printStackTrace() } } - private fun ensureConfigEncrypted(config: ConfigWrapper?) { + private fun ensureConfigEncrypted(config: AppConfigWrapper?) { config?.database?.encryptPassword() config?.websocket?.encryptToken() config?.http?.encryptToken() @@ -38,15 +42,15 @@ object YamlConfigLoader { config?.dgLab?.wsServer?.encryptPassword() config?.imgTu?.encryptPassword() } - private fun loadConfig(): ConfigWrapper { - if (!Files.exists(configFilePath)) { - throw RuntimeException("配置文件未找到: $configFilePath") + private fun loadAppConfigWrapper(): AppConfigWrapper { + if (!Files.exists(appConfigFilePath)) { + throw RuntimeException("应用配置文件未找到: $appConfigFilePath") } try { - val yamlContent = Files.readString(configFilePath) + val yamlContent = Files.readString(appConfigFilePath) - return Yaml(getConstructor()).load(yamlContent) + return Yaml(getConstructor(AppConfigWrapper::class.java)).load(yamlContent) ?: throw RuntimeException("YAML解析返回null") } catch (e: Exception) { @@ -54,7 +58,23 @@ object YamlConfigLoader { } } - private fun getConstructor(): Constructor { + private fun loadModuleConfigWrapper(): ModuleConfigWrapper { + if (!Files.exists(moduleConfigFilePath)) { + throw RuntimeException("模块配置文件未找到: $moduleConfigFilePath") + } + + try { + val yamlContent = Files.readString(moduleConfigFilePath) + + return Yaml(getConstructor(ModuleConfigWrapper::class.java)).load(yamlContent) + ?: throw RuntimeException("YAML解析返回null") + + } catch (e: Exception) { + throw RuntimeException("YAML解析失败: ${e.message}", e) + } + + } + private fun getConstructor(clazz: Class<*>): Constructor { val propertyUtils = object : PropertyUtils() { override fun getProperty(type: Class<*>, name: String): Property { val processedName = if (name.contains("-")) { @@ -66,23 +86,24 @@ object YamlConfigLoader { } } - return Constructor(ConfigWrapper::class.java, LoaderOptions()).apply { + return Constructor(clazz, LoaderOptions()).apply { setPropertyUtils(propertyUtils) } } - fun loadDatabaseConfig(): DatabaseConfig = config.database - fun loadCryptoConfig(): CryptoConfig = config.crypto - fun loadMcsmConfig(): McsmConfig = config.mcsm - fun loadWebsocketConfig(): WebsocketConfig = config.websocket - fun loadHttpConfig(): HttpConfig = config.http - fun loadModeConfig(): ModeConfig = config.mode - fun loadToolConfig(): ToolConfig = config.tools - fun loadMailConfig(): MailConfig = config.mail - fun loadBlessingSkinServerConfig(): BlessingSkinServerConfig = config.blessingSkinServer - fun loadDgLabConfig(): DgLabConfig = config.dgLab - fun loadTuImgConfig(): ImgTuConfig = config.imgTu - data class ConfigWrapper( + fun loadDatabaseConfig(): DatabaseConfig = appConfig.database + fun loadCryptoConfig(): CryptoConfig = appConfig.crypto + fun loadMcsmConfig(): McsmConfig = appConfig.mcsm + fun loadWebsocketConfig(): WebsocketConfig = appConfig.websocket + fun loadHttpConfig(): HttpConfig = appConfig.http + fun loadModeConfig(): ModeConfig = appConfig.mode + fun loadToolConfig(): ToolConfig = appConfig.tools + fun loadMailConfig(): MailConfig = appConfig.mail + fun loadBlessingSkinServerConfig(): BlessingSkinServerConfig = appConfig.blessingSkinServer + fun loadDgLabConfig(): DgLabConfig = appConfig.dgLab + fun loadTuImgConfig(): ImgTuConfig = appConfig.imgTu + fun loadModuleConfig(): ModuleConfig = moduleConfig.module + data class AppConfigWrapper( var database: DatabaseConfig = DatabaseConfig(), var crypto: CryptoConfig = CryptoConfig(), var mode: ModeConfig = ModeConfig(), @@ -94,6 +115,9 @@ object YamlConfigLoader { var blessingSkinServer: BlessingSkinServerConfig = BlessingSkinServerConfig(), var dgLab: DgLabConfig = DgLabConfig(), var imgTu: ImgTuConfig = ImgTuConfig(), + ) + data class ModuleConfigWrapper( + var module: ModuleConfig = ModuleConfig(), ) } \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/init/DependencyResolver.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/init/DependencyResolver.kt deleted file mode 100644 index 1f2cd7b..0000000 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/init/DependencyResolver.kt +++ /dev/null @@ -1,4 +0,0 @@ -package top.r3944realms.ltdmanager.core.init - -class DependencyResolver() { -} \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleConfig.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleConfig.kt deleted file mode 100644 index 1004da4..0000000 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleConfig.kt +++ /dev/null @@ -1,149 +0,0 @@ -package top.r3944realms.ltdmanager.core.init - -import top.r3944realms.ltdmanager.module.Modules -import top.r3944realms.ltdmanager.module.exception.ConfigError - -data class ModuleConfig( - val name: String, - val type: ModuleType, - val enabled: Boolean, - val dependencies: List = emptyList(), - val config: Map = emptyMap() -) { - data class Dependency( - private val name: String, - val type: ModuleType, - val required: Boolean = true - ) { - private val dependencyName: String = "${type.modName}-$name" - - fun getDepName() :String = dependencyName - - } - enum class ModuleType(val modName: String) { - GROUP_MESSAGE_POLLING_MODULE(Modules.GROUP_MESSAGE_POLLING), - GROUP_REQUEST_HANDLER_MODULE(Modules.GROUP_REQUEST_HANDLER), - MAIL_MODULE(Modules.MAIL), - BAN_MODULE(Modules.BAN), - DG_LAB_MODULE(Modules.DG_LAB), - INVITE_MODULE(Modules.INVITATION_CODE), - MC_SERVER_STATUS_MODULE(Modules.MC_SERVER_STATUS), - MOD_GROUP_HANDLER_MODULE(Modules.MOD_GROUP_HANDLER), - RCON_PLAYER_LIST_MODULE(Modules.RCON_PLAYER_LIST), - STATE_MODULE(Modules.STATE), - HELP_MODULE(Modules.HELP),; - } - // 基础获取方法 - fun value(paramName: String): Any = - config[paramName] ?: throw ConfigError( - ConfigError.Type.MISSING_PARAMETER, - name, - paramName - ) - - // 泛型获取方法 - private inline fun get(paramName: String): T { - val value = value(paramName) - return when (T::class) { - Long::class -> convertToLong(value, paramName) as T - Int::class -> convertToInt(value, paramName) as T - String::class -> value.toString() as T - Boolean::class -> convertToBoolean(value, paramName) as T - Double::class -> convertToDouble(value, paramName) as T - Float::class -> convertToFloat(value, paramName) as T - else -> { - if (value is T) value - else throw typeMismatchError(value, paramName) - } - } - } - - // 特定类型方法(向后兼容) - fun long(paramName: String): Long = get(paramName) - fun int(paramName: String): Int = get(paramName) - fun string(paramName: String): String = get(paramName) - fun boolean(paramName: String): Boolean = get(paramName) - fun double(paramName: String): Double = get(paramName) - fun float(paramName: String): Float = get(paramName) - - // 可选值方法 - inline fun getOrNull(paramName: String): T? = - config[paramName] as? T ?: run { - val value = config[paramName] - if (value == null) null - else if (value is T) value - else null - } - - inline fun getOrDefault(paramName: String, defaultValue: T): T = - getOrNull(paramName) ?: defaultValue - - // 类型转换辅助方法 - private fun convertToLong(value: Any, paramName: String): Long = when (value) { - is Long -> value - is Number -> value.toLong() - is String -> try { - value.toLong() - } catch (e: NumberFormatException) { - throw typeMismatchError(value, paramName) - } - else -> throw typeMismatchError(value, paramName) - } - - private fun convertToInt(value: Any, paramName: String): Int = when (value) { - is Int -> value - is Number -> value.toInt() - is String -> try { - value.toInt() - } catch (e: NumberFormatException) { - throw typeMismatchError(value, paramName) - } - else -> throw typeMismatchError(value, paramName) - } - - private fun convertToBoolean(value: Any, paramName: String): Boolean = when (value) { - is Boolean -> value - is String -> when (value.lowercase()) { - "true", "yes", "1" -> true - "false", "no", "0" -> false - else -> throw typeMismatchError(value, paramName) - } - is Number -> value.toInt() != 0 - else -> throw typeMismatchError(value, paramName) - } - - private fun convertToDouble(value: Any, paramName: String): Double = when (value) { - is Double -> value - is Number -> value.toDouble() - is String -> try { - value.toDouble() - } catch (e: NumberFormatException) { - throw typeMismatchError(value, paramName) - } - else -> throw typeMismatchError(value, paramName) - } - - private fun convertToFloat(value: Any, paramName: String): Float = when (value) { - is Float -> value - is Number -> value.toFloat() - is String -> try { - value.toFloat() - } catch (e: NumberFormatException) { - throw typeMismatchError(value, paramName) - } - else -> throw typeMismatchError(value, paramName) - } - - // 错误处理辅助方法 - private inline fun typeMismatchError( - actualValue: Any, - paramName: String - ): Nothing { - throw ConfigError( - ConfigError.Type.NOT_EXPECTED_VALUE, - name, - T::class.simpleName ?: T::class.java.simpleName, - actualValue::class.simpleName ?: actualValue::class.java.simpleName - ) - } -} diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleFactory.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleFactory.kt deleted file mode 100644 index fdc8264..0000000 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleFactory.kt +++ /dev/null @@ -1,32 +0,0 @@ -package top.r3944realms.ltdmanager.core.init - -import top.r3944realms.ltdmanager.GlobalManager -import top.r3944realms.ltdmanager.core.init.ModuleConfig.ModuleType.* -import top.r3944realms.ltdmanager.module.BaseModule -import top.r3944realms.ltdmanager.module.GroupRequestHandlerModule - -object ModuleFactory { - fun createModule(config: ModuleConfig): BaseModule { - return when(config.type) { - GROUP_MESSAGE_POLLING_MODULE -> TODO() - GROUP_REQUEST_HANDLER_MODULE -> createGroupRequestHandler(config) - MAIL_MODULE -> TODO() - BAN_MODULE -> TODO() - DG_LAB_MODULE -> TODO() - INVITE_MODULE -> TODO() - MC_SERVER_STATUS_MODULE -> TODO() - RCON_PLAYER_LIST_MODULE -> TODO() - STATE_MODULE -> TODO() - MOD_GROUP_HANDLER_MODULE -> TODO() - HELP_MODULE -> TODO() - } - } - private fun createGroupRequestHandler(config: ModuleConfig): GroupRequestHandlerModule { - val targetGroupId = config.long("targetGroupId") - val pollIntervalMillis = config.getOrDefault("pollIntervalMillis", 30_000L) - return GroupRequestHandlerModule( - config.name, GlobalManager.napCatClient, - targetGroupId, pollIntervalMillis - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleLoader.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleLoader.kt deleted file mode 100644 index a6f5cad..0000000 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleLoader.kt +++ /dev/null @@ -1,10 +0,0 @@ -package top.r3944realms.ltdmanager.core.init - -import java.nio.file.Paths - -object ModuleLoader { - val configFilePath = Paths.get("config/modules.yaml") - init { - - } -} \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleRegistry.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleRegistry.kt deleted file mode 100644 index 8aae51b..0000000 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/init/ModuleRegistry.kt +++ /dev/null @@ -1,15 +0,0 @@ -package top.r3944realms.ltdmanager.core.init - -import top.r3944realms.ltdmanager.module.BaseModule - -object ModuleRegistry { - private val registry: MutableMap = mutableMapOf() - - fun register(baseModule: BaseModule) { - registry.putIfAbsent(baseModule.name, baseModule) - } - - fun get(moduleName: String): BaseModule? { - return registry[moduleName] - } -} \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/main.kt b/src/main/kotlin/top/r3944realms/ltdmanager/main.kt index 6b319a4..246fe12 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/main.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/main.kt @@ -5,160 +5,161 @@ import top.r3944realms.ltdmanager.module.* // DSL fun main() = GlobalManager.runBlockingMain { - val commonGroupId:Long = 538751386 - val whitelistGroupId:Long = 920719236 - val selfQQId = 3327379836 - val selfNickName = "闲趣老土豆" - // 创建模块实例 - val groupModule = GroupRequestHandlerModule( - moduleName = "WhiteListGroup", - client = GlobalManager.napCatClient, - targetGroupId = whitelistGroupId - ) - val commonGroupMsgPollingModule = GroupMessagePollingModule( - moduleName = "CommonGroupMsgPolling", - targetGroupId = commonGroupId, - pollIntervalMillis = 5_000L, - msgHistoryCheck = 15 - ) - val whiteListGroupMsgPollingModule = GroupMessagePollingModule( - moduleName = "WhiteListGroup", - targetGroupId = whitelistGroupId, - pollIntervalMillis = 5_000L, - msgHistoryCheck = 15 - ) - val commonHelpModule = HelpModule( - moduleName = "CommonGroup", - keywords = listOf("help", "帮助"), - groupMessagePollingModule = commonGroupMsgPollingModule, - selfId = selfQQId, - selfNickName = selfNickName, - ) - val whitelistHelpModule = HelpModule( - moduleName = "WhiteListGroup", - keywords = listOf("help", "帮助"), - groupMessagePollingModule = whiteListGroupMsgPollingModule, - selfId = selfQQId, - selfNickName = selfNickName, - ) - val toolConfig = YamlConfigLoader.loadToolConfig() - val corconModule = RconPlayerListModule( - moduleName = "CommonGroup", - groupMessagePollingModule = commonGroupMsgPollingModule, - rconTimeOut = 2_000L, - cooldownMillis = 10_000L, - selfId = selfQQId, - selfNickName = selfNickName, - rconPath = toolConfig.rcon.mcRconToolPath.toString(), - rconConfigPath = toolConfig.rcon.mcRconToolConfigPath.toString(), - keywords = setOf( - //形容 - "土豆", "马铃薯", "Potato", "potato", "POTATO", - "Potatoes", "potatoes", "POTATOES", "🥔", - //正经 - "列表","服务器状态", "TPS", "tps", "list", "List" - ) - ) - val rconModule = RconPlayerListModule( - moduleName = "WhiteListGroup", - groupMessagePollingModule = whiteListGroupMsgPollingModule, - rconTimeOut = 2_000L, - cooldownMillis = 10_000L, - selfId = selfQQId, - selfNickName = selfNickName, - rconPath = toolConfig.rcon.mcRconToolPath.toString(), - rconConfigPath = toolConfig.rcon.mcRconToolConfigPath.toString(), - keywords = setOf( - //形容 - "土豆", "马铃薯", "Potato", "potato", "POTATO", - "Potatoes", "potatoes", "POTATOES", "🥔", - //正经 - "列表","服务器状态", "TPS", "tps", "list", "List" - ) - ) -// val mailConfig = YamlConfigLoader.loadMailConfig() -// val mailModule = MailModule( + GlobalManager.initApplication() +// val commonGroupId:Long = 538751386 +// val whitelistGroupId:Long = 920719236 +// val selfQQId = 3327379836 +// val selfNickName = "闲趣老土豆" +// // 创建模块实例 +// val groupModule = GroupRequestHandlerModule( // moduleName = "WhiteListGroup", -// host = mailConfig.host.toString(), -// authToken = mailConfig.decryptedPassword.toString(), -// port = mailConfig.port!!, -// senderEmailAddress = mailConfig.mailAddress!!, +// client = GlobalManager.napCatClient, +// targetGroupId = whitelistGroupId // ) -// val blessingSkinConfig = YamlConfigLoader.loadBlessingSkinServerConfig() -// val invitationCodesModule = InvitationCodesModule( +// val commonGroupMsgPollingModule = GroupMessagePollingModule( +// moduleName = "CommonGroupMsgPolling", +// targetGroupId = commonGroupId, +// pollIntervalMillis = 5_000L, +// msgHistoryCheck = 15 +// ) +// val whiteListGroupMsgPollingModule = GroupMessagePollingModule( // moduleName = "WhiteListGroup", -// groupMessagePollingModule = commonGroupMsgPollingModule, -// mailModule = mailModule, -// apiToken = blessingSkinConfig.invitationApi?.decryptedToken!!, -// selfId = selfQQId, -// keywords = setOf( -// "申请皮肤站注册邀请码", -// "申请土豆服务器注册邀请码", -// "申请LTD邀请码", -// "Apply for an invitation code" -// ) +// targetGroupId = whitelistGroupId, +// pollIntervalMillis = 5_000L, +// msgHistoryCheck = 15 // ) -// val commonMcServerStatusModule = McServerStatusModule( +// val commonHelpModule = HelpModule( // moduleName = "CommonGroup", +// keywords = listOf("help", "帮助"), // groupMessagePollingModule = commonGroupMsgPollingModule, // selfId = selfQQId, -// cooldownMillis = 20_000L, // selfNickName = selfNickName, -// commands = listOf("/m", "/mcs", "seek", "s", "test"), -// presetServer = mapOf( -// setOf("老土豆", "七周目", "7" ,"ZZ", "zz", "Zz", "seven") to "main.mmccdd.top:11106", -// setOf("土豆", "八周目", "8" ,"39", "eight") to "ac.r3944realms.top" -// ) // ) -// val whitelistMcServerStatusModule = McServerStatusModule( +// val whitelistHelpModule = HelpModule( // moduleName = "WhiteListGroup", +// keywords = listOf("help", "帮助"), // groupMessagePollingModule = whiteListGroupMsgPollingModule, // selfId = selfQQId, -// cooldownMillis = 20_000L, // selfNickName = selfNickName, -// commands = listOf("/m", "/mcs", "seek", "s", "test"), -// presetServer = mapOf( -// setOf("老土豆", "七周目", "7" ,"ZZ", "zz", "Zz", "seven") to "main.mmccdd.top:11106", -// setOf("土豆", "八周目", "8" ,"39", "eight") to "ac.r3944realms.top" +// ) +// val toolConfig = YamlConfigLoader.loadToolConfig() +// val corconModule = RconPlayerListModule( +// moduleName = "CommonGroup", +// groupMessagePollingModule = commonGroupMsgPollingModule, +// rconTimeOut = 2_000L, +// cooldownMillis = 10_000L, +// selfId = selfQQId, +// selfNickName = selfNickName, +// rconPath = toolConfig.rcon.mcRconToolPath.toString(), +// rconConfigPath = toolConfig.rcon.mcRconToolConfigPath.toString(), +// keywords = setOf( +// //形容 +// "土豆", "马铃薯", "Potato", "potato", "POTATO", +// "Potatoes", "potatoes", "POTATOES", "🥔", +// //正经 +// "列表","服务器状态", "TPS", "tps", "list", "List" // ) // ) - val dgLabModule = DGLabModule( - moduleName = "DG", - groupMessagePollingModule = commonGroupMsgPollingModule, - selfId = selfQQId, - adminIds = listOf(2561098830L), - commandHead = listOf("dglab") - ) - - // 注册模块到全局模块管理器 - GlobalManager.moduleManager.registerModule(groupModule) - GlobalManager.moduleManager.registerModule(commonGroupMsgPollingModule) - GlobalManager.moduleManager.registerModule(whiteListGroupMsgPollingModule) -// GlobalManager.moduleManager.registerModule(commonMcServerStatusModule) - GlobalManager.moduleManager.registerModule(rconModule) - GlobalManager.moduleManager.registerModule(corconModule) -// GlobalManager.moduleManager.registerModule(whitelistMcServerStatusModule) -// GlobalManager.moduleManager.registerModule(mailModule) -// GlobalManager.moduleManager.registerModule(invitationCodesModule) - GlobalManager.moduleManager.registerModule(whitelistHelpModule) - GlobalManager.moduleManager.registerModule(commonHelpModule) - GlobalManager.moduleManager.registerModule(dgLabModule) -// GlobalManager.moduleManager.registerModule(banModule) -// GlobalManager.moduleManager.registerModule(modGroupHandlerModule) - - // 加载模块 - GlobalManager.moduleManager.loadModule(groupModule.name) - GlobalManager.moduleManager.loadModule(commonGroupMsgPollingModule.name) - GlobalManager.moduleManager.loadModule(whiteListGroupMsgPollingModule.name) -// GlobalManager.moduleManager.loadModule(commonMcServerStatusModule.name) - GlobalManager.moduleManager.loadModule(corconModule.name) - GlobalManager.moduleManager.loadModule(rconModule.name) -// GlobalManager.moduleManager.loadModule(mailModule.name) -// GlobalManager.moduleManager.loadModule(invitationCodesModule.name) - GlobalManager.moduleManager.loadModule(commonHelpModule.name) -// GlobalManager.moduleManager.loadModule(whitelistMcServerStatusModule.name) - GlobalManager.moduleManager.loadModule(whitelistHelpModule.name) - GlobalManager.moduleManager.loadModule(dgLabModule.name) -// GlobalManager.moduleManager.loadModule(banModule.name) -// GlobalManager.moduleManager.loadModule(modGroupHandlerModule.name) +// val rconModule = RconPlayerListModule( +// moduleName = "WhiteListGroup", +// groupMessagePollingModule = whiteListGroupMsgPollingModule, +// rconTimeOut = 2_000L, +// cooldownMillis = 10_000L, +// selfId = selfQQId, +// selfNickName = selfNickName, +// rconPath = toolConfig.rcon.mcRconToolPath.toString(), +// rconConfigPath = toolConfig.rcon.mcRconToolConfigPath.toString(), +// keywords = setOf( +// //形容 +// "土豆", "马铃薯", "Potato", "potato", "POTATO", +// "Potatoes", "potatoes", "POTATOES", "🥔", +// //正经 +// "列表","服务器状态", "TPS", "tps", "list", "List" +// ) +// ) +//// val mailConfig = YamlConfigLoader.loadMailConfig() +//// val mailModule = MailModule( +//// moduleName = "WhiteListGroup", +//// host = mailConfig.host.toString(), +//// authToken = mailConfig.decryptedPassword.toString(), +//// port = mailConfig.port!!, +//// senderEmailAddress = mailConfig.mailAddress!!, +//// ) +//// val blessingSkinConfig = YamlConfigLoader.loadBlessingSkinServerConfig() +//// val invitationCodesModule = InvitationCodesModule( +//// moduleName = "WhiteListGroup", +//// groupMessagePollingModule = commonGroupMsgPollingModule, +//// mailModule = mailModule, +//// apiToken = blessingSkinConfig.invitationApi?.decryptedToken!!, +//// selfId = selfQQId, +//// keywords = setOf( +//// "申请皮肤站注册邀请码", +//// "申请土豆服务器注册邀请码", +//// "申请LTD邀请码", +//// "Apply for an invitation code" +//// ) +//// ) +//// val commonMcServerStatusModule = McServerStatusModule( +//// moduleName = "CommonGroup", +//// groupMessagePollingModule = commonGroupMsgPollingModule, +//// selfId = selfQQId, +//// cooldownMillis = 20_000L, +//// selfNickName = selfNickName, +//// commands = listOf("/m", "/mcs", "seek", "s", "test"), +//// presetServer = mapOf( +//// setOf("老土豆", "七周目", "7" ,"ZZ", "zz", "Zz", "seven") to "main.mmccdd.top:11106", +//// setOf("土豆", "八周目", "8" ,"39", "eight") to "ac.r3944realms.top" +//// ) +//// ) +//// val whitelistMcServerStatusModule = McServerStatusModule( +//// moduleName = "WhiteListGroup", +//// groupMessagePollingModule = whiteListGroupMsgPollingModule, +//// selfId = selfQQId, +//// cooldownMillis = 20_000L, +//// selfNickName = selfNickName, +//// commands = listOf("/m", "/mcs", "seek", "s", "test"), +//// presetServer = mapOf( +//// setOf("老土豆", "七周目", "7" ,"ZZ", "zz", "Zz", "seven") to "main.mmccdd.top:11106", +//// setOf("土豆", "八周目", "8" ,"39", "eight") to "ac.r3944realms.top" +//// ) +//// ) +// val dgLabModule = DGLabModule( +// moduleName = "DG", +// groupMessagePollingModule = commonGroupMsgPollingModule, +// selfId = selfQQId, +// adminIds = listOf(2561098830L), +// commandHead = listOf("dglab") +// ) +// +// // 注册模块到全局模块管理器 +// GlobalManager.moduleManager.register(groupModule) +// GlobalManager.moduleManager.register(commonGroupMsgPollingModule) +// GlobalManager.moduleManager.register(whiteListGroupMsgPollingModule) +//// GlobalManager.moduleManager.registerModule(commonMcServerStatusModule) +// GlobalManager.moduleManager.register(rconModule) +// GlobalManager.moduleManager.register(corconModule) +//// GlobalManager.moduleManager.registerModule(whitelistMcServerStatusModule) +//// GlobalManager.moduleManager.registerModule(mailModule) +//// GlobalManager.moduleManager.registerModule(invitationCodesModule) +// GlobalManager.moduleManager.register(whitelistHelpModule) +// GlobalManager.moduleManager.register(commonHelpModule) +// GlobalManager.moduleManager.register(dgLabModule) +//// GlobalManager.moduleManager.registerModule(banModule) +//// GlobalManager.moduleManager.registerModule(modGroupHandlerModule) +// +// // 加载模块 +// GlobalManager.moduleManager.load(groupModule.name) +// GlobalManager.moduleManager.load(commonGroupMsgPollingModule.name) +// GlobalManager.moduleManager.load(whiteListGroupMsgPollingModule.name) +//// GlobalManager.moduleManager.loadModule(commonMcServerStatusModule.name) +// GlobalManager.moduleManager.load(corconModule.name) +// GlobalManager.moduleManager.load(rconModule.name) +//// GlobalManager.moduleManager.loadModule(mailModule.name) +//// GlobalManager.moduleManager.loadModule(invitationCodesModule.name) +// GlobalManager.moduleManager.load(commonHelpModule.name) +//// GlobalManager.moduleManager.loadModule(whitelistMcServerStatusModule.name) +// GlobalManager.moduleManager.load(whitelistHelpModule.name) +// GlobalManager.moduleManager.load(dgLabModule.name) +//// GlobalManager.moduleManager.loadModule(banModule.name) +//// GlobalManager.moduleManager.loadModule(modGroupHandlerModule.name) } \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/module/GroupRequestHandlerModule.kt b/src/main/kotlin/top/r3944realms/ltdmanager/module/GroupRequestHandlerModule.kt index b0c8282..b65ae7f 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/module/GroupRequestHandlerModule.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/module/GroupRequestHandlerModule.kt @@ -137,7 +137,7 @@ class GroupRequestHandlerModule( try { getConnection().use { conn -> val stmt = conn.prepareStatement( - "SELECT status FROM minecraft_manager_ltd_8.players WHERE qq=?" + "SELECT status FROM minecraft_manager_ltd_9.players WHERE qq=?" ) stmt.setLong(1, actor) val rs = stmt.executeQuery() diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/module/ModuleFactory.kt b/src/main/kotlin/top/r3944realms/ltdmanager/module/ModuleFactory.kt new file mode 100644 index 0000000..ad3d113 --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/module/ModuleFactory.kt @@ -0,0 +1,193 @@ +package top.r3944realms.ltdmanager.module + +import top.r3944realms.ltdmanager.GlobalManager +import top.r3944realms.ltdmanager.core.config.ModuleConfig +import top.r3944realms.ltdmanager.core.config.ModuleConfig.Module.ModuleType.* +import top.r3944realms.ltdmanager.core.config.YamlConfigLoader +import top.r3944realms.ltdmanager.module.exception.ConfigError + +object ModuleFactory { + fun createModule(config: ModuleConfig.Module): BaseModule { + return when(config.type) { + GROUP_MESSAGE_POLLING_MODULE -> createGroupMessagePolling(config) + GROUP_REQUEST_HANDLER_MODULE -> createGroupRequestHandler(config) + MAIL_MODULE -> createMail(config) + BAN_MODULE -> createBan(config) + DG_LAB_MODULE -> createDgLab(config) + INVITE_MODULE -> createInvite(config) + MC_SERVER_STATUS_MODULE -> createMcServerStatus(config) + RCON_PLAYER_LIST_MODULE -> createRconPlayerList(config) + STATE_MODULE -> createState(config) + MOD_GROUP_HANDLER_MODULE -> createModGroupHandler(config) + HELP_MODULE -> createHelpModule(config) + } + } + private fun resolveDependency(dep: ModuleConfig.Module.Dependency?, name: String): BaseModule? { + if (dep != null) { + return GlobalManager.moduleManager.getModule(dep.getDepName()) + } else throw ConfigError (ConfigError.Type.MISSING_PARAMETER, "dependency", name) + } + private fun createGroupMessagePolling(config: ModuleConfig.Module): GroupMessagePollingModule { + val targetGroupId = config.long("target-group-id") + val pollIntervalMillis = config.getOrDefault("poll-interval-millis", 5_000L) + val msgHistoryCheck = config.getOrDefault("msg-history-check", 15) + return GroupMessagePollingModule( + config.name, targetGroupId, + pollIntervalMillis, msgHistoryCheck, + ) + } + private fun createGroupRequestHandler(config: ModuleConfig.Module): GroupRequestHandlerModule { + val targetGroupId = config.long("target-group-id") + val pollIntervalMillis = config.getOrDefault("poll-interval-millis", 30_000L) + return GroupRequestHandlerModule( + config.name, GlobalManager.napCatClient, + targetGroupId, pollIntervalMillis + ) + } + + private fun createMail(config: ModuleConfig.Module): MailModule { + val mailConfig = YamlConfigLoader.loadMailConfig() + return MailModule( + moduleName = config.name, + host = mailConfig.host.toString(), + authToken = mailConfig.decryptedPassword.toString(), + port = mailConfig.port!!, + senderEmailAddress = mailConfig.mailAddress!! + ) + } + + private fun createBan(config: ModuleConfig.Module): BanModule { + val selfId = config.long("self-id") + val adminIds = config.list("admin-ids") + val muteCommandPrefixList = config.stringList("mute-command-prefix-list") + val unmuteCommandPrefixList = config.stringList("unmute-command-prefix-list") + val groupMessagePollingModule = resolveDependency(config.findDependency(GROUP_MESSAGE_POLLING_MODULE), "groupMessagePolling") as GroupMessagePollingModule + val minBanMinutes = config.int("min-ban-minutes") + val maxBanMinutes = config.int("max-ban-minutes") + val factorX: Int = config.int("factor-x") + return BanModule( + config.name, + groupMessagePollingModule, + selfId, + adminIds, + muteCommandPrefixList, + unmuteCommandPrefixList, + minBanMinutes, + maxBanMinutes, + factorX + ) + } + + private fun createDgLab(config: ModuleConfig.Module): DGLabModule { + val selfId = config.long("self-id") + val adminIds = config.list("admin-ids") + val maxClientNumber = config.int("max-client-number") + val commandHead = config.stringList("command-head") + val groupMessagePollingModule = resolveDependency(config.findDependency(GROUP_MESSAGE_POLLING_MODULE), "groupMessagePolling") as GroupMessagePollingModule + return DGLabModule( + config.name, + groupMessagePollingModule, + selfId, + adminIds, + maxClientNumber, + commandHead + ) + } + + private fun createInvite(config: ModuleConfig.Module): InvitationCodesModule { + val selfId = config.long("self-id") + val groupMessagePollingModule = resolveDependency(config.findDependency(GROUP_MESSAGE_POLLING_MODULE), "groupMessagePolling") as GroupMessagePollingModule + val mailModule = resolveDependency(config.findDependency(MAIL_MODULE), "mailModule") as MailModule + val blessingSkinConfig = YamlConfigLoader.loadBlessingSkinServerConfig() + val cooldownMillis = config.getOrDefault("cooldown-millis", 120_000L) + val keywords = config.stringList("keywords") + return InvitationCodesModule( + config.name, + groupMessagePollingModule, + mailModule, + blessingSkinConfig.invitationApi?.decryptedToken!!, + selfId, + cooldownMillis, + keywords.toSet() + ) + } + + private fun createMcServerStatus(config: ModuleConfig.Module): McServerStatusModule { + val selfId = config.long("self-id") + val cooldownMillis = config.getOrDefault("cooldown-millis", 60_000L) + val groupMessagePollingModule = resolveDependency(config.findDependency(GROUP_MESSAGE_POLLING_MODULE), "groupMessagePolling") as GroupMessagePollingModule + val commands = config.stringList("commands") + val selfNickName = config.string("self-nick-name") + val preset = config.map, String>("preset-server") + return McServerStatusModule( + config.name, + groupMessagePollingModule, + selfId, + selfNickName, + cooldownMillis, + commands, + preset + ) + } + + private fun createRconPlayerList(config: ModuleConfig.Module): RconPlayerListModule { + val toolConfig = YamlConfigLoader.loadToolConfig() + val selfId = config.long("self-id") + val cooldownMillis = config.getOrDefault("cooldown-millis", 10_000L) + val rconTimeout = config.getOrDefault("rcon-timeout-millis", 2_000L) + val groupMessagePollingModule = resolveDependency(config.findDependency(GROUP_MESSAGE_POLLING_MODULE), "groupMessagePolling") as GroupMessagePollingModule + val selfNickName = config.string("self-nick-name") + val keywords = config.stringList("keywords") + return RconPlayerListModule( + config.name, + groupMessagePollingModule, + rconTimeout, + cooldownMillis, + selfId, + selfNickName, + toolConfig.rcon.mcRconToolPath.toString(), + toolConfig.rcon.mcRconToolConfigPath.toString(), + keywords.toSet() + ) + } + + private fun createState(config: ModuleConfig.Module): StateModule { + val onlineName = config.string("online-name") + val offlineName = config.string("offline-name") + return StateModule( + config.name, + onlineName, + offlineName + ) + } + + private fun createModGroupHandler(config: ModuleConfig.Module): ModGroupHandlerModule { + val targetGroupId = config.long("target-group-id") + val answers = config.stringList("answers") + val pollingMillis = config.getOrDefault("poll-interval-millis", 30_000L) + return ModGroupHandlerModule( + config.name, + targetGroupId, + answers, + pollingMillis + ) + } + + private fun createHelpModule(config: ModuleConfig.Module): HelpModule { + val selfId = config.long("self-id") + val cooldownMillis = config.getOrDefault("cooldown-millis", 10_000L) + config.getOrDefault("rcon-timeout-millis", 2_000L) + val groupMessagePollingModule = resolveDependency(config.findDependency(GROUP_MESSAGE_POLLING_MODULE), "groupMessagePolling") as GroupMessagePollingModule + val selfNickName = config.string("self-nick-name") + val keywords = config.stringList("keywords") + return HelpModule( + config.name, + groupMessagePollingModule, + selfId, + selfNickName, + keywords, + cooldownMillis + ) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/module/ModuleManager.kt b/src/main/kotlin/top/r3944realms/ltdmanager/module/ModuleManager.kt index 79a3e8b..5e9fb94 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/module/ModuleManager.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/module/ModuleManager.kt @@ -1,18 +1,43 @@ package top.r3944realms.ltdmanager.module +import top.r3944realms.ltdmanager.core.config.YamlConfigLoader import top.r3944realms.ltdmanager.utils.LoggerUtil +import java.util.* class ModuleManager { - private val modules = mutableMapOf() - + private var hasLoaded = false fun getModules(): Map { return (modules).toMap() } + fun getModule(name: String): BaseModule? { + return modules[name] + } + fun loadConfig() { + if (!hasLoaded) { + hasLoaded = true + val moduleConfig = YamlConfigLoader.loadModuleConfig() + moduleConfig.modules.let { + val enableBaseModules = LinkedList() + if (it != null) { + for (mod in it) { + val module = ModuleFactory.createModule(mod) + register(module) + if (mod.enabled) { + enableBaseModules.add(module) + } + } + } + for (module in enableBaseModules) { + load(module.name) + } + } + } + } /** * 注册模块到管理器 */ - fun registerModule(module: BaseModule) { + fun register(module: BaseModule) { if (modules.containsKey(module.name)) { LoggerUtil.logger.warn("模块已注册: ${module.name}") return @@ -23,16 +48,16 @@ class ModuleManager { /** * 注册多模块到管理器 */ - fun registerModules(moduleList: List) { + fun register(moduleList: List) { for (module in moduleList) { - registerModule(module) + register(module) } } /** * 加载指定模块 */ - fun loadModule(name: String) { + fun load(name: String) { val module = modules[name] if (module == null) { LoggerUtil.logger.warn("尝试加载不存在的模块: $name") @@ -52,7 +77,7 @@ class ModuleManager { /** * 卸载指定模块 */ - suspend fun unloadModule(name: String) { + suspend fun unload(name: String) { val module = modules[name] if (module == null) { LoggerUtil.logger.warn("尝试卸载不存在的模块: $name") @@ -107,14 +132,14 @@ class ModuleManager { * 扩展方法:批量加载模块 */ fun ModuleManager.loadModules(vararg names: String) { - names.forEach { loadModule(it) } + names.forEach { load(it) } } /** * 扩展方法:批量卸载模块 */ suspend fun ModuleManager.unloadModules(vararg names: String) { - names.forEach { unloadModule(it) } + names.forEach { unload(it) } } /** * 关闭所有模块 diff --git a/src/main/resources/module.yaml b/src/main/resources/module.yaml new file mode 100644 index 0000000..59b3e7b --- /dev/null +++ b/src/main/resources/module.yaml @@ -0,0 +1,2 @@ +module: + modules: \ No newline at end of file diff --git a/src/test/kotlin/top/r394realms/ltdmanagertest/help/helpTest.kt b/src/test/kotlin/top/r394realms/ltdmanagertest/help/helpTest.kt index 22e14bc..88c9b3b 100644 --- a/src/test/kotlin/top/r394realms/ltdmanagertest/help/helpTest.kt +++ b/src/test/kotlin/top/r394realms/ltdmanagertest/help/helpTest.kt @@ -29,11 +29,11 @@ fun main() = GlobalManager.runBlockingMain { adminIds = listOf(2561098830L), commandHead = listOf("dglab") ) - GlobalManager.moduleManager.registerModule(groupMsgPollingModule) - GlobalManager.moduleManager.registerModule(helpModule) - GlobalManager.moduleManager.registerModule(dgLabModule) + GlobalManager.moduleManager.register(groupMsgPollingModule) + GlobalManager.moduleManager.register(helpModule) + GlobalManager.moduleManager.register(dgLabModule) - GlobalManager.moduleManager.loadModule(groupMsgPollingModule.name) - GlobalManager.moduleManager.loadModule(helpModule.name) - GlobalManager.moduleManager.loadModule(dgLabModule.name) + GlobalManager.moduleManager.load(groupMsgPollingModule.name) + GlobalManager.moduleManager.load(helpModule.name) + GlobalManager.moduleManager.load(dgLabModule.name) } \ No newline at end of file diff --git a/src/test/kotlin/top/r394realms/ltdmanagertest/mail/MailTest.kt b/src/test/kotlin/top/r394realms/ltdmanagertest/mail/MailTest.kt index 944f670..3976694 100644 --- a/src/test/kotlin/top/r394realms/ltdmanagertest/mail/MailTest.kt +++ b/src/test/kotlin/top/r394realms/ltdmanagertest/mail/MailTest.kt @@ -22,9 +22,9 @@ fun main() = GlobalManager.runBlockingMain { } } if (mailModule == null) throw IllegalStateException("Lost Required Argument") - GlobalManager.moduleManager.registerModule(mailModule) + GlobalManager.moduleManager.register(mailModule) - GlobalManager.moduleManager.loadModule(mailModule.name) + GlobalManager.moduleManager.load(mailModule.name) val template = object {}.javaClass.classLoader .getResource("mail-body.html")?: throw IllegalArgumentException("模板文件未找到") val expireHours = 24 // 有效期 24 小时 diff --git a/src/test/kotlin/top/r394realms/ltdmanagertest/mod/ModTest.kt b/src/test/kotlin/top/r394realms/ltdmanagertest/mod/ModTest.kt index 2534075..99c3827 100644 --- a/src/test/kotlin/top/r394realms/ltdmanagertest/mod/ModTest.kt +++ b/src/test/kotlin/top/r394realms/ltdmanagertest/mod/ModTest.kt @@ -1,12 +1,7 @@ package top.r394realms.ltdmanagertest.mod -import kotlinx.coroutines.delay import top.r3944realms.ltdmanager.GlobalManager -import top.r3944realms.ltdmanager.GlobalManager.napCatClient import top.r3944realms.ltdmanager.module.ModGroupHandlerModule -import top.r3944realms.ltdmanager.napcat.data.ID -import top.r3944realms.ltdmanager.napcat.data.MessageType -import top.r3944realms.ltdmanager.napcat.request.message.SendForwardMsgRequest fun main() = GlobalManager.runBlockingMain { @@ -23,8 +18,8 @@ fun main() = GlobalManager.runBlockingMain { // 注册模块到全局模块管理器 - GlobalManager.moduleManager.registerModule(modGroupHandlerModule) + GlobalManager.moduleManager.register(modGroupHandlerModule) // 加载模块 - GlobalManager.moduleManager.loadModule(modGroupHandlerModule.name) + GlobalManager.moduleManager.load(modGroupHandlerModule.name) } diff --git a/src/test/kotlin/top/r394realms/ltdmanagertest/test.kt b/src/test/kotlin/top/r394realms/ltdmanagertest/test.kt index 663ce29..47bd5fa 100644 --- a/src/test/kotlin/top/r394realms/ltdmanagertest/test.kt +++ b/src/test/kotlin/top/r394realms/ltdmanagertest/test.kt @@ -1,7 +1,6 @@ package top.r394realms.ltdmanagertest import top.r3944realms.ltdmanager.GlobalManager -import top.r3944realms.ltdmanager.module.GroupRequestHandlerModule import top.r3944realms.ltdmanager.module.StateModule @@ -15,8 +14,8 @@ fun main() = GlobalManager.runBlockingMain { // 注册模块到全局模块管理器 - GlobalManager.moduleManager.registerModule(stateModule) + GlobalManager.moduleManager.register(stateModule) // 加载模块 - GlobalManager.moduleManager.loadModule(stateModule.name) + GlobalManager.moduleManager.load(stateModule.name) } \ No newline at end of file