defmodule Ravenx.Strategy.Pusher do @moduledoc """ RavenxPusher is a Strategy to send notifications through Pusher with Ravenx. """ @behaviour Ravenx.StrategyBehaviour import Pusher, only: [trigger: 4, configure!: 5] alias RavenxPusher.Push @push_required [:data, :event, :channels] @required_options [:host, :port, :app_id, :app_key, :secret] @doc """ `call/2` Accepts a payload and an options map an returns `{:ok, %Push{}}` if the notification could be sent, `{:error, {:missing_config, error}}` in case any required config fields are missing, or `{:error, {:pusher_error, %Push{}}}` in case there was an error when sending the notification. """ @spec call(Ravenx.notif_payload(), Ravenx.notif_options()) :: {:ok, Push.t()} | {:error, {:missing_config, any}} | {:error, {:pusher_error, Push.t()}} def call(payload, opts \\ %{}) when is_map(payload) and is_map(opts) do options = parse_options(opts) %Push{} |> parse_payload(payload) |> send_push(options) end @spec send_push(payload :: map, options :: map) :: {:ok, Push.t()} | {:error, {:missing_config, any}} | {:error, {:pusher_error, Push.t()}} defp send_push(payload, opts) for field <- @required_options do defp send_push(_push, %{unquote(field) => f}) when f in [nil, ""] do {:error, {:missing_config, unquote(field)}} end end for field <- @push_required do defp send_push(%Push{unquote(field) => f}, _opts) when f in [nil, ""] do {:error, {:missing_field, unquote(field)}} end end defp send_push(%Push{} = push, %{ host: host, port: port, app_id: aid, app_key: akey, secret: secret }) do configure!(host, port, aid, akey, secret) case trigger(push.event, push.data, push.channels, push.socket_id) do :ok -> {:ok, %{push | sent?: true}} :error -> {:error, {:pusher_error, push}} end end defp parse_payload(push, payload) do push |> add_to_push(:data, Map.get(payload, :data)) |> add_to_push(:event, Map.get(payload, :event)) |> add_to_push(:channels, get_channels(Map.get(payload, :channels))) |> add_to_push(:socket_id, Map.get(payload, :socket_id)) end defp parse_options(opts) do %{} |> add_to_options(:host, Map.get(opts, :host)) |> add_to_options(:port, Map.get(opts, :port)) |> add_to_options(:app_id, Map.get(opts, :app_id)) |> add_to_options(:app_key, Map.get(opts, :app_key)) |> add_to_options(:secret, Map.get(opts, :secret)) end defp add_to_push(push, key, value), do: Map.put(push, key, value) defp add_to_options(opts, key, value), do: Map.put(opts, key, value) defp get_channels(nil), do: nil defp get_channels(channels) when is_list(channels) and length(channels) > 0, do: channels defp get_channels(channels) when is_binary(channels), do: [channels] defp get_channels(_channels), do: nil end