Автоматическая фильтрация контента через Angie

Опубликовано 3 окт. 2025 г.

На подходе новый закон о глобальном запрете мата в сети, поэтому к нему нужно подготовиться. Переебашивать каждый пост в блоге — проблематично, да и лень.

Поэтому, как обычно, будем изобретать велосипед.

ЧИТАТЬ ПЕРВЫМ В ТЕЛЕГРАМ

Суть идеи — налету в DOM менять маты на синонимы. То есть в момент отдачи контента, контент будет насильно зацензурен.

Хуйня == Фигня, Пезда == 3.14зда ну и в таком духе.

А там уже можно будет добавить регулярки и гибко всё затюнить, мало ли, может можно будет звездочками разбавлять такой контент.

Реализация

За основу я возьму angie (форк nginx) с модулем LUA. Я давно на это решение пересел, так как всё из коробки работает, включая генерацию SSL. Не нужно ебстись с компиляций модулей и страдать.

Как настроить автополучение SSL в angie, писал в этом посте.

Если LUA не установлен, ставим:

apt install angie-module-lua

В /etc/angie/angie.conf добавляем:

load_module modules/ndk_http_module.so;
load_module modules/ngx_http_lua_module.so;
load_module modules/ngx_stream_lua_module.so;

В /etc/angie/sites-available/bashdays.ru.conf добавляем в корневой локейшен:

location / {
    root /var/www/bashdays.ru/htdocs;
    index index.html;
    gzip off;

    body_filter_by_lua_block {
        local replacements = dofile("/etc/angie/wordmap.lua")

        local chunk = ngx.arg[1]
        if chunk then
            for _, pair in ipairs(replacements) do
                chunk = ngx.re.gsub(chunk, pair[1], pair[2], "ijo")
            end
            ngx.arg[1] = chunk
        end
    }
}

Ну и создаем файл /etc/angie/wordmap.lua который будет содержать шаблоны замены:

return {
    {"хуйня", "фигня"},
    {"хуй", "писька"},
    {"говн%w*", "ерунда"},
    {"еба%w*", "плохой"},
}

Проверяем: angie -t и если всё ок, можно сделать systemctl restart angie.

Открываем сайт и видим что все маты зацензурились согласно шаблону в файле /etc/angie/wordmap.lua.

Если всё осталось по-прежнему, скинь кеш, в 99% дело в нем.

Давай разберемся как это работает.

body_filter_by_lua_block — перед отправкой ответа клиенту, запустится Lua-скрипт, который изменит тело ответа.

dofile("/etc/angie/wordmap.lua") — загружает Lua-файл со словарём замен.

ngx.arg[1] — текущий кусок (chunk) ответа (HTML, JSON и т.п.), который angie собирается отправить клиенту. Ответ приходит потоками.

for _, pair in ipairs(replacements) — перебор всех замен из словаря.

ngx.re.gsub(chunk, pair[1], pair[2], "ijo") — регулярная замена, [1] что искать, [2] на что заменить.

"ijo" — флаги: i — без учёта регистра, j — dotall (точка матчится на \n), o — оптимизация.

ngx.arg[1] = chunk — возвращаем изменённый кусок, который уйдёт клиенту.

И получаем — блок берёт HTML-страницу, проходит по каждому чанку тела ответа, и заменяет в нём «запрещённые» слова из словаря на синонимы.

Ааа, еще в словаре {"говн%w*", "ерунда"} есть символы %w* это регулярка.

Любая буква, цифра или подчёркивание ([0-9A-Za-z_]). В UTF-8 оно обычно ловит только латиницу, а кириллицу нет.

Поэтому лучше сделать как-то так: {"говн[А-Яа-яЁё]*", "ерунда"}. Короче тут тебе карты в руки, сам натыкай паттерны.

LUA — сила! Рекомендую хоть раз потыкать, проникнешься и уже не сможешь без этого модуля жить. Костыли клепать милое дело.

Есть конечно нюансы, например — Если слово вдруг разорвётся между чанками (например, ху в одном чанке и йня в другом) — фильтр его не заменит. Для надёжности нужно буферизовать весь ответ.

Ну и с кириллицей надо вопрос дофиксить, но это я реализую чуть позже. Главное концепт. Всё остальное реализуемо.

Как вариант, позже еще запилю «специальный» заголовок, при передаче которого angie будет отключать цензуру и выводить посты в оригинале.

А можно разработчиков подъебать, пусть ищут в своем коде, почему у них слова странным образом заменяются.

Ну заебись же! Осталось придумать, как зацензурить 1000 постов в телеге.

Комментарии