2017-05-08 50 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