Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
-export([
init/1
, content_types_provided/2
, provide_content/2
]).
-include_lib("webmachine_resource.hrl").
-include_lib("zotonic.hrl").
-define(DEFAULT_LENGTH, 64).
-define(DEFAULT_LABEL, "world ! {self(), erlanger}").
-record(image, {
type="normal",
style="light",
label=?DEFAULT_LABEL,
url=undefined,
glyph_dir,
out_dir,
out_file,
path_to_images
}).
init(Args) -> {ok, Args}.
content_types_provided(ReqData, Context) ->
{[{"image/png", provide_content}], ReqData, Context}.
provide_content(ReqData, Context) ->
Context1 = z_context:set_reqdata(ReqData, Context),
Context2 = z_context:ensure_all(Context1),
File = get_image(Context2),
%% http://hg.rabbitmq.com/rabbitmq-server/file/50890ac979ba/src/worker_pool.erl
%% see article at
%% http://www.lshift.net/blog/2010/03/29/on-the-limits-of-concurrency-worker-pools-in-erlang
case worker_pool:submit(fun() -> maybe_fetch_object(File) end) of
{true, Value} ->
{Value, ReqData, Context};
{false, _} ->
{"none", ReqData, Context}
end.
get_image(Context) ->
{Type, Style, Label, Url} = get_relevant_vars(Context),
Hash = hash_file(Label, Url, Type, Style),
LibDir = filename:join([z_utils:lib_dir(Context), "lib", "images"]),
GlyphDir = filename:join([LibDir, "glyphs"]),
OutDir = filename:join([LibDir, "out"]),
% hash all incoming data
% LabelShort is of type "3xHd5Mug0DLZjxjMeWgPxD2"
OutFileDir = filename:join([
OutDir,
lists:sublist(Hash, 1, 1),
lists:sublist(Hash, 2, 1),
lists:sublist(Hash, 3, 1),
lists:sublist(Hash, 4, 2)
]) ++ "/",
OutFileName = lists:sublist(Hash, 6, length(Hash)) ++ ".png",
OutFile = filename:join([OutFileDir, OutFileName]),
File = case mod_redis:action({exists, [io_lib:format("image:~s", [Hash])]}, Context) of
false ->
%% using redis here, can be any DB at all
%% используем Redis, можно использовать любую базу
Inc = z_convert:to_list(mod_redis:action({incr, ["imagecount"]}, Context)),
mod_redis:action({set, [io_lib:format("image:~s", [Hash]), Inc]}, Context),
filelib:ensure_dir(OutFileDir),
gen_image(
#image{
type = Type,
style = Style,
label = Label,
url = Url,
glyph_dir = GlyphDir,
out_dir = OutFileDir,
out_file = OutFile,
path_to_images = LibDir
}
),
mod_redis:action({set, [io_lib:format("image:file:~s", [Inc]), OutFile]}, Context),
OutFile;
_ ->
Id = mod_redis:action({get, [io_lib:format("image:~s", [Hash])]}, Context),
F = mod_redis:action({get, [io_lib:format("image:file:~s", [z_convert:to_list(Id)])]}, Context),
F
end,
z_convert:to_list(File).
hash_file(Label, Url, Type, Style) ->
<<Label2:128/unsigned-integer>> = crypto:md5(unicode:characters_to_binary(Label)),
<<Url2:128/unsigned-integer>> = crypto:md5(unicode:characters_to_binary(Url)),
LabelShort = base62:encode(Label2),
UrlShort = base62:encode(Url2),
lists:flatten([short(Type), short(Style), LabelShort, UrlShort]).
gen_image(#image{type=Type, style=Style, label=Label, out_file=OutFile, glyph_dir=GlyphDir, path_to_images = PathToImages}) ->
Theme = get_theme(Style),
Size = get_size(Type),
Cmd = [
"cd ", PathToImages, " && python ",
"draw_text.py",
" -o ", OutFile,
" -t ", Theme,
" -b ", Size,
" -l ", binary_to_list(unicode:characters_to_binary(mochiweb_util:shell_quote(Label)))
],
worker_pool:submit(fun() -> os:cmd(Cmd) end).
get_theme(Theme) when Theme =:= "light" orelse Theme =:= "dark" ->
Theme;
get_theme(Theme) ->
"light".
get_size("big") ->
"big";
get_size("normal") ->
"medium";
get_size("medium") ->
"medium";
get_size("small") ->
"small";
get_size(_) ->
"medium".
get_glyph_dir(GlyphDir, Size, Theme) ->
filename:join([GlyphDir, z_convert:to_list(Size), Theme]).
get_out_path(Context) ->
filename:join([z_utils:lib_dir(Context), "lib", "out"]).
short(S) ->
lists:sublist(S, 1).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment