miyagawaさんのAnyEvent::Twitter::Streamを使って「NullPointerException」をtrackして「Ga!!」を返信するスクリプトを書いてみた。trackにマルチバイトが使えないのが残念。「がっ!!」にしても良いけど、出来れば欧米の方達にも反応したい。
#!/usr/bin/perl
use strict;
use warnings;
use Config::Pit;
use AnyEvent::Twitter::Stream;
use Net::Twitter::Lite;
binmode STDOUT, ":utf8";
my $config = pit_get("nullpo-ga", require => {
"username" => "your username on twitter.com",
"password" => "your password on twitter.com"
});
my $nt = Net::Twitter::Lite->new(
username => $config->{username},
password => $config->{password},
);
my $done = AnyEvent->condvar;
my $streamer = AnyEvent::Twitter::Stream->new(
username => $config->{username},
password => $config->{password},
method => "track",
( track => 'NullPointerException' ),
on_tweet => sub {
my $tweet = shift;
print "$tweet->{user}{screen_name}: $tweet->{text}\n";
eval { $nt->update("\@$tweet->{user}{screen_name} Ga!!") };
},
on_error => sub {
my $error = shift;
warn "ERROR: $error";
$done->send;
},
on_eof => sub {
$done->send;
},
);
$done->recv;
追記
miyagawaさんから返信のupdateでブロックしちゃうのでAnyEvent::Twitter使えば良いと教えて貰いました。
#!/usr/bin/perl
use strict;
use warnings;
use Config::Pit;
use AnyEvent::Twitter;
use AnyEvent::Twitter::Stream;
binmode STDOUT, ":utf8";
my $config = pit_get("nullpo-ga", require => {
"username" => "your username on twitter.com",
"password" => "your password on twitter.com"
}
);
my $done = AnyEvent->condvar;
my $twitty = AnyEvent::Twitter->new(
username => $config->{username},
password => $config->{password},
);
my $streamer = AnyEvent::Twitter::Stream->new(
username => $config->{username},
password => $config->{password},
method => "track",
( track => 'NullPointerException' ),
on_tweet => sub {
my $tweet = shift;
print "$tweet->{user}{screen_name}: $tweet->{text}\n";
$twitty->update_status("\@$tweet->{user}{screen_name} Ga!!", sub {
my ($twitty, $status, $js_status, $error) = @_;
if (defined $error) {
warn "ERROR: $error";
}
}
);
},
on_error => sub {
my $error = shift;
warn "ERROR: $error";
$done->send;
},
on_eof => sub {
$done->send;
},
);
$done->recv;
MOONGIFTでKeepNoteってのを知った。
MOONGIFT: » Evernoteのような個人用スクラップブック「KeepNote」:オープンソースを毎日紹介
今回紹介するオープンソース・ソフトウェアはKeepNote、マルチプラットフォームで動作するメモアプリケーションだ。
http://www.moongift.jp/2009/07/keepnote/
試してみた。WYSIWYGエディタでなかなか良い。
MOONGIFTでは
GTKとあって、Windows上での動作がちょっと不安定な気もする。マルチプラットフォームで動作するメモ環境に興味のある方は試してみよう。
と書かれていたけど、少し手を加えるだけで結構使い勝手が良くなった。
以下、WindowsでKeepNoteを使う場合のフリカケ。
日付表示でロケールを使わない
そのままだと、一覧に表示される作成日付が「%p」というAM/PMをロケールに直した物が使われるが、utf-8なGTKにも関わらずWindowsなのでシフトJISが使われてしまう。設定画面で、AM/PM付き12時間表記「%I:%M %p」から24時間表記「%H:%M」に直す。
ちなみに、もしソースからコンパイルされたのであれば g_locale_to_utf8 という関数で utf-8 に直すようなpatchを書くといい。
入力モジュールを追加する
KeepNoteのWindows版にはimmoduleというGTK上での入力機構モジュールが同根されていない。入力出来ない訳ではないが OverTheSpot な入力は出来ない。そこで
ここからGTKのランタイムを持ってきて中にある
lib/gtk-2.0/2.10.0/immodules/
をKeepNoteにコピーする。これで完了。
この2つだけでもグンと使いやすくなった。
このKeepNote、ページ自身はHTMLで出力されるのでノート出力先フォルダをDropboxにしておけば、もうEvernoteですね。
Linux版もあるので、試してみよう。
jjencode素晴らしいですね。記号だけでjavascriptが実行出来てしまいます。
何かに使えないかなーと考えて、apacheのmod_ext_filterを使ってjavascriptの難読サーブをやってみようかと思います。
javascriptエンジンとして使うのは、v8。本当は全部Cで書けば速いのでしょうがメンドクサイのでやりません。
以下フィルタのソース
crypt-js.cc
#include <v8.h>
#include <string>
#include <iostream>
static std::string&
replace_string(std::string& str, const std::string from, const std::string dest) {
std::string::size_type n, nb = 0;
while((n = str.find(from, nb)) != std::string::npos) {
str.replace(n, from.size(), dest);
nb = n + dest.size();
}
return str;
}
v8::Handle<v8::Value> Print(const v8::Arguments& args) {
bool first = true;
for (int i = 0; i < args.Length(); i++) {
v8::HandleScope handle_scope;
if (first) {
first = false;
} else {
printf(" ");
}
v8::String::Utf8Value str(args[i]);
const char* cstr = *str ? *str : "";
printf("%s", cstr);
}
printf("\n");
return v8::Undefined();
}
int main(int argc, char* argv[]) {
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
v8::HandleScope handle_scope;
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print));
v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context);
std::string line, content;
while(!std::cin.eof()) {
std::getline(std::cin, line);
content += line;
}
replace_string(content, "\\", "\\\\");
replace_string(content, "'", "\\'");
line = "var text = '";
line += content;
line += "';";
line +=
"var r=\"\";"
"var n;"
"var t;"
"var b=[ \"___\", \"__$\", \"_$_\", \"_$$\", \"$__\", \"$_$\", \"$$_\", \"$$$\", \"$___\", \"$__$\", \"$_$_\", \"$_$$\", \"$$__\", \"$$_$\", \"$$$_\", \"$$$$\", ];"
"for( var i = 0; i < text.length; i++ ){"
" n = text.charCodeAt( i );"
" if( n < 128 ){"
" r += \"\\\"\\\\\\\\\\\"+\" + n.toString( 8 ).replace( /[0-7]/g, function(c){ return \"$.\"+b[ c ]+\"+\" } );"
" }else{"
" r += \"\\\"\\\\\\\\\\\"+$._+\" + n.toString(16).replace( /[0-9a-f]/gi, function(c){ return \"$.\"+b[parseInt(c,16)]+\"+\"} );"
" }"
"}"
"print("
"\"$=~[];$={___:++$,$$$$:(![]+\\\"\\\")[$],__$:++$,$_$_:(![]+\\\"\\\")[$],_$_:++$,$_$$:({}+\\\"\\\")[$],$$_$:($[$]+\\\"\\\")[$],_$$:++$,$$$_:(!\\\"\\\"+\\\"\\\")[$],$__:++$,$_$:++$,$$__:({}+\\\"\\\")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};\"+"
"\"$.$_=\"+"
"\"($.$_=$+\\\"\\\")[$.$_$]+\"+"
"\"($._$=$.$_[$.__$])+\"+"
"\"($.$$=($.$+\\\"\\\")[$.__$])+\"+"
"\"((!$)+\\\"\\\")[$._$$]+\"+"
"\"($.__=$.$_[$.$$_])+\"+"
"\"($.$=(!\\\"\\\"+\\\"\\\")[$.__$])+\"+"
"\"($._=(!\\\"\\\"+\\\"\\\")[$._$_])+\"+"
"\"$.$_[$.$_$]+\"+"
"\"$.__+\"+"
"\"$._$+\"+"
"\"$.$;\"+"
"\"$.$$=\"+"
"\"$.$+\"+"
"\"(!\\\"\\\"+\\\"\\\")[$._$$]+\"+"
"\"$.__+\"+"
"\"$._+\"+"
"\"$.$+\"+"
"\"$.$$;\"+"
"\"$.$=($.___)[$.$_][$.$_];\"+"
"\"$.$($.$($.$$+\\\"\\\\\\\"\\\"+\" + r + \"\\\"\\\\\\\"\\\")())();\");";
v8::Handle<v8::String> source = v8::String::New(line.c_str(), line.size());
v8::TryCatch try_catch;
v8::Handle<v8::Script> script = v8::Script::Compile(source, v8::String::New(""));
v8::Handle<v8::Value> result = script->Run();
return 0;
}
エスケープして変数textに入れて、残りはjjencodeそのままです。
これをhttpd.confで以下の様に設定します。
LoadModule ext_filter_module modules/mod_ext_filter.so
ExtFilterDefine crypt_js mode=output intype=application/x-javascript cmd="/path/to/crypt-js"
出来ました。簡単ですね。
これで以下のjavascriptをダウンロードしてみます。
window.alert('hasegawa!');
コマンドラインから...
curl http://localhost:8080/filter/foo.js
$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+"\\"+$.__$+$.$$_+$.$$$+"\\"+$.__$+$.$_$+$.__$+"\\"+$.__$+$.$_$+$.$$_+"\\"+$.__$+$.$__+$.$__+"\\"+$.__$+$.$_$+$.$$$+"\\"+$.__$+$.$$_+$.$$$+"\\"+$.$_$+$.$$_+"\\"+$.__$+$.$__+$.__$+"\\"+$.__$+$.$_$+$.$__+"\\"+$.__$+$.$__+$.$_$+"\\"+$.__$+$.$$_+$._$_+"\\"+$.__$+$.$$_+$.$__+"\\"+$.$_$+$.___+"\\"+$.$__+$.$$$+"\\"+$.__$+$.$_$+$.___+"\\"+$.__$+$.$__+$.__$+"\\"+$.__$+$.$$_+$._$$+"\\"+$.__$+$.$__+$.$_$+"\\"+$.__$+$.$__+$.$$$+"\\"+$.__$+$.$__+$.__$+"\\"+$.__$+$.$$_+$.$$$+"\\"+$.__$+$.$__+$.__$+"\\"+$.$__+$.__$+"\\"+$.$__+$.$$$+"\\"+$.$_$+$.__$+"\\"+$.$$$+$._$$+"\"")())();
おぉ!
HTMLから実行してみました。
おぉ!
これいいね!とか思ってjQueryでやってみたら、30秒以上は戻って来ませんでした... orz