はてなブックマークAtomAPIの使い方を紹介します。2010年末にOAuthをサポートしたので、ここでもそれを試します。言語はJava、ライブラリはscribe-javaを使います。前にoauth-signpostを使う方法を紹介しましたが、こちらのほうがおそらく簡単です(準備のためにクラスを1つ余計に作らなければなりませんが)。
アプリケーションの登録
アプリケーション登録ページでアプリケーションを登録し、Consumer keyとConsumer secretを取得します。
ライブラリの準備
scribe-バージョン番号.jarとcommons-codec-バージョン番号.jarを使えるようにします(このあたりの詳細については、拙著『Webアプリケーション』などを参照してください)。
APIを定義するクラス
TwitterのようなメジャーなAPIはあらかじめscribe-javaで定義されているので(一覧)、後のコードで「TwitterApi.class
」などと書くだけでいいのですが、はてなはそこまでメジャーでもないようで、APIを定義するクラスを自分で作らなければなりません。
import org.scribe.builder.api.*;
import org.scribe.model.*;
import org.scribe.utils.OAuthEncoder;
public class HatenaApi extends DefaultApi10a {
@Override
public String getAccessTokenEndpoint() {
return "https://www.hatena.com/oauth/token";
}
@Override
public String getRequestTokenEndpoint() {
String scope = "?scope=read_public%2Cwrite_public%2Cread_private%2Cwrite_private";
return "https://www.hatena.com/oauth/initiate" + scope;
}
@Override
public String getAuthorizationUrl(Token requestToken) {
return String.format("https://www.hatena.ne.jp/oauth/authorize?oauth_token=%s",
OAuthEncoder.encode(requestToken.getToken()));
}
}
TwitterのOAuthと違うのは、どのような権利を求めるかを「score=...
」という形で書いておくところです。
Access tokenとToken secretの取得
OAuthでユーザの権利を譲り受けるためのAccess tokenとToken secretを取得します。ここで紹介するコンソール上で行う方法の他に、ブラウザ上でリダイレクトを使う方法もありますが、両者の違いはTwitterの場合などと同じなので、Twitterでの方法を見れば、リダイレクトを使う方法も実現できるでしょう。
先に取得したConsumer keyとConsumer secretを下のコードに埋め込んでください。
import java.io.*;
import org.scribe.builder.*;
import org.scribe.model.*;
import org.scribe.oauth.*;
public class ScribeTokenCreator {
public static void main(String[] args) throws Exception {
// プロキシサーバの設定
//System.setProperty("http.proxyHost", "proxy.example.net");
//System.setProperty("http.proxyPort", "3128");
//System.setProperty("https.proxyHost", "proxy.example.net");
//System.setProperty("https.proxyPort", "3128");
String consumerKey = ***** Consumer key *****;
String consumerSecret = ***** Consumer secret *****;
OAuthService service = new ServiceBuilder().provider(HatenaApi.class).apiKey(consumerKey).apiSecret(consumerSecret).build();
Token requestToken = service.getRequestToken();
//System.out.println(requestToken.getRawResponse());
String authUrl = service.getAuthorizationUrl(requestToken);
System.out.println("このURLにアクセスし、表示されるPINを入力してください。");
System.out.println(authUrl);
System.out.print("PIN:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String pin = br.readLine();
Token accessToken = service.getAccessToken(requestToken, new Verifier(pin));
System.out.println("Access token: " + accessToken.getToken());
System.out.println("Token secret: " + accessToken.getSecret());
}
}
上のコード実行するとURLが表示されるので、そのURLにブラウザでアクセスしてください。下のようなページが表示されます。scoreの記述によって内容は変わります。この例では、公開・非公開の両方の情報への読み書き権限を要求しています。

「許可」をクリックすると下のようなページが表示されるので、表示された文字列を先のコードからのプロンプトで入力してください。Access tokenとToken secretが得られます。

ブックマーク
譲り受けた権利を使って「http://b.hatena.ne.jp/atom/post」にURLをPOSTすれば、そのURLをはてなブックマークに登録できます。例として「http://www.google.com/」を登録するコードは次のようになります。先に取得したConsumer keyとConsumer secret、Access token、Token secretを埋め込んで実行してください。
import org.scribe.builder.*;
import org.scribe.model.*;
import org.scribe.oauth.*;
public class ScribeBookmark {
public static void main(String[] args) throws Exception {
// プロキシサーバの設定
//System.setProperty("http.proxyHost", "proxy.example.net");
//System.setProperty("http.proxyPort", "3128");
// これはユーザによらない
String consumerKey = ***** Consumer key *****;
String consumerSecret = ***** Consumer secret *****;
OAuthService service = new ServiceBuilder().provider(HatenaApi.class).apiKey(consumerKey).apiSecret(consumerSecret).build();
// これはユーザごとに異なる
Token accessToken = new Token(
***** Access token *****,
***** Token secret *****);
// ターゲット
String target = "http://www.google.com/";
String xml = String.format("<entry xmlns='http://purl.org/atom/ns#'>"
+ "<title>dummy</title>"
+ "<link rel='related' type='text/html' href='%s' />"
+ "<summary type='text/plain'></summary>"
+ "</entry>",
target);
// HTTPリクエスト(POST)
OAuthRequest request = new OAuthRequest(Verb.POST, "http://b.hatena.ne.jp/atom/post");
request.addHeader("Content-Type", "application/octed-stream");
service.signRequest(accessToken, request);
request.addPayload(xml);
Response response = request.send();
// 結果の表示
System.out.println(response.getCode());
System.out.println(response.getBody());
}
}
Twitterの場合との違うのは、リクエストボディにXMLを書かなければならないこと、それを送信するためにContent-Typeをapplication/octed-streamにしておくことです。
ブックマークの編集
ブックマークを編集したいときは、上記のPOSTのレスポンス・ヘッダ (Location) に対して、GETで現状を取得し、PUTで新しいデータを送信します。例として、現在のコメントに「♡」を追記するコードは次のようになります(javax.xml.parsers.*とorg.w3c.dom.*、org.xml.sax.*をインポートしておく必要があります)。タイトルははてな全体で共有されるので、よほどの理由がない限りは変更しない方がいいでしょう。
// 編集のためのURL
String editUrl = response.getHeader("Location");
// 現コメントの取得
// HTTPリクエスト(GET)
request = new OAuthRequest(Verb.GET, editUrl);
service.signRequest(accessToken, request);
response = request.send();
System.out.println(response.getCode());
// 結果(XML)の処理
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(response.getStream()));
String comment = doc.getElementsByTagName("summary").item(0).getTextContent();
// コメントの更新(「♡」を付加する)
String newComment = comment + "♡";
xml = String.format("<entry xmlns='http://purl.org/atom/ns#'>"
//+ "<title>Google 2</title>"
+ "<summary type='text/plain'>%s</summary>"
+ "</entry>",
newComment);
// HTTPリクエスト(PUT)
request = new OAuthRequest(Verb.PUT, editUrl);
request.addHeader("Content-Type", "application/octed-stream");
service.signRequest(accessToken, request);
request.addPayload(xml);
response = request.send();
// 結果の表示
System.out.println(response.getCode());
System.out.println(response.getBody());
補足
アプリケーションに与えた許可を取り消したいときは、「Myはてな」→「ユーザ設定」→「外部アプリケーション認証」→「外部のアプリケーションから、はてなのサービスを利用する」の順にクリックしてください。「https://www.hatena.ne.jp/はてなID/config/auth/provider」にアクセスしてもいいでしょう。