package vip.mate.tool.builtin; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Server-side hard compliance scan for content bound for 公众号 / 小红书. * Model-side self-checks (skills) can be skipped or hallucinated; this is a * deterministic backstop that publish paths can enforce. * *

Four categories, roughly ordered by account risk: *

* The first three are treated as high-risk (a publish path may block on them). */ final class ComplianceScanner { private ComplianceScanner() { } /** Category name → matching pattern. Ordered by severity for stable output. */ private static final Map RULES = new LinkedHashMap<>(); /** Categories that a publish path should hard-block on. */ private static final List HIGH_RISK = List.of("广告法极限词", "微信诱导", "承诺收益/效果"); static { RULES.put("广告法极限词", Pattern.compile( "最佳|最好|最优|最强|最高级|最便宜|最先进|最顶级|第一品牌|全国第一|全球第一" + "|唯一|独家|首个|首选|冠军|领导品牌|国家级|世界级|国际级|顶级|极致" + "|100%|百分百|绝对|彻底根治|永久|包治|一劳永逸")); RULES.put("微信诱导", Pattern.compile( "集赞|助力|砍一刀|分享到朋友圈|分享后解锁|分享解锁|分享可见|转发抽奖|转发领取" + "|不转不是|关注才能看|关注才可见|关注领取|关注解锁|扫码加个人微信|加我微信领")); RULES.put("承诺收益/效果", Pattern.compile( "保本|稳赚|稳赚不赔|保收益|保底收益|包赚|躺赚|一夜暴富" + "|包过|保过|保分|名校保录|包录取|包就业|包瘦身")); RULES.put("医疗功效", Pattern.compile( "治愈|根治|抗癌|防癌|包瘦|排毒|壮阳|丰胸|生发防脱|药到病除|无副作用")); } /** One category's hits. */ record CategoryHit(String category, List terms, boolean highRisk) {} /** Full scan result. */ record Result(List hits) { boolean clean() { return hits.isEmpty(); } boolean hasHighRisk() { return hits.stream().anyMatch(CategoryHit::highRisk); } } /** Scan text for policy violations across all categories. */ static Result scan(String text) { List hits = new ArrayList<>(); if (text == null || text.isBlank()) { return new Result(hits); } for (Map.Entry rule : RULES.entrySet()) { List terms = new ArrayList<>(); Matcher m = rule.getValue().matcher(text); while (m.find()) { String term = m.group(); if (!terms.contains(term)) { terms.add(term); } } if (!terms.isEmpty()) { hits.add(new CategoryHit(rule.getKey(), terms, HIGH_RISK.contains(rule.getKey()))); } } return new Result(hits); } /** * Scan with additional user-supplied banned words merged in as a * (non-high-risk) {@code 自定义禁用词} category — e.g. the user's * {@code banned_words} memory or brand-forbidden terms. */ static Result scan(String text, Collection extraTerms) { Result base = scan(text); if (extraTerms == null || extraTerms.isEmpty() || text == null || text.isBlank()) { return base; } List hitTerms = new ArrayList<>(); for (String t : extraTerms) { if (t == null) { continue; } String term = t.trim(); if (!term.isEmpty() && text.contains(term) && !hitTerms.contains(term)) { hitTerms.add(term); } } if (hitTerms.isEmpty()) { return base; } List all = new ArrayList<>(base.hits()); all.add(new CategoryHit("自定义禁用词", hitTerms, false)); return new Result(all); } /** Render a scan result as a short Chinese report. */ static String report(Result result) { if (result.clean()) { return "✅ 合规扫描:未命中极限词 / 诱导词 / 承诺收益 / 功效违禁词。"; } StringBuilder sb = new StringBuilder("⚠️ 合规扫描命中:\n"); for (CategoryHit h : result.hits()) { sb.append("- [").append(h.category()).append(h.highRisk() ? " · 高危" : "") .append("] ").append(String.join("、", h.terms())).append('\n'); } sb.append(result.hasHighRisk() ? "含高危词,发布前必须替换(尤其微信诱导词,易限流/封号)。" : "建议替换后再发布。"); return sb.toString(); } }