--[[ Скрипт блокировки сообщений в чате и личных сообщениях по шаблону. ]] -- Шаблоны запрещенных выражений local FORBIDDEN_PATTERNS = { 'd%s*c%s*h%s*u%s*b%s*:%s*/%s*/', -- dchub:// 'h%s*t%s*t%s*p%s*:%s*/%s*/', -- http:// 'w%s*w%s*w%s*%.', -- www. '%d+%.%d+%.%d+%.%d+', -- IP } -- Шаблоны разрешенных выражений local ALLOWED_PATTERNS = { 'http://google%.ru', 'www%.google%.ru', '127%.0%.0%.1', } -- Что показать пользователю при блокировке сообщения local BLOCK_MESSAGE = 'Сообщение заблокировано.' --[[ Преобразует строку в кодировке cp1251 в нижний регистр. NOTE Я не уверен, что работает в ОС Windows. ]] local function lower_cp1251(string_) local old_locale = os.setlocale() os.setlocale('ru_RU.cp1251') string_ = string_:lower() os.setlocale(old_locale) return string_ end --[[ Возвращает итератор, который, при каждом вызове, возвращает индексы начала и конца совпадения с шаблоном и захваченные значения (captures). ]] local function gfind_patterns(string_, patterns) return coroutine.wrap(function () for _, pattern in ipairs(patterns) do local i = 1 while true do local results = {string_:find(pattern, i)} if not results[1] then break end i = results[2] + 1 coroutine.yield(unpack(results)) end end end) end --[[ "Поглощает" итератор и возвращает все полученные значения в виде массива. ]] local function collect_results(iterator) local all_results = {} while true do local results = {iterator()} if not results[1] then break end table.insert(all_results, results) end return all_results end --[[ Возвращает true если сообщение содержит части совпадающие с forbidden_patterns и не совпадающие с allowed_patterns, иначе возвращает false. ]] local function is_forbidden(message, forbidden_patterns, allowed_patterns) local allowed_indexes for start, end_ in gfind_patterns(message, forbidden_patterns) do if not allowed_indexes then allowed_indexes = collect_results(gfind_patterns(message, allowed_patterns)) end local forbid = true for _, indexes in ipairs(allowed_indexes) do if start >= indexes[1] and end_ <= indexes[2] then forbid = false break end end if forbid then return true end end return false end --[[ Блокирует запрещенные сообщения в чате. ]] function ChatArrival(user, data) local message = data:match('%b<>%s*(.+)|$') if message then message = lower_cp1251(message) if is_forbidden(message, FORBIDDEN_PATTERNS, ALLOWED_PATTERNS) then -- Здесь можно, например, забанить пользователя Core.SendToUser(user, '<' .. Core.GetHubSecAlias() .. '> ' .. BLOCK_MESSAGE .. '|') return true end end return false end ToArrival = ChatArrival