summaryrefslogblamecommitdiff
path: root/lib/tmpl.ex
blob: f4dac0204fb37e54f71746342569c9679f02e6f9 (plain) (tree)












































                                                                                                                                                 
                                                                                




















                                                                             
                                                                  























































                                                                           
defmodule Tmpl do
  require Logger

  defmodule Filter do
    use Liquex.Filter

    def repeat(text, val, _) do
      String.duplicate(text, val)
    end

    def rrepeat(text, max, _) do
      String.duplicate(text, :random.uniform(max))
    end

    def rrepeat(text, var) do
      rrepeat(text, 20, var)
    end

    def bold(text, %{variables: variables}) do
      unless Map.get(variables, "_no_format") || Map.get(variables, "_no_bold") do
        <<2>> <> text <> <<2>>
      else
        text
      end
    end

    @colors [:white, :black, :blue, :green, :red, :brown, :purple, :orange, :yellow, :light_green, :cyan, :light_blue, :pink, :grey, :light_grey]

    for {color, index} <- Enum.with_index(@colors) do
      code = 48+index

      def color_code(unquote(color)) do
        unquote(code)
      end

      def unquote(color)(text, %{variables: variables}) do
        unless Map.get(variables, "_no_format") || Map.get(variables, "_no_colors") do
          <<3, unquote(code)>> <> text <> <<3>>
        else
          text
        end
      end
    end

    def account_nick(%{"id" => id, "name" => name}, %{variables: %{"message" => %{"network" => network}}}) do
      if user = IRC.UserTrack.find_by_account(network, %Nola.Account{id: id}) do
        user.nick
      else
        name
      end
    end

    def account_nick(val, ctx) do
      "{{account_nick}}"
    end

  end

  def render(template, msg = %IRC.Message{}, context \\ %{}, safe \\ true) do
    do_render(template, Map.put(context, "message", msg), safe)
  end

  defp do_render(template, context, safe) when is_binary(template) do
    case Liquex.parse(template) do
      {:ok, template_ast} ->
        do_render(template_ast, context, safe)
      {:error, err, pos} ->
        Logger.debug("Liquid error: #{pos} - #{inspect template}")
        "[liquid ast error (at #{pos}): #{inspect err}]"
    end
  end

  defp do_render(template_ast, context, safe) when is_list(template_ast) do
    context = Liquex.Context.new(mapify(context, safe))
              |> Map.put(:filter_module, Tmpl.Filter)
    {content, _context} = Liquex.render(template_ast, context)
    to_string(content)
  rescue
    e ->
      Logger.error("Liquid error: #{inspect e}")
      "[liquid rendering error]"
  end

  defp mapify(struct = %{__struct__: _}, safe) do
    mapify(Map.from_struct(struct), safe)
  end

  defp mapify(map = %{}, safe) do
    map
    |> Enum.reduce(Map.new, fn({k,v}, acc) ->
      k = to_string(k)
      if safe?(k, safe) do
        if v = mapify(v, safe) do
          Map.put(acc, k, v)
        else
          acc
        end
      else
        acc
      end
    end)
  end

  defp mapify(fun, _) when is_function(fun) do
    nil
  end

  defp mapify(atom, _) when is_atom(atom) do
    to_string(atom)
  end

  defp mapify(v, _) do
    v
  end

  defp safe?(_, false) do
    true
  end

  defp safe?("token", true), do: false
  defp safe?("password", true), do: false
  defp safe?(_, true), do: true
end