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
|
defmodule Irc.Mask do
alias Irc.Addressable
@type t :: %__MODULE__{nick: nil | String.t(), user: nil | String.t(), host: nil | String.t(), server: nil | String.t()}
defstruct [:nick, :user, :host, :server, {:__private__, %{owner: nil, owner_module: nil}}]
@spec parse(String.t) :: {:ok, t()} | {:error, :invalid_mask}
def parse(string) do
cond do
String.contains?(string, "!") -> parse_user_mask(string)
String.contains?(string, ".") -> parse_server_mask(string)
true -> {:error, :invalid_mask}
end
end
def parse(string, module, pid) do
case parse(string) do
{:ok, x} -> {:ok, set_owner(x, module, pid)}
error -> error
end
end
@spec equal?(Addressable.t(), Addressable.t()) :: boolean
def equal?(a, b) do
import Addressable
(owner(a) == owner(b)) && (nick(a) == nick(b))
end
def from_addressable(addressable) do
import Addressable
new(nick(addressable),
user(addressable),
host(addressable)
)
|> set_owner(owner_module(addressable), owner(addressable))
end
def new(nick, user, host) do
%__MODULE__{nick: nick, user: user, host: host}
end
def set_owner(t = %{__private__: private = %{owner: nil, owner_module: nil}}, module, pid) when is_atom(module) and is_pid(pid) do
private = private
|> Map.put(:owner, pid)
|> Map.put(:owner_module, module)
%{t | __private__: private}
end
def to_string(%__MODULE__{server: nil, nick: nick, user: user, host: host}) do
Enum.join([nick, "!", user, "@", host])
end
def to_string(%__MODULE__{server: server}), do: server
defp parse_user_mask(string) do
case String.split(string, ~r/[!@]/, parts: 3) do
[nick, user, host] ->
{:ok, %__MODULE__{nick: nick, user: user, host: host}}
_ ->
{:error, :invalid_mask}
end
end
defp parse_server_mask(string) do
{:ok, %__MODULE__{server: string}}
end
defimpl String.Chars, for: __MODULE__ do
@moduledoc false
defdelegate to_string(struct), to: Irc.Mask
end
defimpl Irc.Addressable, for: __MODULE__ do
def nick(%{nick: nick}), do: nick
def user(%{user: user}), do: user
def host(%{host: host}), do: host
end
defimpl Inspect, for: __MODULE__ do
@moduledoc false
import Inspect.Algebra
def inspect(struct, _opts) do
concat(["#Irc.Mask<", Irc.Mask.to_string(struct), ">"])
end
end
end
|