summaryrefslogtreecommitdiff
path: root/lib/irc/parser/isupport.ex
blob: dda42206e721a81b392256ee4b4d9522ee34f513 (plain) (blame)
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
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