OAuth::LiteではてなのOAuth対応APIを使う - koba::blog で、はてなのOAuth対応APIは使ってみたので、今度はTwitterのAPIにチャレンジ。
AP登録
Twitterの参照系のAPIにはAP登録しなくても使えるものもあるけれど、更新系のAPIは当然ながらAP登録が必要。以下のURLから登録する。
Callback URL を指定しないと、xAuthでの認証になるので要注意。Callback URL は Request Token 取得時に指定できるので、WebSite欄と同じものを記入しておけばOK。*1
Name にはAP名を指定するのだけど、重複が許されないので空いている名前を探すのがちょっと面倒。
ここでの設定値は後で変更することもできるので、あまり悩まずに登録すればいい。
登録が済むと、以下の設定値が表示されるので、これを認証時に使う。
Consumer key | (AP固有の値) |
Consumer secret | (AP固有の値) |
Request token URL | https://api.twitter.com/oauth/request_token |
Authorize URL | https://api.twitter.com/oauth/authorize |
Access token URL | https://api.twitter.com/oauth/access_token |
認証のプログラムは OAuth::Liteを使って、はてなでOAuth認証 - koba::blog とほぼ同じなので省略。
account/verify_credentials
認証者の情報を取得するAPI。認証がうまくいったか確認するために、まずアクセスするとよい。いろんな値が返って来るけど、今回はユーザ名、アイコン画像のURL、自己紹介を使う。
my $response = $consumer->request( method => 'GET', url => 'http://api.twitter.com/1/account/verify_credentials.json', token => $access_token, ); my $user = from_json($response->decoded_content); my $screen_name = $user->{screen_name}; my $image_url = $user->{profile_image_url}; my $description = $user->{description};
statuses/home_timeline
認証者のタイムラインを取得するAPI。ツイート内容と、投稿者の情報を使う。
$response = $consumer->request( method => 'GET', url => 'http://api.twitter.com/1/statuses/home_timeline.json', token => $access_token, ); my @status = map { my $text = $_->{text}; my $screen_name = $_->{user}{screen_name}; my $image_url = $_->{user}{profile_image_url}; $text =~ s|(http://\S+)|<a href="$1">$1</a>|g; $cgi->div( $cgi->img({-src=>$image_url,-alt=>'',-style=>'float:left'}), $cgi->div({-style=>'margin-left:60px'}, $cgi->strong($screen_name), $cgi->p($text)), $cgi->hr({-style=>'clear:left'}), ); } @{from_json($response->decoded_content)};
statuses/update
ツイートするAPI。当然ながらメソッドはPOST。
my $response = $consumer->request( method => 'POST', url => 'http://api.twitter.com/1/statuses/update.json', params => { status => $status }, token => $access_token, );
全体のコード
#!/usr/bin/perl -T use strict; use warnings; use CGI; use CGI::Carp qw(fatalsToBrowser); use OAuth::Lite::Consumer; use OAuth::Lite::Token; use JSON; my $consumer_key = '_____________________'; my $consumer_secret = '_________________________________________'; my $title = 'Twitter'; my $cgi = new CGI; $cgi->charset('utf-8'); my $consumer = new OAuth::Lite::Consumer( consumer_key => $consumer_key, consumer_secret => $consumer_secret, ); if ($cgi->path_info eq '/') { my $access_token = OAuth::Lite::Token->from_encoded( $cgi->cookie('TWITTER_OAUTH')); my $response = $consumer->request( method => 'GET', url => 'http://api.twitter.com/1/account/verify_credentials.json', token => $access_token, ); if (! $response->is_success) { print $cgi->redirect($cgi->url.'/initiate'); exit; } my $user = from_json($response->decoded_content); my $screen_name = $user->{screen_name}; my $image_url = $user->{profile_image_url}; my $description = $user->{description}; $response = $consumer->request( method => 'GET', url => 'http://api.twitter.com/1/statuses/home_timeline.json', token => $access_token, ); my @status = map { my $text = $_->{text}; my $screen_name = $_->{user}{screen_name}; my $image_url = $_->{user}{profile_image_url}; $text =~ s|(http://\S+)|<a href="$1">$1</a>|gs; $cgi->div( $cgi->img({-src=>$image_url,-alt=>'',-style=>'float:left'}), $cgi->div({-style=>'margin-left:60px'}, $cgi->strong($screen_name), $cgi->p($text)), $cgi->hr({-style=>'clear:left'}), ); } @{from_json($response->decoded_content)}; print $cgi->header, $cgi->start_html( -title => "[$title] $screen_name", -encoding => $cgi->charset, -lang => 'ja-JP', ), $cgi->img({-src=>$image_url,-alt=>'',-style=>'float:left'}), $cgi->div({-style=>'margin-left:60px'}, $cgi->a({-href=>$cgi->url.'/'}, $cgi->h1({-style=>'font-size:120%'},$screen_name)), $cgi->p($cgi->em($description))), $cgi->start_form('POST',$cgi->url.'/post'), $cgi->textarea('status','',3,40), $cgi->div($cgi->submit), $cgi->endform, $cgi->hr, $cgi->div(join("\n", @status)), $cgi->end_html; } elsif ($cgi->path_info eq '/post') { my $status = $cgi->param('status'); my $access_token = OAuth::Lite::Token->from_encoded( $cgi->cookie('TWITTER_OAUTH')); my $response = $consumer->request( method => 'POST', url => 'http://api.twitter.com/1/statuses/update.json', params => { status => $status }, token => $access_token, ); print $cgi->redirect($cgi->url.'/'); } elsif ($cgi->path_info eq '/initiate') { my $request_token = $consumer->get_request_token( url => 'https://api.twitter.com/oauth/request_token', callback_url => $cgi->url.'/token', ) or die $consumer->errstr."\n"; my $cookie = $cgi->cookie( -name => 'TWITTER_OAUTH', -value => $request_token->as_encoded, -path => $cgi->url(-absolute=>1), ); my $url = $consumer->url_to_authorize( url => 'https://api.twitter.com/oauth/authorize', token => $request_token, ); print $cgi->redirect( -url => $url, -cookie => $cookie, ); } elsif ($cgi->path_info eq '/token') { my $oauth_verifier = $cgi->param('oauth_verifier'); my $request_token = OAuth::Lite::Token->from_encoded( $cgi->cookie('TWITTER_OAUTH')); my $access_token = $consumer->get_access_token( url => 'https://api.twitter.com/oauth/access_token', token => $request_token, verifier => $oauth_verifier, ) or die Dumper([$consumer,$request_token]); my $cookie = $cgi->cookie( -name => 'TWITTER_OAUTH', -value => $access_token->as_encoded, -path => $cgi->url(-absolute=>1), -expires => '+90d', ); print $cgi->redirect( -url => $cgi->url.'/', -cookie => $cookie, ); } else { print $cgi->redirect($cgi->url.'/'); }