zapo-js 0.2.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (863) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +103 -179
  3. package/dist/appstate/{WaAppStateCrypto.js → crypto/WaAppStateCrypto.js} +79 -62
  4. package/dist/appstate/index.js +8 -7
  5. package/dist/appstate/{encoding.js → parsers/encoding.js} +11 -4
  6. package/dist/appstate/{WaAppStateSyncResponseParser.js → parsers/response-parser.js} +20 -8
  7. package/dist/appstate/{WaAppStateSyncClient.js → sync/WaAppStateSyncClient.js} +246 -88
  8. package/dist/appstate/utils.js +16 -0
  9. package/dist/appstate-spec.js +89 -0
  10. package/dist/auth/WaAuthClient.js +117 -13
  11. package/dist/auth/credentials-flow.js +207 -0
  12. package/dist/auth/pairing/WaPairingFlow.js +53 -47
  13. package/dist/auth/pairing/pairing-code-crypto.js +91 -0
  14. package/dist/client/WaClient.js +369 -460
  15. package/dist/client/WaClientFactory.js +377 -93
  16. package/dist/client/connection/WaConnectionManager.js +31 -11
  17. package/dist/client/coordinators/WaAbPropsCoordinator.js +140 -0
  18. package/dist/client/coordinators/WaAppStateMutationCoordinator.js +663 -143
  19. package/dist/client/coordinators/WaBotCoordinator.js +345 -0
  20. package/dist/client/coordinators/WaBroadcastListCoordinator.js +20 -0
  21. package/dist/client/coordinators/WaBusinessCoordinator.js +81 -180
  22. package/dist/client/coordinators/WaEmailCoordinator.js +64 -0
  23. package/dist/client/coordinators/WaGroupCoordinator.js +529 -52
  24. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +130 -20
  25. package/dist/client/coordinators/WaLowLevelCoordinator.js +41 -0
  26. package/dist/client/coordinators/WaMessageCoordinator.js +365 -0
  27. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +724 -216
  28. package/dist/client/coordinators/WaNewsletterCoordinator.js +18 -0
  29. package/dist/client/coordinators/WaOfflineResumeCoordinator.js +114 -0
  30. package/dist/client/coordinators/WaPassiveTasksCoordinator.js +53 -22
  31. package/dist/client/coordinators/WaPresenceCoordinator.js +21 -0
  32. package/dist/client/coordinators/WaPrivacyCoordinator.js +7 -5
  33. package/dist/client/coordinators/WaProfileCoordinator.js +223 -50
  34. package/dist/client/coordinators/WaRetryCoordinator.js +256 -123
  35. package/dist/client/coordinators/WaStatusCoordinator.js +49 -0
  36. package/dist/client/coordinators/WaStreamControlCoordinator.js +6 -6
  37. package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +29 -10
  38. package/dist/client/events/abprops.js +43 -0
  39. package/dist/client/events/appstate-mutation.js +133 -0
  40. package/dist/client/events/business.js +375 -0
  41. package/dist/client/events/call.js +58 -0
  42. package/dist/client/events/chatstate.js +23 -0
  43. package/dist/client/events/devices.js +15 -16
  44. package/dist/client/{dirty.js → events/dirty.js} +34 -20
  45. package/dist/client/events/group.js +13 -24
  46. package/dist/client/events/identity.js +2 -1
  47. package/dist/client/events/incoming.js +502 -0
  48. package/dist/client/events/mex-notification.js +181 -0
  49. package/dist/client/events/picture.js +33 -0
  50. package/dist/client/events/presence.js +44 -0
  51. package/dist/client/events/privacy-token.js +1 -2
  52. package/dist/client/events/receipt.js +26 -0
  53. package/dist/client/events/registration.js +42 -0
  54. package/dist/client/media.js +400 -0
  55. package/dist/client/messaging/fanout.js +9 -10
  56. package/dist/client/messaging/{participants.js → group-metadata.js} +73 -35
  57. package/dist/client/messaging/ignore-key.js +132 -0
  58. package/dist/client/messaging/key-protocol.js +3 -17
  59. package/dist/client/messaging/link-preview.js +159 -0
  60. package/dist/client/messaging/messages.js +671 -0
  61. package/dist/client/newsletter/admin.js +165 -0
  62. package/dist/client/newsletter/content.js +253 -0
  63. package/dist/client/newsletter/discovery.js +115 -0
  64. package/dist/client/newsletter/messaging.js +197 -0
  65. package/dist/client/newsletter/mex.js +41 -0
  66. package/dist/client/newsletter/parse.js +217 -0
  67. package/dist/client/persistence/WriteBehindPersistence.js +31 -4
  68. package/dist/client/{history-sync.js → persistence/history-sync.js} +125 -18
  69. package/dist/client/persistence/mailbox.js +104 -0
  70. package/dist/client/tokens/cs-token.js +11 -17
  71. package/dist/crypto/core/hkdf.js +12 -12
  72. package/dist/crypto/core/index.js +9 -8
  73. package/dist/crypto/core/keys.js +1 -8
  74. package/dist/crypto/core/nonce.js +12 -12
  75. package/dist/crypto/core/primitives.js +123 -93
  76. package/dist/crypto/core/random.js +9 -9
  77. package/dist/crypto/core/xeddsa.js +59 -0
  78. package/dist/crypto/curves/Ed25519.js +32 -21
  79. package/dist/crypto/curves/X25519.js +71 -17
  80. package/dist/crypto/curves/constants.js +3 -1
  81. package/dist/crypto/math/constants.js +1 -2
  82. package/dist/crypto/math/mod.js +0 -33
  83. package/dist/esm/appstate/{WaAppStateCrypto.js → crypto/WaAppStateCrypto.js} +72 -55
  84. package/dist/esm/appstate/index.js +5 -5
  85. package/dist/esm/appstate/{encoding.js → parsers/encoding.js} +11 -4
  86. package/dist/esm/appstate/{WaAppStateSyncResponseParser.js → parsers/response-parser.js} +20 -8
  87. package/dist/esm/appstate/{WaAppStateSyncClient.js → sync/WaAppStateSyncClient.js} +235 -76
  88. package/dist/esm/appstate/utils.js +16 -0
  89. package/dist/esm/appstate-spec.js +79 -0
  90. package/dist/esm/auth/WaAuthClient.js +114 -10
  91. package/dist/esm/auth/credentials-flow.js +202 -0
  92. package/dist/esm/auth/pairing/WaPairingFlow.js +52 -46
  93. package/dist/esm/auth/pairing/pairing-code-crypto.js +85 -0
  94. package/dist/esm/client/WaClient.js +372 -463
  95. package/dist/esm/client/WaClientFactory.js +380 -96
  96. package/dist/esm/client/connection/WaConnectionManager.js +31 -11
  97. package/dist/esm/client/coordinators/WaAbPropsCoordinator.js +136 -0
  98. package/dist/esm/client/coordinators/WaAppStateMutationCoordinator.js +665 -145
  99. package/dist/esm/client/coordinators/WaBotCoordinator.js +342 -0
  100. package/dist/esm/client/coordinators/WaBroadcastListCoordinator.js +17 -0
  101. package/dist/esm/client/coordinators/WaBusinessCoordinator.js +78 -177
  102. package/dist/esm/client/coordinators/WaEmailCoordinator.js +61 -0
  103. package/dist/esm/client/coordinators/WaGroupCoordinator.js +532 -55
  104. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +132 -22
  105. package/dist/esm/client/coordinators/WaLowLevelCoordinator.js +38 -0
  106. package/dist/esm/client/coordinators/WaMessageCoordinator.js +361 -0
  107. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +719 -211
  108. package/dist/esm/client/coordinators/WaNewsletterCoordinator.js +13 -0
  109. package/dist/esm/client/coordinators/WaOfflineResumeCoordinator.js +110 -0
  110. package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +54 -23
  111. package/dist/esm/client/coordinators/WaPresenceCoordinator.js +18 -0
  112. package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +7 -5
  113. package/dist/esm/client/coordinators/WaProfileCoordinator.js +226 -53
  114. package/dist/esm/client/coordinators/WaRetryCoordinator.js +258 -125
  115. package/dist/esm/client/coordinators/WaStatusCoordinator.js +46 -0
  116. package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +6 -6
  117. package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +31 -12
  118. package/dist/esm/client/events/abprops.js +40 -0
  119. package/dist/esm/client/events/appstate-mutation.js +130 -0
  120. package/dist/esm/client/events/business.js +370 -0
  121. package/dist/esm/client/events/call.js +55 -0
  122. package/dist/esm/client/events/chatstate.js +20 -0
  123. package/dist/esm/client/events/devices.js +15 -16
  124. package/dist/esm/client/{dirty.js → events/dirty.js} +34 -20
  125. package/dist/esm/client/events/group.js +14 -25
  126. package/dist/esm/client/events/identity.js +2 -1
  127. package/dist/esm/client/events/incoming.js +487 -0
  128. package/dist/esm/client/events/mex-notification.js +178 -0
  129. package/dist/esm/client/events/picture.js +30 -0
  130. package/dist/esm/client/events/presence.js +41 -0
  131. package/dist/esm/client/events/privacy-token.js +1 -2
  132. package/dist/esm/client/events/receipt.js +23 -0
  133. package/dist/esm/client/events/registration.js +39 -0
  134. package/dist/esm/client/media.js +384 -0
  135. package/dist/esm/client/messaging/fanout.js +10 -11
  136. package/dist/esm/client/messaging/{participants.js → group-metadata.js} +72 -34
  137. package/dist/esm/client/messaging/ignore-key.js +126 -0
  138. package/dist/esm/client/messaging/key-protocol.js +3 -17
  139. package/dist/esm/client/messaging/link-preview.js +156 -0
  140. package/dist/esm/client/messaging/messages.js +667 -0
  141. package/dist/esm/client/newsletter/admin.js +162 -0
  142. package/dist/esm/client/newsletter/content.js +249 -0
  143. package/dist/esm/client/newsletter/discovery.js +112 -0
  144. package/dist/esm/client/newsletter/messaging.js +194 -0
  145. package/dist/esm/client/newsletter/mex.js +37 -0
  146. package/dist/esm/client/newsletter/parse.js +200 -0
  147. package/dist/esm/client/persistence/WriteBehindPersistence.js +31 -4
  148. package/dist/esm/client/{history-sync.js → persistence/history-sync.js} +124 -18
  149. package/dist/esm/client/persistence/mailbox.js +101 -0
  150. package/dist/esm/client/tokens/cs-token.js +12 -18
  151. package/dist/esm/crypto/core/hkdf.js +14 -14
  152. package/dist/esm/crypto/core/index.js +3 -2
  153. package/dist/esm/crypto/core/keys.js +1 -7
  154. package/dist/esm/crypto/core/nonce.js +11 -11
  155. package/dist/esm/crypto/core/primitives.js +121 -88
  156. package/dist/esm/crypto/core/random.js +8 -7
  157. package/dist/esm/crypto/core/xeddsa.js +55 -0
  158. package/dist/esm/crypto/curves/Ed25519.js +35 -24
  159. package/dist/esm/crypto/curves/X25519.js +74 -20
  160. package/dist/esm/crypto/curves/constants.js +2 -0
  161. package/dist/esm/crypto/math/constants.js +1 -2
  162. package/dist/esm/crypto/math/mod.js +0 -32
  163. package/dist/esm/index.js +7 -2
  164. package/dist/esm/infra/log/ConsoleLogger.js +30 -6
  165. package/dist/esm/infra/log/PinoLogger.js +64 -0
  166. package/dist/esm/infra/log/types.js +4 -2
  167. package/dist/esm/infra/perf/BackgroundQueue.js +55 -13
  168. package/dist/esm/infra/perf/StoreLock.js +7 -4
  169. package/dist/esm/media/constants.js +35 -2
  170. package/dist/esm/media/crypto/WaMediaCrypto.js +374 -0
  171. package/dist/esm/media/index.js +4 -3
  172. package/dist/esm/media/processor.js +1 -0
  173. package/dist/esm/media/sticker/sticker-pack.js +133 -0
  174. package/dist/esm/media/{WaMediaTransferClient.js → transfer/WaMediaTransferClient.js} +84 -196
  175. package/dist/esm/media/{conn.js → transfer/conn.js} +10 -5
  176. package/dist/esm/message/WaMessageClient.js +46 -15
  177. package/dist/esm/message/addons/link-preview/builder.js +36 -0
  178. package/dist/esm/message/addons/link-preview/detect.js +55 -0
  179. package/dist/esm/message/addons/link-preview/fetcher.js +391 -0
  180. package/dist/esm/message/addons/link-preview/types.js +1 -0
  181. package/dist/esm/message/context-info.js +123 -0
  182. package/dist/esm/message/crypto/addon-crypto.js +244 -0
  183. package/dist/esm/message/{icdc.js → crypto/icdc.js} +11 -13
  184. package/dist/esm/message/crypto/phash.js +133 -0
  185. package/dist/esm/message/{reporting-token.js → crypto/reporting-token.js} +7 -7
  186. package/dist/esm/message/{use-case-secret.js → crypto/use-case-secret.js} +21 -4
  187. package/dist/esm/message/{content.js → encode/content.js} +183 -8
  188. package/dist/esm/message/encode/media-payload.js +42 -0
  189. package/dist/esm/message/{padding.js → encode/padding.js} +9 -3
  190. package/dist/esm/message/index.js +2 -2
  191. package/dist/esm/message/kinds/bot.js +111 -0
  192. package/dist/esm/message/kinds/newsletter.js +244 -0
  193. package/dist/esm/message/kinds/sticker-pack.js +29 -0
  194. package/dist/esm/message/{ack.js → primitives/ack.js} +8 -1
  195. package/dist/esm/message/primitives/incoming.js +511 -0
  196. package/dist/esm/message/primitives/peer-data-operation.js +93 -0
  197. package/dist/esm/mex.js +1 -0
  198. package/dist/esm/protocol/abprops.js +169 -0
  199. package/dist/esm/protocol/appstate.js +6 -30
  200. package/dist/esm/protocol/auth.js +3 -2
  201. package/dist/esm/protocol/bot.js +77 -0
  202. package/dist/esm/protocol/browser.js +22 -0
  203. package/dist/esm/protocol/business.js +19 -0
  204. package/dist/esm/protocol/call.js +48 -0
  205. package/dist/esm/protocol/constants.js +10 -2
  206. package/dist/esm/protocol/defaults.js +3 -0
  207. package/dist/esm/protocol/email.js +30 -0
  208. package/dist/esm/protocol/index.js +1 -1
  209. package/dist/esm/protocol/jid.js +142 -11
  210. package/dist/esm/protocol/media.js +25 -12
  211. package/dist/esm/protocol/message.js +4 -1
  212. package/dist/esm/protocol/newsletter.js +61 -0
  213. package/dist/esm/protocol/nodes.js +26 -2
  214. package/dist/esm/protocol/notification.js +24 -2
  215. package/dist/esm/protocol/presence.js +13 -0
  216. package/dist/esm/protocol/status.js +6 -0
  217. package/dist/esm/retry/codec.js +5 -0
  218. package/dist/esm/retry/parse.js +20 -38
  219. package/dist/esm/retry/reason.js +6 -1
  220. package/dist/esm/retry/replay.js +131 -37
  221. package/dist/esm/retry/tracker.js +4 -8
  222. package/dist/esm/signal/api/SignalDeviceSyncApi.js +71 -21
  223. package/dist/esm/signal/api/SignalDigestSyncApi.js +15 -8
  224. package/dist/esm/signal/api/SignalIdentitySyncApi.js +13 -4
  225. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +24 -63
  226. package/dist/esm/signal/api/SignalRotateKeyApi.js +10 -0
  227. package/dist/esm/signal/api/SignalSessionSyncApi.js +23 -51
  228. package/dist/esm/signal/api/codec.js +52 -1
  229. package/dist/esm/signal/api/prekeys.js +4 -0
  230. package/dist/esm/signal/attestation/WaAdvSignature.js +17 -0
  231. package/dist/esm/signal/{crypto → attestation}/constants.js +0 -4
  232. package/dist/esm/signal/constants.js +3 -0
  233. package/dist/esm/signal/encoding.js +6 -332
  234. package/dist/esm/signal/group/SenderKeyChain.js +20 -35
  235. package/dist/esm/signal/group/SenderKeyCodec.js +5 -6
  236. package/dist/esm/signal/group/SenderKeyManager.js +37 -17
  237. package/dist/esm/signal/group/encoding.js +96 -0
  238. package/dist/esm/signal/index.js +4 -1
  239. package/dist/esm/signal/registration/encoding.js +34 -0
  240. package/dist/esm/signal/registration/keygen.js +12 -3
  241. package/dist/esm/signal/registration/utils.js +8 -2
  242. package/dist/esm/signal/session/SignalProtocol.js +129 -26
  243. package/dist/esm/signal/session/SignalRatchet.js +46 -64
  244. package/dist/esm/signal/session/SignalSerializer.js +5 -6
  245. package/dist/esm/signal/session/SignalSession.js +14 -19
  246. package/dist/esm/signal/session/encoding.js +173 -0
  247. package/dist/esm/signal/session/resolver.js +144 -35
  248. package/dist/esm/store/cache/identity.cache.js +75 -0
  249. package/dist/esm/store/cache/privacy-token.cache.js +57 -0
  250. package/dist/esm/store/cache/sender-key.cache.js +101 -0
  251. package/dist/esm/store/cache/session.cache.js +92 -0
  252. package/dist/esm/store/contracts/group-metadata.store.js +1 -0
  253. package/dist/esm/store/contracts/identity.store.js +1 -0
  254. package/dist/esm/store/contracts/message-secret.store.js +1 -0
  255. package/dist/esm/store/contracts/pre-key.store.js +1 -0
  256. package/dist/esm/store/contracts/session.store.js +1 -0
  257. package/dist/esm/store/createStore.js +129 -39
  258. package/dist/esm/store/index.js +15 -10
  259. package/dist/esm/store/locks/contact.lock.js +1 -0
  260. package/dist/esm/store/locks/device-list.lock.js +1 -0
  261. package/dist/esm/store/locks/group-metadata.lock.js +20 -0
  262. package/dist/esm/store/locks/identity.lock.js +16 -0
  263. package/dist/esm/store/locks/message-secret.lock.js +17 -0
  264. package/dist/esm/store/locks/pre-key.lock.js +27 -0
  265. package/dist/esm/store/locks/session.lock.js +19 -0
  266. package/dist/esm/store/locks/signal.lock.js +0 -24
  267. package/dist/esm/store/{providers/memory → memory}/appstate.store.js +5 -5
  268. package/dist/esm/store/memory/auth.store.js +24 -0
  269. package/dist/esm/store/memory/contact.store.js +79 -0
  270. package/dist/esm/store/memory/device-list.store.js +103 -0
  271. package/dist/esm/store/{providers/memory/participants.store.js → memory/group-metadata.store.js} +24 -12
  272. package/dist/esm/store/memory/identity.store.js +31 -0
  273. package/dist/esm/store/memory/message-secret.store.js +90 -0
  274. package/dist/esm/store/{providers/memory → memory}/message.store.js +2 -2
  275. package/dist/esm/store/memory/pre-key.store.js +97 -0
  276. package/dist/esm/store/{providers/memory → memory}/privacy-token.store.js +1 -1
  277. package/dist/esm/store/{providers/memory → memory}/retry.store.js +49 -14
  278. package/dist/esm/store/{providers/memory → memory}/sender-key.store.js +3 -3
  279. package/dist/esm/store/memory/session.store.js +45 -0
  280. package/dist/esm/store/memory/signal.store.js +36 -0
  281. package/dist/esm/store/{providers/memory → memory}/thread.store.js +2 -2
  282. package/dist/esm/store/noop.store.js +26 -4
  283. package/dist/esm/transport/WaComms.js +18 -8
  284. package/dist/esm/transport/WaWebSocket.js +41 -9
  285. package/dist/esm/transport/binary/constants.js +10 -4
  286. package/dist/esm/transport/binary/decoder.js +21 -15
  287. package/dist/esm/transport/binary/encoder.js +96 -21
  288. package/dist/esm/transport/binary/tokens.js +12 -12
  289. package/dist/esm/transport/index.js +7 -0
  290. package/dist/esm/transport/keepalive/WaKeepAlive.js +35 -12
  291. package/dist/esm/transport/node/WaMobileTcpSocket.js +120 -0
  292. package/dist/esm/transport/node/WaNodeOrchestrator.js +26 -13
  293. package/dist/esm/transport/node/WaNodeTransport.js +13 -0
  294. package/dist/esm/transport/node/builders/abprops.js +20 -0
  295. package/dist/esm/transport/node/builders/account-sync.js +7 -15
  296. package/dist/esm/transport/node/builders/bot.js +38 -0
  297. package/dist/esm/transport/node/builders/business.js +30 -30
  298. package/dist/esm/transport/node/builders/chatstate.js +28 -0
  299. package/dist/esm/transport/node/builders/community.js +53 -0
  300. package/dist/esm/transport/node/builders/device.js +11 -0
  301. package/dist/esm/transport/node/builders/email.js +66 -0
  302. package/dist/esm/transport/node/builders/global.js +1 -1
  303. package/dist/esm/transport/node/builders/group.js +114 -4
  304. package/dist/esm/transport/node/builders/media.js +2 -2
  305. package/dist/esm/transport/node/builders/message.js +83 -49
  306. package/dist/esm/transport/node/builders/newsletter.js +176 -0
  307. package/dist/esm/transport/node/builders/offline.js +14 -0
  308. package/dist/esm/transport/node/builders/passive.js +7 -0
  309. package/dist/esm/transport/node/builders/prekeys.js +40 -43
  310. package/dist/esm/transport/node/builders/presence.js +39 -0
  311. package/dist/esm/transport/node/builders/privacy-token.js +19 -23
  312. package/dist/esm/transport/node/builders/privacy.js +6 -6
  313. package/dist/esm/transport/node/builders/profile.js +28 -8
  314. package/dist/esm/transport/node/builders/retry.js +1 -1
  315. package/dist/esm/transport/node/builders/tos.js +58 -0
  316. package/dist/esm/transport/node/builders/usync.js +51 -2
  317. package/dist/esm/transport/node/helpers.js +27 -1
  318. package/dist/esm/transport/node/mex/argo-decoder.js +152 -0
  319. package/dist/esm/transport/node/mex/client.js +105 -0
  320. package/dist/esm/transport/node/query.js +17 -0
  321. package/dist/esm/transport/node/usync.js +12 -0
  322. package/dist/esm/transport/noise/WaClientPayload.js +23 -18
  323. package/dist/esm/transport/noise/WaFrameCodec.js +2 -2
  324. package/dist/esm/transport/noise/WaMobileClientPayload.js +58 -0
  325. package/dist/esm/transport/noise/WaNoiseCert.js +14 -27
  326. package/dist/esm/transport/noise/WaNoiseHandshake.js +27 -25
  327. package/dist/esm/transport/noise/WaNoiseSession.js +48 -67
  328. package/dist/esm/transport/noise/WaNoiseSocket.js +19 -13
  329. package/dist/esm/transport/noise/constants.js +0 -1
  330. package/dist/esm/transport/proxy.js +5 -0
  331. package/dist/esm/transport/stream/parse.js +3 -7
  332. package/dist/esm/transport/wa-web-version-fetcher.js +91 -0
  333. package/dist/esm/util/async.js +4 -0
  334. package/dist/esm/util/bytes.js +37 -2
  335. package/dist/esm/util/clock.js +15 -0
  336. package/dist/esm/util/coercion.js +45 -3
  337. package/dist/esm/util/collections.js +11 -0
  338. package/dist/esm/util/index.js +2 -2
  339. package/dist/esm/util/primitives.js +19 -0
  340. package/dist/esm/util/runtime.js +5 -0
  341. package/dist/esm/version-spec.js +1 -0
  342. package/dist/index.js +31 -1
  343. package/dist/infra/log/ConsoleLogger.js +30 -6
  344. package/dist/infra/log/PinoLogger.js +64 -0
  345. package/dist/infra/log/types.js +4 -2
  346. package/dist/infra/perf/BackgroundQueue.js +55 -13
  347. package/dist/infra/perf/StoreLock.js +7 -4
  348. package/dist/media/constants.js +36 -3
  349. package/dist/media/crypto/WaMediaCrypto.js +378 -0
  350. package/dist/media/index.js +9 -4
  351. package/dist/media/processor.js +2 -0
  352. package/dist/media/sticker/sticker-pack.js +136 -0
  353. package/dist/media/{WaMediaTransferClient.js → transfer/WaMediaTransferClient.js} +87 -229
  354. package/dist/media/{conn.js → transfer/conn.js} +10 -5
  355. package/dist/message/WaMessageClient.js +46 -15
  356. package/dist/message/addons/link-preview/builder.js +39 -0
  357. package/dist/message/addons/link-preview/detect.js +58 -0
  358. package/dist/message/addons/link-preview/fetcher.js +394 -0
  359. package/dist/message/addons/link-preview/types.js +2 -0
  360. package/dist/message/context-info.js +129 -0
  361. package/dist/message/crypto/addon-crypto.js +254 -0
  362. package/dist/message/{icdc.js → crypto/icdc.js} +11 -13
  363. package/dist/message/crypto/phash.js +136 -0
  364. package/dist/message/{reporting-token.js → crypto/reporting-token.js} +7 -7
  365. package/dist/message/{use-case-secret.js → crypto/use-case-secret.js} +21 -4
  366. package/dist/message/{content.js → encode/content.js} +200 -7
  367. package/dist/message/encode/media-payload.js +45 -0
  368. package/dist/message/{padding.js → encode/padding.js} +9 -3
  369. package/dist/message/index.js +2 -2
  370. package/dist/message/kinds/bot.js +120 -0
  371. package/dist/message/kinds/newsletter.js +248 -0
  372. package/dist/message/kinds/sticker-pack.js +34 -0
  373. package/dist/message/{ack.js → primitives/ack.js} +8 -1
  374. package/dist/message/{incoming.js → primitives/incoming.js} +225 -38
  375. package/dist/message/primitives/peer-data-operation.js +96 -0
  376. package/dist/mex.js +6 -0
  377. package/dist/proto.js +1 -1
  378. package/dist/protocol/abprops.js +173 -0
  379. package/dist/protocol/appstate.js +7 -31
  380. package/dist/protocol/auth.js +3 -2
  381. package/dist/protocol/bot.js +81 -0
  382. package/dist/protocol/browser.js +23 -0
  383. package/dist/protocol/business.js +22 -0
  384. package/dist/protocol/call.js +51 -0
  385. package/dist/protocol/constants.js +51 -3
  386. package/dist/protocol/defaults.js +3 -0
  387. package/dist/protocol/email.js +33 -0
  388. package/dist/protocol/index.js +12 -3
  389. package/dist/protocol/jid.js +148 -11
  390. package/dist/protocol/media.js +25 -12
  391. package/dist/protocol/message.js +4 -1
  392. package/dist/protocol/newsletter.js +64 -0
  393. package/dist/protocol/nodes.js +26 -2
  394. package/dist/protocol/notification.js +25 -3
  395. package/dist/protocol/presence.js +16 -0
  396. package/dist/protocol/status.js +9 -0
  397. package/dist/retry/codec.js +5 -0
  398. package/dist/retry/parse.js +16 -34
  399. package/dist/retry/reason.js +6 -1
  400. package/dist/retry/replay.js +129 -35
  401. package/dist/retry/tracker.js +3 -7
  402. package/dist/signal/api/SignalDeviceSyncApi.js +69 -19
  403. package/dist/signal/api/SignalDigestSyncApi.js +14 -7
  404. package/dist/signal/api/SignalIdentitySyncApi.js +13 -4
  405. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +21 -60
  406. package/dist/signal/api/SignalRotateKeyApi.js +10 -0
  407. package/dist/signal/api/SignalSessionSyncApi.js +20 -48
  408. package/dist/signal/api/codec.js +52 -0
  409. package/dist/signal/api/prekeys.js +4 -0
  410. package/dist/signal/attestation/WaAdvSignature.js +26 -0
  411. package/dist/signal/{crypto → attestation}/constants.js +1 -5
  412. package/dist/signal/constants.js +4 -1
  413. package/dist/signal/encoding.js +5 -341
  414. package/dist/signal/group/SenderKeyChain.js +19 -34
  415. package/dist/signal/group/SenderKeyCodec.js +4 -5
  416. package/dist/signal/group/SenderKeyManager.js +36 -16
  417. package/dist/signal/group/encoding.js +101 -0
  418. package/dist/signal/index.js +13 -10
  419. package/dist/signal/registration/encoding.js +39 -0
  420. package/dist/signal/registration/keygen.js +11 -2
  421. package/dist/signal/registration/utils.js +8 -2
  422. package/dist/signal/session/SignalProtocol.js +128 -25
  423. package/dist/signal/session/SignalRatchet.js +41 -60
  424. package/dist/signal/session/SignalSerializer.js +5 -6
  425. package/dist/signal/session/SignalSession.js +13 -19
  426. package/dist/signal/session/encoding.js +183 -0
  427. package/dist/signal/session/resolver.js +144 -35
  428. package/dist/store/cache/identity.cache.js +78 -0
  429. package/dist/store/cache/privacy-token.cache.js +60 -0
  430. package/dist/store/cache/sender-key.cache.js +104 -0
  431. package/dist/store/cache/session.cache.js +95 -0
  432. package/dist/store/contracts/group-metadata.store.js +2 -0
  433. package/dist/store/contracts/identity.store.js +2 -0
  434. package/dist/store/contracts/message-secret.store.js +2 -0
  435. package/dist/store/contracts/pre-key.store.js +2 -0
  436. package/dist/store/contracts/session.store.js +2 -0
  437. package/dist/store/createStore.js +128 -38
  438. package/dist/store/index.js +22 -12
  439. package/dist/store/locks/contact.lock.js +1 -0
  440. package/dist/store/locks/device-list.lock.js +1 -0
  441. package/dist/store/locks/group-metadata.lock.js +23 -0
  442. package/dist/store/locks/identity.lock.js +19 -0
  443. package/dist/store/locks/message-secret.lock.js +20 -0
  444. package/dist/store/locks/pre-key.lock.js +30 -0
  445. package/dist/store/locks/session.lock.js +22 -0
  446. package/dist/store/locks/signal.lock.js +0 -24
  447. package/dist/store/{providers/memory → memory}/appstate.store.js +5 -5
  448. package/dist/store/memory/auth.store.js +28 -0
  449. package/dist/store/memory/contact.store.js +83 -0
  450. package/dist/store/memory/device-list.store.js +107 -0
  451. package/dist/store/{providers/memory/participants.store.js → memory/group-metadata.store.js} +26 -14
  452. package/dist/store/memory/identity.store.js +35 -0
  453. package/dist/store/memory/message-secret.store.js +94 -0
  454. package/dist/store/{providers/memory → memory}/message.store.js +2 -2
  455. package/dist/store/memory/pre-key.store.js +101 -0
  456. package/dist/store/{providers/memory → memory}/privacy-token.store.js +1 -1
  457. package/dist/store/{providers/memory → memory}/retry.store.js +49 -14
  458. package/dist/store/{providers/memory → memory}/sender-key.store.js +3 -3
  459. package/dist/store/memory/session.store.js +49 -0
  460. package/dist/store/memory/signal.store.js +40 -0
  461. package/dist/store/{providers/memory → memory}/thread.store.js +2 -2
  462. package/dist/store/noop.store.js +27 -5
  463. package/dist/transport/WaComms.js +18 -8
  464. package/dist/transport/WaWebSocket.js +41 -9
  465. package/dist/transport/binary/constants.js +11 -5
  466. package/dist/transport/binary/decoder.js +24 -18
  467. package/dist/transport/binary/encoder.js +109 -34
  468. package/dist/transport/binary/tokens.js +12 -12
  469. package/dist/transport/index.js +19 -1
  470. package/dist/transport/keepalive/WaKeepAlive.js +35 -12
  471. package/dist/transport/node/WaMobileTcpSocket.js +124 -0
  472. package/dist/transport/node/WaNodeOrchestrator.js +25 -12
  473. package/dist/transport/node/WaNodeTransport.js +13 -0
  474. package/dist/transport/node/builders/abprops.js +23 -0
  475. package/dist/transport/node/builders/account-sync.js +7 -16
  476. package/dist/transport/node/builders/bot.js +43 -0
  477. package/dist/transport/node/builders/business.js +31 -31
  478. package/dist/transport/node/builders/chatstate.js +31 -0
  479. package/dist/transport/node/builders/community.js +59 -0
  480. package/dist/transport/node/builders/device.js +14 -0
  481. package/dist/transport/node/builders/email.js +73 -0
  482. package/dist/transport/node/builders/global.js +1 -1
  483. package/dist/transport/node/builders/group.js +121 -3
  484. package/dist/transport/node/builders/media.js +1 -1
  485. package/dist/transport/node/builders/message.js +84 -49
  486. package/dist/transport/node/builders/newsletter.js +183 -0
  487. package/dist/transport/node/builders/offline.js +17 -0
  488. package/dist/transport/node/builders/passive.js +10 -0
  489. package/dist/transport/node/builders/prekeys.js +38 -41
  490. package/dist/transport/node/builders/presence.js +43 -0
  491. package/dist/transport/node/builders/privacy-token.js +18 -22
  492. package/dist/transport/node/builders/privacy.js +5 -5
  493. package/dist/transport/node/builders/profile.js +30 -7
  494. package/dist/transport/node/builders/retry.js +1 -1
  495. package/dist/transport/node/builders/tos.js +63 -0
  496. package/dist/transport/node/builders/usync.js +52 -1
  497. package/dist/transport/node/helpers.js +28 -1
  498. package/dist/transport/node/mex/argo-decoder.js +189 -0
  499. package/dist/transport/node/mex/client.js +109 -0
  500. package/dist/transport/node/query.js +17 -0
  501. package/dist/transport/node/usync.js +13 -0
  502. package/dist/transport/noise/WaClientPayload.js +22 -17
  503. package/dist/transport/noise/WaFrameCodec.js +1 -1
  504. package/dist/transport/noise/WaMobileClientPayload.js +61 -0
  505. package/dist/transport/noise/WaNoiseCert.js +13 -26
  506. package/dist/transport/noise/WaNoiseHandshake.js +25 -23
  507. package/dist/transport/noise/WaNoiseSession.js +47 -66
  508. package/dist/transport/noise/WaNoiseSocket.js +18 -12
  509. package/dist/transport/noise/constants.js +1 -2
  510. package/dist/transport/proxy.js +5 -0
  511. package/dist/transport/stream/parse.js +3 -7
  512. package/dist/transport/wa-web-version-fetcher.js +94 -0
  513. package/dist/types/appstate/constants.d.ts +1 -1
  514. package/dist/types/appstate/{WaAppStateCrypto.d.ts → crypto/WaAppStateCrypto.d.ts} +29 -9
  515. package/dist/types/appstate/index.d.ts +5 -5
  516. package/dist/types/appstate/{encoding.d.ts → parsers/encoding.d.ts} +8 -1
  517. package/dist/types/appstate/{WaAppStateSyncResponseParser.d.ts → parsers/response-parser.d.ts} +13 -3
  518. package/dist/types/appstate/sync/WaAppStateSyncClient.d.ts +105 -0
  519. package/dist/types/appstate/types.d.ts +1 -1
  520. package/dist/types/appstate/utils.d.ts +17 -1
  521. package/dist/types/appstate-spec.d.ts +24 -0
  522. package/dist/types/auth/WaAuthClient.d.ts +95 -3
  523. package/dist/types/auth/credentials-flow.d.ts +21 -0
  524. package/dist/types/auth/pairing/WaPairingFlow.d.ts +3 -2
  525. package/dist/types/auth/pairing/{WaPairingCodeCrypto.d.ts → pairing-code-crypto.d.ts} +5 -1
  526. package/dist/types/auth/types.d.ts +88 -1
  527. package/dist/types/client/WaClient.d.ts +183 -65
  528. package/dist/types/client/WaClientFactory.d.ts +40 -9
  529. package/dist/types/client/connection/WaConnectionManager.d.ts +4 -2
  530. package/dist/types/client/connection/WaReceiptQueue.d.ts +1 -1
  531. package/dist/types/client/coordinators/WaAbPropsCoordinator.d.ts +26 -0
  532. package/dist/types/client/coordinators/WaAppStateMutationCoordinator.d.ts +215 -5
  533. package/dist/types/client/coordinators/WaBotCoordinator.d.ts +117 -0
  534. package/dist/types/client/coordinators/WaBroadcastListCoordinator.d.ts +39 -0
  535. package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +45 -44
  536. package/dist/types/client/coordinators/WaEmailCoordinator.d.ts +40 -0
  537. package/dist/types/client/coordinators/WaGroupCoordinator.d.ts +311 -9
  538. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +16 -4
  539. package/dist/types/client/coordinators/WaLowLevelCoordinator.d.ts +47 -0
  540. package/dist/types/client/coordinators/WaMessageCoordinator.d.ts +232 -0
  541. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +65 -29
  542. package/dist/types/client/coordinators/WaNewsletterCoordinator.d.ts +13 -0
  543. package/dist/types/client/coordinators/WaOfflineResumeCoordinator.d.ts +31 -0
  544. package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +15 -3
  545. package/dist/types/client/coordinators/WaPresenceCoordinator.d.ts +27 -0
  546. package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +28 -1
  547. package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +117 -2
  548. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +23 -15
  549. package/dist/types/client/coordinators/WaStatusCoordinator.d.ts +42 -0
  550. package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +16 -2
  551. package/dist/types/client/events/abprops.d.ts +15 -0
  552. package/dist/types/client/events/appstate-mutation.d.ts +3 -0
  553. package/dist/types/client/events/business.d.ts +10 -0
  554. package/dist/types/client/events/call.d.ts +31 -0
  555. package/dist/types/client/events/chatstate.d.ts +9 -0
  556. package/dist/types/client/events/devices.d.ts +5 -4
  557. package/dist/types/client/{dirty.d.ts → events/dirty.d.ts} +7 -4
  558. package/dist/types/client/events/group.d.ts +2 -1
  559. package/dist/types/client/events/identity.d.ts +2 -1
  560. package/dist/types/client/events/incoming.d.ts +65 -0
  561. package/dist/types/client/events/mex-notification.d.ts +6 -0
  562. package/dist/types/client/events/picture.d.ts +8 -0
  563. package/dist/types/client/events/presence.d.ts +28 -0
  564. package/dist/types/client/events/receipt.d.ts +14 -0
  565. package/dist/types/client/events/registration.d.ts +18 -0
  566. package/dist/types/client/index.d.ts +1 -1
  567. package/dist/types/client/media.d.ts +65 -0
  568. package/dist/types/client/messaging/fanout.d.ts +2 -2
  569. package/dist/types/client/messaging/group-metadata.d.ts +19 -0
  570. package/dist/types/client/messaging/ignore-key.d.ts +11 -0
  571. package/dist/types/client/messaging/key-protocol.d.ts +9 -7
  572. package/dist/types/client/messaging/link-preview.d.ts +19 -0
  573. package/dist/types/client/messaging/messages.d.ts +28 -0
  574. package/dist/types/client/newsletter/admin.d.ts +71 -0
  575. package/dist/types/client/newsletter/content.d.ts +42 -0
  576. package/dist/types/client/newsletter/discovery.d.ts +33 -0
  577. package/dist/types/client/newsletter/messaging.d.ts +66 -0
  578. package/dist/types/client/newsletter/mex.d.ts +14 -0
  579. package/dist/types/client/newsletter/parse.d.ts +19 -0
  580. package/dist/types/client/newsletter/types.d.ts +190 -0
  581. package/dist/types/client/persistence/WriteBehindPersistence.d.ts +13 -2
  582. package/dist/types/client/persistence/history-sync.d.ts +29 -0
  583. package/dist/types/client/persistence/mailbox.d.ts +12 -0
  584. package/dist/types/client/tokens/cs-token.d.ts +1 -3
  585. package/dist/types/client/types.d.ts +926 -55
  586. package/dist/types/crypto/core/hkdf.d.ts +10 -2
  587. package/dist/types/crypto/core/index.d.ts +3 -2
  588. package/dist/types/crypto/core/keys.d.ts +0 -4
  589. package/dist/types/crypto/core/nonce.d.ts +4 -5
  590. package/dist/types/crypto/core/primitives.d.ts +31 -20
  591. package/dist/types/crypto/core/random.d.ts +7 -1
  592. package/dist/types/crypto/core/xeddsa.d.ts +11 -0
  593. package/dist/types/crypto/curves/Ed25519.d.ts +7 -1
  594. package/dist/types/crypto/curves/X25519.d.ts +20 -1
  595. package/dist/types/crypto/curves/constants.d.ts +4 -2
  596. package/dist/types/crypto/curves/types.d.ts +0 -5
  597. package/dist/types/crypto/index.d.ts +1 -0
  598. package/dist/types/crypto/math/constants.d.ts +0 -1
  599. package/dist/types/crypto/math/mod.d.ts +0 -1
  600. package/dist/types/index.d.ts +32 -5
  601. package/dist/types/infra/log/ConsoleLogger.d.ts +19 -2
  602. package/dist/types/infra/log/PinoLogger.d.ts +56 -2
  603. package/dist/types/infra/log/types.d.ts +6 -0
  604. package/dist/types/infra/perf/BackgroundQueue.d.ts +19 -0
  605. package/dist/types/infra/perf/StoreLock.d.ts +1 -0
  606. package/dist/types/media/constants.d.ts +9 -2
  607. package/dist/types/media/crypto/WaMediaCrypto.d.ts +59 -0
  608. package/dist/types/media/index.d.ts +7 -4
  609. package/dist/types/media/processor.d.ts +50 -0
  610. package/dist/types/media/sticker/sticker-pack.d.ts +6 -0
  611. package/dist/types/media/{WaMediaTransferClient.d.ts → transfer/WaMediaTransferClient.d.ts} +33 -12
  612. package/dist/types/media/transfer/conn.d.ts +7 -0
  613. package/dist/types/media/types.d.ts +10 -5
  614. package/dist/types/message/WaMessageClient.d.ts +14 -0
  615. package/dist/types/message/addons/link-preview/builder.d.ts +13 -0
  616. package/dist/types/message/addons/link-preview/detect.d.ts +5 -0
  617. package/dist/types/message/addons/link-preview/fetcher.d.ts +13 -0
  618. package/dist/types/message/addons/link-preview/types.d.ts +51 -0
  619. package/dist/types/message/context-info.d.ts +66 -0
  620. package/dist/types/message/crypto/addon-crypto.d.ts +78 -0
  621. package/dist/types/message/{icdc.d.ts → crypto/icdc.d.ts} +6 -6
  622. package/dist/types/message/{phash.d.ts → crypto/phash.d.ts} +1 -1
  623. package/dist/types/message/{reporting-token.d.ts → crypto/reporting-token.d.ts} +2 -2
  624. package/dist/types/message/{use-case-secret.d.ts → crypto/use-case-secret.d.ts} +17 -1
  625. package/dist/types/message/encode/content.d.ts +43 -0
  626. package/dist/types/message/{device-sent.d.ts → encode/device-sent.d.ts} +1 -1
  627. package/dist/types/message/encode/media-payload.d.ts +12 -0
  628. package/dist/types/message/index.d.ts +2 -2
  629. package/dist/types/message/kinds/bot.d.ts +31 -0
  630. package/dist/types/message/kinds/newsletter.d.ts +12 -0
  631. package/dist/types/message/kinds/sticker-pack.d.ts +6 -0
  632. package/dist/types/message/{ack.d.ts → primitives/ack.d.ts} +1 -1
  633. package/dist/types/message/primitives/incoming.d.ts +21 -0
  634. package/dist/types/message/primitives/peer-data-operation.d.ts +23 -0
  635. package/dist/types/message/types.d.ts +218 -28
  636. package/dist/types/mex.d.ts +2 -0
  637. package/dist/types/proto.d.ts +2 -2
  638. package/dist/types/protocol/abprops.d.ts +151 -0
  639. package/dist/types/protocol/appstate.d.ts +4 -49
  640. package/dist/types/protocol/auth.d.ts +2 -2
  641. package/dist/types/protocol/bot.d.ts +45 -0
  642. package/dist/types/protocol/browser.d.ts +9 -0
  643. package/dist/types/protocol/business.d.ts +21 -0
  644. package/dist/types/protocol/call.d.ts +44 -0
  645. package/dist/types/protocol/constants.d.ts +20 -3
  646. package/dist/types/protocol/defaults.d.ts +3 -0
  647. package/dist/types/protocol/email.d.ts +32 -0
  648. package/dist/types/protocol/group.d.ts +1 -1
  649. package/dist/types/protocol/index.d.ts +2 -1
  650. package/dist/types/protocol/jid.d.ts +79 -0
  651. package/dist/types/protocol/media.d.ts +21 -13
  652. package/dist/types/protocol/message.d.ts +4 -0
  653. package/dist/types/protocol/newsletter.d.ts +65 -0
  654. package/dist/types/protocol/nodes.d.ts +24 -0
  655. package/dist/types/protocol/notification.d.ts +22 -0
  656. package/dist/types/protocol/presence.d.ts +16 -0
  657. package/dist/types/protocol/status.d.ts +7 -0
  658. package/dist/types/protocol/stream.d.ts +1 -0
  659. package/dist/types/retry/codec.d.ts +5 -0
  660. package/dist/types/retry/index.d.ts +1 -1
  661. package/dist/types/retry/parse.d.ts +9 -0
  662. package/dist/types/retry/reason.d.ts +6 -1
  663. package/dist/types/retry/replay.d.ts +19 -5
  664. package/dist/types/retry/tracker.d.ts +10 -3
  665. package/dist/types/retry/types.d.ts +3 -8
  666. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +20 -0
  667. package/dist/types/signal/api/SignalDigestSyncApi.d.ts +13 -0
  668. package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +12 -3
  669. package/dist/types/signal/api/SignalMissingPreKeysSyncApi.d.ts +8 -0
  670. package/dist/types/signal/api/SignalRotateKeyApi.d.ts +10 -0
  671. package/dist/types/signal/api/SignalSessionSyncApi.d.ts +13 -0
  672. package/dist/types/signal/api/codec.d.ts +20 -0
  673. package/dist/types/signal/api/constants.d.ts +1 -1
  674. package/dist/types/signal/api/prekeys.d.ts +4 -0
  675. package/dist/types/signal/{crypto → attestation}/WaAdvSignature.d.ts +2 -4
  676. package/dist/types/signal/attestation/constants.d.ts +4 -0
  677. package/dist/types/signal/constants.d.ts +7 -4
  678. package/dist/types/signal/encoding.d.ts +6 -62
  679. package/dist/types/signal/group/SenderKeyChain.d.ts +2 -2
  680. package/dist/types/signal/group/SenderKeyManager.d.ts +24 -2
  681. package/dist/types/signal/group/encoding.d.ts +25 -0
  682. package/dist/types/signal/index.d.ts +4 -1
  683. package/dist/types/signal/registration/encoding.d.ts +30 -0
  684. package/dist/types/signal/registration/keygen.d.ts +10 -0
  685. package/dist/types/signal/registration/utils.d.ts +7 -1
  686. package/dist/types/signal/session/SignalProtocol.d.ts +66 -2
  687. package/dist/types/signal/session/SignalRatchet.d.ts +2 -3
  688. package/dist/types/signal/session/SignalSerializer.d.ts +2 -1
  689. package/dist/types/signal/session/SignalSession.d.ts +0 -1
  690. package/dist/types/signal/session/encoding.d.ts +28 -0
  691. package/dist/types/signal/session/resolver.d.ts +18 -2
  692. package/dist/types/signal/types.d.ts +16 -4
  693. package/dist/types/store/cache/identity.cache.d.ts +15 -0
  694. package/dist/types/store/cache/privacy-token.cache.d.ts +15 -0
  695. package/dist/types/store/cache/sender-key.cache.d.ts +18 -0
  696. package/dist/types/store/cache/session.cache.d.ts +23 -0
  697. package/dist/types/store/contracts/contact.store.d.ts +14 -0
  698. package/dist/types/store/contracts/device-list.store.d.ts +13 -0
  699. package/dist/types/store/contracts/group-metadata.store.d.ts +14 -0
  700. package/dist/types/store/contracts/identity.store.d.ts +11 -0
  701. package/dist/types/store/contracts/message-secret.store.d.ts +16 -0
  702. package/dist/types/store/contracts/message.store.d.ts +0 -2
  703. package/dist/types/store/contracts/pre-key.store.d.ts +13 -0
  704. package/dist/types/store/contracts/session.store.d.ts +14 -0
  705. package/dist/types/store/contracts/signal.store.d.ts +1 -34
  706. package/dist/types/store/createStore.d.ts +54 -2
  707. package/dist/types/store/index.d.ts +22 -13
  708. package/dist/types/store/locks/group-metadata.lock.d.ts +2 -0
  709. package/dist/types/store/locks/identity.lock.d.ts +3 -0
  710. package/dist/types/store/locks/message-secret.lock.d.ts +3 -0
  711. package/dist/types/store/locks/pre-key.lock.d.ts +3 -0
  712. package/dist/types/store/locks/session.lock.d.ts +3 -0
  713. package/dist/types/store/{providers/memory → memory}/appstate.store.d.ts +2 -2
  714. package/dist/types/store/memory/auth.store.d.ts +18 -0
  715. package/dist/types/store/{providers/memory → memory}/contact.store.d.ts +6 -1
  716. package/dist/types/store/{providers/memory → memory}/device-list.store.d.ts +15 -2
  717. package/dist/types/store/memory/group-metadata.store.d.ts +27 -0
  718. package/dist/types/store/memory/identity.store.d.ts +18 -0
  719. package/dist/types/store/memory/message-secret.store.d.ts +31 -0
  720. package/dist/types/store/{providers/memory → memory}/message.store.d.ts +1 -1
  721. package/dist/types/store/memory/pre-key.store.d.ts +23 -0
  722. package/dist/types/store/{providers/memory → memory}/privacy-token.store.d.ts +1 -1
  723. package/dist/types/store/{providers/memory → memory}/retry.store.d.ts +23 -4
  724. package/dist/types/store/{providers/memory → memory}/sender-key.store.d.ts +2 -2
  725. package/dist/types/store/memory/session.store.d.ts +21 -0
  726. package/dist/types/store/memory/signal.store.d.ts +16 -0
  727. package/dist/types/store/{providers/memory → memory}/thread.store.d.ts +1 -1
  728. package/dist/types/store/noop.store.d.ts +6 -2
  729. package/dist/types/store/types.d.ts +271 -7
  730. package/dist/types/transport/WaComms.d.ts +5 -0
  731. package/dist/types/transport/WaWebSocket.d.ts +6 -0
  732. package/dist/types/transport/binary/constants.d.ts +8 -2
  733. package/dist/types/transport/binary/decoder.d.ts +5 -0
  734. package/dist/types/transport/binary/encoder.d.ts +5 -0
  735. package/dist/types/transport/binary/tokens.d.ts +6 -6
  736. package/dist/types/transport/index.d.ts +9 -0
  737. package/dist/types/transport/keepalive/WaKeepAlive.d.ts +11 -1
  738. package/dist/types/transport/node/WaMobileTcpSocket.d.ts +24 -0
  739. package/dist/types/transport/node/WaNodeOrchestrator.d.ts +11 -2
  740. package/dist/types/transport/node/WaNodeTransport.d.ts +13 -0
  741. package/dist/types/transport/node/builders/abprops.d.ts +5 -0
  742. package/dist/types/transport/node/builders/account-sync.d.ts +1 -2
  743. package/dist/types/transport/node/builders/bot.d.ts +4 -0
  744. package/dist/types/transport/node/builders/business.d.ts +21 -4
  745. package/dist/types/transport/node/builders/chatstate.d.ts +11 -0
  746. package/dist/types/transport/node/builders/community.d.ts +17 -0
  747. package/dist/types/transport/node/builders/device.d.ts +2 -0
  748. package/dist/types/transport/node/builders/email.d.ts +11 -0
  749. package/dist/types/transport/node/builders/group.d.ts +44 -2
  750. package/dist/types/transport/node/builders/message.d.ts +11 -6
  751. package/dist/types/transport/node/builders/newsletter.d.ts +73 -0
  752. package/dist/types/transport/node/builders/offline.d.ts +2 -0
  753. package/dist/types/transport/node/builders/passive.d.ts +3 -0
  754. package/dist/types/transport/node/builders/prekeys.d.ts +4 -3
  755. package/dist/types/transport/node/builders/presence.d.ts +13 -0
  756. package/dist/types/transport/node/builders/profile.d.ts +3 -0
  757. package/dist/types/transport/node/builders/tos.d.ts +12 -0
  758. package/dist/types/transport/node/builders/usync.d.ts +16 -0
  759. package/dist/types/transport/node/helpers.d.ts +3 -1
  760. package/dist/types/transport/node/mex/argo-decoder.d.ts +11 -0
  761. package/dist/types/transport/node/mex/client.d.ts +29 -0
  762. package/dist/types/transport/node/query.d.ts +19 -1
  763. package/dist/types/transport/node/usync.d.ts +3 -0
  764. package/dist/types/transport/noise/WaMobileClientPayload.d.ts +34 -0
  765. package/dist/types/transport/noise/WaNoiseCert.d.ts +12 -1
  766. package/dist/types/transport/noise/WaNoiseHandshake.d.ts +12 -6
  767. package/dist/types/transport/noise/WaNoiseSession.d.ts +1 -1
  768. package/dist/types/transport/noise/WaNoiseSocket.d.ts +12 -6
  769. package/dist/types/transport/noise/constants.d.ts +4 -5
  770. package/dist/types/transport/proxy.d.ts +5 -0
  771. package/dist/types/transport/types.d.ts +15 -0
  772. package/dist/types/transport/wa-web-version-fetcher.d.ts +44 -0
  773. package/dist/types/util/async.d.ts +4 -0
  774. package/dist/types/util/bytes.d.ts +36 -1
  775. package/dist/types/util/clock.d.ts +6 -0
  776. package/dist/types/util/coercion.d.ts +25 -0
  777. package/dist/types/util/collections.d.ts +8 -0
  778. package/dist/types/util/index.d.ts +2 -2
  779. package/dist/types/util/primitives.d.ts +11 -0
  780. package/dist/types/util/runtime.d.ts +5 -0
  781. package/dist/types/version-spec.d.ts +1 -0
  782. package/dist/util/async.js +4 -0
  783. package/dist/util/bytes.js +37 -2
  784. package/dist/util/clock.js +18 -0
  785. package/dist/util/coercion.js +48 -3
  786. package/dist/util/collections.js +12 -0
  787. package/dist/util/index.js +7 -1
  788. package/dist/util/primitives.js +20 -0
  789. package/dist/util/runtime.js +5 -0
  790. package/dist/version-spec.js +5 -0
  791. package/package.json +37 -11
  792. package/spec/appstate/index.d.ts +188 -0
  793. package/spec/appstate/index.js +850 -0
  794. package/spec/mex/index.d.ts +4172 -0
  795. package/spec/mex/index.js +261 -0
  796. package/spec/proto/index.d.ts +16305 -0
  797. package/spec/proto/index.js +1 -0
  798. package/spec/version/index.d.ts +4 -0
  799. package/spec/version/index.js +9 -0
  800. package/spec/version/version.json +3 -0
  801. package/dist/auth/flow/WaAuthCredentialsFlow.js +0 -130
  802. package/dist/auth/pairing/WaPairingCodeCrypto.js +0 -77
  803. package/dist/auth/pairing/constants.js +0 -5
  804. package/dist/client/connection/WaKeyShareCoordinator.js +0 -63
  805. package/dist/client/events/chat.js +0 -227
  806. package/dist/client/incoming.js +0 -269
  807. package/dist/client/mailbox.js +0 -50
  808. package/dist/client/messages.js +0 -228
  809. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +0 -125
  810. package/dist/esm/auth/pairing/WaPairingCodeCrypto.js +0 -73
  811. package/dist/esm/auth/pairing/constants.js +0 -2
  812. package/dist/esm/client/connection/WaKeyShareCoordinator.js +0 -59
  813. package/dist/esm/client/events/chat.js +0 -224
  814. package/dist/esm/client/incoming.js +0 -260
  815. package/dist/esm/client/mailbox.js +0 -47
  816. package/dist/esm/client/messages.js +0 -224
  817. package/dist/esm/media/WaMediaCrypto.js +0 -304
  818. package/dist/esm/message/addon-crypto.js +0 -59
  819. package/dist/esm/message/incoming.js +0 -325
  820. package/dist/esm/message/phash.js +0 -27
  821. package/dist/esm/signal/crypto/WaAdvSignature.js +0 -64
  822. package/dist/esm/store/locks/participants.lock.js +0 -20
  823. package/dist/esm/store/providers/memory/contact.store.js +0 -28
  824. package/dist/esm/store/providers/memory/device-list.store.js +0 -64
  825. package/dist/esm/store/providers/memory/signal.store.js +0 -199
  826. package/dist/esm/transport/node/builders/index.js +0 -11
  827. package/dist/media/WaMediaCrypto.js +0 -308
  828. package/dist/message/addon-crypto.js +0 -65
  829. package/dist/message/phash.js +0 -30
  830. package/dist/signal/crypto/WaAdvSignature.js +0 -76
  831. package/dist/store/locks/participants.lock.js +0 -23
  832. package/dist/store/providers/memory/contact.store.js +0 -32
  833. package/dist/store/providers/memory/device-list.store.js +0 -68
  834. package/dist/store/providers/memory/signal.store.js +0 -203
  835. package/dist/transport/node/builders/index.js +0 -51
  836. package/dist/types/appstate/WaAppStateSyncClient.d.ts +0 -66
  837. package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +0 -14
  838. package/dist/types/auth/pairing/constants.d.ts +0 -2
  839. package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +0 -14
  840. package/dist/types/client/events/chat.d.ts +0 -3
  841. package/dist/types/client/history-sync.d.ts +0 -20
  842. package/dist/types/client/incoming.d.ts +0 -37
  843. package/dist/types/client/mailbox.d.ts +0 -10
  844. package/dist/types/client/messages.d.ts +0 -16
  845. package/dist/types/client/messaging/participants.d.ts +0 -13
  846. package/dist/types/media/WaMediaCrypto.d.ts +0 -13
  847. package/dist/types/media/conn.d.ts +0 -3
  848. package/dist/types/message/addon-crypto.d.ts +0 -25
  849. package/dist/types/message/content.d.ts +0 -12
  850. package/dist/types/message/incoming.d.ts +0 -18
  851. package/dist/types/signal/crypto/constants.d.ts +0 -5
  852. package/dist/types/store/contracts/participants.store.d.ts +0 -13
  853. package/dist/types/store/locks/participants.lock.d.ts +0 -2
  854. package/dist/types/store/providers/memory/participants.store.d.ts +0 -17
  855. package/dist/types/store/providers/memory/signal.store.d.ts +0 -58
  856. package/dist/types/transport/node/builders/index.d.ts +0 -11
  857. package/proto/index.d.ts +0 -10903
  858. package/proto/index.js +0 -1
  859. /package/dist/{store/contracts/participants.store.js → client/newsletter/types.js} +0 -0
  860. /package/dist/esm/{store/contracts/participants.store.js → client/newsletter/types.js} +0 -0
  861. /package/dist/esm/message/{device-sent.js → encode/device-sent.js} +0 -0
  862. /package/dist/message/{device-sent.js → encode/device-sent.js} +0 -0
  863. /package/dist/types/message/{padding.d.ts → encode/padding.d.ts} +0 -0
@@ -1,65 +1,49 @@
1
1
  import { randomBytesAsync, sha256 } from '../../crypto/index.js';
2
+ import { md5Bytes } from '../../crypto/core/primitives.js';
2
3
  import { PromiseDedup } from '../../infra/perf/PromiseDedup.js';
3
- import { ensureMessageSecret } from '../../message/index.js';
4
- import { resolveEditAttr, resolveEncMediaType, resolveMessageTypeAttr, resolveMetaAttrs } from '../../message/content.js';
5
- import { wrapDeviceSentMessage } from '../../message/device-sent.js';
6
- import { injectDeviceListMetadata, resolveIcdcMeta } from '../../message/icdc.js';
7
- import { writeRandomPadMax16 } from '../../message/padding.js';
8
- import { computePhashV2 } from '../../message/phash.js';
9
- import { buildReportingTokenArtifacts } from '../../message/reporting-token.js';
4
+ import { assertMessageSecret, ensureMessageSecret } from '../../message/index.js';
5
+ import { applyContextInfo, resolveSendContextInfo } from '../../message/context-info.js';
6
+ import { injectDeviceListMetadata, resolveIcdcMeta } from '../../message/crypto/icdc.js';
7
+ import { computePhashV2 } from '../../message/crypto/phash.js';
8
+ import { buildReportingTokenArtifacts } from '../../message/crypto/reporting-token.js';
9
+ import { isSendAddonCryptoMessage, isSendMediaMessage, isSendTextMessage, needsSecretPersistence, resolveButtonAddonKind, resolveDecryptFailAttr, resolveEditAttr, resolveEncMediaType, resolveMessageTypeAttr, resolveMetaAttrs, wrapAsViewOnce } from '../../message/encode/content.js';
10
+ import { wrapDeviceSentMessage } from '../../message/encode/device-sent.js';
11
+ import { writeRandomPadMax16 } from '../../message/encode/padding.js';
12
+ import { buildBotInvokeProtoCopy, extractInvokedBotJid, genBotMsgSecret } from '../../message/kinds/bot.js';
10
13
  import { proto } from '../../proto.js';
11
14
  import { WA_DEFAULTS } from '../../protocol/constants.js';
12
- import { isGroupJid, normalizeDeviceJid, normalizeRecipientJid, parseJidFull, parseSignalAddressFromJid, splitJid, toUserJid } from '../../protocol/jid.js';
13
- import { signalAddressKey } from '../../protocol/jid.js';
15
+ import { isBotJid, isGroupJid, isHostedDeviceJid, isLidJid, isNewsletterJid, normalizeDeviceJid, normalizeRecipientJid, parseJidFull, parseSignalAddressFromJid, signalAddressKey, toUserJid } from '../../protocol/jid.js';
14
16
  import { encodeBinaryNode } from '../../transport/binary/index.js';
15
- import { buildDirectMessageFanoutNode, buildGroupSenderKeyMessageNode, buildMetaNode } from '../../transport/node/builders/message.js';
16
- import { bytesToHex, concatBytes, TEXT_ENCODER } from '../../util/bytes.js';
17
+ import { buildButtonAddonNode, buildDirectMessageFanoutNode, buildGroupSenderKeyMessageNode, buildMetaNode } from '../../transport/node/builders/message.js';
18
+ import { bytesToHex, TEXT_ENCODER } from '../../util/bytes.js';
17
19
  import { toError } from '../../util/primitives.js';
18
20
  export class WaMessageDispatchCoordinator {
19
21
  constructor(options) {
20
22
  this.icdcDedup = new PromiseDedup();
21
23
  this.privacyTokenDedup = new PromiseDedup();
22
24
  this.distributionDedup = new PromiseDedup();
23
- this.logger = options.logger;
24
- this.messageClient = options.messageClient;
25
- this.retryTracker = options.retryTracker;
26
- this.sessionResolver = options.sessionResolver;
27
- this.fanoutResolver = options.fanoutResolver;
28
- this.participantsCache = options.participantsCache;
29
- this.appStateSyncKeyProtocol = options.appStateSyncKeyProtocol;
30
- this.buildMessageContent = options.buildMessageContent;
31
- this.senderKeyManager = options.senderKeyManager;
32
- this.signalProtocol = options.signalProtocol;
33
- this.signalStore = options.signalStore;
34
- this.deviceListStore = options.deviceListStore;
35
- this.getCurrentMeJid = options.getCurrentMeJid;
36
- this.getCurrentMeLid = options.getCurrentMeLid;
37
- this.getCurrentSignedIdentity = options.getCurrentSignedIdentity;
38
- this.resolvePrivacyTokenNode = options.resolvePrivacyTokenNode;
39
- this.onDirectMessageSent = options.onDirectMessageSent;
25
+ this.deps = options;
26
+ this.mobileMessageIdFormat = options.mobileMessageIdFormat ?? false;
27
+ this.serverClock = options.serverClock;
40
28
  }
41
29
  async publishMessageNode(node, options = {}) {
42
- this.logger.debug('wa client publish message node', {
30
+ this.deps.logger.trace('wa client publish message node', {
43
31
  tag: node.tag,
44
32
  type: node.attrs.type,
45
33
  to: node.attrs.to
46
34
  });
47
- const messageType = node.attrs.type ?? 'text';
48
35
  const replayPayload = {
49
36
  mode: 'opaque_node',
50
37
  node: encodeBinaryNode(node)
51
38
  };
52
- return this.retryTracker.track({
39
+ return this.deps.retryTracker.track({
53
40
  messageIdHint: node.attrs.id,
54
41
  toJid: node.attrs.to,
55
- type: messageType,
56
- replayPayload,
57
- participantJid: node.attrs.participant,
58
- recipientJid: node.attrs.recipient
59
- }, async () => this.messageClient.publishNode(node, options));
42
+ replayPayload
43
+ }, async () => this.deps.messageClient.publishNode(node, options));
60
44
  }
61
45
  async publishEncryptedMessage(input, options = {}) {
62
- this.logger.debug('wa client publish encrypted message', {
46
+ this.deps.logger.trace('wa client publish encrypted message', {
63
47
  to: input.to,
64
48
  type: input.type,
65
49
  encType: input.encType
@@ -72,14 +56,12 @@ export class WaMessageDispatchCoordinator {
72
56
  ciphertext: input.ciphertext,
73
57
  participant: input.participant
74
58
  };
75
- return this.retryTracker.track({
59
+ return this.deps.retryTracker.track({
76
60
  messageIdHint: input.id,
77
61
  toJid: input.to,
78
- type: input.type ?? 'text',
79
62
  replayPayload,
80
- participantJid: input.participant,
81
63
  eligibleRequesterDeviceJids: [input.to]
82
- }, async () => this.messageClient.publishEncrypted(input, options));
64
+ }, async () => this.deps.messageClient.publishEncrypted(input, options));
83
65
  }
84
66
  async publishSignalMessage(input, options = {}) {
85
67
  this.requireCurrentMeJid('publishSignalMessage');
@@ -87,30 +69,29 @@ export class WaMessageDispatchCoordinator {
87
69
  if (address.server === WA_DEFAULTS.GROUP_SERVER) {
88
70
  throw new Error('publishSignalMessage currently supports only direct chats; use sender-key flow for groups');
89
71
  }
90
- this.logger.debug('wa client publish signal message', {
72
+ this.deps.logger.trace('wa client publish signal message', {
91
73
  to: input.to,
92
74
  type: input.type
93
75
  });
94
76
  const [paddedPlaintext] = await Promise.all([
95
77
  writeRandomPadMax16(input.plaintext),
96
- this.sessionResolver.ensureSession(address, input.to, input.expectedIdentity)
78
+ this.deps.sessionResolver.ensureSession(address, input.to, input.expectedIdentity)
97
79
  ]);
98
- const encrypted = await this.signalProtocol.encryptMessage(address, paddedPlaintext, input.expectedIdentity);
80
+ const encrypted = await this.deps.signalProtocol.encryptMessage(address, paddedPlaintext, input.expectedIdentity);
99
81
  const messageType = input.type ?? 'text';
82
+ const deviceIdentity = encrypted.type === 'pkmsg' ? this.getEncodedSignedDeviceIdentity() : undefined;
100
83
  const replayPayload = {
101
84
  mode: 'plaintext',
102
85
  to: input.to,
103
86
  type: messageType,
104
87
  plaintext: paddedPlaintext
105
88
  };
106
- return this.retryTracker.track({
89
+ return this.deps.retryTracker.track({
107
90
  messageIdHint: input.id,
108
91
  toJid: input.to,
109
- type: messageType,
110
92
  replayPayload,
111
- participantJid: input.participant,
112
93
  eligibleRequesterDeviceJids: [input.to]
113
- }, async () => this.messageClient.publishEncrypted({
94
+ }, async () => this.deps.messageClient.publishEncrypted({
114
95
  to: input.to,
115
96
  encType: encrypted.type,
116
97
  ciphertext: encrypted.ciphertext,
@@ -119,18 +100,130 @@ export class WaMessageDispatchCoordinator {
119
100
  category: input.category,
120
101
  pushPriority: input.pushPriority,
121
102
  participant: input.participant,
122
- deviceFanout: input.deviceFanout
103
+ deviceFanout: input.deviceFanout,
104
+ deviceIdentity,
105
+ metaNode: input.metaNode
123
106
  }, options));
124
107
  }
125
108
  async sendMessage(to, content, options = {}) {
126
109
  const recipientJid = normalizeRecipientJid(to);
127
- const [message, sendOptions] = await Promise.all([
128
- this.buildMessageContent(content),
129
- this.withResolvedMessageId(options)
130
- ]);
131
- const messageWithSecret = await ensureMessageSecret(message);
132
- const meJid = this.getCurrentMeJid();
133
- const regInfo = meJid ? await this.signalStore.getRegistrationInfo() : null;
110
+ if (isNewsletterJid(recipientJid)) {
111
+ if (!this.deps.sendNewsletterMessage) {
112
+ throw new Error('newsletter sendMessage requires sendNewsletterMessage dependency');
113
+ }
114
+ const newsletterCtx = resolveSendContextInfo({
115
+ contentLevel: pickContentContextInfo(content),
116
+ optionsLevel: options.contextInfo,
117
+ quote: options.quote,
118
+ forward: options.forward,
119
+ mentions: options.mentions
120
+ });
121
+ assertNewsletterContextInfoCompatible(newsletterCtx);
122
+ const sendOptions = await this.withResolvedMessageId(options);
123
+ return this.deps.sendNewsletterMessage(recipientJid, content, sendOptions, newsletterCtx);
124
+ }
125
+ let built;
126
+ let sendOptions;
127
+ if (isSendAddonCryptoMessage(content)) {
128
+ sendOptions = await this.withResolvedMessageId(options);
129
+ const meJid = this.deps.getCurrentCredentials()?.meJid;
130
+ if (!meJid) {
131
+ throw new Error(`${content.type} sendMessage requires registered meJid`);
132
+ }
133
+ built = await this.deps.buildMessageContent(content, {
134
+ to: recipientJid,
135
+ outgoingStanzaId: sendOptions.id,
136
+ meJid: toUserJid(meJid)
137
+ });
138
+ }
139
+ else {
140
+ ;
141
+ [built, sendOptions] = await Promise.all([
142
+ this.deps.buildMessageContent(content, { to: recipientJid }),
143
+ this.withResolvedMessageId(options)
144
+ ]);
145
+ }
146
+ let optionsCtx = options.contextInfo;
147
+ if (options.expirationSeconds !== undefined) {
148
+ optionsCtx = { ...optionsCtx, expirationSeconds: options.expirationSeconds };
149
+ }
150
+ if (isGroupJid(recipientJid) &&
151
+ optionsCtx?.expirationSeconds === undefined &&
152
+ !options.disableGroupEphemeralAutoInject) {
153
+ const cachedEphemeral = await this.deps.groupMetadataCache.resolveEphemeral(recipientJid);
154
+ if (cachedEphemeral !== null && cachedEphemeral > 0) {
155
+ optionsCtx = { ...optionsCtx, expirationSeconds: cachedEphemeral };
156
+ }
157
+ }
158
+ const ctx = resolveSendContextInfo({
159
+ contentLevel: pickContentContextInfo(content),
160
+ optionsLevel: optionsCtx,
161
+ quote: options.quote,
162
+ forward: options.forward,
163
+ mentions: options.mentions,
164
+ meLid: this.deps.getCurrentCredentials()?.meLid
165
+ });
166
+ const withCtx = ctx ? applyContextInfo(built.message, ctx) : built.message;
167
+ const withViewOnce = options.viewOnce ? wrapAsViewOnce(withCtx) : withCtx;
168
+ const editKey = options.editKey;
169
+ let editId;
170
+ let editParticipant;
171
+ let editTimestamp;
172
+ if (editKey) {
173
+ if ('rawNode' in editKey) {
174
+ editId = editKey.key?.id ?? undefined;
175
+ editParticipant = editKey.key?.participant ?? undefined;
176
+ }
177
+ else {
178
+ editId = editKey.id;
179
+ editParticipant = editKey.participant;
180
+ editTimestamp = 'timestampMs' in editKey ? editKey.timestampMs : undefined;
181
+ }
182
+ }
183
+ const message = editKey
184
+ ? {
185
+ protocolMessage: {
186
+ type: proto.Message.ProtocolMessage.Type.MESSAGE_EDIT,
187
+ key: {
188
+ remoteJid: recipientJid,
189
+ fromMe: true,
190
+ id: editId,
191
+ ...(editParticipant ? { participant: editParticipant } : {})
192
+ },
193
+ editedMessage: withViewOnce,
194
+ timestampMs: editTimestamp ?? this.serverClock.nowMs()
195
+ }
196
+ }
197
+ : withViewOnce;
198
+ const upload = built.upload;
199
+ const messageWithOverride = options.messageSecret
200
+ ? {
201
+ ...message,
202
+ messageContextInfo: {
203
+ ...(message.messageContextInfo ?? {}),
204
+ messageSecret: assertMessageSecret(options.messageSecret, 'options.messageSecret')
205
+ }
206
+ }
207
+ : message;
208
+ const messageWithSecret = await ensureMessageSecret(messageWithOverride);
209
+ const rawSecret = messageWithSecret.messageContextInfo?.messageSecret;
210
+ if (rawSecret &&
211
+ rawSecret.length > 0 &&
212
+ sendOptions.id &&
213
+ needsSecretPersistence(messageWithSecret)) {
214
+ const meJid = this.deps.getCurrentCredentials()?.meJid ?? '';
215
+ void this.deps.messageSecretStore
216
+ .set(sendOptions.id, { secret: rawSecret, senderJid: meJid })
217
+ .catch((error) => {
218
+ this.deps.logger.warn('failed to persist outgoing message secret', {
219
+ id: sendOptions.id,
220
+ to: recipientJid,
221
+ message: toError(error).message
222
+ });
223
+ });
224
+ }
225
+ const meJid = this.deps.getCurrentCredentials()?.meJid;
226
+ const regInfo = meJid ? await this.deps.signalStore.getRegistrationInfo() : null;
134
227
  const localPubKey = regInfo?.identityKeyPair.pubKey;
135
228
  const meParsed = meJid ? parseJidFull(meJid) : undefined;
136
229
  const meUserJid = meParsed?.userJid;
@@ -142,67 +235,343 @@ export class WaMessageDispatchCoordinator {
142
235
  ]);
143
236
  const messageWithIcdc = injectDeviceListMetadata(messageWithSecret, senderIcdc, recipientIcdc);
144
237
  const plaintext = await writeRandomPadMax16(proto.Message.encode(messageWithIcdc).finish());
145
- const type = resolveMessageTypeAttr(messageWithIcdc);
146
- const edit = resolveEditAttr(messageWithIcdc, sendOptions.subtype) ?? undefined;
147
- const mediatype = resolveEncMediaType(messageWithIcdc) ?? undefined;
238
+ const buttonAddonKind = resolveButtonAddonKind(messageWithIcdc);
239
+ const buttonAddonNode = buttonAddonKind ? buildButtonAddonNode(buttonAddonKind) : undefined;
240
+ // when a <biz> companion is attached the stanza must advertise type=text and
241
+ // omit enc.mediatype; sending type=media + mediatype=list/button alongside the
242
+ // companion is rejected by the server as SMAX_INVALID (479).
243
+ const type = buttonAddonKind ? 'text' : resolveMessageTypeAttr(messageWithIcdc);
244
+ const edit = resolveEditAttr(messageWithIcdc) ?? undefined;
245
+ const mediatype = buttonAddonKind
246
+ ? undefined
247
+ : (resolveEncMediaType(messageWithIcdc) ?? undefined);
148
248
  const metaAttrs = resolveMetaAttrs(messageWithIcdc);
149
249
  const metaNode = metaAttrs ? buildMetaNode(metaAttrs) : undefined;
150
- if (isGroup) {
151
- if (this.shouldUseGroupDirectPath(messageWithIcdc)) {
152
- return this.publishGroupDirectMessage(recipientJid, messageWithIcdc, plaintext, type, sendOptions, {}, edit, mediatype, metaNode);
250
+ const customNodes = [];
251
+ if (metaNode)
252
+ customNodes.push(metaNode);
253
+ if (buttonAddonNode)
254
+ customNodes.push(buttonAddonNode);
255
+ if (options.customNodes) {
256
+ for (const node of options.customNodes) {
257
+ customNodes.push(node);
153
258
  }
154
- return this.publishGroupSenderKeyMessage(recipientJid, messageWithIcdc, plaintext, type, sendOptions, {}, edit, mediatype, metaNode);
155
259
  }
156
- const directRecipientJid = toUserJid(recipientJid);
157
- return this.publishDirectSignalMessageWithFanout(directRecipientJid, messageWithIcdc, plaintext, type, sendOptions, edit, mediatype, metaNode);
260
+ const decryptFail = resolveDecryptFailAttr(messageWithIcdc);
261
+ const envelope = {
262
+ message: messageWithIcdc,
263
+ plaintext,
264
+ type,
265
+ edit,
266
+ mediatype,
267
+ decryptFail,
268
+ customNodes: customNodes.length > 0 ? customNodes : undefined,
269
+ sendOptions
270
+ };
271
+ const directRecipientJid = isGroup
272
+ ? recipientJid
273
+ : await this.resolveDirectRecipientLid(toUserJid(recipientJid));
274
+ const publishResult = isGroup
275
+ ? this.shouldUseGroupDirectPath(messageWithIcdc)
276
+ ? await this.publishGroupDirectMessage(recipientJid, envelope)
277
+ : await this.publishGroupSenderKeyMessage(recipientJid, envelope)
278
+ : await this.publishDirectSignalMessageWithFanout(directRecipientJid, envelope);
279
+ return upload ? { ...publishResult, upload } : publishResult;
280
+ }
281
+ /**
282
+ * For a 1:1 recipient passed in PN form, returns the LID-addressed user JID
283
+ * (cache-first; falls back to a one-shot `queryLidsByPhoneJids`). Switching
284
+ * to LID before fanout ensures the envelope, eligible-requester list, and
285
+ * retry-receipt addressing all agree, which keeps the retry tracker from
286
+ * rejecting receipts that arrive in LID form. Returns the original PN if
287
+ * no LID is known/resolvable. Inputs already in LID form pass through.
288
+ */
289
+ async resolveDirectRecipientLid(pnUserJid) {
290
+ if (isLidJid(pnUserJid))
291
+ return pnUserJid;
292
+ const cached = await this.deps.deviceListStore.findByAnyUserJid(pnUserJid);
293
+ if (cached) {
294
+ if (isLidJid(cached.userJid))
295
+ return cached.userJid;
296
+ if (cached.altUserJid && isLidJid(cached.altUserJid))
297
+ return cached.altUserJid;
298
+ }
299
+ try {
300
+ const results = await this.deps.signalDeviceSync.queryLidsByPhoneJids([pnUserJid]);
301
+ const match = results.find((entry) => entry.phoneJid === pnUserJid);
302
+ if (match?.lidJid)
303
+ return match.lidJid;
304
+ }
305
+ catch (error) {
306
+ this.deps.logger.debug('lid resolution failed for direct recipient', {
307
+ pnUserJid,
308
+ message: toError(error).message
309
+ });
310
+ }
311
+ return pnUserJid;
158
312
  }
159
313
  async syncSignalSession(jid, reasonIdentity = false) {
160
314
  const address = parseSignalAddressFromJid(jid);
161
315
  if (address.server === WA_DEFAULTS.GROUP_SERVER) {
162
316
  throw new Error('syncSignalSession supports only direct chats');
163
317
  }
164
- await this.sessionResolver.ensureSession(address, jid, undefined, reasonIdentity);
318
+ await this.deps.sessionResolver.ensureSession(address, jid, undefined, reasonIdentity);
165
319
  }
166
320
  async sendReceipt(input) {
167
- await this.messageClient.sendReceipt(input);
321
+ await this.deps.messageClient.sendReceipt(input);
322
+ }
323
+ async publishProtocolMessageToDevice(deviceJid, protocolMessage, options) {
324
+ const meJid = this.deps.getCurrentCredentials()?.meJid;
325
+ const meParsed = meJid ? parseJidFull(meJid) : undefined;
326
+ const meUserJid = meParsed?.userJid;
327
+ let senderIcdc = null;
328
+ if (meUserJid) {
329
+ const regInfo = await this.deps.signalStore.getRegistrationInfo();
330
+ const localPubKey = regInfo?.identityKeyPair.pubKey;
331
+ const localIdentity = meParsed && localPubKey
332
+ ? { address: meParsed.address, pubKey: localPubKey }
333
+ : undefined;
334
+ senderIcdc = await this.resolveUserIcdc(meUserJid, localIdentity);
335
+ }
336
+ const message = injectDeviceListMetadata({ protocolMessage }, senderIcdc, null);
337
+ return this.publishSignalMessage({
338
+ to: deviceJid,
339
+ plaintext: proto.Message.encode(message).finish(),
340
+ id: options?.id,
341
+ type: 'text',
342
+ category: 'peer',
343
+ pushPriority: options?.pushPriority ?? 'high',
344
+ metaNode: buildMetaNode({ appdata: 'default' })
345
+ });
346
+ }
347
+ async publishStatusMessage(input) {
348
+ if (input.recipients.length === 0) {
349
+ throw new Error('publishStatusMessage requires at least one recipient');
350
+ }
351
+ this.requireCurrentMeJid('publishStatusMessage');
352
+ const meLid = this.deps.getCurrentCredentials()?.meLid;
353
+ if (!meLid) {
354
+ throw new Error('publishStatusMessage requires current me lid');
355
+ }
356
+ const senderJid = normalizeDeviceJid(meLid);
357
+ const meUserLid = toUserJid(meLid);
358
+ const seen = new Set();
359
+ const recipientsWithSelf = [];
360
+ for (const jid of input.recipients) {
361
+ if (seen.has(jid))
362
+ continue;
363
+ seen.add(jid);
364
+ recipientsWithSelf.push(jid);
365
+ }
366
+ if (!seen.has(meUserLid)) {
367
+ recipientsWithSelf.push(meUserLid);
368
+ }
369
+ const statusSetting = input.statusSetting ?? 'contacts';
370
+ return this.publishSenderKeyFanout({
371
+ groupJid: WA_DEFAULTS.STATUS_BROADCAST_JID,
372
+ senderJid,
373
+ recipients: recipientsWithSelf,
374
+ message: input.message,
375
+ options: input.options ?? {},
376
+ logTag: 'status',
377
+ replayStatusSetting: statusSetting,
378
+ // Bare `<to jid=user>` ack hints route the skmsg through primary
379
+ // devices that already hold the sender key.
380
+ customize: async ({ fanoutDeviceJids, distributionParticipants, messageWithSecret, sendOptions }) => {
381
+ const distributedAddressKeys = new Set();
382
+ for (let i = 0; i < distributionParticipants.length; i += 1) {
383
+ distributedAddressKeys.add(signalAddressKey(distributionParticipants[i].address));
384
+ }
385
+ const ackHints = [];
386
+ const seenAck = new Set();
387
+ for (let i = 0; i < fanoutDeviceJids.length; i += 1) {
388
+ const deviceJid = fanoutDeviceJids[i];
389
+ const address = parseSignalAddressFromJid(deviceJid);
390
+ if (distributedAddressKeys.has(signalAddressKey(address)))
391
+ continue;
392
+ if (address.device !== 0)
393
+ continue;
394
+ const userJid = toUserJid(deviceJid);
395
+ if (seenAck.has(userJid))
396
+ continue;
397
+ seenAck.add(userJid);
398
+ ackHints.push({ jid: userJid });
399
+ }
400
+ const reportingArtifacts = await this.tryBuildReportingTokenArtifacts({
401
+ message: messageWithSecret,
402
+ stanzaId: sendOptions.id,
403
+ senderUserJid: toUserJid(senderJid),
404
+ remoteJid: WA_DEFAULTS.STATUS_BROADCAST_JID,
405
+ context: 'status'
406
+ });
407
+ const customNodes = [buildMetaNode({ status_setting: statusSetting })];
408
+ if (reportingArtifacts?.node)
409
+ customNodes.push(reportingArtifacts.node);
410
+ return {
411
+ extraParticipants: ackHints,
412
+ customNodes
413
+ };
414
+ }
415
+ });
416
+ }
417
+ async publishBroadcastListMessage(input) {
418
+ if (input.recipients.length === 0) {
419
+ throw new Error('publishBroadcastListMessage requires at least one recipient');
420
+ }
421
+ const meJid = this.requireCurrentMeJid('publishBroadcastListMessage');
422
+ const senderJid = normalizeDeviceJid(meJid);
423
+ return this.publishSenderKeyFanout({
424
+ groupJid: input.listJid,
425
+ senderJid,
426
+ recipients: input.recipients,
427
+ message: input.message,
428
+ options: input.options ?? {},
429
+ logTag: 'broadcast list',
430
+ customize: ({ fanoutDeviceJids }) => {
431
+ const phashTargets = new Array(fanoutDeviceJids.length + 1);
432
+ let phashTargetCount = 0;
433
+ for (let i = 0; i < fanoutDeviceJids.length; i += 1) {
434
+ const candidate = fanoutDeviceJids[i];
435
+ if (isHostedDeviceJid(candidate))
436
+ continue;
437
+ phashTargets[phashTargetCount] = candidate;
438
+ phashTargetCount += 1;
439
+ }
440
+ phashTargets[phashTargetCount] = senderJid;
441
+ phashTargets.length = phashTargetCount + 1;
442
+ return Promise.resolve({ phash: computePhashV2(phashTargets) });
443
+ }
444
+ });
445
+ }
446
+ async publishSenderKeyFanout(input) {
447
+ const sendOptions = await this.withResolvedMessageId(input.options);
448
+ const sender = parseSignalAddressFromJid(input.senderJid);
449
+ const messageWithSecret = await ensureMessageSecret(input.message);
450
+ const plaintext = await writeRandomPadMax16(proto.Message.encode(messageWithSecret).finish());
451
+ const { distributionMessage, ciphertext: groupCiphertext, keyId: senderKeyId } = await this.deps.senderKeyManager.prepareGroupEncryption(input.groupJid, sender, plaintext);
452
+ const { fanoutDeviceJids, distributionParticipants } = await this.encryptGroupDistributionParticipants(input.groupJid, senderKeyId, distributionMessage, input.recipients);
453
+ let shouldAttachDeviceIdentity = false;
454
+ for (let i = 0; i < distributionParticipants.length; i += 1) {
455
+ if (distributionParticipants[i].encType === 'pkmsg') {
456
+ shouldAttachDeviceIdentity = true;
457
+ break;
458
+ }
459
+ }
460
+ const extras = input.customize
461
+ ? await input.customize({
462
+ fanoutDeviceJids,
463
+ distributionParticipants,
464
+ messageWithSecret,
465
+ sendOptions
466
+ })
467
+ : {};
468
+ const participants = distributionParticipants.map((p) => ({
469
+ jid: p.jid,
470
+ encType: p.encType,
471
+ ciphertext: p.ciphertext
472
+ }));
473
+ if (extras.extraParticipants) {
474
+ for (const entry of extras.extraParticipants) {
475
+ participants.push(entry);
476
+ }
477
+ }
478
+ const messageNode = buildGroupSenderKeyMessageNode({
479
+ to: input.groupJid,
480
+ type: resolveMessageTypeAttr(messageWithSecret),
481
+ id: sendOptions.id,
482
+ phash: extras.phash,
483
+ edit: resolveEditAttr(messageWithSecret) ?? undefined,
484
+ mediatype: resolveEncMediaType(messageWithSecret) ?? undefined,
485
+ decryptFail: resolveDecryptFailAttr(messageWithSecret),
486
+ groupCiphertext: groupCiphertext.ciphertext,
487
+ participants,
488
+ deviceIdentity: shouldAttachDeviceIdentity
489
+ ? this.getEncodedSignedDeviceIdentity()
490
+ : undefined,
491
+ customNodes: extras.customNodes,
492
+ additionalAttributes: sendOptions.additionalAttributes
493
+ });
494
+ const replayPayload = {
495
+ mode: 'plaintext',
496
+ to: input.groupJid,
497
+ type: messageNode.attrs.type,
498
+ plaintext,
499
+ ...(input.replayStatusSetting ? { statusSetting: input.replayStatusSetting } : {})
500
+ };
501
+ const result = await this.deps.retryTracker.track({
502
+ messageIdHint: messageNode.attrs.id ?? sendOptions.id,
503
+ toJid: input.groupJid,
504
+ replayPayload,
505
+ eligibleRequesterDeviceJids: undefined
506
+ }, async () => this.deps.messageClient.publishNode(messageNode, sendOptions));
507
+ const distributedAddresses = new Array(distributionParticipants.length);
508
+ for (let i = 0; i < distributionParticipants.length; i += 1) {
509
+ distributedAddresses[i] = distributionParticipants[i].address;
510
+ }
511
+ try {
512
+ await this.deps.senderKeyManager.markSenderKeyDistributed(input.groupJid, senderKeyId, distributedAddresses);
513
+ }
514
+ catch (error) {
515
+ this.deps.logger.warn('failed to mark sender key distribution targets', {
516
+ logTag: input.logTag,
517
+ groupJid: input.groupJid,
518
+ participants: distributedAddresses.length,
519
+ message: toError(error).message
520
+ });
521
+ }
522
+ return result;
168
523
  }
169
524
  async requestAppStateSyncKeys(keyIds) {
170
- return this.appStateSyncKeyProtocol.requestKeys(keyIds);
525
+ return this.deps.appStateSyncKeyProtocol.requestKeys(keyIds);
171
526
  }
172
527
  async sendAppStateSyncKeyShare(toDeviceJid, keys, missingKeyIds = []) {
173
- await this.appStateSyncKeyProtocol.sendKeyShare(toDeviceJid, keys, missingKeyIds);
528
+ await this.deps.appStateSyncKeyProtocol.sendKeyShare(toDeviceJid, keys, missingKeyIds);
174
529
  }
175
- async mutateParticipantsCacheFromGroupEvent(event) {
176
- await this.participantsCache.mutateFromGroupEvent(event);
530
+ async mutateGroupMetadataCacheFromGroupEvent(event) {
531
+ await this.deps.groupMetadataCache.mutateFromGroupEvent(event);
177
532
  }
533
+ // noop for now
178
534
  shouldUseGroupDirectPath(message) {
179
- const protocolType = message.protocolMessage?.type;
180
- if (protocolType === proto.Message.ProtocolMessage.Type.REVOKE ||
181
- protocolType === proto.Message.ProtocolMessage.Type.MESSAGE_EDIT) {
182
- return true;
183
- }
184
- return message.keepInChatMessage?.keepType === proto.KeepType.UNDO_KEEP_FOR_ALL;
535
+ return false;
185
536
  }
186
- async publishGroupDirectMessage(groupJid, message, plaintext, type, options, retryContext = {}, edit, mediatype, metaNode) {
187
- const sendOptions = await this.withResolvedMessageId(options);
537
+ async publishGroupDirectMessage(groupJid, envelope, retryContext = {}) {
538
+ const { message, plaintext, type, edit, mediatype, sendOptions } = envelope;
188
539
  const meJid = this.requireCurrentMeJid('sendMessage');
189
540
  const participantUserJids = retryContext.forceRefreshParticipants
190
- ? await this.participantsCache.refreshParticipantUsers(groupJid)
191
- : await this.participantsCache.resolveParticipantUsers(groupJid);
541
+ ? await this.deps.groupMetadataCache.refreshParticipantUsers(groupJid)
542
+ : await this.deps.groupMetadataCache.resolveParticipantUsers(groupJid);
192
543
  const addressingMode = retryContext.forceAddressingMode ??
193
544
  this.resolveGroupAddressingMode(participantUserJids, groupJid);
194
545
  const senderForPhash = this.resolveSenderForAddressingMode(addressingMode, meJid);
195
- const fanoutDeviceJids = await this.fanoutResolver.resolveGroupParticipantDeviceJids(participantUserJids);
546
+ const fanoutDeviceJids = await this.deps.fanoutResolver.resolveGroupParticipantDeviceJids(participantUserJids);
196
547
  if (fanoutDeviceJids.length === 0) {
197
548
  throw new Error('group direct send resolved no target devices');
198
549
  }
199
- const resolvedFanoutTargets = await this.sessionResolver.ensureSessionsBatch(fanoutDeviceJids);
550
+ const resolvedFanoutTargets = await this.deps.sessionResolver.ensureSessionsBatch(fanoutDeviceJids);
551
+ const resolvedNormalizedJids = new Set();
552
+ for (let index = 0; index < resolvedFanoutTargets.length; index += 1) {
553
+ resolvedNormalizedJids.add(resolvedFanoutTargets[index].jid);
554
+ }
200
555
  const uniqueNormalizedFanoutJids = new Set();
201
556
  for (let index = 0; index < fanoutDeviceJids.length; index += 1) {
202
557
  uniqueNormalizedFanoutJids.add(normalizeDeviceJid(fanoutDeviceJids[index]));
203
558
  }
204
- if (resolvedFanoutTargets.length !== uniqueNormalizedFanoutJids.size) {
205
- throw new Error('group direct send resolved incomplete signal sessions');
559
+ const droppedDevices = [];
560
+ for (const expected of uniqueNormalizedFanoutJids) {
561
+ if (!resolvedNormalizedJids.has(expected)) {
562
+ droppedDevices.push(expected);
563
+ }
564
+ }
565
+ if (droppedDevices.length > 0) {
566
+ this.deps.logger.warn('group direct fanout dropping devices without signal session', {
567
+ groupJid,
568
+ droppedCount: droppedDevices.length,
569
+ totalExpected: uniqueNormalizedFanoutJids.size,
570
+ sample: droppedDevices.slice(0, 3)
571
+ });
572
+ }
573
+ if (resolvedFanoutTargets.length === 0) {
574
+ throw new Error('group direct send resolved no signal sessions');
206
575
  }
207
576
  const participantEncryptRequests = new Array(resolvedFanoutTargets.length);
208
577
  for (let index = 0; index < resolvedFanoutTargets.length; index += 1) {
@@ -212,7 +581,7 @@ export class WaMessageDispatchCoordinator {
212
581
  plaintext
213
582
  };
214
583
  }
215
- const encryptedParticipants = await this.signalProtocol.encryptMessagesBatch(participantEncryptRequests, resolvedFanoutTargets);
584
+ const encryptedParticipants = await this.deps.signalProtocol.encryptMessagesBatch(participantEncryptRequests, resolvedFanoutTargets);
216
585
  const participants = new Array(resolvedFanoutTargets.length);
217
586
  for (let index = 0; index < resolvedFanoutTargets.length; index += 1) {
218
587
  const target = resolvedFanoutTargets[index];
@@ -230,20 +599,27 @@ export class WaMessageDispatchCoordinator {
230
599
  }
231
600
  }
232
601
  const phashTargets = new Array(resolvedFanoutTargets.length + 1);
602
+ let phashTargetCount = 0;
233
603
  for (let index = 0; index < resolvedFanoutTargets.length; index += 1) {
234
- phashTargets[index] = resolvedFanoutTargets[index].jid;
235
- }
236
- phashTargets[resolvedFanoutTargets.length] = senderForPhash;
237
- const [localPhash, reportingArtifacts] = await Promise.all([
238
- computePhashV2(phashTargets),
239
- this.tryBuildReportingTokenArtifacts({
240
- message,
241
- stanzaId: sendOptions.id,
242
- senderUserJid: toUserJid(senderForPhash),
243
- remoteJid: groupJid,
244
- context: 'group_direct'
245
- })
246
- ]);
604
+ const candidate = resolvedFanoutTargets[index].jid;
605
+ if (isHostedDeviceJid(candidate))
606
+ continue;
607
+ phashTargets[phashTargetCount] = candidate;
608
+ phashTargetCount += 1;
609
+ }
610
+ phashTargets[phashTargetCount] = senderForPhash;
611
+ phashTargets.length = phashTargetCount + 1;
612
+ const localPhash = computePhashV2(phashTargets);
613
+ const reportingArtifacts = await this.tryBuildReportingTokenArtifacts({
614
+ message,
615
+ stanzaId: sendOptions.id,
616
+ senderUserJid: toUserJid(senderForPhash),
617
+ remoteJid: groupJid,
618
+ context: 'group_direct'
619
+ });
620
+ const customNodes = envelope.customNodes ? [...envelope.customNodes] : [];
621
+ if (reportingArtifacts?.node)
622
+ customNodes.push(reportingArtifacts.node);
247
623
  const messageNode = buildDirectMessageFanoutNode({
248
624
  to: groupJid,
249
625
  type,
@@ -255,9 +631,10 @@ export class WaMessageDispatchCoordinator {
255
631
  deviceIdentity: shouldAttachDeviceIdentity
256
632
  ? this.getEncodedSignedDeviceIdentity()
257
633
  : undefined,
258
- reportingNode: reportingArtifacts?.node ?? undefined,
259
- metaNode,
260
- mediatype
634
+ customNodes: customNodes.length > 0 ? customNodes : undefined,
635
+ mediatype,
636
+ decryptFail: envelope.decryptFail,
637
+ additionalAttributes: sendOptions.additionalAttributes
261
638
  });
262
639
  const replayPayload = {
263
640
  mode: 'plaintext',
@@ -265,13 +642,12 @@ export class WaMessageDispatchCoordinator {
265
642
  type,
266
643
  plaintext
267
644
  };
268
- const result = await this.retryTracker.track({
269
- messageIdHint: sendOptions.id ?? messageNode.attrs.id,
645
+ const result = await this.deps.retryTracker.track({
646
+ messageIdHint: messageNode.attrs.id ?? sendOptions.id,
270
647
  toJid: groupJid,
271
- type,
272
648
  replayPayload,
273
649
  eligibleRequesterDeviceJids: undefined
274
- }, async () => this.messageClient.publishNode(messageNode, sendOptions));
650
+ }, async () => this.deps.messageClient.publishNode(messageNode, sendOptions));
275
651
  const ackError = result.ack.error;
276
652
  const serverPhash = result.ack.phash;
277
653
  const serverAddressingMode = result.ack.addressingMode;
@@ -280,7 +656,7 @@ export class WaMessageDispatchCoordinator {
280
656
  const hasAddressingError = ackError === 421;
281
657
  if (!retryContext.retried &&
282
658
  (hasPhashMismatch || hasAddressingMismatch || hasAddressingError)) {
283
- this.logger.warn('group direct publish acknowledged with mismatch metadata', {
659
+ this.deps.logger.warn('group direct publish acknowledged with mismatch metadata', {
284
660
  id: result.id,
285
661
  groupJid,
286
662
  localPhash,
@@ -289,28 +665,88 @@ export class WaMessageDispatchCoordinator {
289
665
  serverAddressingMode,
290
666
  ackError
291
667
  });
292
- return this.publishGroupDirectMessage(groupJid, message, plaintext, type, {
293
- ...sendOptions,
294
- id: result.id
668
+ return this.publishGroupDirectMessage(groupJid, {
669
+ ...envelope,
670
+ sendOptions: { ...sendOptions, id: result.id }
295
671
  }, {
296
672
  retried: true,
297
673
  forceRefreshParticipants: true,
298
674
  forceAddressingMode: serverAddressingMode
299
- }, edit, mediatype, metaNode);
675
+ });
300
676
  }
301
677
  return result;
302
678
  }
303
- async publishGroupSenderKeyMessage(groupJid, message, plaintext, type, options, retryContext = {}, edit, mediatype, metaNode) {
304
- const sendOptions = await this.withResolvedMessageId(options);
679
+ // Returns null on any failure so the group send still goes out unchanged.
680
+ async buildBotSidecarParticipant(message) {
681
+ const botJid = extractInvokedBotJid(message);
682
+ if (!botJid)
683
+ return null;
684
+ let address;
685
+ try {
686
+ address = parseSignalAddressFromJid(botJid);
687
+ }
688
+ catch (error) {
689
+ this.deps.logger.debug('bot sidecar: failed to parse bot jid', {
690
+ botJid,
691
+ message: toError(error).message
692
+ });
693
+ return null;
694
+ }
695
+ let resolvedTargets;
696
+ try {
697
+ resolvedTargets = await this.deps.sessionResolver.ensureSessionsBatch([botJid]);
698
+ }
699
+ catch (error) {
700
+ this.deps.logger.debug('bot sidecar: signal session sync failed', {
701
+ botJid,
702
+ message: toError(error).message
703
+ });
704
+ return null;
705
+ }
706
+ if (resolvedTargets.length === 0) {
707
+ this.deps.logger.debug('bot sidecar: signal session not established', { botJid });
708
+ return null;
709
+ }
710
+ // The bot seeds its streaming-response keys from this HKDF derivation.
711
+ const parentMessageSecret = message.messageContextInfo?.messageSecret;
712
+ const botMessageSecret = parentMessageSecret && parentMessageSecret.byteLength > 0
713
+ ? genBotMsgSecret(parentMessageSecret)
714
+ : undefined;
715
+ const botCopy = buildBotInvokeProtoCopy(message, botMessageSecret);
716
+ const botPlaintext = await writeRandomPadMax16(proto.Message.encode(botCopy).finish());
717
+ try {
718
+ const [encrypted] = await this.deps.signalProtocol.encryptMessagesBatch([{ address, plaintext: botPlaintext }], resolvedTargets.map((target) => ({
719
+ address: target.address,
720
+ session: target.session
721
+ })));
722
+ if (!encrypted)
723
+ return null;
724
+ this.deps.logger.trace('bot sidecar encrypted', { botJid, encType: encrypted.type });
725
+ return {
726
+ jid: botJid,
727
+ encType: encrypted.type,
728
+ ciphertext: encrypted.ciphertext
729
+ };
730
+ }
731
+ catch (error) {
732
+ this.deps.logger.debug('bot sidecar: encryption failed', {
733
+ botJid,
734
+ message: toError(error).message
735
+ });
736
+ return null;
737
+ }
738
+ }
739
+ async publishGroupSenderKeyMessage(groupJid, envelope, retryContext = {}) {
740
+ const { message, plaintext, type, edit, mediatype, sendOptions } = envelope;
305
741
  const meJid = this.requireCurrentMeJid('sendMessage');
306
742
  const participantUserJids = retryContext.forceRefreshParticipants
307
- ? await this.participantsCache.refreshParticipantUsers(groupJid)
308
- : await this.participantsCache.resolveParticipantUsers(groupJid);
743
+ ? await this.deps.groupMetadataCache.refreshParticipantUsers(groupJid)
744
+ : await this.deps.groupMetadataCache.resolveParticipantUsers(groupJid);
309
745
  const addressingMode = retryContext.forceAddressingMode ??
310
746
  this.resolveGroupAddressingMode(participantUserJids, groupJid);
311
747
  const senderJid = this.resolveSenderForAddressingMode(addressingMode, meJid);
312
748
  const sender = parseSignalAddressFromJid(senderJid);
313
- const { distributionMessage: senderKeyDistributionMessage, ciphertext: groupCiphertext, keyId: senderKeyId } = await this.senderKeyManager.prepareGroupEncryption(groupJid, sender, plaintext);
749
+ const { distributionMessage: senderKeyDistributionMessage, ciphertext: groupCiphertext, keyId: senderKeyId } = await this.deps.senderKeyManager.prepareGroupEncryption(groupJid, sender, plaintext);
314
750
  const distributionData = await this.distributionDedup.run(`dist:${groupJid}:${senderKeyId}`, () => this.encryptGroupDistributionParticipants(groupJid, senderKeyId, senderKeyDistributionMessage, participantUserJids));
315
751
  const { fanoutDeviceJids, distributionParticipants } = distributionData;
316
752
  let shouldAttachDeviceIdentity = false;
@@ -321,20 +757,28 @@ export class WaMessageDispatchCoordinator {
321
757
  }
322
758
  }
323
759
  const phashTargets = new Array(fanoutDeviceJids.length + 1);
760
+ let phashTargetCount = 0;
324
761
  for (let index = 0; index < fanoutDeviceJids.length; index += 1) {
325
- phashTargets[index] = fanoutDeviceJids[index];
326
- }
327
- phashTargets[fanoutDeviceJids.length] = senderJid;
328
- const [localPhash, reportingArtifacts] = await Promise.all([
329
- computePhashV2(phashTargets),
330
- this.tryBuildReportingTokenArtifacts({
331
- message,
332
- stanzaId: sendOptions.id,
333
- senderUserJid: toUserJid(senderJid),
334
- remoteJid: groupJid,
335
- context: 'group_sender_key'
336
- })
337
- ]);
762
+ const candidate = fanoutDeviceJids[index];
763
+ if (isHostedDeviceJid(candidate))
764
+ continue;
765
+ phashTargets[phashTargetCount] = candidate;
766
+ phashTargetCount += 1;
767
+ }
768
+ phashTargets[phashTargetCount] = senderJid;
769
+ phashTargets.length = phashTargetCount + 1;
770
+ const localPhash = computePhashV2(phashTargets);
771
+ const reportingArtifacts = await this.tryBuildReportingTokenArtifacts({
772
+ message,
773
+ stanzaId: sendOptions.id,
774
+ senderUserJid: toUserJid(senderJid),
775
+ remoteJid: groupJid,
776
+ context: 'group_sender_key'
777
+ });
778
+ const botSidecar = await this.buildBotSidecarParticipant(message);
779
+ const customNodes = envelope.customNodes ? [...envelope.customNodes] : [];
780
+ if (reportingArtifacts?.node)
781
+ customNodes.push(reportingArtifacts.node);
338
782
  const messageNode = buildGroupSenderKeyMessageNode({
339
783
  to: groupJid,
340
784
  type,
@@ -344,12 +788,14 @@ export class WaMessageDispatchCoordinator {
344
788
  addressingMode,
345
789
  groupCiphertext: groupCiphertext.ciphertext,
346
790
  participants: distributionParticipants,
347
- deviceIdentity: shouldAttachDeviceIdentity
791
+ deviceIdentity: shouldAttachDeviceIdentity || botSidecar?.encType === 'pkmsg'
348
792
  ? this.getEncodedSignedDeviceIdentity()
349
793
  : undefined,
350
- reportingNode: reportingArtifacts?.node ?? undefined,
351
- metaNode,
352
- mediatype
794
+ customNodes: customNodes.length > 0 ? customNodes : undefined,
795
+ mediatype,
796
+ decryptFail: envelope.decryptFail,
797
+ botParticipants: botSidecar ? [botSidecar] : undefined,
798
+ additionalAttributes: sendOptions.additionalAttributes
353
799
  });
354
800
  const replayPayload = {
355
801
  mode: 'plaintext',
@@ -357,22 +803,21 @@ export class WaMessageDispatchCoordinator {
357
803
  type,
358
804
  plaintext
359
805
  };
360
- const result = await this.retryTracker.track({
361
- messageIdHint: sendOptions.id ?? messageNode.attrs.id,
806
+ const result = await this.deps.retryTracker.track({
807
+ messageIdHint: messageNode.attrs.id ?? sendOptions.id,
362
808
  toJid: groupJid,
363
- type,
364
809
  replayPayload,
365
810
  eligibleRequesterDeviceJids: undefined
366
- }, async () => this.messageClient.publishNode(messageNode, sendOptions));
811
+ }, async () => this.deps.messageClient.publishNode(messageNode, sendOptions));
367
812
  const distributedAddresses = new Array(distributionParticipants.length);
368
813
  for (let index = 0; index < distributionParticipants.length; index += 1) {
369
814
  distributedAddresses[index] = distributionParticipants[index].address;
370
815
  }
371
816
  try {
372
- await this.senderKeyManager.markSenderKeyDistributed(groupJid, senderKeyId, distributedAddresses);
817
+ await this.deps.senderKeyManager.markSenderKeyDistributed(groupJid, senderKeyId, distributedAddresses);
373
818
  }
374
819
  catch (error) {
375
- this.logger.warn('failed to mark sender key distribution targets', {
820
+ this.deps.logger.warn('failed to mark sender key distribution targets', {
376
821
  groupJid,
377
822
  participants: distributedAddresses.length,
378
823
  message: toError(error).message
@@ -386,7 +831,7 @@ export class WaMessageDispatchCoordinator {
386
831
  const hasAddressingError = ackError === 421;
387
832
  if (!retryContext.retried &&
388
833
  (hasPhashMismatch || hasAddressingMismatch || hasAddressingError)) {
389
- this.logger.warn('group message publish acknowledged with mismatch metadata', {
834
+ this.deps.logger.warn('group message publish acknowledged with mismatch metadata', {
390
835
  id: result.id,
391
836
  groupJid,
392
837
  localPhash,
@@ -395,30 +840,24 @@ export class WaMessageDispatchCoordinator {
395
840
  serverAddressingMode,
396
841
  ackError
397
842
  });
398
- return this.publishGroupSenderKeyMessage(groupJid, message, plaintext, type, {
399
- ...sendOptions,
400
- id: result.id
843
+ return this.publishGroupSenderKeyMessage(groupJid, {
844
+ ...envelope,
845
+ sendOptions: { ...sendOptions, id: result.id }
401
846
  }, {
402
847
  retried: true,
403
848
  forceRefreshParticipants: true,
404
849
  forceAddressingMode: serverAddressingMode
405
- }, edit, mediatype, metaNode);
850
+ });
406
851
  }
407
852
  return result;
408
853
  }
409
854
  resolveGroupAddressingMode(participantUserJids, groupJid) {
410
855
  for (let index = 0; index < participantUserJids.length; index += 1) {
411
- const participantJid = participantUserJids[index];
412
- try {
413
- if (splitJid(participantJid).server === 'lid') {
414
- return 'lid';
415
- }
416
- }
417
- catch (error) {
418
- this.logger.trace('ignoring malformed participant jid in addressing mode resolution', { participantJid, message: toError(error).message });
856
+ if (isLidJid(participantUserJids[index])) {
857
+ return 'lid';
419
858
  }
420
859
  }
421
- this.logger.trace('group addressing mode resolved to pn (default)', {
860
+ this.deps.logger.trace('group addressing mode resolved to pn (default)', {
422
861
  groupJid,
423
862
  participants: participantUserJids.length
424
863
  });
@@ -426,13 +865,13 @@ export class WaMessageDispatchCoordinator {
426
865
  }
427
866
  resolveSenderForAddressingMode(addressingMode, meJid) {
428
867
  if (addressingMode === 'lid') {
429
- const meLid = this.getCurrentMeLid();
868
+ const meLid = this.deps.getCurrentCredentials()?.meLid;
430
869
  if (meLid && meLid.includes('@')) {
431
870
  try {
432
871
  return normalizeDeviceJid(meLid);
433
872
  }
434
873
  catch (error) {
435
- this.logger.trace('ignoring malformed me lid jid', {
874
+ this.deps.logger.trace('ignoring malformed me lid jid', {
436
875
  meLid,
437
876
  message: toError(error).message
438
877
  });
@@ -445,7 +884,7 @@ export class WaMessageDispatchCoordinator {
445
884
  const distributionPayload = await writeRandomPadMax16(proto.Message.encode({
446
885
  senderKeyDistributionMessage
447
886
  }).finish());
448
- const fanoutDeviceJids = await this.fanoutResolver.resolveGroupParticipantDeviceJids(participantUserJids);
887
+ const fanoutDeviceJids = await this.deps.fanoutResolver.resolveGroupParticipantDeviceJids(participantUserJids);
449
888
  if (fanoutDeviceJids.length === 0) {
450
889
  return {
451
890
  fanoutDeviceJids,
@@ -460,7 +899,7 @@ export class WaMessageDispatchCoordinator {
460
899
  fanoutAddresses[index] = address;
461
900
  fanoutTargetsByAddressKey.set(signalAddressKey(address), { jid, address });
462
901
  }
463
- const pendingAddresses = await this.senderKeyManager.filterParticipantsNeedingDistribution(groupJid, senderKeyId, fanoutAddresses);
902
+ const pendingAddresses = await this.deps.senderKeyManager.filterParticipantsNeedingDistribution(groupJid, senderKeyId, fanoutAddresses);
464
903
  if (pendingAddresses.length === 0) {
465
904
  return {
466
905
  fanoutDeviceJids,
@@ -493,7 +932,7 @@ export class WaMessageDispatchCoordinator {
493
932
  let availableTargets = [];
494
933
  let prefetchedAvailableTargets;
495
934
  try {
496
- const resolvedTargets = await this.sessionResolver.ensureSessionsBatch(pendingTargetJids);
935
+ const resolvedTargets = await this.deps.sessionResolver.ensureSessionsBatch(pendingTargetJids);
497
936
  availableTargets = resolvedTargets;
498
937
  prefetchedAvailableTargets = resolvedTargets;
499
938
  }
@@ -502,7 +941,7 @@ export class WaMessageDispatchCoordinator {
502
941
  if (normalized.message === 'identity mismatch') {
503
942
  throw normalized;
504
943
  }
505
- this.logger.warn('group sender-key distribution session sync failed, continuing with available sessions', {
944
+ this.deps.logger.warn('group sender-key distribution session sync failed, continuing with available sessions', {
506
945
  groupJid,
507
946
  requested: pendingTargetJids.length,
508
947
  message: normalized.message
@@ -511,7 +950,7 @@ export class WaMessageDispatchCoordinator {
511
950
  for (let index = 0; index < pendingTargets.length; index += 1) {
512
951
  pendingTargetAddresses[index] = pendingTargets[index].address;
513
952
  }
514
- const hasPendingSessions = await this.signalStore.hasSessions(pendingTargetAddresses);
953
+ const hasPendingSessions = await this.deps.sessionStore.hasSessions(pendingTargetAddresses);
515
954
  const nextAvailableTargets = [];
516
955
  for (let index = 0; index < pendingTargets.length; index += 1) {
517
956
  if (hasPendingSessions[index]) {
@@ -534,7 +973,7 @@ export class WaMessageDispatchCoordinator {
534
973
  plaintext: distributionPayload
535
974
  };
536
975
  }
537
- const encryptedDistributionParticipants = await this.signalProtocol.encryptMessagesBatch(distributionEncryptRequests, prefetchedAvailableTargets);
976
+ const encryptedDistributionParticipants = await this.deps.signalProtocol.encryptMessagesBatch(distributionEncryptRequests, prefetchedAvailableTargets);
538
977
  const distributionParticipants = new Array(availableTargets.length);
539
978
  for (let index = 0; index < availableTargets.length; index += 1) {
540
979
  const target = availableTargets[index];
@@ -550,12 +989,12 @@ export class WaMessageDispatchCoordinator {
550
989
  distributionParticipants
551
990
  };
552
991
  }
553
- async publishDirectSignalMessageWithFanout(recipientJid, message, plaintext, type, options, edit, mediatype, metaNode) {
554
- const sendOptions = await this.withResolvedMessageId(options);
992
+ async publishDirectSignalMessageWithFanout(recipientJid, envelope) {
993
+ const { message, plaintext, type, edit, mediatype, sendOptions } = envelope;
555
994
  const meJid = this.requireCurrentMeJid('sendMessage');
556
- const meLid = this.getCurrentMeLid();
557
- const selfDeviceJidForRecipient = this.fanoutResolver.resolveSelfDeviceJidForRecipient(recipientJid, meJid, meLid);
558
- const deviceJids = await this.fanoutResolver.resolveDirectFanoutDeviceJids(recipientJid, selfDeviceJidForRecipient);
995
+ const meLid = this.deps.getCurrentCredentials()?.meLid;
996
+ const selfDeviceJidForRecipient = this.deps.fanoutResolver.resolveSelfDeviceJidForRecipient(recipientJid, meJid, meLid);
997
+ const deviceJids = await this.deps.fanoutResolver.resolveDirectFanoutDeviceJids(recipientJid, selfDeviceJidForRecipient);
559
998
  const targets = new Array(deviceJids.length);
560
999
  for (let index = 0; index < deviceJids.length; index += 1) {
561
1000
  const jid = deviceJids[index];
@@ -568,7 +1007,7 @@ export class WaMessageDispatchCoordinator {
568
1007
  }
569
1008
  const recipientUserJid = toUserJid(recipientJid);
570
1009
  const meUserJid = toUserJid(selfDeviceJidForRecipient);
571
- this.logger.debug('wa client publish signal fanout', {
1010
+ this.deps.logger.trace('wa client publish signal fanout', {
572
1011
  to: recipientJid,
573
1012
  devices: deviceJids.length,
574
1013
  type
@@ -582,20 +1021,42 @@ export class WaMessageDispatchCoordinator {
582
1021
  }
583
1022
  }
584
1023
  }
585
- const resolvedFanoutTargets = await this.sessionResolver.ensureSessionsBatch(deviceJids, expectedIdentityByJid);
1024
+ const resolvedFanoutTargets = await this.deps.sessionResolver.ensureSessionsBatch(deviceJids, expectedIdentityByJid);
586
1025
  const resolvedFanoutTargetsByJid = new Map();
587
1026
  for (let index = 0; index < resolvedFanoutTargets.length; index += 1) {
588
1027
  const target = resolvedFanoutTargets[index];
589
1028
  resolvedFanoutTargetsByJid.set(normalizeDeviceJid(target.jid), target);
590
1029
  }
1030
+ const liveTargets = [];
1031
+ const droppedSecondaryDevices = [];
591
1032
  for (let index = 0; index < targets.length; index += 1) {
592
- if (!resolvedFanoutTargetsByJid.has(targets[index].normalizedJid)) {
593
- throw new Error('direct fanout missing signal sessions for one or more targets');
1033
+ const target = targets[index];
1034
+ if (resolvedFanoutTargetsByJid.has(target.normalizedJid)) {
1035
+ liveTargets.push(target);
1036
+ continue;
594
1037
  }
1038
+ const isPrimaryRecipient = target.userJid === recipientUserJid && target.normalizedJid === target.userJid;
1039
+ if (isPrimaryRecipient) {
1040
+ this.deps.logger.error('direct fanout dropping primary recipient device without signal session', { to: recipientJid, device: target.jid });
1041
+ }
1042
+ else {
1043
+ droppedSecondaryDevices.push(target.jid);
1044
+ }
1045
+ }
1046
+ if (droppedSecondaryDevices.length > 0) {
1047
+ this.deps.logger.warn('direct fanout dropping secondary devices without signal session', {
1048
+ to: recipientJid,
1049
+ droppedCount: droppedSecondaryDevices.length,
1050
+ totalExpected: targets.length,
1051
+ sample: droppedSecondaryDevices.slice(0, 3)
1052
+ });
1053
+ }
1054
+ if (liveTargets.length === 0) {
1055
+ throw new Error('direct fanout missing signal sessions for all targets');
595
1056
  }
596
1057
  let hasSelfDeviceFanout = false;
597
- for (let index = 0; index < targets.length; index += 1) {
598
- if (targets[index].userJid === meUserJid) {
1058
+ for (let index = 0; index < liveTargets.length; index += 1) {
1059
+ if (liveTargets[index].userJid === meUserJid) {
599
1060
  hasSelfDeviceFanout = true;
600
1061
  break;
601
1062
  }
@@ -603,13 +1064,10 @@ export class WaMessageDispatchCoordinator {
603
1064
  const selfDevicePlaintext = hasSelfDeviceFanout
604
1065
  ? await writeRandomPadMax16(proto.Message.encode(wrapDeviceSentMessage(message, recipientUserJid)).finish())
605
1066
  : null;
606
- const participantRequests = new Array(targets.length);
607
- for (let index = 0; index < targets.length; index += 1) {
608
- const target = targets[index];
1067
+ const participantRequests = new Array(liveTargets.length);
1068
+ for (let index = 0; index < liveTargets.length; index += 1) {
1069
+ const target = liveTargets[index];
609
1070
  const resolvedTarget = resolvedFanoutTargetsByJid.get(target.normalizedJid);
610
- if (!resolvedTarget) {
611
- throw new Error('direct fanout missing signal session for target');
612
- }
613
1071
  participantRequests[index] = {
614
1072
  target,
615
1073
  address: resolvedTarget.address,
@@ -634,15 +1092,20 @@ export class WaMessageDispatchCoordinator {
634
1092
  session: request.session
635
1093
  };
636
1094
  }
637
- const encryptedParticipants = await this.signalProtocol.encryptMessagesBatch(encryptRequests, prefetchedSessions);
638
- const participants = new Array(participantRequests.length);
1095
+ const encryptedParticipants = await this.deps.signalProtocol.encryptMessagesBatch(encryptRequests, prefetchedSessions);
1096
+ const isBotRecipient = isBotJid(recipientJid);
1097
+ const participants = [];
639
1098
  for (let index = 0; index < participantRequests.length; index += 1) {
640
1099
  const request = participantRequests[index];
641
- participants[index] = {
1100
+ const entry = {
642
1101
  jid: request.target.jid,
643
1102
  encType: encryptedParticipants[index].type,
644
1103
  ciphertext: encryptedParticipants[index].ciphertext
645
1104
  };
1105
+ // wa-web direct 1:1 to bot puts the bot device alongside self devices
1106
+ // inside `<participants>`; the `<bot>` envelope is only used for group
1107
+ // mentions (the sidecar copy) or for bot feedback / revoke flows.
1108
+ participants.push(entry);
646
1109
  }
647
1110
  let shouldAttachDeviceIdentity = false;
648
1111
  for (let index = 0; index < participants.length; index += 1) {
@@ -662,16 +1125,23 @@ export class WaMessageDispatchCoordinator {
662
1125
  context: 'direct_fanout'
663
1126
  });
664
1127
  let privacyTokenNode;
665
- try {
666
- privacyTokenNode =
667
- (await this.privacyTokenDedup.run(`pt:${recipientUserJid}`, () => this.resolvePrivacyTokenNode(recipientUserJid))) ?? undefined;
668
- }
669
- catch (error) {
670
- this.logger.warn('privacy token resolution failed', {
671
- to: recipientUserJid,
672
- message: toError(error).message
673
- });
1128
+ if (!isBotRecipient) {
1129
+ try {
1130
+ privacyTokenNode =
1131
+ (await this.privacyTokenDedup.run(`pt:${recipientUserJid}`, () => this.deps.resolvePrivacyTokenNode(recipientUserJid))) ?? undefined;
1132
+ }
1133
+ catch (error) {
1134
+ this.deps.logger.warn('privacy token resolution failed', {
1135
+ to: recipientUserJid,
1136
+ message: toError(error).message
1137
+ });
1138
+ }
674
1139
  }
1140
+ const customNodes = envelope.customNodes ? [...envelope.customNodes] : [];
1141
+ if (reportingArtifacts?.node)
1142
+ customNodes.push(reportingArtifacts.node);
1143
+ if (privacyTokenNode)
1144
+ customNodes.push(privacyTokenNode);
675
1145
  const messageNode = buildDirectMessageFanoutNode({
676
1146
  to: recipientJid,
677
1147
  type,
@@ -679,10 +1149,10 @@ export class WaMessageDispatchCoordinator {
679
1149
  edit,
680
1150
  participants,
681
1151
  deviceIdentity,
682
- reportingNode: reportingArtifacts?.node ?? undefined,
683
- privacyTokenNode,
684
- metaNode,
685
- mediatype
1152
+ customNodes: customNodes.length > 0 ? customNodes : undefined,
1153
+ mediatype,
1154
+ decryptFail: envelope.decryptFail,
1155
+ additionalAttributes: sendOptions.additionalAttributes
686
1156
  });
687
1157
  const replayPayload = {
688
1158
  mode: 'plaintext',
@@ -690,14 +1160,13 @@ export class WaMessageDispatchCoordinator {
690
1160
  type,
691
1161
  plaintext
692
1162
  };
693
- const result = await this.retryTracker.track({
694
- messageIdHint: sendOptions.id ?? messageNode.attrs.id,
1163
+ const result = await this.deps.retryTracker.track({
1164
+ messageIdHint: messageNode.attrs.id ?? sendOptions.id,
695
1165
  toJid: recipientJid,
696
- type,
697
1166
  replayPayload,
698
1167
  eligibleRequesterDeviceJids: deviceJids
699
- }, async () => this.messageClient.publishNode(messageNode, sendOptions));
700
- this.onDirectMessageSent(recipientUserJid);
1168
+ }, async () => this.deps.messageClient.publishNode(messageNode, sendOptions));
1169
+ this.deps.onDirectMessageSent(recipientUserJid);
701
1170
  return result;
702
1171
  }
703
1172
  async withResolvedMessageId(options) {
@@ -719,21 +1188,35 @@ export class WaMessageDispatchCoordinator {
719
1188
  async generateOutgoingMessageId() {
720
1189
  try {
721
1190
  const meUserJid = toUserJid(this.requireCurrentMeJid('sendMessage'));
722
- const timestampSeconds = Math.floor(Date.now() / 1000);
723
1191
  const timestampBytes = new Uint8Array(8);
724
- new DataView(timestampBytes.buffer, timestampBytes.byteOffset, timestampBytes.byteLength).setBigUint64(0, BigInt(timestampSeconds), false);
725
- const entropy = concatBytes([
1192
+ const dv = new DataView(timestampBytes.buffer, timestampBytes.byteOffset, timestampBytes.byteLength);
1193
+ if (this.mobileMessageIdFormat) {
1194
+ dv.setBigUint64(0, BigInt(Date.now()), false);
1195
+ const digest = md5Bytes([
1196
+ timestampBytes,
1197
+ TEXT_ENCODER.encode(meUserJid),
1198
+ await randomBytesAsync(16)
1199
+ ]);
1200
+ digest[0] = 0xac;
1201
+ return bytesToHex(digest).toUpperCase();
1202
+ }
1203
+ dv.setBigUint64(0, BigInt(Math.floor(Date.now() / 1000)), false);
1204
+ const digest = sha256([
726
1205
  timestampBytes,
727
1206
  TEXT_ENCODER.encode(meUserJid),
728
1207
  await randomBytesAsync(8)
729
1208
  ]);
730
- const digest = await sha256(entropy);
731
1209
  return `3EB0${bytesToHex(digest.subarray(0, 9)).toUpperCase()}`;
732
1210
  }
733
1211
  catch (error) {
734
- this.logger.warn('failed to generate sha256 message id, falling back to random id', {
1212
+ this.deps.logger.warn('failed to generate message id, falling back to random', {
735
1213
  message: toError(error).message
736
1214
  });
1215
+ if (this.mobileMessageIdFormat) {
1216
+ const bytes = await randomBytesAsync(16);
1217
+ bytes[0] = 0xac;
1218
+ return bytesToHex(bytes).toUpperCase();
1219
+ }
737
1220
  return `3EB0${bytesToHex(await randomBytesAsync(8)).toUpperCase()}`;
738
1221
  }
739
1222
  }
@@ -750,7 +1233,7 @@ export class WaMessageDispatchCoordinator {
750
1233
  });
751
1234
  }
752
1235
  catch (error) {
753
- this.logger.warn('failed to generate reporting token', {
1236
+ this.deps.logger.warn('failed to generate reporting token', {
754
1237
  context: input.context,
755
1238
  id: input.stanzaId,
756
1239
  remoteJid: input.remoteJid,
@@ -760,24 +1243,24 @@ export class WaMessageDispatchCoordinator {
760
1243
  }
761
1244
  }
762
1245
  getEncodedSignedDeviceIdentity() {
763
- const signedIdentity = this.getCurrentSignedIdentity();
1246
+ const signedIdentity = this.deps.getCurrentCredentials()?.signedIdentity;
764
1247
  if (!signedIdentity) {
765
- throw new Error('missing signed identity for pkmsg fanout');
1248
+ return undefined;
766
1249
  }
767
1250
  return proto.ADVSignedDeviceIdentity.encode(signedIdentity).finish();
768
1251
  }
769
1252
  resolveUserIcdc(userJid, localIdentity) {
770
1253
  return this.icdcDedup.run(`icdc:${userJid}:${localIdentity ? '1' : '0'}`, async () => {
771
1254
  try {
772
- const snapshots = await this.deviceListStore.getUserDevicesBatch([userJid]);
1255
+ const snapshots = await this.deps.deviceListStore.getUserDevicesBatch([userJid]);
773
1256
  const snapshot = snapshots[0];
774
1257
  if (!snapshot || snapshot.deviceJids.length === 0) {
775
1258
  return null;
776
1259
  }
777
- return resolveIcdcMeta(snapshot.deviceJids, this.signalStore, snapshot.updatedAtMs, localIdentity);
1260
+ return resolveIcdcMeta(snapshot.deviceJids, this.deps.identityStore, snapshot.updatedAtMs, localIdentity, this.deps.getIcdcHashLength?.());
778
1261
  }
779
1262
  catch (error) {
780
- this.logger.trace('icdc resolution failed', {
1263
+ this.deps.logger.trace('icdc resolution failed', {
781
1264
  userJid,
782
1265
  message: toError(error).message
783
1266
  });
@@ -786,10 +1269,35 @@ export class WaMessageDispatchCoordinator {
786
1269
  });
787
1270
  }
788
1271
  requireCurrentMeJid(context) {
789
- const meJid = this.getCurrentMeJid();
1272
+ const meJid = this.deps.getCurrentCredentials()?.meJid;
790
1273
  if (meJid) {
791
1274
  return meJid;
792
1275
  }
793
1276
  throw new Error(`${context} requires registered meJid`);
794
1277
  }
795
1278
  }
1279
+ function pickContentContextInfo(content) {
1280
+ if (typeof content !== 'object' || content === null)
1281
+ return undefined;
1282
+ if (isSendTextMessage(content) || isSendMediaMessage(content)) {
1283
+ return content.contextInfo;
1284
+ }
1285
+ return undefined;
1286
+ }
1287
+ function assertNewsletterContextInfoCompatible(ctx) {
1288
+ if (!ctx)
1289
+ return;
1290
+ const unsupported = [];
1291
+ if (ctx.quotedMessageId !== undefined)
1292
+ unsupported.push('quote');
1293
+ if (ctx.mentionedJids?.length)
1294
+ unsupported.push('mentions');
1295
+ if (ctx.isSpoiler === true)
1296
+ unsupported.push('isSpoiler');
1297
+ if (ctx.groupSubject !== undefined || ctx.parentGroupJid !== undefined) {
1298
+ unsupported.push('group invite reply (groupSubject/parentGroupJid)');
1299
+ }
1300
+ if (unsupported.length > 0) {
1301
+ throw new Error(`newsletter sends do not support: ${unsupported.join(', ')}`);
1302
+ }
1303
+ }