Skip to content

Instantly share code, notes, and snippets.

@mworrell mworrell/m_omdb.erl
Last active Nov 9, 2017

Embed
What would you like to do?
Zotonic 1.0 - Template model for the OMDB movie database - source code to accompany the documentation
-module(m_omdb).
-behaviour(gen_model).
-export([
m_get/2
]).
-include_lib("zotonic_core/include/zotonic.hrl").
-define(API_URL, "http://www.omdbapi.com/?").
-spec m_get(Keys, Context) -> { term(), RestKeys } when
Keys :: list(),
RestKeys :: list(),
Context:: z:context().
% Syntax: m.omdb.api_url
m_get([ api_url | Rest ], _Context) ->
{?API_URL, Rest};
% Syntax: m.omdb["tt0123456789"]
m_get([ <<"tt", _/binary>> = Id | Rest ], _Context) ->
{fetch_data([ {id, Id} ]), Rest};
% Syntax: m.omdb["some title"]
m_get([ Title | Rest ], _Context) when is_binary(Title) ->
{fetch_data([ {id, Id} ]), Rest};
% Syntax: m.omdb.sometype["tt0123456789"]
m_get([ Type, <<"tt", _/binary>> = Id | Rest ], _Context)
when Type =:= movies;
Type =:= series;
Type =:= episode ->
{fetch_data([ {type, Type}, {id, Id} ]), Rest};
% Syntax: m.omdb.sometype[QueryString]
m_get([ Type, QueryString | Rest ], _Context)
when Type =:= movies;
Type =:= series;
Type =:= episode ->
{fetch_data([ {type, Type}, {title, QueryString} ]), Rest};
% Syntax: m.omdb[{query QueryParams}]
% For m.omdb[{query title="Dollhouse"}], Query is: [{title,"Dollhouse"}]
m_get([ {query, Query} | Rest ], _Context) ->
{fetch_data(Query), Rest};
% Syntax: m.omdb.sometype[{query QueryParams}]
% For m.omdb.series[{query title="Dollhouse"}], Query is: [{title,"Dollhouse"}] and Q is: [{type,"series"}]
m_get([ Type, {query, Query} | Rest ], _Context)
when Type =:= movies;
Type =:= series;
Type =:= episode ->
{fetch_data([ {type, Type} | Query ]), Rest}.
-spec fetch_data(Query) -> list() when Query:: list().
fetch_data([]) ->
[{error, "Params missing"}];
fetch_data(Query) ->
case proplists:is_defined(title, Query) or proplists:is_defined(id, Query) of
false -> [{error, "Param id or title missing"}];
true ->
QueryParts = lists:map(fun(Q) ->
make_query_string(Q)
end, Query),
Url = ?API_URL ++ string:join(QueryParts, "&"),
case get_page_body(Url) of
{error, Error} ->
[{error, Error}];
Json ->
{struct, JsonData} = mochijson2:decode(Json),
lists:map(fun(D) ->
convert_data_prop(D)
end, JsonData)
end
end.
%% Translate query params id, title and type into parameters that OMDB wants
-spec make_query_string({Key, Value}) -> string() when
Key:: atom(),
Value:: binary() | string() | atom().
make_query_string({id, Id}) ->
"i=" ++ z_url:url_encode(Id);
make_query_string({title, Title}) ->
"t=" ++ z_url:url_encode(Title);
make_query_string({type, Type}) ->
"type=" ++ z_url:url_encode(Type);
make_query_string(_) ->
"".
%% Translate binary keys to atoms
-spec convert_data_prop({Key, Value}) -> {atom(), string()} when
Key:: binary(),
Value:: binary().
convert_data_prop({Key, Value}) ->
{z_convert:to_atom(string:to_lower(z_convert:to_list(Key))), Value}.
get_page_body(Url) ->
case httpc:request(get, {Url, []}, [], []) of
{ok, {_, Headers, Body}} ->
case content_length(Headers) of
0 -> {error, "No content"};
_ -> Body
end;
Error ->
{error, Error}
end.
content_length(Headers) ->
list_to_integer(proplists:get_value("content-length", Headers, "0")).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.