Wikipedia:編集フィルター/作り方

半保護されたページ

フィルターを作る

この節では、最近更新したフィルターをあふれさせないように、予備テストをしてフィルターを作る方法を説明します。

  • ルールの書式を読みます。
  • デバッグツール
    たとえば、'文字列' rlike '正規表現'を入力します。結果が真ならば1が表示され、偽なら何も表示されません。
  • テストページ
    対象にしたい操作を最近行なった利用者を探します。
    「変更した利用者:」欄にそのユーザー名を入力し、「テスト」ボタンをクリックします。
    もし、発動条件が有効にならない場合、
    「フィルターに一致しない変更を表示する」を有効にし、再度テストします。
    あなたが対象としていた操作を見つけたら、「(分析)」をクリックし、変数を確認してください。
  • 作成したいフィルターが有用なものに出来そうであれば、Wikipedia:編集フィルター/提案で提案し、作成に関して合意形成をしてください。
  • 合意がとれたら、特別:不正利用フィルター/newから、対処操作のない(つまり、ログを取るだけの)フィルターを作成し、1週間の試験運用を行ないます。
    これは、誤作動(対象ではないのに作動する、あるいは対象なのに作動しないなど)がないかのテストのために必要です。
    メモ:の欄に「試験運用中 -- あなたの利用者名 日付」のように、試験運用を開始したことを書いてください。
  • Wikipedia:編集フィルター/提案にある提案を試験運用中に変更し、他の人があなたのフィルターを修正したり警告を改善したりできるようにしてください。
  • 試験期間を経て問題が起きなければ、最後に、作成したフィルターに対処操作を付与してください。

既存のフィルターの再利用

削除/無効化してあるフィルターを、中身を全く違うものとして書き直して使用したり、フィルターの中身を分離し分離元のフィルターと目的も中身も全く違うものにしたりすると、過去のコードや一致記録に複数条件が混在してしまうため、読みにくく、検索しにくくなります。可能な限り新規に作成するようにしましょう。

フィルターを編集する

編集フィルターは、編集フィルター編集者であれば、誰でも編集することができます。

フィルターを編集した際には、メモの部分に、その変更の要約と署名を「要約 -- あなたの利用者名 日付」のように書いてください。

性能を上げる

これらのフィルターはあらゆる編集時に働くので、フィルターは編集速度の著しい低下や、大きなページのタイムアウトを引き起こす可能性があります。しかし、発動条件へのほんの小さな修正でフィルターの動作時間を短縮できるかもしれません。演算の順序を意識することでパフォーマンスの差が生じることがあります。

演算順序

演算は原則として左から右に向かいますが、それ以外の順序もありえます。フィルターが条件の一つに引っかかると、残りの条件チェックは中止され(短絡評価)、次のフィルターに移ります。評価順序は次の通りです。

  1. 括弧の中 ((Expression))
  2. 数値、文字列、変数 (123, "abc", user_name, …)
  3. 関数 (norm ,lcase, …)
  4. 符号 (+, -)
  5. キーワード
  6. 論理否定 (!x)
  7. 累乗 (2**3)
  8. 乗算、除算、剰余(*, /, %)
  9. 比較演算子 (<, >, ==)
  10. 論理演算子 (&, |, ^, in)

フィルターの負荷を軽くする

rlike, incontainsのようなキーワードを使う場合、フィルターは文字列全体から検索しなければなりません。old_wikitext のような変数はとても大きくなりがちです。そういった場合、added_linesremoved_linesのような変数で、それに近い、または同等の効果を得られ、かつ何倍にも高速にすることができます。また、old_size にチェックを入れることで、テキスト全体をチェックしようとしているのではないと確認することができます。

もっとも当てはまりやすいような条件が最初に来るようにフィルターを順序づけるべきです。おおむね、利用者グループや利用者の編集回数のチェックがこれに当たります。原則として、あなたがターゲットにしている種類の荒らしを探す正規表現を最終条件とすべきです。

発動条件にはコメントを書く

発動条件式は「式」であるので、一般的に、人間にとってそのまま理解しやすい形式ではありません。 特に、条件が複雑になってくると、その式(1行)が何を目的とした式なのかを理解することは難しくなります。

ですから、発動条件には、なるべく詳しくコメントを書くようにしてください。 コメントは/* コメント */のように、「/*」と「*/」で挟んでください。

メモを活用する

各編集フィルターには、発動条件のみではなく、公開フィルターであれば誰でも、非公開フィルターであれば編集フィルター編集者が閲覧することができる「メモ」があります。

このメモは通常、フィルターの簡単な説明と変更要約の保存に使われており、概ね以下のような形式が推奨されます。

このフィルターは、こういう条件のもとでこういう動作を実行します。
:[[Wikipedia:編集フィルター/一覧/フィルター名]]

== 変更要約 ==
変更したことA -- 編集者名 (変更日)
: 変更したことAa -- ウィキすけ 2011-01-01
: 変更したことAb -- ウィキさん 2011-01-02
:: 変更したことAba -- ウィキすけ 2011-02-01

変更したことB -- ウィキくん 2011-01-15
: 変更したことBa -- ウィキくん 2011-01-16

他のフィルター編集者または利用者のためにも、メモは面倒臭がらず丁寧に作成し残すようにしてください。

誤動作を防ぐ工夫をする

以下のような構文上の工夫をすることで、誤動作を防ぐことができる場合があります。

「追加除去キーワード一致」系の編集フィルター

特定のキーワードが追加除去された場合に発動するフィルターを作る場合、利用者がそのキーワードを追加除去していない場合には発動しないように正しく設定する必要があります。具体的には、Aというキーワードに反応したいフィルターがあった場合

contains_any(added_lines, A) /* よくない例です! */

というような式にすると問題が発生する場合があります。なぜなら(added|removed)_lines変数は名前にlinesと書かれている通り行単位なので、利用者がそのキーワードを追加除去していない場合にも、元の行にそのキーワードが含まれていると発動してしまうからです。その場合、次のようにすれば正しく設定できます。

/* 追加系の場合 */
contains_any(added_lines, A) & !contains_any(removed_lines, A)
/* 除去系の場合 */
contains_any(removed_lines, A) & !contains_any(added_lines, A)

具体的には、例えば次のようにすることができます。

& contains_any(rmwhitespace(lcase(added_lines)),
    "ほげほげ",
    "ほげっほげ",
    "ふがふが"
)
& !contains_any(rmwhitespace(lcase(removed_lines)),
    "ほげほげ",
    "ほげっほげ",
    "ふがふが"
)
/* 除外ワード */
& !contains_any(rmwhitespace(lcase(added_lines)),
    "ほげほげ山",
    "ふがふが高原"
)

編集フィルターは変数が使用できるので、場合によっては、例えば

& (
 keywords := "(ほげ(|っ)ほげ|ふがふが)";
 !(removed_lines regex keywords)
 &(  added_lines regex keywords)
)

とすれば、NGワードを1回ずつ記載するだけで上記の動作をさせることができます(上の例では「ほげほげ」「ほげっほげ」「ふがふが」が含まれている文を投稿しようとしたら発動します)。

ただし、contains_any関数を使う場合は、配列変数に対応しているのは第1引数(通常added_linesやremoved_linesなどを書きます)だけで、第2引数以降は対応していないので、例えば、

keywords := ["A", "B", "C"];
contains_any(added_lines, keywords) & !contains_any(removed_lines, keywords) /* よくない例です */

の様なコードを書いても正常動作しませんので、複雑な条件付けをする場合には、最初の例のように第2引数以降に列挙するのがよいでしょう。

既存のフィルターを真似る

もし初めてフィルターを作成または編集する場合、力をつける最良の方法は既存の運用中のフィルターを真似ることです。

発動条件はもちろん、メモや通知文の作り方など、他のフィルターを参考にすることが何よりの近道です。