Искал скрипт для антирекламы, чтобы был эффективный и не громоздкий. Полностью не устраивал ни один, поэтому решил взять от каждого лучшее. Получилось вполне прилично, в нём примерно 3 разных скрипта, соединил, добавил и изменил. Но лазия по форуму прочитал, что можно скрипт с исключениями обойти, если в одной строке есть и реклама, и исключение. Проверил - так и есть. Пробовал сам исправить, но опыт общения с lua меньше недели, причину не понял. Пытался поиграть с for и if, но в итоге получилось с точностью да наоборот - рекламу пропускает, исключения убирает, вместе тоже убирает. Идей больше нет.
Встречал на форумах уже готовые скрипты с решённой проблемой, но они довольно сложные, я там вообще ничего не понимаю. А когда много не понимаешь, чувствуешь себя некомфортно. Буду признателен, если поможете.
--[[
Возвращает итератор, который, при каждом вызове, возвращает индексы начала и
конца совпадения с шаблоном и захваченные значения (captures).
]]
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
--[[
"Поглощает" итератор и возвращает все полученные значения в виде массива.
]]
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.
]]
function is_forbidden(message, forbidden_patterns, allowed_patterns)
local allowed_indexes = collect_results(gfind_patterns(message, allowed_patterns))
for start, end_ in gfind_patterns(message, forbidden_patterns) do
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
--[[
Тесты.
]]
local forbidden_patterns = {'http://', 'www%.', '%d+%.%d+%.%d+%.%d+'}
local allowed_patterns = {'http://dchublist%.ru', 'www%.dchublist%.ru', '127%.0%.0%.1'}
for _, test in ipairs({
'http://spam.net',
'www.spam.net 127.0.0.1',
'http://dchublist.ru www.spam.net',
}) do
assert(is_forbidden(test, forbidden_patterns, allowed_patterns), 'failed: ' .. test)
end
Вот вам готовый работающий скрипт для блокировки сообщений. Чтобы приделать к нему различные варианты бана не надо знать Lua дольше недели, думаю, справитесь самостоятельно.
Авторы: Damaks ™ и nd
Совместимость: PtokaX 0.4, Lua 5.1, API 2
- Сканирует чат и личку.
- Запрещённые слова ищутся по шаблонам, что во много раз уменьшает количество примеров рекламных фраз.
- Регистр не важен, www и wWw фильтруются одинаково (самый эффективный и компактный на сегодняшний день алгоритм преобразования кодировки cp1251 в нижний регистр).
- Не существует проблемы с обходом защиты благодаря оптимальному поисковому алгоритму (распространённая проблема в большинстве скриптов, случается при нахождении в одном сообщении заперещённой фразы и исключения).
- Раздельные функции сканирования чата и лички (выбрать нужный режим можно изменением одной цифры в скрипте).
- Приличный выбор самых необходимых режимов наказания: возможность бана на заданное время (задаётся в скрипте), разъединения (сообщение юзеру о рекламе и disconnect), просто замены запрещённой фразы (сообщение с рекламой заменяется информационным, его видит только отправитель), тихого фильтрования (отправитель думает, что всё нормально и сообщение доставлено, в личке и общем чате же оно не появляется).
- Возможность информирования операторов о попытке рекламы с показом запрещённой фразы (если хотите знать, кто что отсылает).
В скрипте есть подробные пояснения, которые помогут разобраться даже новичку в lua.