diff --git a/CHANGE_LOG.md b/CHANGE_LOG.md index e65846e..4e571bf 100644 --- a/CHANGE_LOG.md +++ b/CHANGE_LOG.md @@ -374,3 +374,9 @@ | 序号 | 变更类型 | 说明 | 时间 | 备注 | |:---|:-----|----------|:--------------------|:------------------------------------------------------| | 1 | F | 修正数字匹配问题 | 2024-11-10 22:43:08 | https://github.com/houbb/sensitive-word/issues/84 | + +# release_0.23.0 + +| 序号 | 变更类型 | 说明 | 时间 | 备注 | +|:---|:-----|------------|:-------------------|:-----------| +| 1 | A | 进一步拓展结果条件类 | 2024-12-8 21:13:44 | 支持同时指定多个条件 | \ No newline at end of file diff --git a/README.md b/README.md index 59e3998..2572222 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,10 @@ - 修正单个敏感词修改时,对应的格式处理问题 +### V0.23.0 + +- 结果条件拓展支持 wordTags 和 chains + ## 更多资料 ### 敏感词控台 @@ -94,7 +98,7 @@ com.github.houbb sensitive-word - 0.22.0 + 0.23.0 ``` @@ -656,11 +660,13 @@ public class SensitiveWordService { WordResultConditions 工具类可以获取匹配策略 -| 实现 | 说明 | 支持版本 | -|:----|:------------|:--------| -| alwaysTrue | 恒为真 | | -| englishWordMatch | 英文单词全词匹配 | v0.13.0 | -| englishWordNumMatch | 英文单词/数字全词匹配 | v0.20.0 | +| 实现 | 说明 | 支持版本 | +|:-------------------------------------------|:--------------------|:--------| +| alwaysTrue | 恒为真 | | +| englishWordMatch | 英文单词全词匹配 | v0.13.0 | +| englishWordNumMatch | 英文单词/数字全词匹配 | v0.20.0 | +| wordTags | 满足特定标签的,比如只关注【广告】标签 | v0.23.0 | +| chains(IWordResultCondition ...conditions) | 支持指定多个条件,同时满足 | v0.23.0 | ## 使用例子 @@ -702,6 +708,81 @@ Assert.assertEquals("[]", wordList.toString()); 当然可以根据需要实现更加复杂的策略。 +## wordTags 单词标签 + +支持版本: `v0.23.0` + +我们可以只返回隶属于某一种标签的敏感词。 + +我们指定了两个敏感词:商品、AV + +MyWordTag 是我们定义的一个敏感词标签实现: + +```java +/** + * 自定义单词标签 + * @since 0.23.0 + */ +public class MyWordTag extends AbstractWordTag { + + private static Map> dataMap; + + static { + dataMap = new HashMap<>(); + dataMap.put("商品", buildSet("广告", "中文")); + dataMap.put("AV", buildSet("色情", "单词", "英文")); + } + + private static Set buildSet(String... tags) { + Set set = new HashSet<>(); + for(String tag : tags) { + set.add(tag); + } + return set; + } + + @Override + protected Set doGetTag(String word) { + return dataMap.get(word); + } + +} +``` + +测试用例如下,我们模拟了两个不同的实现类,每一个关注的单词标签不同。 + +```java +// 只关心SE情 +SensitiveWordBs sensitiveWordBsYellow = SensitiveWordBs.newInstance() + .wordDeny(new IWordDeny() { + @Override + public List deny() { + return Arrays.asList("商品", "AV"); + } + }) + .wordAllow(WordAllows.empty()) + .wordTag(new MyWordTag()) + .wordResultCondition(WordResultConditions.wordTags(Arrays.asList("色情"))) + .init(); + +// 只关心广告 +SensitiveWordBs sensitiveWordBsAd = SensitiveWordBs.newInstance() + .wordDeny(new IWordDeny() { + @Override + public List deny() { + return Arrays.asList("商品", "AV"); + } + }) + .wordAllow(WordAllows.empty()) + .wordTag(new MyWordTag()) + .wordResultCondition(WordResultConditions.wordTags(Arrays.asList("广告"))) + .init(); + +final String text = "这些 AV 商品什么价格?"; +Assert.assertEquals("[AV]", sensitiveWordBsYellow.findAll(text).toString()); +Assert.assertEquals("[商品]", sensitiveWordBsAd.findAll(text).toString()); +``` + # 忽略字符 ## 说明 diff --git a/pom.xml b/pom.xml index 9810c4c..d1ea701 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.github.houbb sensitive-word - 0.22.0 + 0.23.0 diff --git a/release.bat b/release.bat index 5563e59..9d85ebd 100644 --- a/release.bat +++ b/release.bat @@ -10,9 +10,9 @@ ECHO "============================= RELEASE START..." :: 版本号信息(需要手动指定) :::: 旧版本名称 -SET version=0.22.0 +SET version=0.23.0 :::: 新版本名称 -SET newVersion=0.23.0 +SET newVersion=0.24.0 :::: 组织名称 SET groupName=com.github.houbb :::: 项目名称 diff --git a/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditionInit.java b/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditionInit.java new file mode 100644 index 0000000..24c77fd --- /dev/null +++ b/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditionInit.java @@ -0,0 +1,43 @@ +package com.github.houbb.sensitive.word.support.resultcondition; + +import com.github.houbb.heaven.support.pipeline.Pipeline; +import com.github.houbb.heaven.support.pipeline.impl.DefaultPipeline; +import com.github.houbb.sensitive.word.api.IWordContext; +import com.github.houbb.sensitive.word.api.IWordResult; +import com.github.houbb.sensitive.word.api.IWordResultCondition; +import com.github.houbb.sensitive.word.constant.enums.WordValidModeEnum; + +import java.util.List; + +/** + * 结果条件的的初始化类 + * + * @since 0.23.0 + */ +public abstract class WordResultConditionInit extends AbstractWordResultCondition { + + /** + * 初始化列表 + * + * @param pipeline 当前列表泳道 + * @since 0.0.13 + */ + protected abstract void init(final Pipeline pipeline); + + @Override + protected boolean doMatch(IWordResult wordResult, String text, WordValidModeEnum modeEnum, IWordContext context) { + Pipeline pipeline = new DefaultPipeline<>(); + this.init(pipeline); + List conditionList = pipeline.list(); + + // 必须满足所有 + for(IWordResultCondition wordResultCondition : conditionList) { + if(!wordResultCondition.match(wordResult, text, modeEnum, context)) { + return false; + } + } + + return true; + } + +} diff --git a/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditionWordTagsMatch.java b/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditionWordTagsMatch.java new file mode 100644 index 0000000..730c706 --- /dev/null +++ b/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditionWordTagsMatch.java @@ -0,0 +1,52 @@ +package com.github.houbb.sensitive.word.support.resultcondition; + +import com.github.houbb.heaven.util.common.ArgUtil; +import com.github.houbb.heaven.util.util.CollectionUtil; +import com.github.houbb.sensitive.word.api.IWordContext; +import com.github.houbb.sensitive.word.api.IWordResult; +import com.github.houbb.sensitive.word.api.IWordTag; +import com.github.houbb.sensitive.word.constant.enums.WordValidModeEnum; + +import java.util.Collection; +import java.util.Set; + +/** + * 结果标签匹配的条件 + * + * @since 0.23.0 + */ +public class WordResultConditionWordTagsMatch extends AbstractWordResultCondition { + + /** + * 指定标签的集合 + */ + private final Collection tags; + + public WordResultConditionWordTagsMatch(Collection tags) { + ArgUtil.notEmpty(tags, "tags"); + + this.tags = tags; + } + + @Override + protected boolean doMatch(IWordResult wordResult, String text, WordValidModeEnum modeEnum, IWordContext context) { + // 判断对应的标签 + String word = text.substring(wordResult.startIndex(), wordResult.endIndex()); + final IWordTag wordTag = context.wordTag(); + Set wordTags = wordTag.getTag(word); + + // 在指定的 tag 中 + if(CollectionUtil.isEmpty(wordTags)) { + return false; + } + + for(String tag : tags) { + if(wordTags.contains(tag)) { + return true; + } + } + + return false; + } + +} diff --git a/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditions.java b/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditions.java index 8bafaa4..00742a5 100644 --- a/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditions.java +++ b/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditions.java @@ -1,7 +1,12 @@ package com.github.houbb.sensitive.word.support.resultcondition; +import com.github.houbb.heaven.support.pipeline.Pipeline; +import com.github.houbb.heaven.util.common.ArgUtil; +import com.github.houbb.heaven.util.util.ArrayUtil; import com.github.houbb.sensitive.word.api.IWordResultCondition; +import java.util.List; + /** * 匹配结果工具类 * @@ -35,4 +40,39 @@ public final class WordResultConditions { return new WordResultConditionEnglishWordNumMatch(); } + /** + * 单词标签 + * @param tags 标签列表 + * @return 结果 + * @since 0.23.0 + */ + public static IWordResultCondition wordTags(List tags) { + ArgUtil.notEmpty(tags, "tags"); + + return new WordResultConditionWordTagsMatch(tags); + } + + /** + * 链式调用,支持同时满足多个条件 + * + * @since 0.23.0 + * @param condition 条件 + * @param others 其他条件 + * @return 结果 + */ + public static IWordResultCondition chains(final IWordResultCondition condition, final IWordResultCondition ... others) { + return new WordResultConditionInit() { + @Override + protected void init(Pipeline pipeline) { + pipeline.addLast(condition); + if(ArrayUtil.isNotEmpty(others)) { + for(IWordResultCondition other : others) { + pipeline.addLast(other); + } + } + } + }; + } + + } diff --git a/src/test/java/com/github/houbb/sensitive/word/support/resultcondition/MyWordTag.java b/src/test/java/com/github/houbb/sensitive/word/support/resultcondition/MyWordTag.java new file mode 100644 index 0000000..9d6cee6 --- /dev/null +++ b/src/test/java/com/github/houbb/sensitive/word/support/resultcondition/MyWordTag.java @@ -0,0 +1,37 @@ +package com.github.houbb.sensitive.word.support.resultcondition; + +import com.github.houbb.sensitive.word.support.tag.AbstractWordTag; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * 自定义单词标签 + * @since 0.23.0 + */ +public class MyWordTag extends AbstractWordTag { + + private static Map> dataMap; + + static { + dataMap = new HashMap<>(); + dataMap.put("商品", buildSet("广告", "中文")); + dataMap.put("AV", buildSet("色情", "单词", "英文")); + } + + private static Set buildSet(String... tags) { + Set set = new HashSet<>(); + for(String tag : tags) { + set.add(tag); + } + return set; + } + + @Override + protected Set doGetTag(String word) { + return dataMap.get(word); + } + +} diff --git a/src/test/java/com/github/houbb/sensitive/word/support/resultcondition/WordTagsTest.java b/src/test/java/com/github/houbb/sensitive/word/support/resultcondition/WordTagsTest.java new file mode 100644 index 0000000..1dbc9d6 --- /dev/null +++ b/src/test/java/com/github/houbb/sensitive/word/support/resultcondition/WordTagsTest.java @@ -0,0 +1,53 @@ +package com.github.houbb.sensitive.word.support.resultcondition; + +import com.github.houbb.sensitive.word.api.IWordDeny; +import com.github.houbb.sensitive.word.bs.SensitiveWordBs; +import com.github.houbb.sensitive.word.support.allow.WordAllows; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +public class WordTagsTest { + + + /** + * 是否包含 + * + * @since 0.23.0 + */ + @Test + public void wordTagsTest() { + // 只关心SE情 + SensitiveWordBs sensitiveWordBsYellow = SensitiveWordBs.newInstance() + .wordDeny(new IWordDeny() { + @Override + public List deny() { + return Arrays.asList("商品", "AV"); + } + }) + .wordAllow(WordAllows.empty()) + .wordTag(new MyWordTag()) + .wordResultCondition(WordResultConditions.wordTags(Arrays.asList("色情"))) + .init(); + + // 只关心广告 + SensitiveWordBs sensitiveWordBsAd = SensitiveWordBs.newInstance() + .wordDeny(new IWordDeny() { + @Override + public List deny() { + return Arrays.asList("商品", "AV"); + } + }) + .wordAllow(WordAllows.empty()) + .wordTag(new MyWordTag()) + .wordResultCondition(WordResultConditions.wordTags(Arrays.asList("广告"))) + .init(); + + final String text = "这些 AV 商品什么价格?"; + Assert.assertEquals("[AV]", sensitiveWordBsYellow.findAll(text).toString()); + Assert.assertEquals("[商品]", sensitiveWordBsAd.findAll(text).toString()); + } + +}