Hatena::ブログ(Diary)

SO NOTE そうのて (;^ω^) このページをアンテナに追加 RSSフィード Twitter

2009.07.30

twitterのなに切るボット用のGreasemonkey作った

麻雀好きなら是非ともfollowすべき、id:hosimituさん作成のtwitterのなに切るボット、その名も@nanikiru。

なに切るボットの詳細についてはこちらのエントリをどうぞ→麻雀のなに切るボット作った - ある日のほしみつの(まわりの?)おしゃべり

で、@nanikiruへのpostを少し楽チンにするのと、@nanikiruのつぶやきを麻雀牌っぽくするGreasemonkey作ったので、upしてみます。

@nanikiruを少し説明

どんなボットかはhosimituさんのエントリ見てもらえばわかるんですが、軽く説明させてもらうと、@nanikiruがつぶやく「なにを切る?」の問題*1

f:id:so_blue:20090730233248p:image

自分ならこの牌切る*2なーってのを@します。

f:id:so_blue:20090730234602p:image

しばらくしたら、@nanikiruが集計結果をつぶやいてくれるので、

f:id:so_blue:20090730234855p:image

「うむ、やはりxx切りが正解だよね」と安心したり、「おいおい、なんでみんなyyきってんだよ!この局面ではzzだろjk!」などとわかった風を装ったりして楽しむ訳です。

先日、@nanikiruのまとめブログも作られたので、そちらもどうぞ→なに切る?

ソース

Greasemonkeyのソースです。おかしいとことかこうした方がいいよ!ってな部分があれば、ご指摘ください。

// ==UserScript==
// @name           nanikiruTileDirectPost
// @namespace      http://d.hatena.ne.jp/so_blue/
// @version        0.5
// @include        http://twitter.com/
// @include        https://twitter.com/
// @include        http://twitter.com/home
// @include        https://twitter.com/home
// ==/UserScript==
(function(){

	//なんとなく麻雀牌っぽくするcss
	GM_addStyle(<><![CDATA[
		span.tiles {
			display: inline-block;
			border: solid 1px #aaa;
			-moz-border-radius: 3px;
			cursor: pointer;
			margin-right: 1px;
		}
		span.tiles:hover {
			background: #ffa500;
			color: #fff;
		}
	]]></>);

	//選択した捨て牌をtextareaにセットする関数
	function choiceTile(evt) {
		var s = '@nanikiru ' + evt.target.textContent;
		var twf = document.forms.namedItem('status_update_form');
		twf.elements.namedItem('status').value = s;
		twf.elements.namedItem('status').focus();
		if (DIRECT_MODE) {
			//DIRECT_MODE = true の時はsubmitまでしちゃう
			twf.submit();
		}
	}

	//nanikiruのつぶやきを取得するXPath
	var xpath = 'id("timeline")/li[@class="hentry status u-nanikiru"]//span[@class="entry-content"]';

	//nanikiruの問題か結果を判定する正規表現
	var re = new RegExp('何を切る?');

	/*
	 * 以下、Greasemonkeyにメニューを追加
	 * http://d.hatena.ne.jp/hitode909/20090706/1246868182
	 * のエントリのソースを流用させてもらいました。(;^ω^)
	 * hitode909さん、ありがとう!!
	 */
	//ダイレクトポスト設定真偽値取得 ※デフォルトはfalse(ダイレクトポストしない)
	var DIRECT_MODE = eval(GM_getValue('DIRECT_MODE'));
	if (typeof(DIRECT_MODE) == 'undefined') {
		DIRECT_MODE = false;
	}
	//ダイレクトポスト設定メニューを作る
	GM_registerMenuCommand(
		'捨て牌ダイレクトポスト切替',
		function() {
			DIRECT_MODE = !DIRECT_MODE;
			GM_setValue("DIRECT_MODE", uneval(DIRECT_MODE));
			var directText = DIRECT_MODE ? 'する': 'しない';
			alert('捨て牌ダイレクトポスト => ' + directText);
		});

	var func = function(docs) {
		var qs = document.evaluate(xpath, docs, null, 7, null);
		if (qs) {
			var i, j, k, l;
			for (i = 0, j = qs.snapshotLength; i < j; i++) {
				var q = qs.snapshotItem(i);
				var txt = q.textContent.replace('カンツモ', '');
				if (re.test(txt)) {
					//textContentを牌部分と問題文部分に切り分け
					var txt1 = txt.substring(0, 14);
					var txt2 = txt.substring(14);
					//牌をsplit
					var arr = txt1.split('');
					//テキストコンテントをクリア
					q.textContent = '';
					//牌の数のspan要素、子要素のテキストノードを生成してappnedChild
					for (k = 0, l = arr.length; k < l; k++) {
						var elm = document.createElement('SPAN');
						elm.className = 'tiles';
						elm.addEventListener('click', choiceTile, false);
						elm.appendChild(document.createTextNode(arr[k]));
						q.appendChild(elm);
					}

					//ツモとカンの選択肢追加
					var elm = document.createElement('SPAN');
					elm.className = 'tiles';
					elm.addEventListener('click', choiceTile, false);
					elm.appendChild(document.createTextNode('カン'));
					q.appendChild(elm);

					var elm = document.createElement('SPAN');
					elm.className = 'tiles';
					elm.addEventListener('click', choiceTile, false);
					elm.appendChild(document.createTextNode('ツモ'));
					q.appendChild(elm);

					//問題文のテキストコンテント追加
					q.appendChild(document.createTextNode(txt2));
				}
			}
		}
	}

	/*
	 * 以下AutoPagerize対応
	 * http://os0x.g.hatena.ne.jp/os0x/20080326/1206542957
	 * のエントリのAutoPagerize対応サンプルを流用させてもらいました。(;^ω^)
	 * os0xさん、ありがとう!!
	 */
	func(document);
	
	if (window.AutoPagerize) {
		boot();
	} else {
		window.addEventListener('GM_AutoPagerizeLoaded', boot, false);
	}
	
	function boot() {
		window.AutoPagerize.addFilter(function(docs) {
			docs.forEach(func);
		});
	}

})();
パクらせて参考にさせてもらったエントリー

効果説明

  • @nanikiruのつぶやきを麻雀牌風にアレンジ
  • 牌部分クリックで直接@nanikiruに@ or 「投稿する」ボタンを自分でクリックして@ を切り替え可能
  • カン、ツモの選択肢追加

f:id:so_blue:20090731010258p:image

f:id:so_blue:20090731012540p:image

インストール

よければどうぞ。

no title

追記

つぶやき部分のli要素に設定されてるclassセレクタの設定順が変わってたんでXPathを修正。

hentry status u-nanikiru → hentry u-nanikiru status

こういうのにも対応出来る様にXPath書くにはどうすればいいんだろ…

[追記ここまで]

ソースを色々修正しました。(なので、現在は↑のソースとは全然違ってます。)
あと、@時に#nanikiruのハッシュタグがつく様にしました。


ついでになに切るボットへの要望みたいなのを…

現状は、なに切るボットがつぶやいた問題に対してフォロワーは回答するのみですが、例えば、

@nanikiru 11122344455678 -Q

といった感じで@すると、フォロワーサイドからも問題が作成出来る、といった機能を追加すると、更に楽しいかもなーなんて思いました。

フォロワーが作成した問題はどっかに蓄積していって、たまにフォロワーが作成した問題をつぶやかせると。更にその時は、「この問題は@so_blueが作成しました」みたいな感じで問題作成者も紹介すると、作った人も嬉しかったりするから、更に問題を@、で、そのうちフォロワーの作った問題だけでボットがつぶやけるみたいな。

これはいいなに切る問題だ!ってのがあれば、フォロワーはその問題をふぁぼるかもしれないので、そうなれば、ふぁぼられ度からなに切る問題ランキングとかも作れたり。

とまぁ

勝手にあれこれ言ってすいません。(;^ω^)

まとまらない感じだけど、久々に長いエントリー書いて疲れたんでこれにてup。

*1:30分に一回ほどつぶやいてくれます。

*2:牌姿によってはツモやカンも出来ます。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/so_blue/20090730/1248974916