aboutsummaryrefslogtreecommitdiff
path: root/shard/lib/cli/cli.ex
blob: 2fbf8c2417cfe3bd522f2ac4b0da3f5bde5ba7e9 (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
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
defmodule SCLI do
  @moduledoc """
  Small command line interface for the chat application
  """

  def run() do
    run(nil)
  end

  defp run(pid) do
    handle_messages()

    nick = Shard.Identity.get_nickname
    prompt = case pid do
      nil -> "(no channel) #{nick}: "
      _ -> 
        {:chat, chan} = GenServer.call(pid, :manifest)
        "##{chan} #{nick}: "
    end

    str = prompt |> IO.gets |> String.trim
    cond do
      str == "/quit" ->
        nil
      String.slice(str, 0..0) == "/" ->
        command = str |> String.slice(1..-1) |> String.split(" ")
        pid2 = handle_command(pid, command)
        run(pid2)
      true -> 
        if str != "" do
          GenServer.cast(pid, {:chat_send, str})
        end
        run(pid)
    end
  end

  defp handle_messages() do
    receive do
      {:chat_recv, chan, {ts, nick, msg}} ->
        IO.puts "#{ts |> DateTime.from_unix! |> DateTime.to_iso8601}  ##{chan}  <#{nick}> #{msg}"
        handle_messages()
      {:chat_send, _, _} ->
        # do nothing
        handle_messages()
    after 10 -> nil
    end
  end

  defp handle_command(pid, ["connect", ipstr, portstr]) do
    {:ok, ip} = :inet.parse_address (to_charlist ipstr)
    {port, _} = Integer.parse portstr
    Shard.Manager.add_peer(ip, port)
    pid
  end

  defp handle_command(pid, ["list"]) do
    IO.puts "List of known channels:"

    for {_chid, manifest, _chpid} <- :ets.tab2list(:shard_db) do
      {:chat, chan} = manifest
      IO.puts "##{chan}"
    end
    pid
  end

  defp handle_command(pid, ["hist"]) do
    GenServer.call(pid, {:read_history, nil, 25})
    |> Enum.each(fn {{ts, nick, msg}, true} ->
      IO.puts "#{ts |> DateTime.from_unix! |> DateTime.to_iso8601}  <#{nick}> #{msg}"
        end)
    pid
  end

  defp handle_command(_pid, ["join", qchan]) do
    list = for {_chid, manifest, chpid} <- :ets.tab2list(:shard_db),
               {:chat, chan} = manifest,
               do: {chan, chpid}
    case List.keyfind(list, qchan, 0) do
      nil ->
        {:ok, pid} = DynamicSupervisor.start_child(Shard.DynamicSupervisor, {SApp.Chat, qchan})
        GenServer.cast(pid, {:subscribe, self()})
        pid
      {_, pid} ->
        IO.puts "Switching to ##{qchan}"
        pid
    end
  end

  defp handle_command(pid, ["nick", nick]) do
    Shard.Identity.set_nickname nick
    pid
  end

  defp handle_command(pid, _cmd) do
    IO.puts "Invalid command"
    pid
  end
end