Skip to content

Instantly share code, notes, and snippets.

@nanto
Created December 21, 2010 09:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nanto/749732 to your computer and use it in GitHub Desktop.
Save nanto/749732 to your computer and use it in GitHub Desktop.
はてなブックマークの OAuth 対応 API 利用サンプル。 Run | $ perl consumer.pl daemon | and access http://localhost:3000/.
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use Mojolicious::Lite;
use OAuth::Lite::Consumer;
use XML::Atom::Feed;
use XML::Atom::Entry;
use URI::Escape qw/uri_escape_utf8/;
use Encode qw/decode_utf8/;
my $origin = 'http://localhost:3000';
my $consumer_key = '__consumer_key__';
my $consumer_secret = '__consumer_secret__';
my $consumer = OAuth::Lite::Consumer->new(
consumer_key => $consumer_key,
consumer_secret => $consumer_secret,
site => 'https://www.hatena.com',
request_token_path => '/oauth/initiate',
access_token_path => '/oauth/token',
authorize_path => 'https://www.hatena.ne.jp/oauth/authorize',
);
get '/' => sub {
my $self = shift;
my $access_token = $self->session('access_token') || '';
$self->stash( access_token => $access_token );
} => 'root';
# リクエストトークン取得から認証用URLにリダイレクトするためのアクション
get '/oauth' => sub {
my $self = shift;
$self->stash( consumer => $consumer );
# リクエストトークンの取得
my $request_token = $consumer->get_request_token(
callback_url => $origin . '/callback',
scope => 'read_public,write_public',
) or die $consumer->errstr;
# セッションへリクエストトークンを保存しておく
$self->session( request_token => $request_token );
# 認証用URLにリダイレクトする
$self->redirect_to( $consumer->url_to_authorize(
token => $request_token,
) );
};
# 認証からコールバックされ、アクセストークンを取得するためのアクション
get '/callback' => sub {
my $self = shift;
$self->stash( consumer => $consumer );
my $verifier = $self->param('oauth_verifier');
my $request_token = $self->session('request_token');
# リクエストトークンとverifierなどを用いてアクセストークンを取得
my $access_token = $consumer->get_access_token(
token => $request_token,
verifier => $verifier,
) or die $consumer->errstr;
$self->session( request_token => undef );
# アクセストークンをセッションに記録しておく
$self->session( access_token => $access_token );
$self->redirect_to('/');
} => 'callback';
get '/add' => sub {
my $self = shift;
} => 'add';
post '/add' => sub {
my $self = shift;
$self->stash( consumer => $consumer );
my $access_token = $self->session('access_token') or return;
$consumer->access_token( $access_token );
my $url = $self->param('url') or return;
my $comment = $self->param('comment');
# PostURI 用の Atom エントリを作成
my $link = XML::Atom::Link->new;
$link->rel('related');
$link->type('text/html');
$link->href( $url );
my $entry = XML::Atom::Entry->new;
$entry->add_link( $link );
$entry->summary( $comment );
# PostURI でブックマークを追加
my $res = $consumer->request(
method => 'POST',
url => 'http://b.hatena.ne.jp/atom/post',
headers => [ 'Content-Type' => 'application/atom+xml' ],
content => $entry->as_xml_utf8,
);
return unless $res->is_success;
$self->redirect_to( '/edit?url=' . uri_escape_utf8( $url ) );
};
get '/edit' => sub {
my $self = shift;
$self->stash( consumer => $consumer );
my $access_token = $self->session('access_token') or return;
$consumer->access_token( $access_token );
my $url = $self->param('url') or return;
# EditURI でブックマークを取得
my $res = $consumer->request(
method => 'GET',
url => 'http://b.hatena.ne.jp/atom/edit',
params => { url => $url },
);
return unless $res->is_success;
my $entry = XML::Atom::Entry->new( \$res->decoded_content );
$self->stash( url => $url );
$self->stash( entry => $entry );
$self->stash( comment => decode_utf8( $entry->summary ) );
} => 'edit';
post '/edit' => sub {
my $self = shift;
$self->stash( consumer => $consumer );
my $access_token = $self->session('access_token') or return;
$consumer->access_token( $access_token );
my $url = $self->param('url') or return;
my $comment = $self->param('comment');
# EditURI 用の Atom エントリを作成
my $entry = XML::Atom::Entry->new;
$entry->summary( $comment );
# EditURI でブックマークを編集
my $res = $consumer->request(
method => 'PUT',
url => 'http://b.hatena.ne.jp/atom/edit',
params => { url => $url },
headers => [ 'Content-Type' => 'application/atom+xml' ],
content => $entry->as_xml_utf8,
);
return unless $res->is_success;
$self->redirect_to( '/edit?url=' . uri_escape_utf8( $url ) );
};
post '/delete' => sub {
my $self = shift;
$self->stash( consumer => $consumer );
my $access_token = $self->session('access_token') or return;
$consumer->access_token( $access_token );
my $url = $self->param('url') or return;
# EditURI でブックマークを削除
my $res = $consumer->request(
method => 'DELETE',
url => 'http://b.hatena.ne.jp/atom/edit',
params => { url => $url },
);
return unless $res->is_success;
$self->redirect_to('/');
};
get '/list' => sub {
my $self = shift;
$self->stash( consumer => $consumer );
my $access_token = $self->session('access_token') or return;
$consumer->access_token( $access_token );
# FeedURI でブックマークの一覧を取得
my $res = $consumer->request(
method => 'GET',
url => 'http://b.hatena.ne.jp/atom/feed',
);
return unless $res->is_success;
my $feed = XML::Atom::Feed->new( \$res->decoded_content );
$self->stash( feed => $feed );
} => 'list';
app->start;
__DATA__
@@ root.html.ep
<!DOCTYPE html><html lang="ja"><meta charset="utf-8">
<title>OAuth対応APIではてなブックマークを利用する</title>
<p><a href="/oauth">はてなOAuth認証をする</a>
% if ( $access_token ) {
<ul>
<li><a href="/add">ブックマークを追加</a>
<li><a href="/list">ブックマーク一覧を表示</a>
</ul>
% }
@@ callback.html.ep
% my $token = $self->stash('token');
<%= $token->token %><br>
<%= $token->secret %>
@@ add.html.ep
<!DOCTYPE html><html lang="ja"><meta charset="utf-8">
<title>ブックマークを追加</title>
<form action="/add" method="post"><p>
<label>URL: <input type="text" name="url" size="50"></label><br>
<label>コメント: <input type="text" name="comment" size="50"></label>
<input type="submit" value="追加">
</form>
@@ edit.html.ep
% my $url = $self->stash('url');
% my $entry = $self->stash('entry');
% my $comment = $self->stash('comment');
<!DOCTYPE html><html lang="ja"><meta charset="utf-8">
<title>ブックマークを編集</title>
<form action="/edit" method="post"><p>
<input type="hidden" name="url" value="<%= $url %>">
URL: <%= $url %><br>
<label>コメント: <input type="text" name="comment" value="<%= $comment %>" size="50"></label>
<input type="submit" value="保存">
</form>
<form action="/delete" method="post"><p>
<input type="hidden" name="url" value="<%= $url %>">
<input type="submit" value="削除">
</form>
@@ list.html.ep
<!DOCTYPE html><html lang="ja"><meta charset="utf-8">
<title>ブックマーク一覧</title>
<ul>
% for ( $feed->entries ) {
% my $url = $_->link->href;
<li><a href="<%= $url %>"><%= $url %></a> <a href="/edit?url=<%= URI::Escape::uri_escape_utf8( $url ) %>">編集</a>
% }
</ul>
@@ exception.html.ep
REQUEST ERROR: <%= $consumer->errstr %> </br>
WWW-Authenticate: <%= $consumer->oauth_res && $consumer->oauth_res->header('www-authenticate') %>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment