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
125
126
127
128
129
|
defmodule ExIrc.Utils do
alias ExIrc.Client.IrcMessage, as: IrcMessage
######################
# IRC Message Parsing
######################
@doc """
Parse an IRC message
"""
def parse(raw_data) do
[[?: | from] | rest] = :string.tokens(raw_data, ' ')
get_cmd rest, parse_from(from, IrcMessage.new(ctcp: false))
end
defp parse_from(from, msg) do
case Regex.split(%r/(!|@|\.)/, from) do
[nick, '!', user, '@', host | host_rest] ->
msg.nick(nick).user(user).host(host ++ host_rest)
[nick, '@', host | host_rest] ->
msg.nick(nick).host(host ++ host_rest)
[_, '.' | _] ->
# from is probably a server name
msg.server(from)
[nick] ->
msg.nick(nick)
end
end
# Parse command from message
defp get_cmd([cmd, arg1, [?:, 1 | ctcp_trail] | restargs], msg) when cmd == 'PRIVMSG' or cmd == 'NOTICE' do
get_cmd([cmd, arg1, [1 | ctcp_trail] | restargs], msg)
end
defp get_cmd([cmd, _arg1, [1 | ctcp_trail] | restargs], msg) when cmd == 'PRIVMSG' or cmd == 'NOTICE' do
args = ctcp_trail ++ lc arg inlist restargs, do: ' ' ++ arg
|> Enum.flatten
|> Enum.reverse
case args do
[1 | ctcp_rev] ->
[ctcp_cmd | args] = ctcp_rev |> Enum.reverse |> :string.tokens(' ')
msg.cmd(ctcp_cmd).args(args).ctcp(true)
_ ->
msg.cmd(cmd).ctcp(:invalid)
end
end
defp get_cmd([cmd | rest], msg) do
get_args(rest, msg.cmd(cmd))
end
# Parse command args from message
defp get_args([], msg) do
msg.args
|> Enum.reverse
|> Enum.filter(fn(arg) -> arg != [] end)
|> msg.args
end
defp get_args([[':' | first_arg] | rest], msg) do
args = lc arg inlist [first_arg | rest], do: ' ' ++ arg |> Enum.flatten
case args do
[_ | []] ->
get_args([], msg.args([msg.args]))
[_ | full_trail] ->
get_args([], msg.args([full_trail | msg.args]))
end
end
defp get_args([arg | []], msg) do
get_args([], msg.args([arg | msg.args]))
end
defp get_args([arg | rest], msg) do
get_args(rest, msg.args([arg | msg.args]))
end
############################
# Parse RPL_ISUPPORT (005)
############################
def isup([], state), do: state
def isup([param | rest], state) do
try do
isup(rest, isup_param(param, state))
rescue
_ -> isup(rest, state)
end
end
def isup_param('CHANTYPES=' ++ channel_prefixes, state) do
state.channel_prefixes(channel_prefixes)
end
def isup_param('NETWORK=' ++ network, state) do
state.network(network)
end
def isup_param('PREFIX=' ++ user_prefixes, state) do
prefixes = Regex.run(%r/\((.*)\)(.*)/, user_prefixes, capture: :all_but_first) |> List.zip
state.user_prefixes(prefixes)
end
def isup_param(_, state) do
state
end
###################
# Helper Functions
###################
@days_of_week ['Mon','Tue','Wed','Thu','Fri','Sat','Sun']
@months_of_year ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
def ctcp_time({{y, m, d}, {h, n, s}}) do
[:lists.nth(:calendar.day_of_the_week(y,m,d), @days_of_week),
' ',
:lists.nth(m, @months_of_year),
' ',
:io_lib.format("~2..0s", [integer_to_list(d)]),
' ',
:io_lib.format("~2..0s", [integer_to_list(h)]),
':',
:io_lib.format("~2..0s", [integer_to_list(n)]),
':',
:io_lib.format("~2..0s", [integer_to_list(s)]),
' ',
integer_to_list(y)] |> List.flatten
end
end
|