前回,Flickr::APIを使ってFlickrの認証のやり方がわかりましたが,なんかFlickrだけの モジュールを使うのもしゃくなので,ゆーすけべーさんが公開している WebSerivice::Simpleを継承して認証できる形のモジュールを作ったので公開します.
WebService::Simple::Flickr
Flickrの認証はちょっと面倒な形をしています.最初に触るAPIにすべきじゃないですw 何が面倒かというと,パラメータを送るとき,それを並べてハッシュをとったものを 署名として付けないといけない点です.この部分を実装しておきます.
get()関数をオーバーライド
my ($self, $args) = @_;
$args->{api_key} = $self->{api_key};
if(defined $self->{api_secret} && length $self->{api_secret}){
if(defined $self->{auth_token} && length $self->{auth_token}){
$args->{auth_token} = $self->{auth_token};
}
$args->{api_sig} = $self->sign_args($args);
}
return $self->SUPER::get($args);
}
まぁコード見てもらえば分かる通りで,Flickr::APIからほぼそのまま持って来た signargs()関数を使ってハッシュを作り,それをapisigというパラメータで 追加しています.apikeyとapisecretはあらかじめ与えておき,auth_tokenは 後に示す手順で取得しておいて与えておきます.
使い方は,WebService::Simpleのget()と同じで,
api_key => $api_key, api_secret => $secret_key, auth_token => $token);
my $res = $flickr->get({method => "flickr.photosets.getList"});
なんて感じでハッシュにつっこんでgetすればOK.この例の場合,(tokenが取得して あれば)自分のSetのリストがプライベート設定のやつも含めて取得できているはずです.
コンストラクタもオーバーライド
my $class = shift;
my %args = @_;
my $api_key = delete $args{api_key} || "";
my $api_secret = delete $args{api_secret} || "";
my $auth_token = delete $args{auth_token} || "";
my $self = $class->SUPER::new(%args);
$self->{api_key} = $api_key;
$self->{api_secret} = $api_secret;
$self->{auth_token} = $auth_token;
return $self;
}
さっきの例で分かる通り,apikeyとかをコンストラクタに渡しちゃってます.
よくわかんないですが,とりあえずWebService::Simpleのコンストラクタのやってることを
パクって,apikey, apisecret, authtokenを持っておくようにします.
ちなみに,インスタンス作ったあとに,$flickr->{auth_token}とかで与えても
大丈夫みたいなので,この実装は要らないかも.
upload_post()メソッドを追加
__PACKAGE__->config(
base_url => "http://api.flickr.com/services/rest/",
upload_url => "http://api.flickr.com/services/upload/",
);
....
sub upload_post {
my ($self, $args) = @_;
$args->{api_key} = $self->{api_key};
local $self->{base_url} = $self->config->{upload_url};
my $photo = delete $args->{photo};
if(defined $self->{api_secret} && length $self->{api_secret}){
if(defined $self->{auth_token} && length $self->{auth_token}){
$args->{auth_token} = $self->{auth_token};
}
$args->{api_sig} = $self->sign_args($args);
}
$args->{photo} = [$photo] if ref $photo ne "ARRAY";
return $self->post("", Content_Type => "form-data", Content => $args);
}
Flickrのアップロード用のAPIはURLが違ったりするし,POSTメソッドだったり するので,別に用意します.WebService::SimpleのPODの中に例が書いてありますが そのままだとextra_urlまわりで失敗するので,postメソッドの最初の変数に空文字列を 与えています.呼び出し方は後の例を参考に.
requestauthurlメソッドを追加
my ($self, $perms, $frob) = @_;
return undef unless defined $self->{api_secret} && length $self->{api_secret};
my %args = (
'api_key' => $self->basic_params->{api_key},
'perms' => $perms
);
if ($frob) {
$args{frob} = $frob;
}
my $sig = $self->sign_args(\%args);
$args{api_sig} = $sig;
my $uri = URI->new('http://flickr.com/services/auth');
$uri->query_form(%args);
return $uri;
}
これはFlickr::APIからまるパクリ.呼び出し方も当然同じ.後で使います.
とりあえずこれを使ってトークンを取得してみよう
前回Flickr::APIでやったことをWebService::Simple::Flickrを使ってやると こんな感じ.
use WebService::Simple::Flickr;
use Data::Dumper;
my $api_key = "*********************************";
my $secret_key = "**********************";
my $flickr = WebService::Simple::Flickr->new(
api_key => $api_key, api_secret => $secret_key);
my $ref;
$ref = $flickr->get({method => "flickr.auth.getFrob"});
my $frob = $ref->parse_response->{frob};
print $frob . "\n";
print $flickr->request_auth_url('write', $frob);
my $line =<STDIN>; #表示されるURLにブラウザからアクセスしてOKしたらEnter
$ref = $flickr->get({method => "flickr.auth.getToken", frob =>$frob});
my $token = $ref->parse_response->{auth}->{token};
print $token . "\n";
$flickr->{auth_token} = $token;
$ref = $flickr->upload({photo => "/home/user/image.jpg"});
print Dumper $ref->parse_response;
こんな感じで写真がアップロードできました.やりましたね!
いつも通りgithubに置いておきます
というわけで,モジュールのソースはgithubに上げておきます.Plaggerとは別の レポジトリを作りました.
perllib/WebService/Simple/Flickr.pm
use Digest::MD5 qw(md5_hex);
use base qw(WebService::Simple);
__PACKAGE__->config(
base_url => "http://api.flickr.com/services/rest/",
upload_url => "http://api.flickr.com/services/upload/",
);
sub new {
my $class = shift;
my %args = @_;
my $api_key = delete $args{api_key} || "";
my $api_secret = delete $args{api_secret} || "";
my $auth_token = delete $args{auth_token} || "";
my $self = $class->SUPER::new(%args);
$self->{api_key} = $api_key;
$self->{api_secret} = $api_secret;
$self->{auth_token} = $auth_token;
return $self;
}
sub api_key { $_[0]->{api_key} }
sub api_secret { $_[0]->{api_secret} }
sub auth_token { $_[0]->{auth_token} }
sub sign_args {
my ($self, $args) = @_;
my $sig = $self->api_secret;
foreach my $key (sort {$a cmp $b} keys %{$args}) {
my $value = (defined($args->{$key})) ? $args->{$key} : "";
$sig .= $key . $value;
}
print "sig=" . $sig . "\n";
return md5_hex($sig);
}
sub get {
my ($self, $args) = @_;
$args->{api_key} = $self->{api_key};
if(defined $self->{api_secret} && length $self->{api_secret}){
if(defined $self->{auth_token} && length $self->{auth_token}){
$args->{auth_token} = $self->{auth_token};
}
$args->{api_sig} = $self->sign_args($args);
}
return $self->SUPER::get($args);
}
sub upload_post {
my ($self, $args) = @_;
$args->{api_key} = $self->{api_key};
local $self->{base_url} = $self->config->{upload_url};
my $photo = delete $args->{photo};
if(defined $self->{api_secret} && length $self->{api_secret}){
if(defined $self->{auth_token} && length $self->{auth_token}){
$args->{auth_token} = $self->{auth_token};
}
$args->{api_sig} = $self->sign_args($args);
}
$args->{photo} = [$photo] if ref $photo ne "ARRAY";
return $self->post("", Content_Type => "form-data", Content => $args);
}
sub request_auth_url {
my ($self, $perms, $frob) = @_;
return undef unless defined $self->{api_secret} && length $self->{api_secret};
my %args = (
'api_key' => $self->basic_params->{api_key},
'perms' => $perms
);
if ($frob) {
$args{frob} = $frob;
}
my $sig = $self->sign_args(\%args);
$args{api_sig} = $sig;
my $uri = URI->new('http://flickr.com/services/auth');
$uri->query_form(%args);
return $uri;
}
- Newer: 蔵書管理サービスにいらついたのでPlaggerするしかないな
- Older: Perl使ってFlickrAPIでの認証法がやっとわかった
Comments:0
Trackbacks:1
- Trackback URL for this entry
- http://blog.riywo.com/2009/01/21/001939/trackback
- Listed below are links to weblogs that reference
- WebService::Simple::Flickrを作りました from As a Futurist...
- trackback from As a Futurist... 09-01-28 (水) 11:54
-
Flickr-Likeな認証をこなすWebService::Simple::Signature作ったよ
前に,Flickr用のモジュールとしてWebService::Simple::Flickrを作りましたが, 昨日調べてたらRemember The Milkもほぼ同様のAPIを使っていることが わかりました(というかRTMがパクっただけ...

