Wednesday 11 February 2009

Facebook API in Erlang

I have heard of Facebook APIs and Facebook applications so today I decided to check out what they can do.

Based on documentation on Facebook, an Application is something that is hosted on an external server (such as your ISP or company web/application server) and can be invoked/accessed from a Facebook page. This seems very disappointing - I first thought a Facebook Application was something you can create using Facebook widgets and be hosted on Facebook servers. This model is not appealing to me, then again, I am not an advertiser.

Nevertheless, I decided to give Facebook API a try. Looking through the list of supported languages, Java was discontinued by Facebook (what do you expect from a PHP shop?!) So the natural choice is Erlang using Erlang2Facebook client library. Before using the library, I had to prepare my environment:

  1. Install the latest Erlang - OTP R12B (v5.6.5). My old OTP R11B would not work because the library uses some new functions from the standard library (e.g. decode_packet).
  2. Download mochiweb_util.erl and mochijson2.erl as they are used by the erlang_facebook library.
  3. Download the erlang_facebook.erl

The Facebook APIs are RESTful services which support both GET and POST methods. Most API calls require a signature input parameter which is a MD5 hash of all the input parameters concatenated alphabetically. This is explained in Facebook Developers Wiki. Also, many API calls require the uid or session_key as input parameters. It is a bit convoluted to get the session key:

  1. Create your own Application by following the instructions from Facebook so that you will get your own API Key, Application Secret, etc.
  2. To get a session_key value, you have to get auth_token by accessing the URL: http://www.facebook.com/login.php?api_key=1f5f..., which will forward to your application's host's URL with an input parameter for the auth_key. In my case, it forwards to the URL: http://romenlaw.blogspot.com/?auth_token=e1761... So now I have an auth_token.
  3. Once I have the auth_token, I can call facebook.auth.getSession API to get the session_key and uid

In Erlang, this is shown below:

Erlang (BEAM) emulator version 5.6.5 [smp:2] [async-threads:0]

Eshell V5.6.5  (abort with ^G)
1> c("/projects/facebook_erl/erlang_facebook.erl").
{ok,erlang_facebook}
2> 
2> c("/projects/facebook_erl/mochiweb_util.erl").
{ok,mochiweb_util}
3> 
3> c("/projects/facebook_erl/mochijson2.erl").
{ok,mochijson2}
4> 
4> [ApiKey, Secret, AppId]=["1fef...", "99f2...", "41..."].
...
9> erlang_facebook:custom(ApiKey, Secret, "facebook.auth.getSession", [{"auth_token", "c92b9...this is the auth_token copied from step 2 above"}]).
{struct,[{<<"session_key">>,
          <<"2.Ryk_v_nVtG...">>},
         {<<"uid">>,109...},
         {<<"expires">>,123...}]}
...
19> erlang_facebook:custom(ApiKey, Secret, "facebook.users.getLoggedInUser", [{"session_key", SessionKey}]).
109...(same as the uid returned by getSession call above)
28> [Fid]=erlang_facebook:custom(ApiKey, Secret, "facebook.friends.get", [{"uid", "1092201851"}]).
[598...]
31> erlang_facebook:custom(ApiKey, Secret, "facebook.friends.get", [{"uid", "598..."}]).            
{struct,[{<<"error_code">>,10},
         {<<"error_msg">>,
          <<"Application does not have permission for this action">>},
         {<<"request_args">>,
...
36> erlang_facebook:custom(ApiKey, Secret, "facebook.users.getInfo", [{"uids", "109..."},{"fields", "uid, first_name, last_name, name, sex, birthday, affiliations, locale, profile_url, proxied_email"}]).
[{struct,[{<<"affiliations">>,
           [{struct,[{<<"nid">>,67...},
                     {<<"name">>,<<"Australia">>},
                     {<<"type">>,<<"region">>},
                     {<<"status">>,<<>>},
                     {<<"year">>,0}]}]},
          {<<"birthday">>,null},
          {<<"first_name">>,<<"Romen">>},
          {<<"last_name">>,<<"Law">>},
          {<<"name">>,<<"Romen Law">>},
          {<<"sex">>,null},
          {<<"uid">>,109...},
          {<<"locale">>,<<"en_US">>},
          {<<"profile_url">>,
           <<"http://www.facebook.com/people/Romen-Law/109...">>},
          {<<"proxied_email">>,
           <<"apps+419..."...>>}]}]

1 comment:

Nick said...

Nice article. I'm glad you liked the erlang_facebook library.