最近発表されて、一部で話題を呼んでいるTwitterの新しいStreaming API「ChirpUserStreams」。
まだdeveloperへのpreviewリリースということでプロダクトに使うようなことはできないけど。
http://apiwiki.twitter.com/ChirpUserStreams
今までのStreaming APIでは基本的に
- public timelineから、指定したキーワードを含む発言を拾う
- 指定したユーザーの発言を拾う
というものだった(はず)。検索系としては便利だけど、home_timelineのように自分がフォローしているユーザーの発言をStreamingで得ようとすると全idを繋げたものをリクエストパラメータとして送らないといけなかったりで、あまりカッコよくない形になってしまっていた。
ところが今回使えるようになった「ChirpUserStreams」は、自分がフォローしているユーザーのアクティビティをStreamingで取得できるらしい。素晴らしい!
さっそくこんなのを書いてみた。
#!/usr/bin/perl use strict; use warnings; use AnyEvent::HTTP 'http_request'; use Config::Pit 'pit_get'; use Encode 'encode_utf8'; use MIME::Base64 'encode_base64'; my $config = pit_get( "twitter.com", require => { "username" => "your username on Twitter", "password" => "your password on Twitter", } ); my $cv = AE::cv; http_request( 'GET', 'http://chirpstream.twitter.com/2b/user.json', headers => { Authorization => "Basic " . encode_base64(join ':', @$config{qw/username password/}), }, want_body_handle => 1, sub { my $hdl = shift; my $r = sub { my (undef, $json) = @_; if (my $text = $json->{text}) { print encode_utf8 "$json->{user}{screen_name}: $text\n"; } }; $hdl->on_read(sub { $hdl->push_read( json => $r ); }); } ); $cv->recv;
たったこれだけのコードで、home_timelineのように自分のfriendsの発言をStreamingで取得できる!
AnyEvent::HTTPでBASIC認証でアクセスして、want_body_handleを使用してAnyEvent::Handleオブジェクトを取得、それを使ってJSONデータを取得し続けるようにしてみた。
statuses/home_timeline REST APIとは違い、自分がフォローしているユーザーから自分がフォローしていないユーザーへのリプライなんかもここにすべて流れてくることになる。それを見る必要がない場合は一番最初にfriendsのid一覧を取得できるので、それを元にフィルタリングするのが良いかも。
そして、発言だけでなく自分のfriendsが「Retweetした」「favoriteした」「followした」といった情報もstreamingでリアルタイムに取得できる。これはマジですごい!
「誰が誰をfollowした」とか「誰が誰のどの発言をfavoriteした」なんてのは今までほとんど取ることができなかったはず。unfollowされたときは残念ながら取れないようだ。これはいずれ追加されるのかな…?
これを使えば、メール監視などをしなくてもAPI経由で瞬間フォロー返しを行うこともできるはず。
Twitter でイチイチ follow するのが面倒くさい - にぽたん研究所
というわけで、こんなのを書いてみたよ。
#!/usr/bin/perl use strict; use warnings; use AnyEvent::HTTP 'http_request'; use Config::Pit 'pit_get'; use Encode 'encode_utf8'; use JSON::XS 'decode_json'; use LWP::UserAgent; use MIME::Base64 'encode_base64'; my $config = pit_get( "twitter.com", require => { username => "your username on Twitter", password => "your password on Twitter", } ); # BASIC認証に使用するヘッダ情報 my $auth_header = HTTP::Headers->new( Authorization => "Basic " . encode_base64(join ':', @$config{qw/username password/}), ); # 自分自身のユーザーIDを取得 my $res = LWP::UserAgent->new( default_headers => $auth_header, )->get('http://twitter.com/account/verify_credentials.json'); my $self_id = decode_json($res->content)->{id}; # Streamingからデータを得た際の挙動 my $callback = sub { my (undef, $json) = @_; my $event = $json->{event} or return; if ($event eq 'follow' && $json->{target}{id} == $self_id) { reply_with($json->{source}{id}, '@%s followありがとうございます!'); } if ($event eq 'favorite' && $json->{target}{id} == $self_id) { reply_with($json->{source}{id}, '@%s favありがとうございます!'); } if ($event eq 'retweet' && $json->{target}{id} == $self_id) { reply_with($json->{source}{id}, '@%s RTありがとうございます!'); } }; # Streaming APIに接続する my $cv = AE::cv; http_request( GET => 'http://chirpstream.twitter.com/2b/user.json', headers => $auth_header, want_body_handle => 1, sub { shift->on_read(sub { shift->push_read( json => $callback ); }); } ); $cv->recv; # idから相手のscreen_nameを取得してreplyする sub reply_with { my ($id, $message) = @_; http_request( GET => "http://twitter.com/users/show/$id.json", headers => $auth_header, sub { my $data = shift; my $screen_name = decode_json($data)->{screen_name}; my $status = sprintf $message, $screen_name; my $uri = URI->new('http://twitter.com/statuses/update.json'); $uri->query_form( status => $status ), http_request( POST => $uri->as_string, headers => $auth_header, sub {}, ); } ) }
follow、favorite、RTされた瞬間に毎回お礼を言います。
まだ正式リリースでもないので仕様変更などされるかも知れないけど、大いに期待できる便利なAPIですね!