Amarula.Address (amarula v0.1.0)
View SourceA WhatsApp address — the consumer-facing way to name who/what a message is for or from. The boundary abstraction over the wire JID string.
Three kinds, distinguished by :kind:
:pn— a phone-number identity (<number>@s.whatsapp.net).:lid— a privacy "Linked ID" (<id>@lid). WhatsApp's wire-preferred identity; the same person has both a PN and a LID.:group— a group chat (<id>@g.us). A container of participants, not a person; its members are fetched separately (group metadata), not stored here.:none— the empty address (empty/0): "no identity". A total value for "we don't have one yet" (e.g.Amarula.own_address/1before login), so callers never have to nil-guard. It names nothing: everyis_*?is false, it is neversame_account?with anything, and rendering it to a wire jid is only allowed via the bang (to_jid!/1raises;to_jid/1returns{:error, :no_jid}).
:device is the device number (nil = account-level / primary). An address
with device: nil names the whole account; with a device it names one client.
Parsed-only
An Address is a pure value — only what's deterministic from the string.
It does NOT carry resolved data (a PN's LID, a group's participants, device
lists): those need connection state, are lazy, and can change, so they stay
internal. Don't expect Address.pn(...) to "know" its LID.
Boundary
parse/1 (wire string → Address) and to_jid/1 (Address → wire string)
are the border crossing, delegating to Amarula.Protocol.Binary.JID. Above the
border (public API, events) everything speaks Address; the wire/protocol layer
speaks JID strings. The public API also accepts a raw string and parses it, so
Amarula.send_text(conn, "5511...@s.whatsapp.net", ...) and
Amarula.send_text(conn, Address.pn("5511..."), ...) both work.
Summary
Functions
The empty address — "no identity". A total stand-in (see the :none kind).
Whether this is the empty address (empty/0, kind :none).
A group address from a bare id or full @g.us jid string.
A LID address from a bare id or full jid string.
The account-level address (device stripped).
Parse a wire jid into an Address (via JID.decode/1). Accepts a string or an
already-parsed Address (passed through), so it's safe to call at the API boundary
on either. Returns nil for an unparseable/unknown-server string. Use parse!/1
when a bad jid should raise instead.
Like parse/1 but raises ArgumentError on an unparseable jid (never nil).
A PN address from a bare number or full jid string.
Whether two addresses name the same account (same user+kind, ignoring device). The
empty address (:none) names nothing, so it is never the same account as anything —
including another empty.
Render an Address to its wire jid string (via JID.encode/1). Total: the empty
address (:none) has no wire form and returns {:error, :no_jid}. Use to_jid!/1
when you have a real address and want the bare string.
Like to_jid/1 but returns the bare string, raising on the empty address.
Coerce a string-or-Address to a wire jid string (boundary → wire). Total; mirrors
to_jid/1 (a binary passes through as {:ok, binary}). Use to_wire!/1 for the
bare string.
Like to_wire/1 but returns the bare string, raising on the empty address.
Types
@type kind() :: :pn | :lid | :group | :none
@type t() :: %Amarula.Address{ device: non_neg_integer() | nil, kind: kind(), user: String.t() }
Functions
@spec empty() :: t()
The empty address — "no identity". A total stand-in (see the :none kind).
Whether this is the empty address (empty/0, kind :none).
A group address from a bare id or full @g.us jid string.
A LID address from a bare id or full jid string.
The account-level address (device stripped).
Parse a wire jid into an Address (via JID.decode/1). Accepts a string or an
already-parsed Address (passed through), so it's safe to call at the API boundary
on either. Returns nil for an unparseable/unknown-server string. Use parse!/1
when a bad jid should raise instead.
Like parse/1 but raises ArgumentError on an unparseable jid (never nil).
A PN address from a bare number or full jid string.
Whether two addresses name the same account (same user+kind, ignoring device). The
empty address (:none) names nothing, so it is never the same account as anything —
including another empty.
Render an Address to its wire jid string (via JID.encode/1). Total: the empty
address (:none) has no wire form and returns {:error, :no_jid}. Use to_jid!/1
when you have a real address and want the bare string.
Like to_jid/1 but returns the bare string, raising on the empty address.
Coerce a string-or-Address to a wire jid string (boundary → wire). Total; mirrors
to_jid/1 (a binary passes through as {:ok, binary}). Use to_wire!/1 for the
bare string.
Like to_wire/1 but returns the bare string, raising on the empty address.