Home > Perl | ウェブサービス > WebService::Simple::Flickrを作りました

WebService::Simple::Flickrを作りました

前回,Flickr::APIを使ってFlickrの認証のやり方がわかりましたが,なんかFlickrだけの モジュールを使うのもしゃくなので,ゆーすけべーさんが公開している WebSerivice::Simpleを継承して認証できる形のモジュールを作ったので公開します.

WebService::Simple::Flickr

Flickrの認証はちょっと面倒な形をしています.最初に触るAPIにすべきじゃないですw 何が面倒かというと,パラメータを送るとき,それを並べてハッシュをとったものを 署名として付けないといけない点です.この部分を実装しておきます.

get()関数をオーバーライド

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);
}

まぁコード見てもらえば分かる通りで,Flickr::APIからほぼそのまま持って来た signargs()関数を使ってハッシュを作り,それをapisigというパラメータで 追加しています.apikeyとapisecretはあらかじめ与えておき,auth_tokenは 後に示す手順で取得しておいて与えておきます.

使い方は,WebService::Simpleのget()と同じで,

my $flickr = WebService::Simple::Flickr->new(
    api_key => $api_key, api_secret => $secret_key, auth_token => $token);
my $res = $flickr->get({method => "flickr.photosets.getList"});


なんて感じでハッシュにつっこんでgetすればOK.この例の場合,(tokenが取得して あれば)自分のSetのリストがプライベート設定のやつも含めて取得できているはずです.

コンストラクタもオーバーライド

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;
}

さっきの例で分かる通り,apikeyとかをコンストラクタに渡しちゃってます. よくわかんないですが,とりあえずWebService::Simpleのコンストラクタのやってることを パクって,apikey, apisecret, authtokenを持っておくようにします. ちなみに,インスタンス作ったあとに,$flickr->{auth_token}とかで与えても 大丈夫みたいなので,この実装は要らないかも.

upload_post()メソッドを追加

use base qw(WebService::Simple);
__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メソッドを追加

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;
}

これはFlickr::APIからまるパクリ.呼び出し方も当然同じ.後で使います.

とりあえずこれを使ってトークンを取得してみよう

前回Flickr::APIでやったことをWebService::Simple::Flickrを使ってやると こんな感じ.

use utf8;
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

package WebService::Simple::Flickr;
 
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;
}

Comments:0

Comment Form
Remember personal info

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がパクっただけ...

Home > Perl | ウェブサービス > WebService::Simple::Flickrを作りました

Tag Cloud
Amazon
Banners
フィードメーター - As a Futurist... Creative Commons License track feed スカウター : As a Futurist...

Return to page top