| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- local DebugProxy = requireProxy("DebugProxy")
- local SensitiveWordProxy = class("SensitiveWordProxy", DebugProxy)
- SensitiveWordProxy.NAME = global.ProxyTable.SensitiveWordProxy
- local utf8 = require("util/utf8")
- local tostring = tostring
- local tinsert = table.insert
- local sfind = string.find
- local sgsub = string.gsub
- local sbyte = string.byte
- local slen = string.len
- local ssub = string.sub
- ------------------------------------------------------------
- -- 简单正则匹配,匹配出所有网址
- local function findSensitivePattren(str)
- local items = {}
-
- while true do
- local pattern = { sfind(str, "(%w+%.%a+)") }
- if not pattern[3] then
- break
- end
- tinsert(items, {b = pattern[1], c = pattern[2] - pattern[1]+1, w = pattern[3]})
- local p = ssub(str, 1, pattern[1]-1)
- local s = ssub(str, pattern[2]+1, slen(str))
- str = p .. s
- end
- return #items > 0, items
- end
- -- 字符串匹配,非正常匹配字符
- local function fixMalformedPattern(v)
- v = sgsub(v, "%%", "%%%%")
- v = sgsub(v, "%.", "%%.")
- v = sgsub(v, "%(", "%%(")
- v = sgsub(v, "%)", "%%)")
- v = sgsub(v, "%+", "%%+")
- v = sgsub(v, "%-", "%%-")
- v = sgsub(v, "%*", "%%*")
- v = sgsub(v, "%?", "%%?")
- v = sgsub(v, "%[", "%%[")
- v = sgsub(v, "%]", "%%]")
- v = sgsub(v, "%^", "%%^")
- v = sgsub(v, "%$", "%%$")
- return v
- end
- -- 结束标记,使用数字作为Key,解决字符作为Key产生的无法匹配问题
- local endFlag = 0
- -- 是否是特殊字符,在处理敏感字时跳过夹在中间的特殊字符
- local charaterHash = {}
- local charaterList = {
- "`","~", "!","!", "@","@", "$","¥", "%", "^","…", "&", "*", "(", ")", "_","-", "+","=", "\\", "/", "?","?", "[","]", " ", " ", "\t", "\n", "\r", "<", ">", "'", "\"", "—",
- "#", ",", ",", ".", "。", ":",";", ":", ";", "�",
- }
- for i, v in ipairs(charaterList) do
- charaterHash[v] = 1
- end
- local function isCharaters(s)
- if charaterHash[s] == 1 then
- return true
- end
- return false
- end
- ------------------------------------------------------------
- -- 字典树
- -- 字母转小写
- -- 排除特殊字符,中间插入特殊字符先清特殊字符再匹配
- ------------------------------------------------------------
- ------------------------------------------------------------
- -- 字典树
- local TrieNode = class("TrieNode")
- function TrieNode:ctor()
- self.subNodes = {}
- end
- function TrieNode:addSubNode(k, subNode)
- self.subNodes[k] = subNode
- end
- function TrieNode:getSubNode(k)
- return self.subNodes[k]
- end
- ---
- local Trie = class("Trie")
- function Trie:ctor()
- self.root = TrieNode.new()
- end
- function Trie:add(word)
- -- 转换为小写
- word = string.lower(word)
- local utf8len = utf8:length(word)
- local currNode = self.root
- for i = 1, utf8len do
- local s = utf8:sub(word, i, 1)
- -- 特殊字符
- if isCharaters(s) then
- else
- local subNode = currNode:getSubNode(s)
- if subNode == nil then
- subNode = TrieNode.new()
- currNode:addSubNode(s, subNode)
- end
-
- currNode = subNode
- end
- end
-
- currNode:addSubNode(endFlag, TrieNode.new())
- end
- function Trie:search(word, isEasy)
- -- 转换为小写
- word = string.lower(word)
-
- local items = {}
- local utf8len = utf8:length(word)
- local index = 1
- while true do
- local numChars = self:search_sub(word, index, utf8len)
- if numChars > 0 then
- tinsert(items, {b = index, c = numChars, w = utf8:sub(word, index, numChars)})
- end
- -- 尽量少匹配
- if isEasy and #items == 1 then
- break
- end
- if index > utf8len then
- break
- end
- if numChars > 0 then
- index = index + numChars
- else
- index = index + 1
- end
- end
- return #items > 0, items
- end
- function Trie:search_sub(word, startIndex, utf8len)
- local numChars = 0
- local complete = false
- local currNode = self.root
- for i = startIndex, utf8len do
- local s = utf8:sub(word, i, 1)
- numChars = numChars + 1
-
- -- 是特殊字符
- if not (isCharaters(s)) then
- -- 不存在子节点
- local subNode = currNode:getSubNode(s)
- if subNode == nil then
- break
- end
-
- -- 完整结束了
- if (subNode:getSubNode(endFlag)) then
- complete = true
- break
- end
-
- currNode = subNode
- end
- end
- if not complete then
- numChars = 0
- end
- return numChars
- end
- ------------------------------------------------------------
- function SensitiveWordProxy:ctor()
- SensitiveWordProxy.super.ctor(self)
- self._words_trie = Trie.new()
- self._talk_charaters = {}
- self._name_charaters = {}
- end
- function SensitiveWordProxy:lazyInit()
- if self._isInited then
- return nil
- end
- self._isInited = true
- -- 基础配置表
- local config = requireGameConfig("cfg_sensitive_normal.lua")
- for k, v in pairs(config) do
- self._words_trie:add(v)
- end
- -- 自定义敏感字
- local filePath = "data_config/sensitive_words.txt"
- local text = ""
- if global.FileUtilCtl:isFileExist(filePath) then
- local function callback(dataTable)
- if dataTable[1] and dataTable[1] ~= "" then
- text = string.trim(dataTable[1])
- if text ~= "" then
- self._words_trie:add(text)
- end
- end
- end
- LoadTxt(filePath, nil, callback)
- end
- -- 聊天 额外屏蔽
- self._talk_charaters = { "\\", "¥", "%", "\t", "\n", "\r", "'", "\"", "卍" }
-
- -- 取名 额外屏蔽
- self._name_charaters = {
- "\\", "/", "¥", "%", "(", ")", "+", "-", "*", "?", "[", "]", "^", "$", " ", " ", "\t", "\n", "\r", "<", ">", "!",
- "@", "&", "=", "'", "\"", "_", "#", ";", ":", "【", "】", "“", "”", "。", ",", "《", "》", "?", "、", "!","卍","卐"
- }
- end
- ----------------------------------------------------------------------
- -- 是否包含敏感字,敏感级别=取名
- function SensitiveWordProxy:IsHaveSensitiveName(str)
- self:lazyInit()
- local found = false
- local items = {}
- -- 特殊字符匹配
- if not found then
- for i, v in ipairs(self._name_charaters) do
- local s = fixMalformedPattern(v)
- if sfind(str, s, 1, true) ~= nil then
- found = true
- break
- end
- end
- end
- -- 字典树匹配
- if not found then
- found, items = self._words_trie:search(str, true)
- end
- -- 正则匹配
- if not found then
- found, items = findSensitivePattren(str)
- end
- return found
- end
- function SensitiveWordProxy:IsHaveSensitiveAddFilter(str, callback)
- local found = self:IsHaveSensitiveName(str)
- if found then
- if callback then
- callback(false)
- end
- return
- end
- -- 使用第三方敏感字检测
- local AuthProxy = global.Facade:retrieveProxy(global.ProxyTable.AuthProxy)
- AuthProxy:RequestWordFilteringQQ(1, str, callback)
- end
- function SensitiveWordProxy:IsHaveSensitiveEx(strList, callback)
- if not strList or #strList <= 0 then
- callback(false)
- return
- end
- local idx = 1
- local function checkHaveSensitive(str)
- self:IsHaveSensitiveAddFilter(str, function(state)
- -- 检测,不通过
- if not state then
- callback(false)
- return
- end
- -- 检测,全部通过
- if idx == #strList then
- callback(true)
- return
- end
- idx = idx + 1
- checkHaveSensitive(strList[idx])
- end)
- end
- checkHaveSensitive(strList[idx])
- end
- ----------------------------------------------------------------------
- ----------------------------------------------------------------------
- -- 是否包含敏感字,敏感级别=聊天
- function SensitiveWordProxy:fixSensitiveTalkAddFilter(str, callback, type, ex_param)
- self:lazyInit()
- local replace = "*"
- local found = false
- local items = {}
- local replacedWords = {}
- local originStr = str
- if ex_param then
- ex_param.originStr = originStr
- end
- -- 特殊字符被替换掉
- for i, v in ipairs(self._talk_charaters) do
- local s = fixMalformedPattern(v)
- local n = 0
- str, n = sgsub(str, s, replace)
- if n > 0 then
- table.insert(replacedWords, s)
- end
- end
- -- 配置表敏感字
- found, items = self._words_trie:search(str)
- for i, v in ipairs(items) do
- local s = fixMalformedPattern(v.w)
- local n = 0
- str, n = sgsub(str, s, replace)
- if n > 0 then
- table.insert(replacedWords, s)
- end
- end
- -- 正则匹配的敏感字,域名等
- found, items = findSensitivePattren(str)
- for _, v in ipairs(items) do
- local s = fixMalformedPattern(v.w)
- local n = 0
- str, n = sgsub(str, s, replace)
- if n > 0 then
- table.insert(replacedWords, s)
- end
- end
- if ex_param then
- ex_param.replacedWords = replacedWords
- end
- -- 使用第三方敏感字检测
- local AuthProxy = global.Facade:retrieveProxy(global.ProxyTable.AuthProxy)
- if type and type == 1 then
- AuthProxy:RequestWordFilteringQQ(3, str, callback)
- else
- AuthProxy:RequestWordFilteringQQ(2, str, callback, ex_param)
- end
- end
- -- 是否包含敏感字,敏感级别=聊天
- function SensitiveWordProxy:IsHaveSensitiveChat(str)
- self:lazyInit()
- local found = false
- local items = {}
- -- 特殊字符匹配
- if not found then
- for i, v in ipairs(self._talk_charaters) do
- local s = fixMalformedPattern(v)
- if sfind(str, s, 1, true) ~= nil then
- found = true
- break
- end
- end
- end
- -- 字典树匹配
- if not found then
- found, items = self._words_trie:search(str, true)
- end
- -- 正则匹配
- if not found then
- found, items = findSensitivePattren(str)
- end
- return found
- end
- function SensitiveWordProxy:IsHaveSensitiveTalkAddFilter(str, callback, ex_param)
- local found = self:IsHaveSensitiveChat(str)
- if found then
- if callback then
- callback(false)
- end
- return
- end
- -- 使用第三方敏感字检测
- local AuthProxy = global.Facade:retrieveProxy(global.ProxyTable.AuthProxy)
- AuthProxy:RequestWordFilteringQQ(2, str, callback, ex_param)
- end
- return SensitiveWordProxy
|