aboutsummaryrefslogblamecommitdiff
path: root/shardweb/lib/channels/chat_channel.ex
blob: 7c8f1f94412667112764ef2f8e4449e982ba7c77 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                 



                        
                                                    

                              
                                                                               

                                        
                              







                                         








                                                                                 
                              







                                         
                                         
                                                        





                                                  
                                    


                       
                                           


                      


                                                                      
                                                              




                                      
                                           



                                                
                                           











                                                             



                                                                
                                                          
 
                                                                   
                                      







                                             
defmodule ShardWeb.ChatChannel do
  use ShardWeb, :channel

  require Logger

  def join("chat:" <> room_name, payload, socket) do
    if authorized?(payload) do

      pid = Shard.Manager.find_or_start %SApp.Chat.Manifest{channel: room_name}
      socket = assign(socket, :pid, pid)

      SApp.Chat.subscribe(pid)
      send(self(), :after_join)
      
      {:ok, socket}
    else
      {:error, %{reason: "unauthorized"}}
    end
  end

  def join("privchat:" <> room_name, payload, socket) do
    if authorized?(payload) do

      pk_list = room_name |> String.split(",") |> Enum.map(&Base.decode16!/1)
      pk_list = [socket.assigns.pk | pk_list] |> Enum.sort() |> Enum.uniq()

      pid = Shard.Manager.find_or_start(SApp.Chat.PrivChat.Manifest.new(pk_list))
      socket = assign(socket, :pid, pid)

      SApp.Chat.subscribe(pid)
      send(self(), :after_join)
      
      {:ok, socket}
    else
      {:error, %{reason: "unauthorized"}}
    end
  end

  def handle_info(:after_join, socket) do
    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
        push(socket, "shout", %{
          name: nick,
          pk16: Shard.Keys.pk_display(pk),
          fullpk: Base.encode16(pk),
          message: msg,
        }) 
      end)
    SApp.Chat.mark_read(socket.assigns.pid)
    {:noreply, socket}
  end

  def handle_info({:chat_recv, _chan, {pk, msgbin, _sign}}, socket) do
    {_ts, msg} = SData.term_unbin msgbin
    nick = SApp.Identity.get_nick pk
    Logger.info("#{inspect self()} :chat_recv #{inspect msg}")
    push socket, "shout", %{
      name: nick,
      pk16: Shard.Keys.pk_display(pk),
      fullpk: Base.encode16(pk),
      message: msg}
    SApp.Chat.mark_read(socket.assigns.pid)
    {:noreply, socket}
  end

  def handle_info({:chat_send, _, _}, socket) do
    SApp.Chat.mark_read(socket.assigns.pid)
    {:noreply, socket}
  end

  # Channels can be used in a request/response fashion
  # by sending replies to requests from the client
  def handle_in("ping", payload, socket) do
    {:reply, {:ok, payload}, socket}
  end

  # It is also common to receive messages from the client and
  # broadcast to everyone in the current topic (room:lobby).
  def handle_in("shout", payload, socket) do
    pk = socket.assigns.pk
    nick = SApp.Identity.get_nick pk
    payload = Map.put(payload, "name", nick)
    payload = Map.put(payload, "pk16", Shard.Keys.pk_display pk)
    payload = Map.put(payload, "fullpk", Base.encode16 pk)

    SApp.Chat.chat_send(socket.assigns.pid, pk, payload["message"])
    broadcast socket, "shout", payload
    {:noreply, socket}
  end

  # Add authorization logic here as required.
  defp authorized?(_payload) do
    true
  end
end