defmodule Chaperon.Action.WebSocket do @moduledoc """ Helper functions for creating WebSocket actions. """ alias __MODULE__ alias Chaperon.Session @type msg_type :: :text | :binary @doc """ Returns a `Chaperon.WebSocket.Connect` action for a given `path`. """ def connect(path, options \\ []) do %WebSocket.Connect{path: path, options: options} end @doc """ Returns a `Chaperon.WebSocket.SendMessage` action with a given `message` and `options`. """ @spec send(any(), Keword.t()) :: WebSocket.SendMessage.t() def send(message, options \\ []) do %WebSocket.SendMessage{ message: message, type: Keyword.get(options, :type, :text), options: options } end @doc """ Returns a `Chaperon.WebSocket.ReceiveMessage` action with `options`. `options` can include a result handler callback to be called once the message arrived. Example: Chaperon.Action.WebSocket.recv(with_result: fn (session, result) -> session |> Chaperon.Session.assign(ws_message: result) end) """ def recv(options \\ []) do decode = Keyword.get(options, :decode, nil) callback = Keyword.get(options, :with_result, nil) options = Keyword.delete(options, :with_result) %WebSocket.ReceiveMessage{ options: options, decode: decode, callback: callback } end @doc """ Returns a `Chaperon.WebSocket.Close` action with `options`. """ def close(options \\ []) do %WebSocket.Close{ options: options } end def for_action(session, action) do case action.options[:name] do nil -> {session.assigned.websocket.connection, session.assigned.websocket.url} name -> Map.get(session.assigned.websocket.named_connections, name) end end def assign_for_action(session, action, ws_conn, ws_url) do case action.options[:name] do nil -> session |> Session.assign( :websocket, connection: ws_conn, url: ws_url ) name -> session |> Session.update_assign(websocket: &(&1 || %{})) |> Session.update_assign( :websocket, named_connections: fn nil -> %{name => {ws_conn, ws_url}} sockets -> Map.put(sockets, name, {ws_conn, ws_url}) end ) end end def delete_for_action(session, action) do case action.options[:name] do nil -> session |> Session.delete_assign(:websocket, :connection) |> Session.delete_assign(:websocket, :url) name -> session |> Session.update_assign(:websocket, named_connections: &Map.delete(&1, name)) end end def reset_websockets(session) do session |> Chaperon.Session.delete_assign(:websocket) end end