はてブのダウンロードをErlangでやってみた
参考にさせていただいたところ
はてなブックマークをダウンロードするスクリプト - 趣味的にっきRubyによるWSSE認証の実装 - 近況はてなフォトライフAtomAPIとは - はてなキーワードConverting Between struct:time and ISO8601 Format - ErlangCentral Wiki
私のコードを見るより、ずっとタメになると思います。
とりあえず、Erlangで困ったのは
- TIMEZONEが取れない→きめ打ちにした
- WSSE認証で使うISO 8601形式の日付に変換するライブラリが無い(上記のサイトを参考にして変換したが、日付と時刻のセパレータである"T"とかは自分で付け加えてみた。
一応、wsseとgetatomという2つのモジュールを作って、下記のように実行してみて、自分のはてブの中身をダウンロードできるところまでは来た。
(2009/2/15追記:hatenaのエンドポイントは?date=latestが無い形じゃないと500 Internal Server errorが出るようになっていた。)
> Latest = getatom:new("ユーザ名", "パスワード", "http://b.hatena.ne.jp/atom/feed?date=latest"). [60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49, 46,48,34,32,101,110,99,111,100,105,110,103,61|...] > io:format("~s",[Latest]).kgbu\343\201\256\343\203\226\343\203\203\343\202\257\343\203\236\343\203\274\343\202\257 以下略
wsse.erl
-module(wsse). -export([new/2]). -define(SHA1DIGESTLENGTH, 20). new (User, Password) -> {A, B, C} = now(), random:seed(A, B, C), Nonce = nonce(?SHA1DIGESTLENGTH, ""), {{Year, Month, Day}, {Hour, Min, Sec}} = Localtime = erlang:localtime(), Created = io_lib:format("~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~2.10.0B", [Year, Month, Day, Hour, Min, Sec]) ++ get_tz(Localtime), crypto:start(), Digest = binary_to_list(crypto:sha(Nonce ++ Created ++ Password)), "UsernameToken Username=\"" ++ User ++ "\", " ++ "PasswordDigest=\"" ++ base64:encode_to_string(Digest) ++ "\", " ++ "Nonce=\"" ++ base64:encode_to_string(Nonce) ++ "\", " ++ "Created=\"" ++ Created ++ "\"". nonce(0,L) -> L ++ [random:uniform(255)]; nonce(N,L) -> nonce(N -1, L ++ [random:uniform(255)]). %% FIXME : きめ打ちだ! %% get_tz(_Localtime) -> "+09:00".
(2009/02/14追記:get_tzは以下のようにも書けたらしい
get_tz(_Localtime) -> Datestr = os:cmd("date +%:z"), io_lib:format("~6s", [Datestr]).
(2009/02/15追記:ちょっと整理して、英文blogにも投稿してみた)