//LimeChat2用のIRCbotスクリプト。apiから編集フィルターのログを取得し、設定したチャンネルに情報を整形して投稿する。
//2010年11月27日 LimeChat 2.38/WindowsXP にて動作を確認。ただし★メモリーリークの為、数時間の動作が今のところ限界★
//LimeChatの「設定」->「スクリプトの設定」->「スクリプトフォルダを開く」で開いたフォルダに、当ファイルを IRCbot.js などと名前を付けて保存。
//対象チャンネルに入室したあと、「スクリプトの設定」でサーバー名の上で右クリックすると、「○」ボタンが表示されてスクリプトが有効化、自動で実行される。
var yourChannel = '##irc-bot-test-channel';//テキスト送信先のチャンネルの設定。##irc-bot-test-channelはテスト用チャンネルなので自由に投稿可。
var wgServer = 'http://ja.wikipedia.org';//サイトの指定
var wgScriptPath = '/w';//スクリプトパス。Wikimediaプロジェクトであれば、おそらく全て /w で共通。
//対処操作の内容を日本語表示に置き換えるための配列。 \x03 の後ろに番号で色が変わる。再度 \x03 と打つと元に戻る。 \x02 で挟まれている部分は太字
//色については http://hiki.koubou.com/IRC/?mIrcColors 等を参照
var lang_filterResult = [
{ before: '', after: '\x0301なし\x03' },
{ before: 'warn', after: '\x02\x0304通知\x03\x02' },
{ before: 'tag', after: '\x0305タグ付け\x03' },
{ before: 'disallow', after: '\x02\x0304防止\x03\x02' }
];
//当スクリプトはapi経由でウィキペディアの最近の更新(Recent changes、こうしたURL↓)を読み込み、
// http://ja.wikipedia.org/w/api.php?action=query&list=recentchanges|logevents|abuselog&rcprop=user|comment|flags|timestamp|title|ids|sizes|tags&format=xml
//そこで得たデータを処理して、IRC上のチャンネルにリアルタイムでテキストを投稿します。
//
//スクリプトは一番下に書かれている関数からまず呼び出され、上へ上へと順に実行されていきます。
//apiの読み込み等に特に問題がなければ、一番上にある filterDescription() および processRC() の二つの関数を変更すれば、大体のカスタマイズが可能です。
//当スクリプトの基幹部分は [[LiveRC]](by [[:fr:User:Educa33e]]他) を元に作成しました。
//編集フィルターについて、id番号からフィルターの内容を取得し、結果を整形してチャンネルに投稿するための関数
function filterDescription(xmlreq, data) {
var xmlinfo = xmlreq.responseXML.getElementsByTagName('api')[0];
if (xmlinfo.firstChild.nodeName == "error") return;//取得した内容がエラーであれば処理中止。
//フィルター番号の内容 例えば「小さすぎる記事の作成」といった名称をを取り出す。
var filterDescription = xmlinfo.getElementsByTagName('abusefilters')[0].getElementsByTagName('filter')[0].getAttribute('description');
var filterlog = data.filterlog;//ログの内容を受け取る。利用者名、ページ名などは全てここに入っている
//対処操作の内容を日本語表示に置き換える。
var filterResult = filterlog.getAttribute('result');
for (var _i=0; _i<lang_filterResult.length; _i++){
if (filterResult == lang_filterResult[_i].before)
filterResult = lang_filterResult[_i].after;
}
var postText;//投稿するテキストを格納するための変数
//テキストを作る。 \x03 の後ろに番号で色が変わる。再度 \x03 と打つと元に戻る。 色については http://hiki.koubou.com/IRC/?mIrcColors 等を参照
postText = ' [[\x0307' + filterlog.getAttribute('title') + '\x03]]'
+ ' \x0305*\x0303 ' + filterlog.getAttribute('user') + '\x03 '
+ ' \x0310' + filterDescription + ' \x0305*\x03'
+ ' 対処操作: ' + filterResult + ' '
+ wgServer + '/wiki/Special:Contributions/' + filterlog.getAttribute('user');
send(yourChannel, postText);//IRCのチャンネルにテキストを送信。
}
//api経由でデータ取得に成功したら、ここでその内容を処理する。
function processRC(xmlreq, data) {
var api = xmlreq.responseXML.getElementsByTagName('api')[0];
if (api.firstChild.nodeName == "error") return; //取得した内容がエラーであれば処理中止。
//普通の編集、ログ、フィルター記録、の三つを切り分けて、別々の変数に格納
var rcs = api.getElementsByTagName('query')[0].getElementsByTagName('recentchanges')[0].getElementsByTagName('rc');
var logs = api.getElementsByTagName('query')[0].getElementsByTagName('logevents')[0].getElementsByTagName('item');
var filters = api.getElementsByTagName('query')[0].getElementsByTagName('abuselog')[0].getElementsByTagName('item');
var itemLength;//ログの個数を格納するための変数
var filter_no;//フィルターの番号を入れる変数
itemLength = filters.length;//フィルター記録の長さを取得
for (i=itemLength-1; i>=0; i--) {//取得したデータの内、古いものから順に表示
if (filters[i].getAttribute('id') > lastFILTERid) {//一度表示したものは表示しない。idが前回 最後に表示したものより大きい場合のみ、表示。
filter_no = filters[i].getAttribute('filter_id');//フィルターの番号を取得
//フィルター番号の内容 例えば「小さすぎる記事の作成」といった名称を、次のようなURLからapi経由で取得。
// http://ja.wikipedia.org/w//api.php?action=query&list=abusefilters&abflimit=1&format=xml&abfstartid=10
//取得に成功したら、ログのデータを data.filterlog という名前で filterDescription() に渡す。
wpajax.http({url: wgServer + wgScriptPath + '/api.php?action=query&list=abusefilters&format=xml&abflimit=1&abfstartid=' + filter_no,
onSuccess: filterDescription, filterlog: filters[i] });
}
}
//次回、重複表示を避けるために、取得したデータの内、最も新しいもののidを取得して変数に格納
lastRCid = rcs[0].getAttribute('rcid');
lastLOGid = logs[0].getAttribute('logid');
lastFILTERid = filters[0].getAttribute('id');
//次にapiを呼び出す時のために、取得したデータの内、最も新しいもののタイムスタンプを取得して変数に格納
lastRCtimestamp = rcs[0].getAttribute('timestamp')
lastLOGtimestamp = logs[0].getAttribute('timestamp')
lastFILTERtimestamp = filters[0].getAttribute('timestamp')
}
//Ajax用の変数、関数
var wpajax = {
http: function(bundle) {
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
if (xmlhttp) {
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4)
wpajax.httpComplete(xmlhttp,bundle);
};
xmlhttp.open('GET', bundle.url, true);
if (bundle.headers) {
for (var field in bundle.headers)
xmlhttp.setRequestHeader(field,bundle.headers[field]);
}
xmlhttp.send(bundle.data ? bundle.data : null);
}
return xmlhttp;
},
httpComplete: function(xmlhttp,bundle) {
if (xmlhttp.status == 200 || xmlhttp.status == 302) {
if (bundle.onSuccess)
bundle.onSuccess(xmlhttp,bundle);
} else if (bundle.onFailure) {
bundle.onFailure(xmlhttp,bundle);
} else {
// その他の場合の設定
// alert(xmlhttp.statusText);
}
}
};
//この関数をループする。定期的にこの関数を呼び出して、api経由で最近の更新のデータを取る。
//データが取れたら processRC() を呼び出す。
var lastRCid=0,lastFILTERid=0,lastLOGid=0,lastRCtimestamp=1,lastLOGtimestamp=1,lastFILTERtimestamp=1,RCLimitSize=10;
function getRCloop() {
var interval = 1; //ループの間隔。秒で指定
setTimeout(getRCloop, 1000*interval);
//apiのURLを設定
var rcURL = wgServer + wgScriptPath
+ '/api.php?action=query&list=recentchanges|logevents|abuselog'
+ '&rcprop=user|comment|flags|timestamp|title|ids|sizes|tags'
+ '&rcend=' + lastRCtimestamp + '&rclimit=' + RCLimitSize
+ '&leend=' + lastLOGtimestamp + '&lelimit=' + RCLimitSize
+ '&aflend=' + lastFILTERtimestamp + '&afllimit=' + RCLimitSize
+ '&format=xml';
//api経由で最近の更新を読み込む。成功したら processRC() に読んだデータを渡す。失敗したらここで終わり。
wpajax.http({url:rcURL, onSuccess: processRC});
}
//一番最初に一度だけ呼び出される関数。 ここで getRCloop() をロードし、後はそちらで永遠にループ。
function event::onLoad(prefix, channel, text) {
getRCloop();
}
//[[Category:IRC (ウィキペディア関連)]]