2.0 KiB · text History 9c0fc16
defmodule LambentExWeb.LinksChannel do
  @moduledoc """
  Mirrors `LambentExWeb.LinksLive.Index`: running links, toggle / enable /
  disable / persist / quit, and both create forms.

  Pushes
    * `"link"` — one link's published state, keyed by `name`, including the
      `chan` it drives and whether it is currently enabled.
  """

  use Phoenix.Channel
  require Logger

  alias LambentEx.Schema.Links
  alias LambentEx.Schema.LinksB
  alias LambentEx.Scan.ESP8266x7777, as: S
  alias LambentExWeb.Channels.Payload

  @pubsub LambentEx.PubSub

  @impl true
  def join("links", _params, socket) do
    Phoenix.PubSub.subscribe(@pubsub, "links_idx")
    {:ok, socket}
  end

  @impl true
  def handle_info({:links_pub, link}, socket) do
    push(socket, "link", Payload.wire(link))
    {:noreply, socket}
  end

  @impl true
  def handle_in(cmd, %{"id" => id}, socket) when cmd in ~w(toggle enable disable persist quit) do
    apply(LambentEx.Link, String.to_existing_atom(cmd), [id])
    {:reply, :ok, socket}
  end

  # %{"link" => %{"name" =>, "source_id" =>, "target_id" =>, "chan" => "all" | "0"}}
  # chan is optional, and is forced to 0 for anything with a single channel
  @impl true
  def handle_in("create", %{"link" => params}, socket) do
    case Links.update_links(%Links{}, params, S.tagged_devices()) do
      {:ok, _link} -> {:reply, :ok, socket}
      {:error, changeset} -> {:reply, {:error, %{errors: errors(changeset)}}, socket}
    end
  end

  # same, with "target_ids" as a list
  @impl true
  def handle_in("create_bulk", %{"link" => params}, socket) do
    case LinksB.update_links(%LinksB{}, params, S.tagged_devices()) do
      {:ok, _links} -> {:reply, :ok, socket}
      {:error, changeset} -> {:reply, {:error, %{errors: errors(changeset)}}, socket}
    end
  end

  defp errors(changeset) do
    Ecto.Changeset.traverse_errors(changeset, fn {msg, opts} ->
      Regex.replace(~r"%{(\w+)}", msg, fn _, key ->
        opts |> Keyword.get(String.to_existing_atom(key), "") |> to_string()
      end)
    end)
  end
end