diff options
author | Alex Auvolat <alex@adnab.me> | 2018-10-12 18:16:46 +0200 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2018-10-12 18:16:46 +0200 |
commit | 574b572fac144135c4381581351445bf5d0de81c (patch) | |
tree | 1ad2fa0157583a955069332e6a957250ff362967 | |
parent | 7bc609a85b43ed86eccb9cd40d9db31f15aaba1d (diff) | |
download | shard-574b572fac144135c4381581351445bf5d0de81c.tar.gz shard-574b572fac144135c4381581351445bf5d0de81c.zip |
Clean up interface to shards0.0.3
-rw-r--r-- | shard/lib/app/chat.ex | 77 | ||||
-rw-r--r-- | shard/lib/app/identity.ex | 45 | ||||
-rw-r--r-- | shard/lib/app/pagestore.ex | 2 | ||||
-rw-r--r-- | shard/lib/cli/cli.ex | 21 | ||||
-rw-r--r-- | shardweb/lib/channels/chat_channel.ex | 14 | ||||
-rw-r--r-- | shardweb/lib/controllers/chat_controller.ex | 2 | ||||
-rw-r--r-- | shardweb/lib/controllers/identity_controller.ex | 4 | ||||
-rw-r--r-- | shardweb/lib/templates/identity/list.html.eex | 2 | ||||
-rw-r--r-- | shardweb/lib/templates/identity/view.html.eex | 2 | ||||
-rw-r--r-- | shardweb/lib/templates/layout/app.html.eex | 8 | ||||
-rw-r--r-- | shardweb/lib/templates/page/peer_list.html.eex | 4 | ||||
-rw-r--r-- | shardweb/lib/templates/page/shard_list.html.eex | 2 | ||||
-rw-r--r-- | shardweb/lib/views/layout_view.ex | 8 |
13 files changed, 148 insertions, 43 deletions
diff --git a/shard/lib/app/chat.ex b/shard/lib/app/chat.ex index 8c55869..be3b848 100644 --- a/shard/lib/app/chat.ex +++ b/shard/lib/app/chat.ex @@ -31,6 +31,10 @@ defmodule SApp.Chat do # ========= defmodule Manifest do + @moduledoc""" + Manifest for a public chat room defined by its name. + """ + defstruct [:channel] end @@ -42,8 +46,17 @@ defmodule SApp.Chat do defmodule PrivChat.Manifest do + @moduledoc""" + Manifest for a private chat room defined by the list of participants. + + Do not instanciate this struct directly, use `new` to ensure a canonical representation. + """ + defstruct [:pk_list] + @doc""" + Ensures a canonical representation by sorting pks and removing duplicates. + """ def new(pk_list) do %__MODULE__{pk_list: pk_list |> Enum.sort |> Enum.uniq} end @@ -322,7 +335,7 @@ defmodule SApp.Chat do end end - def msg_cmp({pk1, msgbin1, _sign1}, {pk2, msgbin2, _sign2}) do + defp msg_cmp({pk1, msgbin1, _sign1}, {pk2, msgbin2, _sign2}) do {ts1, msg1} = SData.term_unbin msgbin1 {ts2, msg2} = SData.term_unbin msgbin2 cond do @@ -335,4 +348,66 @@ defmodule SApp.Chat do true -> :duplicate end end + + # ================ + # PUBLIC INTERFACE + # ================ + + @doc""" + Subscribe to notifications for this chat room. + + The process calling this function will start recieving messages of the form: + + {:chat_recv, manifest, {pk, msgbin, sign}} + + or + + {:chat_send, manifest, {pk, msgbin, sign}} + + msgbin can be used in the following way: + + {timestamp, message} = SData.term_unbin msgbin + """ + def subscribe(shard_pid) do + GenServer.cast(shard_pid, {:subscribe, self()}) + end + + @doc""" + Send a message to a chat room. + """ + def chat_send(shard_pid, pk, msg) do + GenServer.cast(shard_pid, {:chat_send, pk, msg}) + end + + @doc""" + Read the history of a chat room. + + The second argument is the last message to read. + If nil, will read the n last messages. + If not nill, will read the n last messages until the specified bound. + """ + def read_history(shard_pid, bound, n) do + GenServer.call(shard_pid, {:read_history, bound, n}) + end + + @doc""" + Return a shard's manifest from its pid. + """ + def get_manifest(shard_pid) do + GenServer.call(shard_pid, :manifest) + end + + @doc""" + Returns timestamp of last message if chat room has unread messages, nil otherwise. + """ + def has_unread?(shard_pid) do + GenServer.call(shard_pid, :has_unread) + end + + @doc""" + Mark all messages as read + """ + def mark_read(shard_pid) do + GenServer.cast(shard_pid, :mark_read) + end end diff --git a/shard/lib/app/identity.ex b/shard/lib/app/identity.ex index 95ffb92..42d1bf8 100644 --- a/shard/lib/app/identity.ex +++ b/shard/lib/app/identity.ex @@ -1,14 +1,29 @@ defmodule SApp.Identity do + @moduledoc""" + Shard application for keeping state associated with a user's identity. + + Current functionality: + + - nickname + - peer info: ip, port to connect to if we want a secure connection with this person + (used for private chat) + + Future functionnality: + + - friend list + - notifications & invites + """ + use GenServer require Logger defmodule Manifest do - defstruct [:pk] - end + @moduledoc""" + Manifest for a user identity shard, defined by the public key of the user. + """ - defmodule State do - defstruct [:info, :rev, :signed] + defstruct [:pk] end defimpl Shard.Manifest, for: Manifest do @@ -17,6 +32,10 @@ defmodule SApp.Identity do end end + defmodule State do + defstruct [:info, :rev, :signed] + end + def start_link(pk) do GenServer.start_link(__MODULE__, pk) end @@ -139,11 +158,23 @@ defmodule SApp.Identity do end @doc""" + Get the info dict of an identity shard. The pid of the shard must be given as an argument. + """ + def get_info(pid) do + GenServer.call(pid, :get_info) + end + + @doc""" + Set the info dict of an identity shard. + """ + def set_info(pid, new_info) do + GenServer.call(pid, {:set_info, new_info}) + end + + @doc""" Get a user's nickname from his pk """ def get_nick(pk) do - pid = find_proc pk - info = GenServer.call(pid, :get_info) - info.nick + get_info(find_proc pk).nick end end diff --git a/shard/lib/app/pagestore.ex b/shard/lib/app/pagestore.ex index 86b0726..8f6be59 100644 --- a/shard/lib/app/pagestore.ex +++ b/shard/lib/app/pagestore.ex @@ -251,7 +251,7 @@ defmodule SApp.PageStore do end def ask_random_peers(state, key) do - SNet.Group.broadcast(state.netgroup, {state.shard_id, state.path, {:get, key}}, 3) + SNet.Group.broadcast(state.netgroup, {state.shard_id, state.path, {:get, key}}, nmax: 3) end defimpl SData.PageStore do diff --git a/shard/lib/cli/cli.ex b/shard/lib/cli/cli.ex index 319f96b..45eeece 100644 --- a/shard/lib/cli/cli.ex +++ b/shard/lib/cli/cli.ex @@ -9,7 +9,7 @@ defmodule SCLI do def run() do for {_chid, %SApp.Chat.Manifest{}, chpid} <- Shard.Manager.list_shards do - GenServer.cast(chpid, {:subscribe, self()}) + SApp.Chat.subscribe(chpid) end pk = Shard.Keys.get_any_identity @@ -28,14 +28,13 @@ defmodule SCLI do nick = case id_pid do nil -> SApp.Identity.default_nick(state.pk) _ -> - info = GenServer.call(id_pid, :get_info) - info.nick + SApp.Identity.get_info(id_pid).nick end prompt = case state.room_pid do nil -> "(no channel) #{nick}: " _ -> - case GenServer.call(state.room_pid, :manifest) do + case SApp.Chat.get_manifest(state.room_pid) do %SApp.Chat.Manifest{channel: chan} -> "##{chan} #{nick}: " %SApp.Chat.PrivChat.Manifest{pk_list: pk_list} -> @@ -57,7 +56,7 @@ defmodule SCLI do run(state) true -> if str != "" do - GenServer.cast(state.room_pid, {:chat_send, state.pk, str}) + SApp.Chat.chat_send(state.room_pid, state.pk, str) end run(state) end @@ -102,7 +101,7 @@ defmodule SCLI do if state.room_pid == nil do IO.puts "Not currently on a channel!" else - GenServer.call(state.room_pid, {:read_history, nil, 25}) + SApp.Chat.read_history(state.room_pid, nil, 25) |> Enum.each(fn {{pk, msgbin, _sign}, true} -> {ts, msg} = SData.term_unbin msgbin nick = SApp.Identity.get_nick pk @@ -114,14 +113,14 @@ defmodule SCLI do defp handle_command(state, ["join", qchan]) do pid = Shard.Manager.find_or_start %SApp.Chat.Manifest{channel: qchan} - GenServer.cast(pid, {:subscribe, self()}) + SApp.Chat.subscribe(pid) IO.puts "Switching to ##{qchan}" %{state | room_pid: pid} 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) + info = SApp.Identity.get_info(pid) {pk, info.nick} end pk_list = for qname <- people_list do @@ -145,7 +144,7 @@ defmodule SCLI do if Enum.all?(pk_list, &(&1 != :error)) do manifest = SApp.Chat.PrivChat.Manifest.new([state.pk | pk_list]) pid = Shard.Manager.find_or_start manifest - GenServer.cast(pid, {:subscribe, self()}) + SApp.Chat.subscribe(pid) IO.puts "Switching to private conversation." %{state | room_pid: pid} else @@ -161,8 +160,8 @@ defmodule SCLI do if pid == nil do IO.puts "Sorry, we have a problem with the identity shard" else - info = GenServer.call(pid, :get_info) - GenServer.call(pid, {:set_info, %{info | nick: nick}}) + info = SApp.Identity.get_info(pid) + SApp.Identity.set_info(pid, %{info | nick: nick}) end state end diff --git a/shardweb/lib/channels/chat_channel.ex b/shardweb/lib/channels/chat_channel.ex index a413be1..25f1d09 100644 --- a/shardweb/lib/channels/chat_channel.ex +++ b/shardweb/lib/channels/chat_channel.ex @@ -9,7 +9,7 @@ defmodule ShardWeb.ChatChannel do pid = Shard.Manager.find_or_start %SApp.Chat.Manifest{channel: room_name} socket = assign(socket, :pid, pid) - GenServer.cast(pid, {:subscribe, self()}) + SApp.Chat.subscribe(pid) send(self(), :after_join) {:ok, socket} @@ -27,7 +27,7 @@ defmodule ShardWeb.ChatChannel do pid = Shard.Manager.find_or_start(SApp.Chat.PrivChat.Manifest.new(pk_list)) socket = assign(socket, :pid, pid) - GenServer.cast(pid, {:subscribe, self()}) + SApp.Chat.subscribe(pid) send(self(), :after_join) {:ok, socket} @@ -37,7 +37,7 @@ defmodule ShardWeb.ChatChannel do end def handle_info(:after_join, socket) do - GenServer.call(socket.assigns.pid, {:read_history, nil, 100}) + SApp.Chat.read_history(socket.assigns.pid, nil, 100) |> Enum.each(fn {{pk, msgbin, _sign}, true} -> {_ts, msg} = SData.term_unbin msgbin nick = SApp.Identity.get_nick pk @@ -47,7 +47,7 @@ defmodule ShardWeb.ChatChannel do message: msg, }) end) - GenServer.cast(socket.assigns.pid, :mark_read) + SApp.Chat.mark_read(socket.assigns.pid) {:noreply, socket} end @@ -58,12 +58,12 @@ defmodule ShardWeb.ChatChannel do push socket, "shout", %{"name" => nick, "pk16" => Shard.Keys.pk_display(pk), "message" => msg} - GenServer.cast(socket.assigns.pid, :mark_read) + SApp.Chat.mark_read(socket.assigns.pid) {:noreply, socket} end def handle_info({:chat_send, _, _}, socket) do - GenServer.cast(socket.assigns.pid, :mark_read) + SApp.Chat.mark_read(socket.assigns.pid) {:noreply, socket} end @@ -81,7 +81,7 @@ defmodule ShardWeb.ChatChannel do payload = Map.put(payload, "name", nick) payload = Map.put(payload, "pk16", Shard.Keys.pk_display pk) - GenServer.cast(socket.assigns.pid, {:chat_send, pk, payload["message"]}) + SApp.Chat.chat_send(socket.assigns.pid, pk, payload["message"]) broadcast socket, "shout", payload {:noreply, socket} end diff --git a/shardweb/lib/controllers/chat_controller.ex b/shardweb/lib/controllers/chat_controller.ex index 31b80ba..75f2f18 100644 --- a/shardweb/lib/controllers/chat_controller.ex +++ b/shardweb/lib/controllers/chat_controller.ex @@ -14,7 +14,7 @@ defmodule ShardWeb.ChatController do def privchat(conn, %{"people_list" => people_list}) do known_people = for {_, %SApp.Identity.Manifest{pk: pk}, pid} <- Shard.Manager.list_shards() do - info = GenServer.call(pid, :get_info) + info = SApp.Identity.get_info(pid) {pk, info.nick} end diff --git a/shardweb/lib/controllers/identity_controller.ex b/shardweb/lib/controllers/identity_controller.ex index dd254bb..962a888 100644 --- a/shardweb/lib/controllers/identity_controller.ex +++ b/shardweb/lib/controllers/identity_controller.ex @@ -27,9 +27,9 @@ defmodule ShardWeb.IdentityController do def update(conn, params) do pid = SApp.Identity.find_proc(conn.assigns.pk) - info = GenServer.call(pid, :get_info) + info = SApp.Identity.get_info(pid) info = %{info | nick: params["nick"]} - GenServer.call(pid, {:set_info, info}) + SApp.Identity.set_info(pid, info) redirect conn, to: identity_path(conn, :self) end diff --git a/shardweb/lib/templates/identity/list.html.eex b/shardweb/lib/templates/identity/list.html.eex index 6437f9c..19dba2d 100644 --- a/shardweb/lib/templates/identity/list.html.eex +++ b/shardweb/lib/templates/identity/list.html.eex @@ -25,7 +25,7 @@ </tr> <%= for {_id, manifest, pid} <- people_list() do %> <tr> - <td><i class="fa fa-user"></i> <%= GenServer.call(pid, :get_info).nick %> + <td><i class="fa fa-user"></i> <%= SApp.Identity.get_info(pid).nick %> <%= if manifest.pk == @pk do %> <span class="badge badge-success"><i class="fa fa-user"></i> myself</span> <% end %> diff --git a/shardweb/lib/templates/identity/view.html.eex b/shardweb/lib/templates/identity/view.html.eex index 8bb8ca2..58be7e7 100644 --- a/shardweb/lib/templates/identity/view.html.eex +++ b/shardweb/lib/templates/identity/view.html.eex @@ -19,7 +19,7 @@ <%= render ShardWeb.LayoutView, "flashes.html", assigns %> <pre> - <%= inspect((GenServer.call(@pid, :get_info)), pretty: true, width: 40) %> + <%= inspect(SApp.Identity.get_info(@pid), pretty: true, width: 40) %> </pre> diff --git a/shardweb/lib/templates/layout/app.html.eex b/shardweb/lib/templates/layout/app.html.eex index d96bdeb..6cedcaf 100644 --- a/shardweb/lib/templates/layout/app.html.eex +++ b/shardweb/lib/templates/layout/app.html.eex @@ -61,7 +61,7 @@ <b class="caret"></b> </a> <ul class="dropdown-menu message-dropdown"> - <%= for {id, %SApp.Chat.PrivChat.Manifest{pk_list: pk_list}, pid} <- sur do %> + <%= for {_id, %SApp.Chat.PrivChat.Manifest{pk_list: pk_list}, pid} <- sur do %> <li class="message-preview"> <a href="<%= chat_path(@conn, :privchat, str_of_pk_list(@conn, pk_list)) %>"> <div class="media"> @@ -137,7 +137,7 @@ <%= for {id, %SApp.Chat.Manifest{channel: name}, pid} <- shard_list() do %> <li class="<%= if @shard == id do "custom_active" else "" end %>"> <a href="<%= chat_path(@conn, :chat, name) %>"> - <%= if GenServer.call(pid, :has_unread) != nil do %> + <%= if SApp.Chat.has_unread?(pid) != nil do %> <span class="have_unread">#<%= name %></span> <% else %> #<%= name %> @@ -159,7 +159,7 @@ <%= for {id, %SApp.Chat.PrivChat.Manifest{pk_list: pk_list}, pid} <- shard_list() do %> <li class="<%= if id == @shard do "custom_active" else "" end %>"> <a href="<%= chat_path(@conn, :privchat, str_of_pk_list(@conn, pk_list)) %>"> - <%= if GenServer.call(pid, :has_unread) != nil do %> + <%= if SApp.Chat.has_unread?(pid) != nil do %> <span class="have_unread"><%= nicks_of_pk_list(@conn, pk_list) %></span> <% else %> <%= nicks_of_pk_list(@conn, pk_list) %> @@ -171,7 +171,7 @@ <% end %> </li> <li class="<%= if @view_module == ShardWeb.PageView and @view_template == "peer_list.html" do "active" else "" end %>"> - <a href="<%= page_path(@conn, :peer_list) %>"><i class="fa fa-fw fa-globe"></i> Peer list</a> + <a href="<%= page_path(@conn, :peer_list) %>"><i class="fa fa-fw fa-server"></i> Peer list</a> </li> <li> <a href="#"><i class="fa fa-fw fa-gear"></i> Settings</a> diff --git a/shardweb/lib/templates/page/peer_list.html.eex b/shardweb/lib/templates/page/peer_list.html.eex index ff6479f..09060a7 100644 --- a/shardweb/lib/templates/page/peer_list.html.eex +++ b/shardweb/lib/templates/page/peer_list.html.eex @@ -10,7 +10,7 @@ <i class="fa fa-dashboard"></i> Dashboard </li> <li class="active"> - <i class="fa fa-globe"></i> Peer list + <i class="fa fa-server"></i> Peer list </li> </ol> </div> @@ -29,7 +29,7 @@ <tr> <td> <%= case auth do %> - <% nil -> %>(anonymous) + <% nil -> %><i class="fa fa-globe"></i> (anonymous) <% %SNet.Auth{his_pk: his_pk} -> %> <i class="fa fa-user"></i> <%= SApp.Identity.get_nick(his_pk) %> diff --git a/shardweb/lib/templates/page/shard_list.html.eex b/shardweb/lib/templates/page/shard_list.html.eex index 012223a..cc23205 100644 --- a/shardweb/lib/templates/page/shard_list.html.eex +++ b/shardweb/lib/templates/page/shard_list.html.eex @@ -30,7 +30,7 @@ <td> <%= case manifest do %> <% %SApp.Identity.Manifest{pk: pk} -> %><i class="fa fa-user"></i> - <%= GenServer.call(pid, :get_info).nick %> + <%= SApp.Identity.get_info(pid).nick %> <a href="<%= identity_path(@conn, :view, pk|>Base.encode16) %>"> <small><%= Shard.Keys.pk_display pk %></small> </a> diff --git a/shardweb/lib/views/layout_view.ex b/shardweb/lib/views/layout_view.ex index 990df55..d554804 100644 --- a/shardweb/lib/views/layout_view.ex +++ b/shardweb/lib/views/layout_view.ex @@ -26,7 +26,7 @@ defmodule ShardWeb.LayoutView do end def chat_shard_last_msg(pid) do - [{{_, msgbin, _}, true}] = GenServer.call(pid, {:read_history, nil, 1}) + [{{_, msgbin, _}, true}] = SApp.Chat.read_history(pid, nil, 1) {_, msg} = SData.term_unbin msgbin msg end @@ -34,14 +34,14 @@ defmodule ShardWeb.LayoutView do def privchat_with_unread(conn) do for {id, %SApp.Chat.PrivChat.Manifest{pk_list: pk_list}, pid} <- shard_list(), conn.assigns.pk in pk_list, - unread_time = GenServer.call(pid, :has_unread), + unread_time = SApp.Chat.has_unread?(pid), unread_time != nil, do: {id, %SApp.Chat.PrivChat.Manifest{pk_list: pk_list}, pid} end - def chat_with_unread(conn) do + def chat_with_unread(_conn) do for {id, %SApp.Chat.Manifest{channel: c}, pid} <- shard_list(), - unread_time = GenServer.call(pid, :has_unread), + unread_time = SApp.Chat.has_unread?(pid), unread_time != nil, do: {id, %SApp.Chat.Manifest{channel: c}, pid} end |