summaryrefslogtreecommitdiff
path: root/lib/irc/parser
diff options
context:
space:
mode:
Diffstat (limited to 'lib/irc/parser')
-rw-r--r--lib/irc/parser/capabs.ex6
-rw-r--r--lib/irc/parser/line.ex125
2 files changed, 41 insertions, 90 deletions
diff --git a/lib/irc/parser/capabs.ex b/lib/irc/parser/capabs.ex
index 88bf017..1448d75 100644
--- a/lib/irc/parser/capabs.ex
+++ b/lib/irc/parser/capabs.ex
@@ -1,7 +1,10 @@
defmodule Irc.Parser.Capabs do
@moduledoc "Helper to parse capability lists"
+ @type t :: %{capab_name() => capab_value()}
+ @type capab_name :: String.t()
+ @type capab_value :: true | any()
- @spec parse(String.t) :: %{capab :: String.t => true | args :: Map.t}
+ @spec parse(String.t()) :: t()
def parse(string) do
string
|> String.split(" ")
@@ -29,4 +32,3 @@ defmodule Irc.Parser.Capabs do
end
end
-
diff --git a/lib/irc/parser/line.ex b/lib/irc/parser/line.ex
index 48ddd9c..b436c57 100644
--- a/lib/irc/parser/line.ex
+++ b/lib/irc/parser/line.ex
@@ -2,93 +2,58 @@ defmodule Irc.Parser.Line do
@moduledoc """
IRC line parser/encoder
"""
+ alias Irc.Line
+ require Logger
- @type t :: %__MODULE__{
- tags: Map.t(),
- source: Irc.Mask.t() | String.t() | nil,
- command: String.t(),
- args: list()
- }
- defstruct __private__: %{}, tags: %{}, source: nil, command: nil, args: []
-
- @spec parse(string) :: t()
+ @spec parse(string) :: Line.t()
@doc "Parse a server-to-client line."
- def parse(line) do
+ def parse(line, owner_module \\ nil, owner \\ nil)
+
+ def parse(line, context, _) when is_map(context) do
+ module = Irc.Context.module(context)
+ pid = Irc.Context.pid(context)
+ parse(line)
+ |> set_owner(module, pid)
+ end
+
+ def parse(line, owner_module, owner) do
{tags, rest} = parse_tags(line)
- {source, rest} = parse_source(rest)
+ {source, rest} = parse_source(rest, owner_module, owner)
{command, rest} = parse_cmd(rest)
args = parse_args(rest)
private = %{
+ owner: owner,
+ owner_module: owner_module,
at: DateTime.utc_now()
}
- %__MODULE__{__private__: private, tags: tags, source: source, command: command, args: args}
+ %Line{__private__: private, tags: tags, source: source, command: command, args: args}
end
- @spec encode(t()) :: String.t
+ @spec set_owner(Line.t(), module(), pid()) :: Line.t()
+ def set_owner(line = %Line{__private__: private = %{owner: nil, owner_module: nil}}, module, owner) when is_atom(module) and is_pid(owner) do
+ private = Map.put(private, :owner_module, module)
+ |> Map.put(:owner, owner)
+ %Line{line | __private__: private}
+ end
+
+ def set_owner(line = %Line{__private__: private = %{owner: opid, owner_module: omod}}, module, owner) when is_atom(module) and is_pid(owner) do
+ Logger.debug("Parser.Line: tried to re-own an already owned line #{inspect {{omod,opid},{module,owner}}}")
+ line
+ end
+
+ @spec encode(Line.t()) :: String.t
@doc "Encode a line"
- def encode(line = %__MODULE__{}, conn \\ %Irc.Connection{}) do
+ def encode(line = %Line{}, conn \\ %Irc.Connection{}) do
[line.source, line.tags, line.command, line.args]
src = if line.source, do: ":"<>to_string(line.source)
tags = Enum.reduce(line.tags, [], fn({k,v}, acc) -> ["#{k}=#{v}" | acc] end)
|> Enum.join(";")
- tags = if Enum.member?(conn.capabs || [], "message-tags") && tags != "", do: "@"<>tags
+ tags = if Irc.Context.capab?(conn, "message-tags") && tags != "", do: "@"<>tags
[tags, src, line.command, encode_args(line.args)]
|> Enum.filter(fn(x) -> x end)
|> Enum.join(" ")
end
- def new(command) do
- new(command, [])
- end
-
- def new(command, args) do
- new(command, args, %{})
- end
-
- def new(command, arg, tags) when not is_list(arg) do
- new(command, [arg], tags)
- end
-
- def new(command, args, tags) do
- %__MODULE__{command: command, args: args, tags: tags, __private__: %{at: DateTime.utc_now()}}
- end
-
- @doc "Returns the line date (server time if sent, otherwise, parse time)"
- @spec at(t()) :: DateTime.t()
- def at(line = %__MODULE__{__private__: %{at: at}, tags: %{"time" => server_time}}) do
- case DateTime.from_iso8601(server_time) do
- {:ok, date} -> date
- _ -> at
- end
- end
- def at(%__MODULE__{__private__: %{at: at}}), do: at
- def at(_), do: nil
-
- @spec to?(t(), Irc.Connection.t() | Irc.Mask.t() | Irc.User.t()) :: boolean
- @doc "Returns true if the line is adressed to the connection."
- def to?(line = %__MODULE__{args: [nick | _]}, target = %{__struct__: s, nick: nick}) when s in [Irc.Connection, Irc.Mask, Irc.User] do
- true
- end
- def to?(%__MODULE__{}, %{__struct__: s}) when s in [Irc.Connection, Irc.Mask, Irc.User], do: false
-
- @spec self?(t(), Irc.Connection.t() | Irc.Mask.t() | Irc.User.t()) :: boolean
- @doc "Returns true if the line source is the from the given connection/mask."
- def self?(line = %__MODULE__{source: %Irc.Mask{nick: nick}}, target = %Irc.Connection{nick: nick}) do
- true
- end
- def self?(%__MODULE__{source: mask = %Irc.Mask{}}, mask = %Irc.Mask{}) do
- true
- end
- def self?(line = %__MODULE__{source: mask = %Irc.Mask{}}, user = %Irc.User{}) do
- self?(line, Irc.User.to_mask(user))
- end
- def self?(%__MODULE__{source: nick}, %Irc.Connection{nick: nick}) do
- true
- end
- def self?(%__MODULE__{}, %Irc.Connection{}), do: false
- def self?(%__MODULE__{}, %Irc.User{}), do: false
- def self?(%__MODULE__{}, %Irc.Mask{}), do: false
-
# ARGS
defp parse_args(input), do: parse_args(input, [])
@@ -153,18 +118,18 @@ defmodule Irc.Parser.Line do
# SOURCE
- defp parse_source([?: | input]), do: parse_source(input, [])
- defp parse_source(input), do: {nil, input}
+ defp parse_source([?: | input], m, p), do: parse_source(input, [], m, p)
+ defp parse_source(input, _, _), do: {nil, input}
- defp parse_source([0x20 | rest], acc) do
+ defp parse_source([0x20 | rest], acc, m, p) do
string = acc_to_str(acc)
- result = case Irc.Mask.parse(string) do
+ result = case Irc.Mask.parse(string, m, p) do
{:error, _} -> string
{:ok, mask} -> mask
end
{result, rest}
end
- defp parse_source([char | rest], acc), do: parse_source(rest, [char | acc])
+ defp parse_source([char | rest], acc, m, p), do: parse_source(rest, [char | acc], m, p)
# TAGS
@@ -236,20 +201,4 @@ defmodule Irc.Parser.Line do
defp encode_args([], acc), do: acc
- defimpl String.Chars, for: __MODULE__ do
- def to_string(line) do
- Irc.Parser.Line.encode(line)
- end
- end
-
- defimpl Inspect, for: __MODULE__ do
- @moduledoc false
- import Inspect.Algebra
-
- def inspect(struct, _opts) do
- tags = Enum.map(struct.tags, fn({k, v}) -> concat([k, "=", v]) end) |> Enum.join(",")
- Enum.join(["#IRC.Line<", struct.source, " ", struct.command, " ", inspect(struct.args), " (", tags, ")>"], "")
- end
- end
-
end