feat: Groovy 脚本解析引擎,脚本与配置一同管理,提交时支持上传 script 字段

This commit is contained in:
mediabot-pt
2026-07-01 10:24:41 +08:00
parent 1dd600c713
commit 70b1aeda3f
10 changed files with 175 additions and 10 deletions

View File

@@ -25,6 +25,7 @@ import java.util.stream.Collectors;
public class AdapterController {
private final AdapterEngine adapterEngine;
private final GroovyScriptEngine groovyEngine;
private final SiteConfigMapper siteConfigMapper;
private final AccessResultMapper accessResultMapper;
private final CachedStorageService storageService;
@@ -137,14 +138,24 @@ public class AdapterController {
item.put("invalidCount", allResults.stream().filter(r -> url.equals(r.getUrl()) && Boolean.FALSE.equals(r.getIsValid())).count());
item.put("uncheckedCount", allResults.stream().filter(r -> url.equals(r.getUrl()) && r.getIsValid() == null).count());
// 解析内容
// 解析内容:优先 Groovy 脚本,否则用 Java 引擎
try {
String content = storageService.read(ar.getStoragePath());
if (content != null) {
Map<String, Object> parsed = adapterEngine.extract(adapterConfig, content, ar.getContentType(), url);
Map<String, Object> parsed;
if (siteConfig.getScriptStoragePath() != null && !siteConfig.getScriptStoragePath().isBlank()) {
String script = storageService.read(siteConfig.getScriptStoragePath());
if (script != null && !script.isBlank()) {
parsed = groovyEngine.execute(script, content, url);
} else {
parsed = adapterEngine.extract(adapterConfig, content, ar.getContentType(), url);
}
} else {
parsed = adapterEngine.extract(adapterConfig, content, ar.getContentType(), url);
}
item.put("parsed", parsed);
} else {
item.put("parsed", Map.of("matched", false, "message", "内容为空,可能已从存储中删除"));
item.put("parsed", Map.of("matched", false, "message", "内容为空"));
}
} catch (Exception e) {
item.put("parsed", Map.of("matched", false, "message", "解析异常: " + e.getMessage()));

View File

@@ -100,6 +100,16 @@ public class AdminController {
config.setStoragePath(approvedPath);
}
// Groovy 脚本也移到 approved
if (config.getScriptStoragePath() != null && !config.getScriptStoragePath().isBlank()) {
String approvedScriptPath = config.getScriptStoragePath().replace("/pending/", "/approved/");
String script = storageService.read(config.getScriptStoragePath());
if (script != null) {
storageService.store(approvedScriptPath, script);
config.setScriptStoragePath(approvedScriptPath);
}
}
config.setStatus(ConfigStatus.APPROVED);
config.setReviewerId(reviewerId);
config.setReviewedAt(LocalDateTime.now());

View File

@@ -129,6 +129,7 @@ public class ConfigController {
String version = (String) payload.get("version");
String configJson = (String) payload.get("config");
String schemaVersion = (String) payload.get("schemaVersion");
String groovyScript = (String) payload.get("script");
if (version == null || configJson == null) {
return ApiResponse.error(400, "version and config are required");
@@ -136,7 +137,7 @@ public class ConfigController {
Long submitterId = (Long) request.getAttribute("accountId");
SiteConfig config = configService.submitConfig(siteId, version, configJson, schemaVersion, submitterId);
SiteConfig config = configService.submitConfig(siteId, version, configJson, schemaVersion, groovyScript, submitterId);
return ApiResponse.success(configService.toDTO(config));
}
}