AnyEvent::Twitter::Streamで取得結果をブラウザに垂れ流す
#!/usr/bin/env perl use strict; use warnings; use Config::Pit; use AnyEvent::Twitter::Stream; use AnyEvent::Socket; use Data::Section::Simple; use Text::Xslate; use JSON; use HTTP::Parser::XS qw/parse_http_request/; my $config = pit_get('twitter', require => { consumer_key => '', consumer_secret => '', token => '', token_secret => '', }); my $vpath = Data::Section::Simple->new()->get_data_section(); my $tx = Text::Xslate->new( path => [$vpath] ); my $cv = AnyEvent->condvar; my @tweets; my $streamer = AnyEvent::Twitter::Stream->new( %$config, method => 'userstream', on_tweet => sub { my $tweet = shift; push @tweets, { id => $tweet->{user}{id}, user => $tweet->{user}{screen_name}, text => $tweet->{text}, }; }, on_error => sub { warn shift; $cv->send } ); tcp_server undef, 8080, sub { my ($sock, $host, $port) = @_; warn "accept from $host:$port"; my $buf; sysread($sock, $buf, 4096); my %env; my $ret = parse_http_request($buf, \%env); if ($ret == -1 || $ret == -2) { $cv->send; } if (defined $env{PATH_INFO} && $env{PATH_INFO} eq '/stream') { my @send_tweets; while (my $tweet = shift @tweets) { unshift @send_tweets, $tweet; } print ${sock} "HTTP/1.1 200 OK\r\n"; print ${sock} "Content-Type: application/json\r\n"; print ${sock} "\r\n"; print ${sock} encode_json \@send_tweets; } else { print ${sock} "HTTP/1.1 200 OK\r\n"; print ${sock} "Content-Type: text/html\r\n"; print ${sock} "\r\n"; print ${sock} $tx->render('index.tx'); } }; $cv->recv; __DATA__ @@ index.tx <html> <head> <title>stream test</title> <script src="http://code.jquery.com/jquery-1.4.4.min.js" type="text/javascript"></script> <script type="text/javascript"> var list_max = 50; var tweets_id = []; setInterval(function(){ $.ajax({ url : '/stream', dataType: 'json', success : function(data) { var count = data.length; for (var i=0; i<count; i++) { if (data[i].user && data[i].text) { $(".tweets").after( '<div id="'+ data[i].id +'">' +'<p>' + data[i].user +' : ' + data[i].text +'</p>' +'</div>' ); tweets_id.push(data[i].id); } if (tweets_id.length > list_max) { var tweet_id = '#' + tweets_id.shift(); $(tweet_id).remove(); } } }, }); }, 5000); </script> <style type="text/css"> p { font-size: small; border-bottom: 1px solid black; } </style> </head> <body> <div class="tweets"></div> </body> </html>
一応これで出来たけど・・・
$ENV{PATH_INFO}が無いときに死んでしまう。
まあ総じてレスポンスを返すところがイマイチだと思う。もっといい方法あるはず。後で書き直す。
加えてブラウザから定期的にリクエスト送って結果を取得してるんだけどこれももっといい方法があるはず。これも後で書直す。
要するに書直す。
あとwindowsでは多分うごかない