diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 089cf0c..408c5ed 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -5,6 +5,7 @@
diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml
new file mode 100644
index 0000000..648a2a0
--- /dev/null
+++ b/.idea/sqldialects.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 3cde3b0..cb70f11 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.22.2
+project_version=1.22.3
dg_lab_version=4.4.14.19
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 8a8ef33..e1c447c 100644
--- a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/YamlConfigLoader.kt
+++ b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/YamlConfigLoader.kt
@@ -24,6 +24,7 @@ object YamlConfigLoader {
init {
ConfigInitializer.initConfig("module.yaml", "config", false)
ConfigInitializer.initConfig("application.yaml", "config")
+ ConfigInitializer.initSqlTemplates()
runCatching {
ensureConfigEncrypted(_app_config)
}.onFailure { e ->
diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/module/ModuleFactory.kt b/src/main/kotlin/top/r3944realms/ltdmanager/module/ModuleFactory.kt
index c1254af..92a60f7 100644
--- a/src/main/kotlin/top/r3944realms/ltdmanager/module/ModuleFactory.kt
+++ b/src/main/kotlin/top/r3944realms/ltdmanager/module/ModuleFactory.kt
@@ -30,10 +30,17 @@ object ModuleFactory {
UNKNOWN_MODULE -> throw ConfigError(ConfigError.Type.INVALID_PARAMETER, "unknown module")
}
}
- 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 resolveDependency(dep: ModuleConfig.Module.Dependency?, name: String): BaseModule {
+ if (dep == null) {
+ throw ConfigError(ConfigError.Type.MISSING_PARAMETER, "dependency", name)
+ }
+ val depName = dep.getDepName()
+ return GlobalManager.moduleManager.getModule(depName)
+ ?: throw ConfigError(
+ ConfigError.Type.OTHER,
+ "resolveDependency",
+ "依赖模块 '$depName' 未注册 — 请检查 name/type 是否匹配且目标模块定义在 WHITELIST_AUDIT_MODULE 之前"
+ )
}
private fun createGroupMessagePolling(config: ModuleConfig.Module): GroupMessagePollingModule {
val targetGroupId = config.long("target-group-id")
diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/utils/ConfigInitializer.kt b/src/main/kotlin/top/r3944realms/ltdmanager/utils/ConfigInitializer.kt
index 5e8ddb0..1b534fd 100644
--- a/src/main/kotlin/top/r3944realms/ltdmanager/utils/ConfigInitializer.kt
+++ b/src/main/kotlin/top/r3944realms/ltdmanager/utils/ConfigInitializer.kt
@@ -2,17 +2,21 @@ package top.r3944realms.ltdmanager.utils
import top.r3944realms.ltdmanager.core.config.YamlConfigLoader
import java.nio.file.Files
+import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.StandardCopyOption
import kotlin.system.exitProcess
object ConfigInitializer {
- /**
- * 初始化配置文件
- * @param fileName YAML 文件名,如 application.yml
- * @param configDir 配置目录,如 config
- */
+ private val SQL_TEMPLATES = listOf(
+ "sql/invitation/query_qualification.sql",
+ "sql/invitation/query_token_info.sql",
+ "sql/invitation/query_code_ids.sql",
+ "sql/invitation/upsert_ascription.sql",
+ "sql/whitelist/query_whitelist_record.sql",
+ )
+
fun initConfig(fileName: String = "application.yml", configDir: String = "config", shouldExit: Boolean = true) {
val dirPath = Paths.get(configDir)
if (!Files.exists(dirPath)) {
@@ -23,7 +27,6 @@ object ConfigInitializer {
val filePath = dirPath.resolve(fileName)
if (!Files.exists(filePath)) {
- // 从 resources 复制默认配置
val resourceStream = YamlConfigLoader::class.java.classLoader.getResourceAsStream(fileName)
if (resourceStream != null) {
Files.copy(resourceStream, filePath, StandardCopyOption.REPLACE_EXISTING)
@@ -33,9 +36,31 @@ object ConfigInitializer {
exitProcess(-1);
}
} else throw Error("Jar内部资源文件缺失")
-
} else {
LoggerUtil.logger.info("配置文件已存在: $filePath")
}
}
+
+ /** 首次启动时将 SQL 模板从 classpath 复制到 config/sql/ */
+ fun initSqlTemplates() {
+ var copied = 0
+ for (resourcePath in SQL_TEMPLATES) {
+ val target = Paths.get("config", resourcePath)
+ if (Files.exists(target)) continue
+
+ val resourceStream = YamlConfigLoader::class.java.classLoader
+ .getResourceAsStream(resourcePath)
+ if (resourceStream != null) {
+ Files.createDirectories(target.parent)
+ Files.copy(resourceStream, target)
+ resourceStream.close()
+ copied++
+ } else {
+ LoggerUtil.logger.warn("SQL 模板资源缺失: $resourcePath")
+ }
+ }
+ if (copied > 0) {
+ LoggerUtil.logger.info("已从 JAR 复制 $copied 个 SQL 模板到 config/sql/")
+ }
+ }
}
\ No newline at end of file
diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/whitelist/request/WhitelistSystemRequest.kt b/src/main/kotlin/top/r3944realms/ltdmanager/whitelist/request/WhitelistSystemRequest.kt
index 45a6f10..b3fe0e6 100644
--- a/src/main/kotlin/top/r3944realms/ltdmanager/whitelist/request/WhitelistSystemRequest.kt
+++ b/src/main/kotlin/top/r3944realms/ltdmanager/whitelist/request/WhitelistSystemRequest.kt
@@ -1,8 +1,10 @@
package top.r3944realms.ltdmanager.whitelist.request
+import io.ktor.http.HeadersBuilder
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import top.r3944realms.ltdmanager.core.client.request.IRequest
+import top.r3944realms.ltdmanager.core.config.YamlConfigLoader
import top.r3944realms.ltdmanager.whitelist.response.FailedWhitelistSystemResponse
import top.r3944realms.ltdmanager.whitelist.response.WhitelistSystemResponse
@@ -10,4 +12,14 @@ import top.r3944realms.ltdmanager.whitelist.response.WhitelistSystemResponse
abstract class WhitelistSystemRequest(
@Transient
override val createTime: Long = System.currentTimeMillis()
-) : IRequest
+) : IRequest {
+
+ /** 自动注入 X-API-TOKEN 鉴权头 */
+ override fun headers(): HeadersBuilder.() -> Unit = {
+ super.headers().invoke(this)
+ val token = YamlConfigLoader.loadWhitelistSystemConfig().decryptedToken
+ if (!token.isNullOrEmpty()) {
+ append("X-API-TOKEN", token)
+ }
+ }
+}