Current section
Files
Jump to
Current section
Files
lib/azalea/handler.ex
defmodule Azalea.Handler do
@moduledoc """
Define the handler to do some job.
eg:
- use imagemagick to compress picture.
- compress the video
- add watermark to your picture
"""
alias Azalea.File, as: AF
@doc """
Add the handler macro method
"""
defmacro handler(key \\ :main, do: block) do
call_string = Macro.to_string(block)
quote do
Module.put_attribute __MODULE__, :calls, unquote({key, call_string})
end
end
defmacro __before_compile__(env) do
# [main: "(\n name(:mini)\n upload(Azalea.Uploader.Local, path:
# [local_root, \"avatar\"])\n)"]
calls =
env.module
|> Module.get_attribute(:calls)
|> Enum.map(fn({key, value}) ->
{key, handler_string(value)}
end)
keys = Keyword.keys(calls)
method_string = """
def handle(struct) do
if struct == [] do
[]
else
file = struct |> cast_file |> check
file = %{file | module: #{env.module}}
case file.valid do
true ->
#{Macro.to_string(keys)}
|> Enum.map(&do_handler(&1, file))
|> Azalea.Type.BaseType.cast
false ->
{:error, :file_invalid}
end
end
end
defp do_handler(key, file)
#{handler_method_string(calls)}
defp do_handler(_, _) do
raise "you should add the method 'handler' before you start"
end
"""
Code.eval_string(method_string, [], env)
end
defp handler_method_string(calls) do
for {key, value} <- calls do
"""
defp do_handler(#{Macro.to_string(key)}, file) do
#{value}
end
"""
end |> Enum.join("\n")
end
defp handler_string(value) do
~r/\b(?:.*)\B/
|> Regex.scan(value)
|> List.flatten
|> List.insert_at(0, "file")
|> Enum.join(" |> ")
end
@doc """
The background system cmd to do with the File struct
"""
def system(file, cmd, args)
def system(%AF{valid: false} = file, _, _), do: file
def system(file, cmd, args) do
old_path = file.path
new_path = Path.join [System.tmp_dir!, file.filename]
args = [old_path] ++ args ++ [new_path]
case System.cmd(cmd, args) do
{_, 0} -> %{file | path: new_path}
{_, 1} -> raise "Cmd error, check with your command"
end
end
defmacro __using__(_opts) do
quote do
import unquote(__MODULE__)
@callback name(upload_kind :: atom) :: String.t
Module.register_attribute __MODULE__, :calls, accumulate: true
@doc """
Change the name fo the File struct
"""
def name(file, kind) do
%{file | filename: "#{name(kind)}.#{file.type}"}
end
end
end
end