refactor(使用配置加载模块而非硬编码在主类中): 配置加载模块
This commit is contained in:
parent
37eeaf143c
commit
988ed191ec
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ object GlobalManager {
|
|||
}
|
||||
|
||||
fun initApplication() {
|
||||
|
||||
moduleManager.loadConfig()
|
||||
}
|
||||
|
||||
// NapCat 客户端
|
||||
|
|
|
|||
|
|
@ -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!!
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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!!
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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!!
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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!!
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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!!
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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!!
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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!!
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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<Module>? = emptyList()
|
||||
) {
|
||||
data class Module(
|
||||
var name: String = "default",
|
||||
var type: ModuleType = ModuleType.HELP_MODULE,
|
||||
var enabled: Boolean = true,
|
||||
var dependencies: List<Dependency> = emptyList(),
|
||||
var config: Map<String, Any> = 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 <reified T> typedList(paramName: String): List<T> {
|
||||
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 <T> list(paramName: String): List<T> = get<List<T>>(paramName)
|
||||
|
||||
// 特定类型的 Map 方法
|
||||
fun <K, V> map(paramName: String): Map<K, V> = get<Map<K, V>>(paramName)
|
||||
|
||||
// 泛型 List 获取(返回 List<Any>)
|
||||
fun anyList(paramName: String): List<Any> = get<List<Any>>(paramName)
|
||||
|
||||
// 泛型 Map 获取(返回 Map<String, Any>)
|
||||
fun anyMap(paramName: String): Map<String, Any> = get<Map<String, Any>>(paramName)
|
||||
|
||||
// String List 的便捷方法
|
||||
fun stringList(paramName: String): List<String> {
|
||||
val list = anyList(paramName)
|
||||
return list.map { it.toString() }
|
||||
}
|
||||
|
||||
// Int List 的便捷方法
|
||||
fun intList(paramName: String): List<Int> {
|
||||
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<Int>",
|
||||
"元素类型: ${value::class.simpleName}"
|
||||
)
|
||||
else -> throw ConfigError(
|
||||
ConfigError.Type.NOT_EXPECTED_VALUE,
|
||||
name,
|
||||
paramName,
|
||||
"List<Int>",
|
||||
"元素类型: ${value::class.simpleName}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取特定类型的 Map
|
||||
inline fun <reified V> typedMap(paramName: String): Map<String, V> {
|
||||
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 <reified T> 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<T>(value, paramName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 特定类型方法(向后兼容)
|
||||
fun long(paramName: String): Long = get<Long>(paramName)
|
||||
fun int(paramName: String): Int = get<Int>(paramName)
|
||||
fun string(paramName: String): String = get<String>(paramName)
|
||||
fun boolean(paramName: String): Boolean = get<Boolean>(paramName)
|
||||
fun double(paramName: String): Double = get<Double>(paramName)
|
||||
fun float(paramName: String): Float = get<Float>(paramName)
|
||||
|
||||
// 可选值方法
|
||||
inline fun <reified T> 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 <reified T> getOrDefault(paramName: String, defaultValue: T): T =
|
||||
getOrNull<T>(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<Long>(value, paramName)
|
||||
}
|
||||
else -> throw typeMismatchError<Long>(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<Int>(value, paramName)
|
||||
}
|
||||
else -> throw typeMismatchError<Int>(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<Boolean>(value, paramName)
|
||||
}
|
||||
is Number -> value.toInt() != 0
|
||||
else -> throw typeMismatchError<Boolean>(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<Double>(value, paramName)
|
||||
}
|
||||
else -> throw typeMismatchError<Double>(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<Float>(value, paramName)
|
||||
}
|
||||
else -> throw typeMismatchError<Float>(value, paramName)
|
||||
}
|
||||
|
||||
// 错误处理辅助方法
|
||||
private inline fun <reified T> 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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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!!
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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!!
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
package top.r3944realms.ltdmanager.core.init
|
||||
|
||||
class DependencyResolver() {
|
||||
}
|
||||
|
|
@ -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<Dependency> = emptyList(),
|
||||
val config: Map<String, Any> = 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 <reified T> 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<T>(value, paramName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 特定类型方法(向后兼容)
|
||||
fun long(paramName: String): Long = get<Long>(paramName)
|
||||
fun int(paramName: String): Int = get<Int>(paramName)
|
||||
fun string(paramName: String): String = get<String>(paramName)
|
||||
fun boolean(paramName: String): Boolean = get<Boolean>(paramName)
|
||||
fun double(paramName: String): Double = get<Double>(paramName)
|
||||
fun float(paramName: String): Float = get<Float>(paramName)
|
||||
|
||||
// 可选值方法
|
||||
inline fun <reified T> 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 <reified T> getOrDefault(paramName: String, defaultValue: T): T =
|
||||
getOrNull<T>(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<Long>(value, paramName)
|
||||
}
|
||||
else -> throw typeMismatchError<Long>(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<Int>(value, paramName)
|
||||
}
|
||||
else -> throw typeMismatchError<Int>(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<Boolean>(value, paramName)
|
||||
}
|
||||
is Number -> value.toInt() != 0
|
||||
else -> throw typeMismatchError<Boolean>(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<Double>(value, paramName)
|
||||
}
|
||||
else -> throw typeMismatchError<Double>(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<Float>(value, paramName)
|
||||
}
|
||||
else -> throw typeMismatchError<Float>(value, paramName)
|
||||
}
|
||||
|
||||
// 错误处理辅助方法
|
||||
private inline fun <reified T> 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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
package top.r3944realms.ltdmanager.core.init
|
||||
|
||||
import top.r3944realms.ltdmanager.module.BaseModule
|
||||
|
||||
object ModuleRegistry {
|
||||
private val registry: MutableMap<String, BaseModule> = mutableMapOf()
|
||||
|
||||
fun register(baseModule: BaseModule) {
|
||||
registry.putIfAbsent(baseModule.name, baseModule)
|
||||
}
|
||||
|
||||
fun get(moduleName: String): BaseModule? {
|
||||
return registry[moduleName]
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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<Long>("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<Long>("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<Set<String>, 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
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<String, BaseModule>()
|
||||
|
||||
private var hasLoaded = false
|
||||
fun getModules(): Map<String, BaseModule> {
|
||||
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<BaseModule>()
|
||||
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<BaseModule>) {
|
||||
fun register(moduleList: List<BaseModule>) {
|
||||
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) }
|
||||
}
|
||||
/**
|
||||
* 关闭所有模块
|
||||
|
|
|
|||
2
src/main/resources/module.yaml
Normal file
2
src/main/resources/module.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
module:
|
||||
modules:
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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 小时
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user