プロジェクト:ウィキ技術部/スクリプト開発/trunk/LimeChatAbuseFilterBot.js

//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=0; i--) {//取得したデータの内、古いものから順に表示
		if (filtersi.getAttribute('id') > lastFILTERid) {//一度表示したものは表示しない。idが前回 最後に表示したものより大きい場合のみ、表示。
			
			filter_no = filtersi.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: filtersi });
		}
	}
	
	
	//次回、重複表示を避けるために、取得したデータの内、最も新しいもののidを取得して変数に格納
	lastRCid = rcs0.getAttribute('rcid');
	lastLOGid = logs0.getAttribute('logid');
	lastFILTERid = filters0.getAttribute('id');
	
	//次にapiを呼び出す時のために、取得したデータの内、最も新しいもののタイムスタンプを取得して変数に格納
	lastRCtimestamp = rcs0.getAttribute('timestamp')
	lastLOGtimestamp = logs0.getAttribute('timestamp')
	lastFILTERtimestamp = filters0.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.headersfield);
}
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();
}
//