defmodule Irc.Parser.Isupport do @moduledoc """ ISUPPORT list parser. """ @typedoc "Server ISUPPORT." @type t :: %{key => value} @type key :: String.t @type value :: true | Integer.t() | Map.t() | prefix_map @type prefix :: String.t() @type mode :: String.t() @type prefix_map :: %{prefix() => mode()} def parse(list, acc \\ %{}) do list = List.flatten(list) Enum.reduce(list, acc, fn(entry, acc) -> case String.split(entry, "=", parts: 2) do [entry] -> if String.contains?(entry, " ") do acc else Map.put(acc, entry, true) end [entry, value] -> Map.put(acc, entry, parse_value(entry, value)) end end) end defp parse_value(entry, value) do if String.contains?(value, ":") do Enum.reduce(String.split(value, ","), %{}, fn(key_and_value, acc) -> case String.split(key_and_value, ":", parts: 2) do [key] -> Map.put(acc, key, nil) [key, value] -> Map.put(acc, key, format_value(key, value)) end end) else format_value(entry, value) end end def format_value("PREFIX", value) do case String.split(value, ")", parts: 2) do ["("<>modes, prefixes] -> modes = String.split(modes, "", trim: true) prefixes = String.split(prefixes, "", trim: true) Enum.reduce(Enum.with_index(modes), %{}, fn({mode, position}, acc) -> Map.put(acc, Enum.at(prefixes, position), mode) end) end end def format_value(key, value) do case Integer.parse(value) do {i, ""} -> i _ -> value end end end