Amarula.Protocol.Messages.Relay (amarula v0.1.0)

View Source

Build the outbound <message> stanza for a 1:1 send, ported from the single-device path of Baileys relayMessage (src/Socket/messages-send.ts).

Shape (1:1, single device):

<message id=msgId to=jid type="text" t=ts>
  <enc v="2" type="msg"|"pkmsg">ciphertext</enc>
  <device-identity>...</device-identity>   (only when type=pkmsg)
</message>

device-identity is required whenever any enc is a pkmsg so the recipient can verify our companion identity (encodeSignedDeviceIdentity, include sig key).

Summary

Functions

Build a multi-device message stanza, ported from the fan-out path of Baileys relayMessage (the <participants> branch).

Functions

build_group_stanza(msg_id, to, skmsg, participants, account, opts \\ [])

@spec build_group_stanza(
  String.t(),
  String.t(),
  binary(),
  [{String.t(), :msg | :pkmsg, binary()}],
  struct(),
  keyword()
) :: {:ok, Amarula.Protocol.Binary.Node.t()} | {:error, :no_participants}

Build a group message stanza:

<message id=msgId to=group type="text" t=ts>
  <enc v="2" type="skmsg">skmsg</enc>
  <participants>
    <to jid=device1><enc v="2" type="pkmsg">skdm1</enc></to>
    ...
  </participants>
  <device-identity>...</device-identity>   (when any SKDM enc is pkmsg)
</message>

The skmsg is the group ciphertext (sender-key encrypted, one for the whole group). participants are per-device SKDM {jid, enc_type, ciphertext} tuples so each member can rebuild our sender key. {:error, :no_participants} if the SKDM fan-out is empty.

build_message_stanza(msg_id, to, enc_type, ciphertext, account, opts \\ [])

@spec build_message_stanza(
  String.t(),
  String.t(),
  :msg | :pkmsg,
  binary(),
  struct(),
  keyword()
) ::
  Amarula.Protocol.Binary.Node.t()

Build the message stanza.

  • msg_id — the message id (also the WAMessageKey id)
  • to — recipient JID
  • enc_type:msg or :pkmsg
  • ciphertext — Signal ciphertext bytes
  • account — our ADVSignedDeviceIdentity (for device-identity on pkmsg)
  • timestamp — unix seconds (defaults to now)

build_multi_device_stanza(msg_id, to, participants, account, opts \\ [])

@spec build_multi_device_stanza(
  String.t(),
  String.t(),
  [{String.t(), :msg | :pkmsg, binary()}],
  struct(),
  keyword()
) :: {:ok, Amarula.Protocol.Binary.Node.t()} | {:error, :no_participants}

Build a multi-device message stanza, ported from the fan-out path of Baileys relayMessage (the <participants> branch).

Shape:

<message id=msgId to=jid type="text" t=ts>
  <participants>
    <to jid=device1><enc v="2" type=...>ct1</enc></to>
    <to jid=device2><enc v="2" type=...>ct2</enc></to>
    ...
  </participants>
  <device-identity>...</device-identity>   (when any enc is pkmsg)
</message>
  • participants — list of {device_jid, enc_type, ciphertext} tuples, one per recipient device (already encrypted by the caller).

Returns {:error, :no_participants} when the list is empty (all encryptions failed upstream), matching Baileys' "All encryptions failed" guard.