
Розмітка одного з фільтрів на Dev Wiki
Розмітка фільтра зловживань — спеціальний синтаксис, що дозволяє вказувати умови спрацьовування фільтра зловживань.
Опис[]
Фільтр зловживань — розширення, що дозволяє перевірити дії користувачів на відповідність певним умовам і таким чином захищати вікі він потенційно шкідницького внеску. Адміністрація вікі-проєкту может створити скільки завгодно багато фільтрів, а дії перевірятимуться послідовно з кожним з активних умов.
Самі умови вказуються на спеціальній сторінці «Налаштування фільтра зловживань» (Special:AbuseFilter) в спеціальному полі. В цілому синтаксис умов нагадує відповідні конструкції в мовах програмування, подібних до C, Java і Perl.
Синтаксис[]
Типи даних[]
Так само, як і в багатьох інших мовах, у розмітці фільтра зловживань використовуються звичайні типи даних:
- Рядки, обмежені одинарними чи подвійними лапками. Можуть містити escape-послідовності та деякі спецсимволи (наприклад, перенесення рядка
\n
та символ табуляції\t
); - Цілі та дробові числа, як позитивні, і негативні. Дробна частина відокремлюється від цілої символом точки;
- Логічні значення, прийняття лише стану істини (
true
) і хибності (false
). Хибними значеннями крімfalse
вважаються нуль, порожній масив, порожній рядок іnull
; - Масиви, які можуть містити одразу кілька значень. Про них буде окремо згадано пізніше.
Ось кілька прикладів з різними типами даних:
/* рядки */
"Звичайний рядок"
'Рядок\nз перенесенням'
'That\'s a string with escape'
165 -99 34.81 -0.02 /* числа */
true false /* логічні значення */
/* масиви */
['abc', 'def', 'ghi']
[13, 6, 0, -4]
Як видно з прикладів вище, у коді фільтра можна писати коментарі, укладаючи пояснювальний текст у поєднання /* */
.
Масиви[]
Усі масиви у розмітці фільтра індексуються з нуля. Вони не мають жодних методів, проте операції здійснюються з допомогою певних синтаксичних конструкцій.
Отримати та змінити значення певного елемента можна, звернувшись до нього за індексом: array[0]
поверне перший елемент масиву, а array[0] = 6
надасть йому значення 6. Додати нове значення в кінець можна так: array[] := 6
. Тут використовується не знак рівності, а оператор присвоєння :=
, подібний до того, що є в мові Pascal.
Функції length()
та int()
визначають довжину масиву у вигляді цілого числа, а float()
— у вигляді дробового. Наприклад, int( [1, 3, 5, 7] ) == 4
. string()
перетворює масив на рядок, розділений символами перенесення (на кінці з ряду причин також буде такий символ): string( [1, 2, 3] ) == "1\n2\ n3\n"
.
Оператор in
дозволяє перевірити, чи є цей елемент у масиві: 4 in [1, 4, 8] == true
. Однак при роботі з масивами необхідно пам'ятати, що в синтаксисі фільтра зловживань всі масиви зводяться до рядків, де кожен елемент розділений переносом рядка \n
, тобто фактично застосовується функція string ()
. Внаслідок цього аналізований оператор може давати невірний результат:
namespaces := [4, 11, 15]; /* представимо перевірку просторів назв */
4 in namespaces == true /* тут усе правильно */
"4" in namespaces == true /* тут теж, тому що підрядок "4" є в рядку "4\n11\n15\n" */
"4\n11" in namespaces == true /* такий підряд також існує, але за нашою логікою це вже невірно */
1 in namespaces == true /* невірно, але видає true, тому що підрядок "1" у рядку "4\n11\n15\n" присутній */
В даному випадку рекомендується використовувати функцію equals_to_any(a, b, c)
, дія якої ідентична запису a === b | a === c
.
Змінні[]
Всередині умов допускається створювати власні змінні. Ім'я змінної може бути будь-яким, але має складатися з букв латинського алфавіту, цифр (але може з них починатися) чи символів нижнього підкреслення; регістр значення немає. Вміст записується в змінну оператором :=
, а наприкінці рядка обов'язково має стояти крапка з комою. Будучи оголошеної однією умовою, змінна стає доступною й у інших теж.
Як приклад можна навести змінну, що містить регулярне вираз і використовується в одному з фільтрів англійської Вікіпедії:
(
line1:="(\{\{(r|R)еflist|\{\{(r|R)efs|<rеferences\s?/>|</rеferences\s?>)";
rcount(line1, removed_lines)
) > (
rcount(line1, added_lines)
)
Оператори[]
Синтаксис умов фільтра зловживань надає три групи операторів для дій із даними. Перша група — арифметичні дії:
- складання та конкатенація рядків (
+
); - віднімання (
-
); - множення (
*
); - зведення в ступінь (
**
); - ділення (
/
); - залишок від ділення (
%
).
/* складання та конкатенація */
16 + 4 == 20
34.22 + 16.09 == 50.31
"Lorem" + "ipsum" == "Loremipsum"
/* множення і зведення в ступінь */
6 * 4 == 24
29 * 0.1 == 2.9
4 ** 3 == 64
/* ділення */
16 / 5 == 3.2
13 % 10 == 3
Наступна група - бінарні оператори. Їх чотири:
- AND або кон'юнкція (
&
) — істинна, коли істинні обидва аргументи; - OR або диз'юнкція (
|
) — істинна, якщо істинний хоча б один аргумент; - XOR або сувора диз'юнкція (
^
) — істинна, якщо правдивий тільки один аргумент; - NOT або інверсія (
!
) — інвертує значення: істина стає хибним і навпаки.
/* таблиця істинності NOT */
x !x
0 1
1 0
/* таблиця істинності AND, OR і XOR */
x y x & y x | y x ^ y
0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 1 0
І, нарешті, група операторів порівняння, які в сукупності з діями булевої алгебри утворюють логіку умов фільтру:
- суворе порівняння (
<
,>
) — істинно, коли лівий аргумент відповідно менший або більший, ніж правий; - несуворе порівняння (
<=
,>=
) — істинно тільки тоді, коли лівий аргумент відповідно менший або більше, ніж правий, або дорівнює йому; - рівність (
=
,==
) і нерівність (!=
) — істинні тоді, коли всі ліві аргменти відповідно дорівнюють або не рівні всім правим. За необхідності проводиться приведення типів; - сувора рівність (
===
) і нерівність (!==
) — істинні тоді, коли всі ліві аргументи відповідно дорівнюють або не рівні всім правим і при цьому мають один і той же тип даних.
За це відповідають оператори суворої та не суворої рівності:
[1, 2] == [1, 2] /* true */
[1, 2] == ["1", 2] /* true */
[1, 2] === ["1", 2] /* false, різні типи перших елементів */
["1", 2] === ["1", 2] /* true, типи збігаються */
[1, 2, 3] == [1, 2] /* false, різна довжина масивів */
Ключові слова[]
Також синтаксис фільтра зловживань входять кілька операторів, які у документації називаються ключовими словами. Окремо варто згадати, що ці конструкції наводять аргументи до рядків.
like
(абоmatches
) перевіряє входження лівої частини виразу у праве. Можна використовувати маску пошуку (glob pattern).rlike
(абоregex
) робить абсолютно те саме, але замість маски використовується регулярний вираз у форматі PCRE. Ключове словоirlike
робить патерн нечутливим до регістру.in
іcontains
виконують однакові функції — перевірка наявності одного рядка в інший. Різниця лише в порядку:in
намагається знайти лівий операнд у правому, аcontains
— навпаки.
Розмітка фільтра підтримує і конструкції розгалуження if ... then ... end
і if ... then ... else ... end
разом із тернарним оператором condition ? true : false
, однак у контексті написання умов вони навряд чи можуть бути використані.
Стандартні змінні[]
Розширення AbuseFilter додає досить багато змінних, що містять корисні дані, які можна буде проаналізувати в умовах фільтра. Частина доступна завжди, а інша частина — лише за дотримання певних умов.
Змінні, доступні завжди | ||
---|---|---|
Змінна | Тип даних | Опис |
action
|
рядок | Поточна дія, що виконується зі сторінкою. Можливі значення: edit , move , delete , upload , stashupload , createaccount , autocreateaccount .
|
timestamp
|
рядок | UNIX-час у момент здійснення дії. Рекомендується переводити до числа функцією int() .
|
wiki_name
|
рядок | Кодова назва цього вікіпроекту в базі даних Фандому. Наприклад, для Вікі про вікі це буде ukwikies .
|
wiki_language
|
рядок | Мовний код цієї вікі у базі даних Фандому. Для Вікі про вікі це буде uk .
|
user_name
|
рядок | Ім'я користувача, що вчинив дію. |
user_editcount
|
число або null
|
Кількість редагувань користувача. Для анонімів дорівнює null .
|
user_emailconfirm
|
рядок або null
|
Дата підтвердження адреси електронної пошти у форматі YYYYMMDDHHMMSS або null , якщо це анонім.
|
user_age
|
число | Час, що минув з моменту створення облікового запису користувача, в секундах. Для анонімів 0. |
user_blocked
|
логічний | Якщо обліковий запис користувача заблоковано (в тому числі і глобально) або його IP-адреса входить у заблокований діапазон, буде дорівнює true .
|
user_rights і user_groups
|
масив рядків | Перераховує всі права та групи прав користувача відповідно. |
page_id
|
число | Ідентифікатор цієї сторінки. Можна використовувати для перевірки створення сторінки (page_id == 0 ), але цей спосіб не є надійним.
|
page_title и page_prefixedtitle
|
рядок | Назва сторінки без префіксу простору назв та повна назва відповідно. |
page_namespace
|
число | Номер простору назв, в якому розташована сторінка. |
page_age
|
число | Кількість секунд, що пройшли з першого редагування сторінки (при створенні дорівнює 0). Використовується для точного визначення створення сторінки, але працює повільніше, ніж page_id
|
Змінні, доступні за певних обставин | ||
Змінна | Тип даних | Опис |
summary
|
рядок | Опис редагування, що виконується. Потрібно пам'ятати, що автоматично генеровані движком описи на кшталт «Повністю видалено вміст сторінки» створюються після перевірки фільтром. |
old_size и new_size
|
число | Розмір сторінки до та після редагування відповідно. |
edit_delta
|
число | Різниця між розмірами сторінки до та після редагування. Відповідає виразу new_size - old_size .
|
added_lines і removed_lines
|
масив рядків | Рядки, які були відповідно додані та видалені під час редагування. |
added_links і removed_links
|
масив рядків | Містить списки всіх зовнішніх посилань, доданих та віддалених під час редагування. Це повільні змінні, тому для підвищення продуктивності краще спочатку перевіряти added_lines та removed_lines .
|
file_size
|
число | Вага файлу, що завантажується в байтах. |
file_width і file_height
|
число | Геометричні розміри файлу, що завантажується в пікселях — ширина і висота. |
file_mime
|
рядок | MIME-тип файлу, що завантажується. Наприклад, image/jpeg .
|
old_wikitext и new_wikitext
|
рядок | Повний код сторінки до редагування та після. Вміст може досягати величезних розмірів, тому краще спочатку перевіряти added_lines та removed_lines .
|
new_text и new_html
|
рядок | Текст сторінки після редагування, позбавлений будь-якого виду розмітки, і повний HTML-код нового контенту. Можуть містити багато даних, тому краще використовувати інші змінні. |
Функції[]
Крім змінних розширення додає функції. Вони призначені для зміни вхідних даних та спрощення перевірок.
Функція | Опис |
---|---|
bool(arg) , int(arg) , float(arg) і string(arg)
|
Наводять тип аргументу arg до логічного, цілісного, дробового та рядкового відповідно.
|
ccnorm(arg)
|
Нормалізує схожі символи в даному рядку arg та повертає результат у верхньому регістрі. Повний список замін при нормалізації можна знайти на Phabricator Wikimedia.
|
contains_all(example, arg1, arg2, ...)
|
Повертає true , якщо підрядок example входить у кожний з даних аргументів arg .
|
contains_any(example, arg1, arg2, ...)
|
Повертає true , якщо підрядок example входить у будь-який даний аргумент arg .
|
count(needle, haystack)
|
Підраховує кількість входжень підрядка needle у рядок haystack .
|
rcount(needle, haystack)
|
Діє аналогічно до попередньої функції, але як needle набуває регулярного виразу.
|
equals_to_any(left, right1, right2, ...)
|
Повертає true , якщо аргумент left строго дорівнює будь-якому аргументу right . Запис equals_to_any(a, b, c) еквівалентний a === b | a === c .
|
get_matches(needle, haystack)
|
Знаходить всі входження захоплюючих дужок (capture groups) регулярного виразу needle у рядок haystack і повертає їх як масив рядків. Перший елемент такого масиву міститиме повне входження.
|
ip_in_range(ip, range)
|
Перевіряє, чи знаходиться ця IP-адреса ip у діапазоні range згідно з адресацією CIDR.
|
lcase(arg) і ucase(arg)
|
Переводить цей рядок arg у нижній та верхній регістр відповідно.
|
length(arg)
|
Повертає кількість символів у даному рядку або кількість елементів у даному масиві arg .
|
rescape(arg)
|
Екранує спецсимволи в даному рядку arg за допомогою зворотного слешу. Перетворений рядок може бути використаний у регулярному виразі буквально.
|
rmdoubles(arg) , rmspecials(arg) і rmwhitespaces(arg)
|
Підчищають рядок arg відповідно від повторюваних символів, спецсимволів та порожніх місць (пробіли, таби та перенесення рядків).
|
norm(arg)
|
Повністю нормалізує цей рядок arg та повертає результат. Еквівалентна комбінації функцій rmwhitespace(rmspecials(rmdoubles(ccnorm(arg)))) .
|
set(name, value)
|
Записує значення value у змінну name . Еквівалентна запису name:=value; .
|
strpos(haystack, needle, offset?)
|
Знаходить позицію першого входження підрядка needle у рядок haystack . Також можна вказати мінімальний індекс offset , з якого розпочнеться пошук.
|
substr(arg, offset, length?)
|
Видаляє вміст рядка arg до позиції offset і повертає решту. Можна вказати довжину відрізу length , тобто запис substr("foobar", 2, 3) поверне "oba" .
|
Порядок дій[]
Ще один важливий аспект роботи з розміткою фільтра зловживань – це порядок виконання дій. Нижче наданий пріоритет операцій у порядку спадання:
- Вирази в дужках
( )
обробляються насамперед; - Підстановка відповідних даних замість назв змінних (наприклад,
action → "edit"
); - Виклик функцій (наприклад,
upper("foo") → "FOO"
); - Виконання унарних операторів
+
та-
, що визначають знак числа; - Обробка ключових слів (наприклад,
"a" in "bar" → true
); - Логічна інверсія (
!x
); - Зведення в ступінь (
2 ** 6 → 64
); - Множення та розподіл (оператори
* / %
); - Складання та віднімання, у тому числі конкатенація (оператори
+ -
); - Порівняння (оператори
< > ==
); - Бінарні операції (оператори
& | ^
).
Крім того, фільтр перевіряє умови щодо стратегії обчислень Маккарті, тобто до першого true
для логічного OR та до першого false
для логічного AND. Ось кілька прикладів, де наголошено на тій частині умови, після якої подальше обчислення припиняється:
false | true | false | false → true
;false & true & true & false → false
;(true | false) & false & (true & true) → false
(стратегія працює всередині кожної групи).
Підрахунок умов[]
Правила спрацьовування кожного створеного фільтра мають обмеження кількості умов, що використовуються. Ці ліміти накладаються системою для збереження високої продуктивності розширення. За замовчуванням максимальна кількість умов — 1000, фільтри з великим числом не працюватимуть.
При роботі з фільтром зловживань рекомендується складати правила так, щоб використовуваних умов було якнайменше. Однак для цього потрібно знати, як саме відбувається підрахунок, а нижче таблиця це проілюструє:
Правило підрахунку | Приклад | Кількість умов |
---|---|---|
Прості порівняння та перевірки вважаються однією умовою. | "foo" == "bar" |
1 |
"pine" in "pineapple" & 4 < 8 |
2 | |
Вважається кожна умова, яка виконується у стратегії вирахувань Маккарті. Таким чином, у першому прикладі обчислюється тільки перша умова, що дорівнює false , а в другому — перші два, рівні false і true відповідно.
|
"bar" == "bas" & 3 + 4 == 7 |
1 |
4 < 3 | 5 == "5" | "foo" in "bar" |
2 | |
Кожен виклик функції вважається однією умовою. | lcase("EXAMPLE") == "example" |
2 |
Повторний виклик функції з ідентичними аргументами не рахується. | lcase("EXAMPLE") contains "ex" & lcase("EXAMPLE") == "example" |
3 |
lcase("EXAMPLE") contains "ex" & lcase("FOO") == "foo" |
4 |
Додатково можна розглянути приклад фільтра, який використовується на англійській Вікіпедії і зараз:
page_namespace == 6
& !("autoconfirmed" in user_groups)
& !(user_name in page_recent_contributors)
& rcount ("\{\{.*\}\}", removed_lines) > rcount ("\{\{.*\}\}", added_lines)
Можна спростити уявлення: A & !B & !C & fun1 > fun2
. Тепер оцінити кількість умов, що використовуються, стає простіше.
- 1 умова (1 порівняння) використовується, коли номер простору назв відрізняється від 6 (простір «Файл»). Перший тест хибний, все інше принципу коротких обчислень не обробляється.
- 2 умови (2 порівняння) — редагування відбувається у просторі файлів, але користувач не має статусу автопідтвердженого. Перший істинний тест, другий помилковий — інші умови не обчислюються.
- 3 умови (3 порівняння) — редагування робиться підтвердженим користувачем у просторі файлів, але його імені немає у списку недавніх вкладників цієї сторінки. Перші два тести істинні, а цей закладений залишок ігнорується.
- 6 умов (3 порівняння + 2 виклики функцій + 1 порівняння їх результатів) — якщо раніше згаданий користувач пройшов усі попередні перевірки та видалив зі сторінки шаблони, цей тест буде дійсним, а фільтр спрацює. В іншому випадку все правило фільтра буде вважатися хибним, і він промовчить.
Насправді виходить, що розширення завершуватиме обчислення ще першому тесті, оскільки більшість редагувань посідає основний простір назв. Саме тому рекомендується загальні перевірки виносити вперед — черга виконання просто не дійде до важких умов, а фільтр працюватиме швидше.
Посилання[]
- Сторінка розширення AbuseFilter на MediaWiki.org
- Опис синтаксису фільтру на MediaWiki.org
- Як вважається кількість умов фільтру зловживань (MediaWiki.org)
- Тести умов фільтра на Wikimedia Phabricator
Загальні | |
---|---|
Спеціалізовані |
|
Для роботи з ботами |
|