PageRenderTime 21ms CodeModel.GetById 8ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/mod_facebook/models/m_facebook.erl

https://code.google.com/p/zotonic/
Erlang | 166 lines | 97 code | 32 blank | 37 comment | 23 complexity | 1d29d8cbd74966e2121675a9130fb4b5 MD5 | raw file
  1%% @author Maas-Maarten Zeeman <mmzeeman@xs4all.nl>
  2%% @copyright 2011 Maas-Maarten Zeeman 
  3%%
  4%% @doc Model for accessing facebook data via the graph api.
  5
  6%% Copyright 2011 Maas-Maarten Zeeman
  7%%
  8%% Licensed under the Apache License, Version 2.0 (the "License");
  9%% you may not use this file except in compliance with the License.
 10%% You may obtain a copy of the License at
 11%% 
 12%%     http://www.apache.org/licenses/LICENSE-2.0
 13%% 
 14%% Unless required by applicable law or agreed to in writing, software
 15%% distributed under the License is distributed on an "AS IS" BASIS,
 16%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 17%% See the License for the specific language governing permissions and
 18%% limitations under the License.
 19
 20-module(m_facebook).
 21-author("Maas-Maarten Zeeman <mmzeeman@xs4all.nl").
 22
 23-behaviour(gen_model).
 24
 25%% interface functions
 26-export([
 27    m_find_value/3,
 28    m_to_list/2,
 29    m_value/2,
 30
 31    search/3,
 32	 
 33    do_graph_call/5
 34]).
 35
 36-include_lib("zotonic.hrl").
 37
 38%% @doc Fetch the value for the key from a model source
 39%% @spec m_find_value(Key, Source, Context) -> term()
 40m_find_value(CT, M=#m{value=undefined}, _Context)  
 41  when CT == friends; 
 42       CT == home;
 43       CT == feed;
 44       CT == likes;
 45       CT == movies;
 46       CT == music;
 47       CT == books;
 48       CT == notes;
 49       CT == permissions;
 50       CT == picture;
 51       CT == photos;
 52       CT == albums;
 53       CT == videos;
 54       CT == events;
 55       CT == groups; 
 56       CT == checkins ->
 57    M#m{value=CT};
 58m_find_value(Key, #m{value=picture}, Context) ->
 59    %% Getting the picture is strangely enough different from all other fields.
 60    P = do_graph_call(get, Key, undefined, [{fields, "picture"}], Context),
 61    proplists:get_value(picture, P);
 62m_find_value(Key, #m{value=ConnectionType}, Context) ->
 63    do_graph_call(get, Key, ConnectionType, [], Context). 
 64
 65%% @doc Transform a m_config value to a list, used for template loops
 66%% @spec m_to_list(Source, Context) -> []
 67m_to_list(_, _Context) ->
 68    [].
 69
 70%% @doc Transform a model value so that it can be formatted or piped through filters
 71%% @spec m_value(Source, Context) -> term()
 72m_value(#m{value=undefined}, _Context) ->
 73    undefined.
 74
 75%% @doc Return the search as used by z_search and the search model.
 76search({fql, Args}, _OfffsetLimit, _Context) ->
 77    #search_sql{select="dummy", from="dummy", args=Args, run_func=fun facebook_q/4 }.
 78
 79%% Experimental feature to do facebook fql queries.
 80facebook_q(_Q, _Sql, Args, Context) ->
 81    Query = proplists:get_value('query', Args),
 82    FqlUrl = fql_url(Query, Context),
 83
 84    %% 
 85    Payload = case http:request(FqlUrl) of
 86        {ok, {{_, 200, _}, _Headers, Body}} ->
 87            mochijson2:decode(Body);
 88        Other ->
 89            ?DEBUG({error, {http_error, FqlUrl, Other}}),
 90            []
 91    end,
 92
 93    %%
 94    Rows = case Payload of
 95	       {struct, [{<<"error_code">>, _ErrorCode} | _T]} ->
 96		   ?DEBUG(Payload),
 97		   [];
 98	       _ ->
 99		   ?DEBUG(Payload),
100		   convert_json(Payload)
101    end,
102  
103    #search_result{result=Rows}.
104
105%% @doc Do a facebook graph call. See http://developers.facebook.com/docs/reference/api/ for more info
106%%
107do_graph_call(Method, Id, Connection, Args, Context) 
108  when Method == get; Method == post; Method == delete ->
109    ReqArgs = case z_context:get_session(facebook_access_token, Context) of
110		  undefined -> Args;
111		  AccessToken -> [{access_token, AccessToken} | Args]
112	      end,
113    Query = mochiweb_util:urlencode(ReqArgs),
114
115    Path = [$/, string:join([z_utils:url_encode(C) || C <- [Id, Connection], C =/= undefined], "/")],
116
117    Request = make_httpc_request(Method, "https", "graph.facebook.com", Path, Query),
118
119    Payload = case http:request(Method, Request, [], []) of
120		  {ok, {{_, 200, _}, _Headers, Body}} ->
121		      mochijson2:decode(Body);
122		  Other ->
123		      ?DEBUG({error, {http_error, element(1, Request), Other}}),
124		      []
125	      end,
126
127    convert_json(Payload).
128
129%% Create a http request for the inets httpc api.
130%%
131make_httpc_request(post, Scheme, Server, Path, Query) ->
132    Url = mochiweb_util:urlunsplit({Scheme, Server, Path, [], []}),
133    {Url, [], "application/x-www-form-urlencoded", Query};
134make_httpc_request(Method, Scheme, Server, Path, Query) when Method == get; 
135								   Method == delete ->
136    Url = mochiweb_util:urlunsplit({Scheme, Server, Path, Query, []}),
137    {Url, []}.
138
139%% Convert json from facebook favour to an easy to use format for zotonic templates.
140%%
141convert_json({K, V}) when is_binary(K) ->
142    {z_convert:to_atom(K), convert_json(V)};
143convert_json({struct, PropList}) when is_list(PropList) ->
144    convert_json(PropList);
145convert_json(L) when is_list(L) ->
146    [convert_json(V) || V <- L];
147convert_json(V) ->
148    V.
149
150%%
151%%
152fql_url(Query, Context) ->
153    Fql = "https://api.facebook.com/method/fql.query?format=json&query=" ++ z_utils:url_encode(Query),
154    case z_context:get_session(facebook_access_token, Context) of
155        undefined -> Fql;
156        AccessToken -> Fql ++ "&access_token=" ++ z_utils:url_encode(AccessToken)
157    end.
158    
159    
160
161
162
163		  
164					   
165    
166