Amarula.Connection.SendOps (amarula v0.4.2)

View Source

Pure send-path builders for Amarula.Connection.

Each function turns send-callback arguments into a {target, payload, shape} triple that Connection.deliver_async/5 dispatches — no socket, no state mutation, no process. This is the body logic of the {:send_*} / {:fetch_history} / {:request_resend} callbacks, lifted out of the GenServer module so it is testable without a live connection.

The callbacks on Connection stay thin: they call one of these builders and feed the result to deliver_async. The ack lifecycle (park_ack/resolve_ack /monitors) is a separate, shared seam and remains on Connection.

shape is the reply-shaping fun deliver_async applies to the pipe result; most sends use default_send_reply/2, polls override it to carry the secret.

Summary

Functions

Default reply shaping for a send: :ok{:ok, msg_id}, errors pass through. Public so Connection.deliver_async/5 can use it as the default shape.

On-demand history request: a PEER_DATA_OPERATION sent to OURSELVES (me_id) with the peer category + high push priority; the phone replies later with an ON_DEMAND HistorySync notification.

Built media message (already encrypted + uploaded) → %{message: message} for jid. The encrypt/upload Task lives on Connection; this only shapes the ready message for dispatch.

Pre-built %Proto.Message{}%{message: message} for jid.

Poll for jid. Builds the poll message + secret, and a shape that turns the successful {:ok, id} reply into {:ok, id, secret} so the caller can tally votes.

Placeholder-resend request: a PEER_DATA_OPERATION sent to OURSELVES (me_id) with the peer category + high push priority so the phone re-delivers the original message.

Text → a send build for jid. With no reply/mention context it stays the lightweight %{text: text} shorthand (the sandbox/offline path mints a reply without encoding). When :quoted/:mentions are present we build the full %Proto.Message{} here (an extendedTextMessage carrying the contextInfo).

Types

build()

@type build() :: {target(), payload(), shape()}

payload()

@type payload() :: map()

shape()

@type shape() :: (term(), String.t() -> term())

target()

@type target() :: term()

Functions

default_send_reply(arg1, msg_id)

@spec default_send_reply(term(), String.t()) :: term()

Default reply shaping for a send: :ok{:ok, msg_id}, errors pass through. Public so Connection.deliver_async/5 can use it as the default shape.

fetch_history(me_id, oldest_key, oldest_ts, count)

@spec fetch_history(term(), struct(), non_neg_integer(), non_neg_integer()) :: build()

On-demand history request: a PEER_DATA_OPERATION sent to OURSELVES (me_id) with the peer category + high push priority; the phone replies later with an ON_DEMAND HistorySync notification.

media(jid, message)

@spec media(
  term(),
  struct()
) :: build()

Built media message (already encrypted + uploaded) → %{message: message} for jid. The encrypt/upload Task lives on Connection; this only shapes the ready message for dispatch.

message(jid, message)

@spec message(
  term(),
  struct()
) :: build()

Pre-built %Proto.Message{}%{message: message} for jid.

poll(jid, name, options, opts)

@spec poll(term(), String.t(), [String.t()], keyword()) :: build()

Poll for jid. Builds the poll message + secret, and a shape that turns the successful {:ok, id} reply into {:ok, id, secret} so the caller can tally votes.

request_resend(me_id, message_key)

@spec request_resend(
  term(),
  struct()
) :: build()

Placeholder-resend request: a PEER_DATA_OPERATION sent to OURSELVES (me_id) with the peer category + high push priority so the phone re-delivers the original message.

text(jid, text, opts \\ [])

@spec text(term(), String.t(), keyword()) :: build()

Text → a send build for jid. With no reply/mention context it stays the lightweight %{text: text} shorthand (the sandbox/offline path mints a reply without encoding). When :quoted/:mentions are present we build the full %Proto.Message{} here (an extendedTextMessage carrying the contextInfo).