Packages

Elixir client for the Listmonk open-source email platform API

Current section

Files

Jump to
listmonk_client lib listmonk models subscriber.ex
Raw

lib/listmonk/models/subscriber.ex

defmodule Listmonk.Models.Subscriber do
@moduledoc """
Struct representing a Listmonk subscriber.
"""
@type status :: :enabled | :disabled | :blocklisted
@type t :: %__MODULE__{
id: integer() | nil,
email: String.t() | nil,
name: String.t() | nil,
uuid: String.t() | nil,
status: status() | nil,
lists: list(map()) | nil,
attribs: map() | nil,
created_at: DateTime.t() | nil,
updated_at: DateTime.t() | nil
}
defstruct [
:id,
:email,
:name,
:uuid,
:status,
:lists,
:attribs,
:created_at,
:updated_at
]
@doc """
Creates a new subscriber struct from API response data.
"""
@spec from_api(map()) :: t()
def from_api(data) when is_map(data) do
%__MODULE__{
id: data["id"],
email: data["email"],
name: data["name"],
uuid: data["uuid"],
status: parse_status(data["status"]),
lists: data["lists"] || [],
attribs: data["attribs"] || %{},
created_at: parse_datetime(data["created_at"]),
updated_at: parse_datetime(data["updated_at"])
}
end
@doc """
Converts a subscriber struct to API request format.
"""
@spec to_api(t(), keyword()) :: map()
def to_api(%__MODULE__{} = subscriber, opts \\ []) do
list_ids = Keyword.get(opts, :list_ids, extract_list_ids(subscriber.lists))
preconfirm = Keyword.get(opts, :preconfirm, true)
%{
"email" => subscriber.email,
"name" => subscriber.name,
"status" => status_to_string(subscriber.status),
"lists" => list_ids,
"attribs" => subscriber.attribs || %{},
"preconfirm_subscriptions" => preconfirm
}
|> Enum.reject(fn {_k, v} -> is_nil(v) end)
|> Map.new()
end
defp parse_status("enabled"), do: :enabled
defp parse_status("disabled"), do: :disabled
defp parse_status("blocklisted"), do: :blocklisted
defp parse_status(_), do: nil
defp status_to_string(:enabled), do: "enabled"
defp status_to_string(:disabled), do: "disabled"
defp status_to_string(:blocklisted), do: "blocklisted"
defp status_to_string(nil), do: "enabled"
defp parse_datetime(nil), do: nil
defp parse_datetime(datetime_string) when is_binary(datetime_string) do
case DateTime.from_iso8601(datetime_string) do
{:ok, datetime, _offset} -> datetime
{:error, _} -> nil
end
end
defp parse_datetime(_), do: nil
defp extract_list_ids(nil), do: []
defp extract_list_ids([]), do: []
defp extract_list_ids(lists) when is_list(lists) do
Enum.map(lists, fn
%{"id" => id} -> id
id when is_integer(id) -> id
_ -> nil
end)
|> Enum.reject(&is_nil/1)
end
end