From e5a7330d0526efb592e200ab96c3f33585ae8d02 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Thu, 11 Oct 2018 17:25:31 +0200 Subject: Initial support for private conversations --- shard/lib/cli/cli.ex | 74 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 8 deletions(-) (limited to 'shard/lib/cli') 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 -- cgit v1.2.3