日記書くネタもないし、なんか面白そうだったので、http:request/4の練習をかねて。
最初のうちは元ソースを読んでましたが、最終的にPython版の丸写し。*1
色々*2酷い事になっていますが、気にしてはいけません。
使い方:
1> c(googl). {ok,googl} 2> inets:start(). ok 3> googl:get_short_url("http://d.hatena.ne.jp/zubenalt/"). "http://goo.gl/SsZe" 4>
書いてる現在、ちゃんと動いてる・・・はず。
以下はソース。
JSONを読むのにmochijson2を使っているので、mochiwebを取ってくる必要があります。
%%% File : googl.erl %%% Author : Zubenalt %%% Description : depends on mochijson2 %%% Created : 16 Dec 2009 by Zubenalt -module(googl). -export([get_short_url/1, get_short_url/2]). %-compile(export_all). get_short_url(URI) -> get_short_url(URI,"toolbar@google.com"). get_short_url(URI, User) -> Token=make_auth_token(URI), Body="user="++User++"&url="++urlencode(URI)++"&auth_token="++Token, Ggl_URL="http://goo.gl/api/url", case http:request(post, {Ggl_URL,[],"application/x-www-form-urlencoded",Body}, [{timeout, 6000}],[]) of {ok, {_,_,Res}}-> {struct,L}=R=mochijson2:decode(Res), case lists:keyfind(<<"short_url">>,1,L) of {<<"short_url">>,Short_URL} -> binary_to_list(Short_URL); false -> {error, R} end; Others -> Others end. c(A)-> c(0,A). c(L,[])-> L; c(L,[H|T]) -> c(L+(H band 4294967295),T). d(L) when L=<0 -> d(L+4294967296); d(L) -> M=integer_to_list(L), O=d_(0,lists:reverse(M),false), M_=O rem 10, O_=o_1(M_,0,M), integer_to_list(O_)++M. d_(O,[],_) -> O; d_(O,[H|T],true) -> Q=list_to_integer([H])*2, d_(O+Q div 10+Q rem 10,T,false); d_(O,[H|T],false) -> Q=list_to_integer([H]), d_(O+Q,T,true). o_1(0,O,_) -> O; o_1(M_,_O,M) -> o_2(M_,10-M_,M) div 2. o_2(_M_,O,M) when length(M) rem 2 =/=1 -> O; o_2(M_,O,M) -> o_3(M_,O,M). o_3(_M_,O,_M) when O rem 2 =/=1 -> O; o_3(_M_,O,_M) -> O+9. e(URI) -> e_(5381,URI). e_(M,[]) -> M; e_(M,[H|T]) -> e_(c([M bsl 5, M, H]),T). f(URI) -> f_(0,URI). f_(M,[]) -> M; f_(M,[H|T]) -> f_(c([H, M bsl 6, M bsl 16, -1*M]),T). make_auth_token(URI) -> I_1 = e(URI), I_2 = (I_1 bsr 2) band 1073741823, I_3 = (I_2 bsr 4) band 67108800 bor (I_2 band 63), I_4 = (I_3 bsr 4) band 4193280 bor (I_3 band 1023), I = (I_4 bsr 4) band 245760 bor (I_4 band 16383), H = f(URI), K_1 = ((I bsr 2) band 15 bsl 4) bor H band 15, K_2 = K_1 bor ((((I bsr 6) band 15) bsl 12) bor ((H bsr 8) band 15 bsl 8)), K_3 = K_2 bor ((I bsr 10) band 15 bsl 20 bor ((H bsr 16) band 15 bsl 16)), K = K_3 bor (((I bsr 14) band 15) bsl 28 bor ((H bsr 24) band 15 bsl 24)), "7" ++ d(K). -define(is_safe(C), $0=<C andalso C=<$9 orelse $A=<C andalso C=<$Z orelse $a=<C andalso C=<$z orelse C=:=$. orelse C=:=$- orelse C=:=$_ orelse C=:=$~). urlencode(URI) -> urlencode(URI,[]). urlencode([],Res) -> lists:flatten(lists:reverse(Res)); urlencode([H|T],SoFar) when ?is_safe(H) -> urlencode(T,[H|SoFar]); urlencode([$\s|T],SoFar) -> urlencode(T,[$+|SoFar]); urlencode([H|T],SoFar) -> urlencode(T,[[37|io_lib:format("~.16B",[H])]|SoFar]).
*1:id:LaclefYoshiさんありがとうございます、というか勝手に使ってすみませんm(__)m
*2:urlencode/2が勘だったり、http:request/4の引数が適当だったり