package Hatena::API::Auth; use strict; use warnings; our $VERSION = 0.05; use base qw (Class::Accessor::Fast Class::ErrorHandler); use URI; use LWP::UserAgent; use Digest::MD5 qw(md5_hex); BEGIN { use Carp; our $HAVE_JSON_SYCK; eval { require JSON::Syck; $HAVE_JSON_SYCK = 1 }; eval { require JSON } unless $HAVE_JSON_SYCK; Carp::croak("JSON::Syck or JSON required to use " . __PACKAGE__) if $@; *_parse_json = $HAVE_JSON_SYCK ? sub { JSON::Syck::Load($_[1]) } : sub { JSON::jsonToObj($_[1]) }; } __PACKAGE__->mk_accessors(qw(api_key secret)); sub uri_to_login { my $self = shift; my %parameters = ref $_[0] eq 'HASH' ? %{$_[0]} : @_; my $uri = URI->new('http://auth.hatena.ne.jp/auth'); my $request = { api_key => $self->api_key, %parameters, }; $uri->query_form( %$request, api_sig => $self->api_sig($request), ); return $uri; } sub api_sig { my $self = shift; my $args = shift; my $sig = $self->secret; for my $key (sort {$a cmp $b} keys %{$args}) { my $value = $args->{$key} ? $args->{$key} : ''; $sig .= $key . $value; } return Digest::MD5::md5_hex($sig); } sub ua { my $self = shift; if (@_) { $self->{_ua} = shift; } else { $self->{_ua} and return $self->{_ua}; $self->{_ua} = LWP::UserAgent->new; $self->{_ua}->agent(join '/', __PACKAGE__, __PACKAGE__->VERSION); } $self->{_ua}; } sub _get_auth_as_json { my $self = shift; my $cert = shift or croak "You must specify your cert as an argument."; my $uri = URI->new('http://auth.hatena.ne.jp/api/auth.json'); my $request = { api_key => $self->api_key, cert => $cert, }; $uri->query_form( %$request, api_sig => $self->api_sig($request), ); my $res = $self->ua->get($uri->as_string); $res->is_success ? $res->content : $self->error($res->status_line); } sub login { my $self = shift; my $cert = shift or croak "Invalid argumet (no cert)"; my $auth = $self->_get_auth_as_json($cert) or return $self->error($self->errstr); my $json = $self->_parse_json($auth); if ($json->{has_error}) { return $self->error($json->{error}->{message}); } else { return Hatena::API::Auth::User->new($json->{user}); } } package Hatena::API::Auth::User; use base qw(Class::Accessor::Fast); __PACKAGE__->mk_accessors(qw(name image_url thumbnail_url)); 1; __END__ =head1 NAME Hatena::API::Auth - Perl intaface to the Hatena Authentication API =head1 VERSION Version 0.04 =head1 SYNOPSIS use Hatena::API::Auth; my $api = Hatena::API::Auth->new({ api_key => '...', secret => '...', }); my $uri = $api->uri_to_login; print $uri->as_string; my $cert = $q->param('cert'); my $user = $api->login($cert) or die "Couldn't login: " . $api->errstr; $user->name; $user->image_url; $user->thumbnail_url; =head1 DESCRIPTION A simple interface for using the Hatena Authentication API L. =head1 METHODS =over 4 =item new({ api_key => '...', secret => '...' }) Returns an instance of Hatena::API::Auth. It requires two parameters, "api_key" and "secret" which can be retrieved from the Web site of Hatena Authentication API (L). =item uri_to_login(%extra) Returns a URI object which is associated with the login url and required parameters. You can also use this method in your templates of L