aboutsummaryrefslogtreecommitdiff
path: root/shard/lib/cli/cli.ex
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2018-10-11 17:25:31 +0200
committerAlex Auvolat <alex@adnab.me>2018-10-11 17:25:31 +0200
commite5a7330d0526efb592e200ab96c3f33585ae8d02 (patch)
tree906651f53e17002b32e3db3d77bca2918bf62c47 /shard/lib/cli/cli.ex
parent1646bc57eae9880fd408d23ca692364dc6fd6442 (diff)
downloadshard-e5a7330d0526efb592e200ab96c3f33585ae8d02.tar.gz
shard-e5a7330d0526efb592e200ab96c3f33585ae8d02.zip
Initial support for private conversations
Diffstat (limited to 'shard/lib/cli/cli.ex')
-rw-r--r--shard/lib/cli/cli.ex74
1 files changed, 66 insertions, 8 deletions
diff --git a/shard/lib/cli/cli.ex b/shard/lib/cli/cli.ex
index f7e8525..85fa3fc 100644
--- a/shard/lib/cli/cli.ex
+++ b/shard/lib/cli/cli.ex
@@ -17,7 +17,7 @@ defmodule SCLI do
end
defp run(state) do
- handle_messages()
+ handle_messages(state)
id_pid = case state.id_pid do
nil -> SApp.Identity.find_proc(state.pk)
@@ -35,8 +35,16 @@ defmodule SCLI do
prompt = case state.room_pid do
nil -> "(no channel) #{nick}: "
_ ->
- %SApp.Chat.Manifest{channel: chan} = GenServer.call(state.room_pid, :manifest)
- "##{chan} #{nick}: "
+ case GenServer.call(state.room_pid, :manifest) do
+ %SApp.Chat.Manifest{channel: chan} ->
+ "##{chan} #{nick}: "
+ %SApp.Chat.PrivChat.Manifest{pk_list: pk_list} ->
+ nicks = pk_list
+ |> Enum.filter(&(&1 != state.pk))
+ |> Enum.map(&("#{SApp.Identity.get_nick &1} #{Shard.Keys.pk_display &1}"))
+ |> Enum.join(", ")
+ "PM #{nicks} #{nick}: "
+ end
end
str = prompt |> IO.gets |> String.trim
@@ -55,16 +63,21 @@ defmodule SCLI do
end
end
- defp handle_messages() do
+ defp handle_messages(state) do
receive do
- {:chat_recv, chan, {pk, msgbin, _sign}} ->
+ {:chat_recv, manifest, {pk, msgbin, _sign}} ->
{ts, msg} = SData.term_unbin msgbin
nick = SApp.Identity.get_nick pk
- IO.puts "#{ts |> DateTime.from_unix! |> DateTime.to_iso8601} ##{chan} <#{nick} #{Shard.Keys.pk_display pk}> #{msg}"
- handle_messages()
+ case manifest do
+ %SApp.Chat.Manifest{channel: chan} ->
+ IO.puts "#{ts |> DateTime.from_unix! |> DateTime.to_iso8601} ##{chan} <#{nick} #{Shard.Keys.pk_display pk}> #{msg}"
+ %SApp.Chat.PrivChat.Manifest{pk_list: pk_list} ->
+ IO.puts "#{ts |> DateTime.from_unix! |> DateTime.to_iso8601} PM(#{Enum.count pk_list}) <#{nick} #{Shard.Keys.pk_display pk}> #{msg}"
+ end
+ handle_messages(state)
{:chat_send, _, _} ->
# do nothing
- handle_messages()
+ handle_messages(state)
after 10 -> nil
end
end
@@ -105,13 +118,58 @@ defmodule SCLI do
nil ->
{:ok, pid} = Shard.Manifest.start %SApp.Chat.Manifest{channel: qchan}
GenServer.cast(pid, {:subscribe, self()})
+ IO.puts "Joining ##{qchan} (new shard)"
%{state | room_pid: pid}
pid ->
+ GenServer.cast(pid, {:subscribe, self()})
IO.puts "Switching to ##{qchan}"
%{state | room_pid: pid}
end
end
+ defp handle_command(state, ["pm" | people_list]) do
+ known_people = for {_, %SApp.Identity.Manifest{pk: pk}, pid} <- Shard.Manager.list_shards() do
+ info = GenServer.call(pid, :get_info)
+ {pk, info.nick}
+ end
+ pk_list = for qname <- people_list do
+ candidates = for {pk, nick} <- known_people,
+ :binary.longest_common_prefix([qname, nick]) == byte_size(qname)
+ or :binary.longest_common_prefix([qname, Shard.Keys.pk_display pk]) == byte_size(qname),
+ do: {pk, nick}
+ case candidates do
+ [] ->
+ IO.puts "Not found: #{qname}"
+ :error
+ [{pk, _}] -> pk
+ _ ->
+ IO.puts "Several people matching for #{qname}:"
+ for {pk, nick} <- candidates do
+ IO.puts "- #{nick} #{Shard.Keys.pk_display pk}"
+ end
+ :error
+ end
+ end
+ if Enum.all?(pk_list, &(&1 != :error)) do
+ pk_list = [state.pk | pk_list]
+ manifest = SApp.Chat.PrivChat.Manifest.new(pk_list)
+ id = SData.term_hash manifest
+ case Shard.Manager.find_proc id do
+ nil ->
+ {:ok, pid} = Shard.Manifest.start manifest
+ GenServer.cast(pid, {:subscribe, self()})
+ IO.puts "Joining private conversation (new shard)."
+ %{state | room_pid: pid}
+ pid ->
+ GenServer.cast(pid, {:subscribe, self()})
+ IO.puts "Switching to private conversation."
+ %{state | room_pid: pid}
+ end
+ else
+ state
+ end
+ end
+
defp handle_command(state, ["nick", nick]) do
pid = case state.id_pid do
nil -> SApp.Identity.find_proc state.pk