2017-05-08 100 views
1

我將子主題用作其他人可以用來將消息發送給特定其他人的單用戶頻道。如何使用Phoenix Presence追蹤主題/子主題的存在?

例如: - 我是用戶1,我想將消息發送給用戶2 - 我發送郵件與有效載荷{ to: 2, message: 'hi' }handle_in確實App.Endpoint.broadcast("user:2", "hi")

這裏是一個片段從我user_channel.ex

def handle_in("chat", incoming_payload, socket) do 
    from_uid = socket.assigns.uid 
    uid = incoming_payload["to"] 
    message = incoming_payload["message"] 
    topic = "user:#{uid}" 
    payload = %{uid: from_uid, message: message} 

    # Send to the topic based of the incoming_payload's 
    # 'to' param. 
    App.Endpoint.broadcast(topic, "chat", payload) 

    {:reply, :ok, socket} 
end 

對於任何人誰是好奇:代碼是開源的

https://github.com/NullVoxPopuli/mesh-relay-phoenix/tree/feature/presence-tracking

+0

問題是什麼? –

回答

1

由於在仙丹琅鬆弛通道一些優秀的人,我能在這個解決方案(工作)到達:

defmodule MeshRelay.UserChannel do 
    use Phoenix.Channel, :channel 
    alias MeshRelay.Presence 
    require Logger 

    defp uids_present(to_uid, from_uid) do 
    to_uid && from_uid 
    end 

    defp has_valid_payload(payload) do 
    uid = payload["to"] 
    message = payload["message"] 

    uid && message 
    end 

    # uid is the member's channel that 
    # he/she receives their messages on. 
    # no messages not intended to be received by 
    # this member should be sent on this channel/subtopic 
    # 
    # socket.assigns.uid is the uid from the connect 
    def join("user:" <> uid, _params, socket) do 
    has_uids = uids_present(uid, socket.assigns.uid) 

    if has_uids do 
     send(self(), :after_join) 
     # Logger.debug Presence.list(socket) 
     {:ok, socket} 
    else 
     # kick him out he is not allowed here 
     {:error, 
     %{reason: "in order to receive messages, you must join a channel using your own uid"}, 
     socket 
     } 
    end 
    end 

    def handle_in("chat", incoming_payload, socket) do 
    if has_valid_payload(incoming_payload) do 
     from_uid = socket.assigns.uid 
     uid = incoming_payload["to"] 
     message = incoming_payload["message"] 
     topic = "user:#{uid}" 
     payload = %{uid: from_uid, message: message} 

     if is_member_online?(uid) do 
     MeshRelay.Endpoint.broadcast(topic, "chat", payload) 
     # broadcast! socket, "chat", payload 
     {:reply, :ok, socket} 
     else 
     reply_with_error_message(socket, %{ 
      reason: "member not found", 
      to_uid: uid, 
      from_uid: from_uid 
     }) 
     end 
    else 
     reply_with_error_message(socket, %{ 
     reason: "please format your message: { \"to\": \"uidstring\", \"message\": \"encrypted message\" }" 
     }) 
    end 
    end 

    def reply_with_error_message(socket, error) do 
    {:reply, {:error, error}, socket } 
    end 

    def handle_info(:after_join, socket) do 
    Presence.track(socket.channel_pid, "connected_members", socket.assigns.uid, %{ 
     online_at: inspect(System.system_time(:milli_seconds)) 
    }) 

    {:noreply, socket} 
    end 

    def is_member_online?(uid) do 
    Presence.list("connected_members") 
    |> Map.keys 
    |> Enum.any?(fn key -> key == uid end) 
    end 


end