以前からやってみたかったことを実験的に公開。 現在できていることは、 URLを含む全世界中の Twitter 発言を日本語で限定してリアルタイムにだらだらと表示するというもの。 Unix/Linux を使っている人はログを tail -f xxx.log もしくは watch | tail xxx.log なんてコマンドで眺めるのと 同じような感覚で Twitter のタイムラインを見ることができると言えばわかりやすいかも!ということで、 名付けて「Tail-F」。
技術的に面白いアーキテクチャになっています。 発言を取得する部分は Twitter の Streaming API 。 ブラウザで閲覧させる部分は comet という技術を使っています。 なので、取得の度に毎回情報を取りにいくいわゆる polling は使用せずに、 long poll といいますか、「つなぎっぱ」の状態を Twitter サイド/表示サイドともに作って利用している形になります。 具体的には、CPAN の AnyEvent::Twitter::Stream、Continuity と二つのモジュールをフル利用しています。 この2つのモジュールのおかげでかなり短いコードで Stream Server を記述できるのです。 開発は github で行っています。
スクリプトレベルでも同じような機能は再現できるので、 試しに書いてみたものを貼付けておきます。
#!/usr/bin/perl
use strict;
use AnyEvent::Twitter::Stream;
use Continuity;
use Encode;
use utf8;
my $user = 'username';
my $password = 'password';
my $done = AnyEvent->condvar;
my @tweets;
my $streamer = AnyEvent::Twitter::Stream->new(
username => $user,
password => $password,
method => 'filter',
track => 'http',
on_tweet => sub {
my $tweet = shift;
if( $tweet->{text} =~ /[あ-んア-ン]/ ) {
shift @tweets if( $#tweets > 20 );
push( @tweets, encode( 'utf8', "$tweet->{user}{screen_name}: $tweet->{text}\n" ) );
}
},
on_error => sub {
my $error = shift;
warn "ERROR: $error";
$done->send;
},
on_eof => sub {
$done->send;
},
);
my $server = Continuity->new(
port => 16001,
path_session => 1,
cookie_session => 'sid',
staticp => sub { $_[0]->url =~ m/\.(jpg|jpeg|gif|png|css|ico|js|html)$/ },
);
$server->loop;
$done->recv;
sub main {
my ($req) = @_;
my $path = $req->request->url->path;
print STDERR "Path: '$path'\n";
pushstream($req) if $path =~ /pushstream/;
}
sub pushstream {
my ($req) = @_;
while (1) {
my $log = join "<br />", @tweets;
$req->print($log);
$req->next;
}
}
__END__
だらだら眺めていると普段入ってこないような情報がわかって面白いですね。 逗子のデニーズが閉鎖するなんて悲しい事実ですが、おかげで知ることができました。 てなわけで、Stream 系 API と comet 、もしくは AnyEvent::* と Continuity ( Stardust もいいね ) の組み合わせは なんか今後も可能性を感じます。 ということで Enjoy!