summaryrefslogblamecommitdiff
path: root/lib/web/live/chat_live.ex
blob: 0513cc20e76f57a1a40bda9ea6d0d4ed8eb2e0f8 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                             




                                                                                           
                                      
                                                          

                                                                                    
                                                                                       
                                                                                                   
                                                               
                                                                                                           









                                                                        
                                                                               


                                                                                                   

               
 






                                              
                                  









                                                                        
                                                         





                                                                                            

                                                                
                                 

                        






                                                                                             
                               





                                                                                 
                               





                                                                                 
                               







                                                          
                                        
                   
                                 







                                                   
















                                                                                                
   
defmodule NolaWeb.ChatLive do
  use Phoenix.LiveView
  use Phoenix.HTML
  require Logger

  def mount(%{"network" => network, "chan" => chan}, %{"account" => account_id}, socket) do
    chan = NolaWeb.reformat_chan(chan)
    connection = IRC.Connection.get_network(network, chan)
    account = Nola.Account.get(account_id)
    membership = IRC.Membership.of_account(Nola.Account.get("DRgpD4fLf8PDJMLp8Dtb"))
    if account && connection && Enum.member?(membership, {connection.network, chan}) do
      {:ok, _} = Registry.register(Nola.PubSub, "#{connection.network}:events", plugin: __MODULE__)
      for t <- ["messages", "triggers", "outputs", "events"] do
        {:ok, _} = Registry.register(Nola.PubSub, "#{connection.network}/#{chan}:#{t}", plugin: __MODULE__)
      end

      IRC.PuppetConnection.start(account, connection)

      users = IRC.UserTrack.channel(connection.network, chan)
      |> Enum.map(fn(tuple) -> IRC.UserTrack.User.from_tuple(tuple) end)
      |> Enum.reduce(Map.new, fn(user = %{id: id}, acc) ->
        Map.put(acc, id, user)
      end)

      backlog = case Nola.IRC.Buffer.select_buffer(connection.network, chan) do
                  {backlog, _} ->
                    {backlog, _} = Enum.reduce(backlog, {backlog, nil}, &reduce_contextual_event/2)
                    Enum.reverse(backlog)
        _ -> []
      end

      socket = socket
      |> assign(:connection_id, connection.id)
      |> assign(:network, connection.network)
      |> assign(:chan, chan)
      |> assign(:title, "live")
      |> assign(:channel, chan)
      |> assign(:account_id, account.id)
      |> assign(:backlog, backlog)
      |> assign(:users, users)
      |> assign(:counter, 0)

      {:ok, socket}
    else
      {:ok, redirect(socket, to: "/")}
    end
  end

  def handle_event("send", %{"message" => %{"text" => text}}, socket) do
    account = Nola.Account.get(socket.assigns.account_id)
    IRC.send_message_as(account, socket.assigns.network, socket.assigns.channel, text, true)
    {:noreply, assign(socket, :counter, socket.assigns.counter + 1)}
  end

  def handle_info({:irc, :event, event = %{type: :join, user_id: id}}, socket) do
    if user = IRC.UserTrack.lookup(id) do
      socket = socket
      |> assign(:users, Map.put(socket.assigns.users, id, user))
      |> append_to_backlog(event)
      {:noreply, socket}
    else
      {:noreply, socket}
    end
  end

  def handle_info({:irc, :event, event = %{type: :nick, user_id: id, nick: nick}}, socket) do
    socket = socket
    |> assign(:users, update_in(socket.assigns.users, [id, :nick], nick))
    |> append_to_backlog(event)
    {:noreply, socket}
  end

  def handle_info({:irc, :event, event = %{type: :quit, user_id: id}}, socket) do
    socket = socket
    |> assign(:users, Map.delete(socket.assigns.users, id))
    |> append_to_backlog(event)
    {:noreply, socket}
  end

  def handle_info({:irc, :event, event = %{type: :part, user_id: id}}, socket) do
    socket = socket
    |> assign(:users, Map.delete(socket.assigns.users, id))
    |> append_to_backlog(event)
    {:noreply, socket}
  end

  def handle_info({:irc, :trigger, _, message}, socket) do
    handle_info({:irc, nil, message}, socket)
  end

  def handle_info({:irc, :text, message}, socket) do
    IO.inspect({:live_message, message})
    socket = socket
    |> append_to_backlog(message)
    {:noreply, socket}
  end

  def handle_info(info, socket) do
    Logger.debug("Unhandled info: #{inspect info}")
    {:noreply, socket}
  end

  defp append_to_backlog(socket, line) do
    {add, _} = reduce_contextual_event(line, {[], List.last(socket.assigns.backlog)})
    assign(socket, :backlog, socket.assigns.backlog ++ add)
  end

  defp reduce_contextual_event(line, {acc, nil}) do
    {[line | acc], line}
  end
  defp reduce_contextual_event(line, {acc, last}) do
    if NaiveDateTime.to_date(last.at) != NaiveDateTime.to_date(line.at) do
      {[%{type: :day_changed, date: NaiveDateTime.to_date(line.at), at: nil}, line | acc], line}
       else
         {[line | acc], line}
      end

  end

end