Packages

Elixir client for the Listmonk open-source email platform API

Current section

Files

Jump to
listmonk_client lib listmonk lists.ex
Raw

lib/listmonk/lists.ex

defmodule Listmonk.Lists do
@moduledoc """
Functions for managing Listmonk mailing lists.
"""
alias Listmonk.{Server, Error}
alias Listmonk.Models.MailingList
@type server :: pid() | atom()
@doc """
Retrieves all mailing lists.
"""
@spec get(server()) :: {:ok, list(MailingList.t())} | {:error, Error.t()}
def get(server) do
path = "/api/lists?page=1&per_page=1000000"
case Server.request(server, :get, path) do
{:ok, %{"data" => %{"results" => results}}} ->
lists = Enum.map(results, &MailingList.from_api/1)
{:ok, lists}
error ->
error
end
end
@doc """
Retrieves a mailing list by ID.
"""
@spec get_by_id(server(), integer()) :: {:ok, MailingList.t() | nil} | {:error, Error.t()}
def get_by_id(server, id) do
path = "/api/lists/#{id}"
case Server.request(server, :get, path) do
{:ok, %{"data" => data}} when is_map(data) ->
list_data =
case data do
%{"results" => results} when is_list(results) ->
Enum.find(results, &(&1["id"] == id))
_ ->
data
end
if list_data do
{:ok, MailingList.from_api(list_data)}
else
{:ok, nil}
end
error ->
error
end
end
@doc """
Creates a new mailing list.
## Attributes
- `:name` (required) - Name of the list
- `:type` - List type (:public or :private), default: :public
- `:optin` - Opt-in type (:single or :double), default: :single
- `:tags` - List of tags
- `:description` - Description of the list
"""
@spec create(server(), map()) :: {:ok, MailingList.t()} | {:error, Error.t()}
def create(server, attrs) do
with {:ok, payload} <- build_create_payload(attrs) do
case Server.request(server, :post, "/api/lists", json: payload) do
{:ok, %{"data" => data}} -> {:ok, MailingList.from_api(data)}
error -> error
end
end
end
@doc """
Deletes a mailing list by ID.
"""
@spec delete(server(), integer()) :: {:ok, boolean()} | {:error, Error.t()}
def delete(server, id) do
case get_by_id(server, id) do
{:ok, nil} ->
{:ok, false}
{:ok, _list} ->
case Server.request(server, :delete, "/api/lists/#{id}") do
{:ok, %{"data" => result}} -> {:ok, result == true}
error -> error
end
error ->
error
end
end
# Private functions
defp build_create_payload(attrs) do
name = Map.get(attrs, :name) |> validate_required(:name) |> String.trim()
list_type = Map.get(attrs, :type, :public)
optin = Map.get(attrs, :optin, :single)
unless list_type in [:public, :private] do
raise ArgumentError, "type must be :public or :private"
end
unless optin in [:single, :double] do
raise ArgumentError, "optin must be :single or :double"
end
payload = %{
"name" => name,
"type" => to_string(list_type),
"optin" => to_string(optin)
}
payload =
case Map.get(attrs, :tags) do
nil -> payload
tags -> Map.put(payload, "tags", tags)
end
payload =
case Map.get(attrs, :description) do
nil -> payload
description -> Map.put(payload, "description", description)
end
{:ok, payload}
rescue
e in ArgumentError -> {:error, Error.new(e.message)}
end
defp validate_required(nil, field), do: raise(ArgumentError, "#{field} is required")
defp validate_required("", field), do: raise(ArgumentError, "#{field} is required")
defp validate_required(value, _field), do: value
end