1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
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, %IRC.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
|