zapo-js 0.3.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.
- package/LICENSE +21 -0
- package/README.md +97 -177
- package/dist/appstate/{WaAppStateCrypto.js → crypto/WaAppStateCrypto.js} +58 -49
- package/dist/appstate/index.js +7 -6
- package/dist/appstate/{encoding.js → parsers/encoding.js} +11 -4
- package/dist/appstate/{response-parser.js → parsers/response-parser.js} +20 -8
- package/dist/appstate/{WaAppStateSyncClient.js → sync/WaAppStateSyncClient.js} +174 -53
- package/dist/appstate/utils.js +16 -0
- package/dist/appstate-spec.js +89 -0
- package/dist/auth/WaAuthClient.js +100 -5
- package/dist/auth/credentials-flow.js +19 -7
- package/dist/auth/pairing/WaPairingFlow.js +33 -24
- package/dist/auth/pairing/pairing-code-crypto.js +16 -18
- package/dist/client/WaClient.js +342 -473
- package/dist/client/WaClientFactory.js +279 -78
- package/dist/client/connection/WaConnectionManager.js +28 -11
- package/dist/client/coordinators/WaAbPropsCoordinator.js +1 -2
- package/dist/client/coordinators/WaAppStateMutationCoordinator.js +663 -143
- package/dist/client/coordinators/WaBotCoordinator.js +345 -0
- package/dist/client/coordinators/WaBroadcastListCoordinator.js +20 -0
- package/dist/client/coordinators/WaBusinessCoordinator.js +81 -171
- package/dist/client/coordinators/WaEmailCoordinator.js +1 -0
- package/dist/client/coordinators/WaGroupCoordinator.js +529 -52
- package/dist/client/coordinators/WaIncomingNodeCoordinator.js +97 -12
- package/dist/client/coordinators/WaLowLevelCoordinator.js +41 -0
- package/dist/client/coordinators/WaMessageCoordinator.js +365 -0
- package/dist/client/coordinators/WaMessageDispatchCoordinator.js +682 -204
- package/dist/client/coordinators/WaNewsletterCoordinator.js +18 -0
- package/dist/client/coordinators/WaPassiveTasksCoordinator.js +17 -4
- package/dist/client/coordinators/WaPresenceCoordinator.js +21 -0
- package/dist/client/coordinators/WaPrivacyCoordinator.js +7 -5
- package/dist/client/coordinators/WaProfileCoordinator.js +220 -49
- package/dist/client/coordinators/WaRetryCoordinator.js +256 -125
- package/dist/client/coordinators/WaStatusCoordinator.js +49 -0
- package/dist/client/coordinators/WaStreamControlCoordinator.js +6 -6
- package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +7 -6
- package/dist/client/events/appstate-mutation.js +133 -0
- package/dist/client/events/business.js +375 -0
- package/dist/client/events/call.js +58 -0
- package/dist/client/events/chatstate.js +23 -0
- package/dist/client/events/devices.js +15 -16
- package/dist/client/{dirty.js → events/dirty.js} +33 -19
- package/dist/client/events/group.js +13 -24
- package/dist/client/events/identity.js +2 -1
- package/dist/client/events/incoming.js +502 -0
- package/dist/client/events/mex-notification.js +181 -0
- package/dist/client/events/picture.js +33 -0
- package/dist/client/events/presence.js +44 -0
- package/dist/client/events/receipt.js +26 -0
- package/dist/client/media.js +161 -4
- package/dist/client/messaging/fanout.js +9 -10
- package/dist/client/messaging/{participants.js → group-metadata.js} +73 -35
- package/dist/client/messaging/ignore-key.js +132 -0
- package/dist/client/messaging/key-protocol.js +3 -17
- package/dist/client/messaging/link-preview.js +159 -0
- package/dist/client/messaging/messages.js +671 -0
- package/dist/client/newsletter/admin.js +165 -0
- package/dist/client/newsletter/content.js +253 -0
- package/dist/client/newsletter/discovery.js +115 -0
- package/dist/client/newsletter/messaging.js +197 -0
- package/dist/client/newsletter/mex.js +41 -0
- package/dist/client/newsletter/parse.js +217 -0
- package/dist/client/persistence/WriteBehindPersistence.js +31 -4
- package/dist/client/{history-sync.js → persistence/history-sync.js} +125 -18
- package/dist/client/persistence/mailbox.js +104 -0
- package/dist/client/tokens/cs-token.js +11 -17
- package/dist/crypto/core/hkdf.js +12 -12
- package/dist/crypto/core/index.js +6 -8
- package/dist/crypto/core/keys.js +1 -8
- package/dist/crypto/core/nonce.js +12 -12
- package/dist/crypto/core/primitives.js +123 -93
- package/dist/crypto/core/random.js +6 -0
- package/dist/crypto/core/xeddsa.js +11 -9
- package/dist/crypto/curves/Ed25519.js +32 -21
- package/dist/crypto/curves/X25519.js +70 -34
- package/dist/crypto/curves/constants.js +2 -1
- package/dist/crypto/math/constants.js +1 -2
- package/dist/crypto/math/mod.js +0 -33
- package/dist/esm/appstate/{WaAppStateCrypto.js → crypto/WaAppStateCrypto.js} +58 -49
- package/dist/esm/appstate/index.js +5 -5
- package/dist/esm/appstate/{encoding.js → parsers/encoding.js} +11 -4
- package/dist/esm/appstate/{response-parser.js → parsers/response-parser.js} +20 -8
- package/dist/esm/appstate/{WaAppStateSyncClient.js → sync/WaAppStateSyncClient.js} +174 -52
- package/dist/esm/appstate/utils.js +16 -0
- package/dist/esm/appstate-spec.js +79 -0
- package/dist/esm/auth/WaAuthClient.js +100 -5
- package/dist/esm/auth/credentials-flow.js +18 -6
- package/dist/esm/auth/pairing/WaPairingFlow.js +34 -25
- package/dist/esm/auth/pairing/pairing-code-crypto.js +12 -14
- package/dist/esm/client/WaClient.js +345 -476
- package/dist/esm/client/WaClientFactory.js +280 -79
- package/dist/esm/client/connection/WaConnectionManager.js +28 -11
- package/dist/esm/client/coordinators/WaAbPropsCoordinator.js +2 -3
- package/dist/esm/client/coordinators/WaAppStateMutationCoordinator.js +665 -145
- package/dist/esm/client/coordinators/WaBotCoordinator.js +342 -0
- package/dist/esm/client/coordinators/WaBroadcastListCoordinator.js +17 -0
- package/dist/esm/client/coordinators/WaBusinessCoordinator.js +79 -169
- package/dist/esm/client/coordinators/WaEmailCoordinator.js +1 -0
- package/dist/esm/client/coordinators/WaGroupCoordinator.js +532 -55
- package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +98 -13
- package/dist/esm/client/coordinators/WaLowLevelCoordinator.js +38 -0
- package/dist/esm/client/coordinators/WaMessageCoordinator.js +361 -0
- package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +686 -208
- package/dist/esm/client/coordinators/WaNewsletterCoordinator.js +13 -0
- package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +18 -5
- package/dist/esm/client/coordinators/WaPresenceCoordinator.js +18 -0
- package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +7 -5
- package/dist/esm/client/coordinators/WaProfileCoordinator.js +223 -52
- package/dist/esm/client/coordinators/WaRetryCoordinator.js +258 -127
- package/dist/esm/client/coordinators/WaStatusCoordinator.js +46 -0
- package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +6 -6
- package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +7 -6
- package/dist/esm/client/events/appstate-mutation.js +130 -0
- package/dist/esm/client/events/business.js +370 -0
- package/dist/esm/client/events/call.js +55 -0
- package/dist/esm/client/events/chatstate.js +20 -0
- package/dist/esm/client/events/devices.js +15 -16
- package/dist/esm/client/{dirty.js → events/dirty.js} +33 -19
- package/dist/esm/client/events/group.js +14 -25
- package/dist/esm/client/events/identity.js +2 -1
- package/dist/esm/client/events/incoming.js +487 -0
- package/dist/esm/client/events/mex-notification.js +178 -0
- package/dist/esm/client/events/picture.js +30 -0
- package/dist/esm/client/events/presence.js +41 -0
- package/dist/esm/client/events/receipt.js +23 -0
- package/dist/esm/client/media.js +156 -6
- package/dist/esm/client/messaging/fanout.js +10 -11
- package/dist/esm/client/messaging/{participants.js → group-metadata.js} +72 -34
- package/dist/esm/client/messaging/ignore-key.js +126 -0
- package/dist/esm/client/messaging/key-protocol.js +3 -17
- package/dist/esm/client/messaging/link-preview.js +156 -0
- package/dist/esm/client/messaging/messages.js +667 -0
- package/dist/esm/client/newsletter/admin.js +162 -0
- package/dist/esm/client/newsletter/content.js +249 -0
- package/dist/esm/client/newsletter/discovery.js +112 -0
- package/dist/esm/client/newsletter/messaging.js +194 -0
- package/dist/esm/client/newsletter/mex.js +37 -0
- package/dist/esm/client/newsletter/parse.js +200 -0
- package/dist/esm/client/persistence/WriteBehindPersistence.js +31 -4
- package/dist/esm/client/{history-sync.js → persistence/history-sync.js} +124 -18
- package/dist/esm/client/persistence/mailbox.js +101 -0
- package/dist/esm/client/tokens/cs-token.js +12 -18
- package/dist/esm/crypto/core/hkdf.js +14 -14
- package/dist/esm/crypto/core/index.js +2 -2
- package/dist/esm/crypto/core/keys.js +1 -7
- package/dist/esm/crypto/core/nonce.js +11 -11
- package/dist/esm/crypto/core/primitives.js +121 -88
- package/dist/esm/crypto/core/random.js +6 -0
- package/dist/esm/crypto/core/xeddsa.js +11 -9
- package/dist/esm/crypto/curves/Ed25519.js +35 -24
- package/dist/esm/crypto/curves/X25519.js +72 -36
- package/dist/esm/crypto/curves/constants.js +1 -0
- package/dist/esm/crypto/math/constants.js +1 -2
- package/dist/esm/crypto/math/mod.js +0 -32
- package/dist/esm/index.js +7 -2
- package/dist/esm/infra/log/ConsoleLogger.js +30 -6
- package/dist/esm/infra/log/PinoLogger.js +64 -0
- package/dist/esm/infra/log/types.js +4 -2
- package/dist/esm/infra/perf/BackgroundQueue.js +55 -13
- package/dist/esm/media/constants.js +33 -2
- package/dist/esm/media/crypto/WaMediaCrypto.js +374 -0
- package/dist/esm/media/index.js +4 -3
- package/dist/esm/media/sticker/sticker-pack.js +133 -0
- package/dist/esm/media/{WaMediaTransferClient.js → transfer/WaMediaTransferClient.js} +37 -6
- package/dist/esm/media/{conn.js → transfer/conn.js} +10 -5
- package/dist/esm/message/WaMessageClient.js +46 -15
- package/dist/esm/message/addons/link-preview/builder.js +36 -0
- package/dist/esm/message/addons/link-preview/detect.js +55 -0
- package/dist/esm/message/addons/link-preview/fetcher.js +391 -0
- package/dist/esm/message/addons/link-preview/types.js +1 -0
- package/dist/esm/message/context-info.js +123 -0
- package/dist/esm/message/{addon-crypto.js → crypto/addon-crypto.js} +68 -10
- package/dist/esm/message/{icdc.js → crypto/icdc.js} +5 -7
- package/dist/esm/message/crypto/phash.js +133 -0
- package/dist/esm/message/{reporting-token.js → crypto/reporting-token.js} +6 -6
- package/dist/esm/message/{use-case-secret.js → crypto/use-case-secret.js} +20 -3
- package/dist/esm/message/{content.js → encode/content.js} +176 -7
- package/dist/esm/message/encode/media-payload.js +42 -0
- package/dist/esm/message/{padding.js → encode/padding.js} +9 -3
- package/dist/esm/message/index.js +2 -2
- package/dist/esm/message/kinds/bot.js +111 -0
- package/dist/esm/message/kinds/newsletter.js +244 -0
- package/dist/esm/message/kinds/sticker-pack.js +29 -0
- package/dist/esm/message/{ack.js → primitives/ack.js} +8 -1
- package/dist/esm/message/{incoming.js → primitives/incoming.js} +215 -31
- package/dist/esm/message/primitives/peer-data-operation.js +93 -0
- package/dist/esm/mex.js +1 -0
- package/dist/esm/protocol/abprops.js +10 -0
- package/dist/esm/protocol/appstate.js +6 -30
- package/dist/esm/protocol/auth.js +3 -2
- package/dist/esm/protocol/bot.js +77 -0
- package/dist/esm/protocol/browser.js +8 -0
- package/dist/esm/protocol/business.js +19 -0
- package/dist/esm/protocol/call.js +48 -0
- package/dist/esm/protocol/constants.js +8 -2
- package/dist/esm/protocol/defaults.js +3 -0
- package/dist/esm/protocol/index.js +1 -1
- package/dist/esm/protocol/jid.js +102 -5
- package/dist/esm/protocol/media.js +25 -12
- package/dist/esm/protocol/message.js +4 -1
- package/dist/esm/protocol/newsletter.js +61 -0
- package/dist/esm/protocol/nodes.js +22 -2
- package/dist/esm/protocol/notification.js +18 -2
- package/dist/esm/protocol/presence.js +13 -0
- package/dist/esm/protocol/status.js +6 -0
- package/dist/esm/retry/codec.js +5 -0
- package/dist/esm/retry/parse.js +20 -38
- package/dist/esm/retry/reason.js +5 -0
- package/dist/esm/retry/replay.js +131 -37
- package/dist/esm/retry/tracker.js +4 -8
- package/dist/esm/signal/api/SignalDeviceSyncApi.js +66 -19
- package/dist/esm/signal/api/SignalDigestSyncApi.js +7 -2
- package/dist/esm/signal/api/SignalIdentitySyncApi.js +9 -0
- package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +24 -63
- package/dist/esm/signal/api/SignalRotateKeyApi.js +10 -0
- package/dist/esm/signal/api/SignalSessionSyncApi.js +23 -51
- package/dist/esm/signal/api/codec.js +52 -1
- package/dist/esm/signal/api/prekeys.js +4 -0
- package/dist/esm/signal/{crypto → attestation}/WaAdvSignature.js +5 -6
- package/dist/esm/signal/constants.js +3 -0
- package/dist/esm/signal/encoding.js +6 -289
- package/dist/esm/signal/group/SenderKeyChain.js +18 -33
- package/dist/esm/signal/group/SenderKeyManager.js +25 -8
- package/dist/esm/signal/group/encoding.js +96 -0
- package/dist/esm/signal/index.js +4 -1
- package/dist/esm/signal/registration/encoding.js +34 -0
- package/dist/esm/signal/registration/keygen.js +10 -0
- package/dist/esm/signal/registration/utils.js +6 -0
- package/dist/esm/signal/session/SignalProtocol.js +113 -11
- package/dist/esm/signal/session/SignalRatchet.js +29 -58
- package/dist/esm/signal/session/SignalSession.js +7 -14
- package/dist/esm/signal/session/encoding.js +173 -0
- package/dist/esm/signal/session/resolver.js +139 -30
- package/dist/esm/store/cache/identity.cache.js +75 -0
- package/dist/esm/store/cache/privacy-token.cache.js +57 -0
- package/dist/esm/store/cache/sender-key.cache.js +101 -0
- package/dist/esm/store/cache/session.cache.js +92 -0
- package/dist/esm/store/contracts/group-metadata.store.js +1 -0
- package/dist/esm/store/createStore.js +91 -37
- package/dist/esm/store/index.js +15 -14
- package/dist/esm/store/locks/contact.lock.js +1 -0
- package/dist/esm/store/locks/device-list.lock.js +1 -0
- package/dist/esm/store/locks/group-metadata.lock.js +20 -0
- package/dist/esm/store/{providers/memory → memory}/appstate.store.js +5 -5
- package/dist/esm/store/memory/auth.store.js +24 -0
- package/dist/esm/store/memory/contact.store.js +79 -0
- package/dist/esm/store/memory/device-list.store.js +103 -0
- package/dist/esm/store/{providers/memory/participants.store.js → memory/group-metadata.store.js} +22 -13
- package/dist/esm/store/{providers/memory → memory}/identity.store.js +3 -3
- package/dist/esm/store/{providers/memory → memory}/message-secret.store.js +17 -8
- package/dist/esm/store/{providers/memory → memory}/message.store.js +2 -2
- package/dist/esm/store/{providers/memory → memory}/pre-key.store.js +2 -2
- package/dist/esm/store/{providers/memory → memory}/privacy-token.store.js +1 -1
- package/dist/esm/store/{providers/memory → memory}/retry.store.js +28 -7
- package/dist/esm/store/{providers/memory → memory}/sender-key.store.js +3 -3
- package/dist/esm/store/{providers/memory → memory}/session.store.js +3 -3
- package/dist/esm/store/{providers/memory → memory}/thread.store.js +2 -2
- package/dist/esm/store/noop.store.js +6 -4
- package/dist/esm/transport/WaComms.js +14 -5
- package/dist/esm/transport/WaWebSocket.js +32 -8
- package/dist/esm/transport/binary/constants.js +10 -4
- package/dist/esm/transport/binary/decoder.js +21 -15
- package/dist/esm/transport/binary/encoder.js +96 -21
- package/dist/esm/transport/binary/tokens.js +12 -12
- package/dist/esm/transport/index.js +1 -0
- package/dist/esm/transport/keepalive/WaKeepAlive.js +18 -4
- package/dist/esm/transport/node/WaMobileTcpSocket.js +6 -0
- package/dist/esm/transport/node/WaNodeOrchestrator.js +9 -5
- package/dist/esm/transport/node/WaNodeTransport.js +13 -0
- package/dist/esm/transport/node/builders/abprops.js +2 -2
- package/dist/esm/transport/node/builders/account-sync.js +7 -15
- package/dist/esm/transport/node/builders/bot.js +38 -0
- package/dist/esm/transport/node/builders/business.js +30 -30
- package/dist/esm/transport/node/builders/chatstate.js +28 -0
- package/dist/esm/transport/node/builders/community.js +53 -0
- package/dist/esm/transport/node/builders/device.js +2 -2
- package/dist/esm/transport/node/builders/email.js +6 -5
- package/dist/esm/transport/node/builders/global.js +1 -1
- package/dist/esm/transport/node/builders/group.js +114 -4
- package/dist/esm/transport/node/builders/media.js +2 -2
- package/dist/esm/transport/node/builders/message.js +83 -49
- package/dist/esm/transport/node/builders/newsletter.js +176 -0
- package/dist/esm/transport/node/builders/passive.js +7 -0
- package/dist/esm/transport/node/builders/prekeys.js +4 -4
- package/dist/esm/transport/node/builders/presence.js +27 -1
- package/dist/esm/transport/node/builders/privacy-token.js +2 -2
- package/dist/esm/transport/node/builders/privacy.js +6 -6
- package/dist/esm/transport/node/builders/profile.js +28 -8
- package/dist/esm/transport/node/builders/tos.js +58 -0
- package/dist/esm/transport/node/builders/usync.js +51 -2
- package/dist/esm/transport/node/helpers.js +3 -1
- package/dist/esm/transport/node/mex/argo-decoder.js +2 -2
- package/dist/esm/transport/node/mex/client.js +22 -0
- package/dist/esm/transport/node/query.js +17 -0
- package/dist/esm/transport/node/usync.js +12 -0
- package/dist/esm/transport/noise/WaClientPayload.js +8 -8
- package/dist/esm/transport/noise/WaMobileClientPayload.js +5 -0
- package/dist/esm/transport/noise/WaNoiseCert.js +5 -0
- package/dist/esm/transport/noise/WaNoiseHandshake.js +27 -25
- package/dist/esm/transport/noise/WaNoiseSession.js +39 -59
- package/dist/esm/transport/noise/WaNoiseSocket.js +19 -13
- package/dist/esm/transport/noise/constants.js +0 -1
- package/dist/esm/transport/proxy.js +5 -0
- package/dist/esm/transport/stream/parse.js +3 -7
- package/dist/esm/transport/wa-web-version-fetcher.js +91 -0
- package/dist/esm/util/async.js +4 -0
- package/dist/esm/util/bytes.js +37 -2
- package/dist/esm/util/clock.js +15 -0
- package/dist/esm/util/coercion.js +45 -3
- package/dist/esm/util/collections.js +11 -0
- package/dist/esm/util/index.js +2 -2
- package/dist/esm/util/primitives.js +19 -0
- package/dist/esm/util/runtime.js +5 -0
- package/dist/esm/version-spec.js +1 -0
- package/dist/index.js +31 -1
- package/dist/infra/log/ConsoleLogger.js +30 -6
- package/dist/infra/log/PinoLogger.js +64 -0
- package/dist/infra/log/types.js +4 -2
- package/dist/infra/perf/BackgroundQueue.js +55 -13
- package/dist/media/constants.js +34 -3
- package/dist/media/crypto/WaMediaCrypto.js +378 -0
- package/dist/media/index.js +9 -4
- package/dist/media/sticker/sticker-pack.js +136 -0
- package/dist/media/{WaMediaTransferClient.js → transfer/WaMediaTransferClient.js} +37 -6
- package/dist/media/{conn.js → transfer/conn.js} +10 -5
- package/dist/message/WaMessageClient.js +46 -15
- package/dist/message/addons/link-preview/builder.js +39 -0
- package/dist/message/addons/link-preview/detect.js +58 -0
- package/dist/message/addons/link-preview/fetcher.js +394 -0
- package/dist/message/addons/link-preview/types.js +2 -0
- package/dist/message/context-info.js +129 -0
- package/dist/message/{addon-crypto.js → crypto/addon-crypto.js} +68 -10
- package/dist/message/{icdc.js → crypto/icdc.js} +5 -7
- package/dist/message/crypto/phash.js +136 -0
- package/dist/message/{reporting-token.js → crypto/reporting-token.js} +6 -6
- package/dist/message/{use-case-secret.js → crypto/use-case-secret.js} +20 -3
- package/dist/message/{content.js → encode/content.js} +192 -7
- package/dist/message/encode/media-payload.js +45 -0
- package/dist/message/{padding.js → encode/padding.js} +9 -3
- package/dist/message/index.js +2 -2
- package/dist/message/kinds/bot.js +120 -0
- package/dist/message/kinds/newsletter.js +248 -0
- package/dist/message/kinds/sticker-pack.js +34 -0
- package/dist/message/{ack.js → primitives/ack.js} +8 -1
- package/dist/message/{incoming.js → primitives/incoming.js} +216 -31
- package/dist/message/primitives/peer-data-operation.js +96 -0
- package/dist/mex.js +6 -0
- package/dist/proto.js +1 -1
- package/dist/protocol/abprops.js +10 -0
- package/dist/protocol/appstate.js +7 -31
- package/dist/protocol/auth.js +3 -2
- package/dist/protocol/bot.js +81 -0
- package/dist/protocol/browser.js +8 -0
- package/dist/protocol/business.js +22 -0
- package/dist/protocol/call.js +51 -0
- package/dist/protocol/constants.js +39 -3
- package/dist/protocol/defaults.js +3 -0
- package/dist/protocol/index.js +12 -3
- package/dist/protocol/jid.js +107 -5
- package/dist/protocol/media.js +25 -12
- package/dist/protocol/message.js +4 -1
- package/dist/protocol/newsletter.js +64 -0
- package/dist/protocol/nodes.js +22 -2
- package/dist/protocol/notification.js +19 -3
- package/dist/protocol/presence.js +16 -0
- package/dist/protocol/status.js +9 -0
- package/dist/retry/codec.js +5 -0
- package/dist/retry/parse.js +16 -34
- package/dist/retry/reason.js +5 -0
- package/dist/retry/replay.js +129 -35
- package/dist/retry/tracker.js +3 -7
- package/dist/signal/api/SignalDeviceSyncApi.js +64 -17
- package/dist/signal/api/SignalDigestSyncApi.js +6 -1
- package/dist/signal/api/SignalIdentitySyncApi.js +9 -0
- package/dist/signal/api/SignalMissingPreKeysSyncApi.js +21 -60
- package/dist/signal/api/SignalRotateKeyApi.js +10 -0
- package/dist/signal/api/SignalSessionSyncApi.js +20 -48
- package/dist/signal/api/codec.js +52 -0
- package/dist/signal/api/prekeys.js +4 -0
- package/dist/signal/{crypto → attestation}/WaAdvSignature.js +5 -7
- package/dist/signal/constants.js +4 -1
- package/dist/signal/encoding.js +5 -303
- package/dist/signal/group/SenderKeyChain.js +17 -32
- package/dist/signal/group/SenderKeyManager.js +24 -7
- package/dist/signal/group/encoding.js +101 -0
- package/dist/signal/index.js +13 -10
- package/dist/signal/registration/encoding.js +39 -0
- package/dist/signal/registration/keygen.js +10 -0
- package/dist/signal/registration/utils.js +6 -0
- package/dist/signal/session/SignalProtocol.js +112 -10
- package/dist/signal/session/SignalRatchet.js +24 -54
- package/dist/signal/session/SignalSession.js +6 -14
- package/dist/signal/session/encoding.js +183 -0
- package/dist/signal/session/resolver.js +139 -30
- package/dist/store/cache/identity.cache.js +78 -0
- package/dist/store/cache/privacy-token.cache.js +60 -0
- package/dist/store/cache/sender-key.cache.js +104 -0
- package/dist/store/cache/session.cache.js +95 -0
- package/dist/store/contracts/group-metadata.store.js +2 -0
- package/dist/store/createStore.js +90 -36
- package/dist/store/index.js +18 -16
- package/dist/store/locks/contact.lock.js +1 -0
- package/dist/store/locks/device-list.lock.js +1 -0
- package/dist/store/locks/group-metadata.lock.js +23 -0
- package/dist/store/{providers/memory → memory}/appstate.store.js +5 -5
- package/dist/store/memory/auth.store.js +28 -0
- package/dist/store/memory/contact.store.js +83 -0
- package/dist/store/memory/device-list.store.js +107 -0
- package/dist/store/{providers/memory/participants.store.js → memory/group-metadata.store.js} +24 -15
- package/dist/store/{providers/memory → memory}/identity.store.js +3 -3
- package/dist/store/{providers/memory → memory}/message-secret.store.js +17 -8
- package/dist/store/{providers/memory → memory}/message.store.js +2 -2
- package/dist/store/{providers/memory → memory}/pre-key.store.js +2 -2
- package/dist/store/{providers/memory → memory}/privacy-token.store.js +1 -1
- package/dist/store/{providers/memory → memory}/retry.store.js +28 -7
- package/dist/store/{providers/memory → memory}/sender-key.store.js +3 -3
- package/dist/store/{providers/memory → memory}/session.store.js +3 -3
- package/dist/store/{providers/memory → memory}/thread.store.js +2 -2
- package/dist/store/noop.store.js +7 -5
- package/dist/transport/WaComms.js +14 -5
- package/dist/transport/WaWebSocket.js +32 -8
- package/dist/transport/binary/constants.js +11 -5
- package/dist/transport/binary/decoder.js +24 -18
- package/dist/transport/binary/encoder.js +109 -34
- package/dist/transport/binary/tokens.js +12 -12
- package/dist/transport/index.js +3 -1
- package/dist/transport/keepalive/WaKeepAlive.js +18 -4
- package/dist/transport/node/WaMobileTcpSocket.js +6 -0
- package/dist/transport/node/WaNodeOrchestrator.js +9 -5
- package/dist/transport/node/WaNodeTransport.js +13 -0
- package/dist/transport/node/builders/abprops.js +1 -1
- package/dist/transport/node/builders/account-sync.js +7 -16
- package/dist/transport/node/builders/bot.js +43 -0
- package/dist/transport/node/builders/business.js +31 -31
- package/dist/transport/node/builders/chatstate.js +31 -0
- package/dist/transport/node/builders/community.js +59 -0
- package/dist/transport/node/builders/device.js +1 -1
- package/dist/transport/node/builders/email.js +6 -5
- package/dist/transport/node/builders/global.js +1 -1
- package/dist/transport/node/builders/group.js +121 -3
- package/dist/transport/node/builders/media.js +1 -1
- package/dist/transport/node/builders/message.js +84 -49
- package/dist/transport/node/builders/newsletter.js +183 -0
- package/dist/transport/node/builders/passive.js +10 -0
- package/dist/transport/node/builders/prekeys.js +3 -3
- package/dist/transport/node/builders/presence.js +28 -1
- package/dist/transport/node/builders/privacy-token.js +1 -1
- package/dist/transport/node/builders/privacy.js +5 -5
- package/dist/transport/node/builders/profile.js +30 -7
- package/dist/transport/node/builders/tos.js +63 -0
- package/dist/transport/node/builders/usync.js +52 -1
- package/dist/transport/node/helpers.js +2 -1
- package/dist/transport/node/mex/argo-decoder.js +2 -2
- package/dist/transport/node/mex/client.js +23 -0
- package/dist/transport/node/query.js +17 -0
- package/dist/transport/node/usync.js +13 -0
- package/dist/transport/noise/WaClientPayload.js +8 -8
- package/dist/transport/noise/WaMobileClientPayload.js +5 -0
- package/dist/transport/noise/WaNoiseCert.js +5 -0
- package/dist/transport/noise/WaNoiseHandshake.js +25 -23
- package/dist/transport/noise/WaNoiseSession.js +39 -59
- package/dist/transport/noise/WaNoiseSocket.js +18 -12
- package/dist/transport/noise/constants.js +1 -2
- package/dist/transport/proxy.js +5 -0
- package/dist/transport/stream/parse.js +3 -7
- package/dist/transport/wa-web-version-fetcher.js +94 -0
- package/dist/types/appstate/constants.d.ts +1 -1
- package/dist/types/appstate/{WaAppStateCrypto.d.ts → crypto/WaAppStateCrypto.d.ts} +26 -9
- package/dist/types/appstate/index.d.ts +5 -5
- package/dist/types/appstate/{encoding.d.ts → parsers/encoding.d.ts} +8 -1
- package/dist/types/appstate/{response-parser.d.ts → parsers/response-parser.d.ts} +13 -3
- package/dist/types/appstate/sync/WaAppStateSyncClient.d.ts +105 -0
- package/dist/types/appstate/utils.d.ts +17 -1
- package/dist/types/appstate-spec.d.ts +24 -0
- package/dist/types/auth/WaAuthClient.d.ts +89 -3
- package/dist/types/auth/credentials-flow.d.ts +4 -3
- package/dist/types/auth/pairing/pairing-code-crypto.d.ts +0 -1
- package/dist/types/auth/types.d.ts +48 -1
- package/dist/types/client/WaClient.d.ts +178 -71
- package/dist/types/client/WaClientFactory.d.ts +30 -5
- package/dist/types/client/connection/WaConnectionManager.d.ts +4 -2
- package/dist/types/client/connection/WaReceiptQueue.d.ts +1 -1
- package/dist/types/client/coordinators/WaAppStateMutationCoordinator.d.ts +215 -5
- package/dist/types/client/coordinators/WaBotCoordinator.d.ts +117 -0
- package/dist/types/client/coordinators/WaBroadcastListCoordinator.d.ts +39 -0
- package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +44 -43
- package/dist/types/client/coordinators/WaEmailCoordinator.d.ts +16 -0
- package/dist/types/client/coordinators/WaGroupCoordinator.d.ts +311 -9
- package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +11 -4
- package/dist/types/client/coordinators/WaLowLevelCoordinator.d.ts +47 -0
- package/dist/types/client/coordinators/WaMessageCoordinator.d.ts +232 -0
- package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +54 -31
- package/dist/types/client/coordinators/WaNewsletterCoordinator.d.ts +13 -0
- package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +4 -3
- package/dist/types/client/coordinators/WaPresenceCoordinator.d.ts +27 -0
- package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +27 -0
- package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +113 -0
- package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +19 -17
- package/dist/types/client/coordinators/WaStatusCoordinator.d.ts +42 -0
- package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +5 -1
- package/dist/types/client/events/abprops.d.ts +2 -1
- package/dist/types/client/events/appstate-mutation.d.ts +3 -0
- package/dist/types/client/events/business.d.ts +10 -0
- package/dist/types/client/events/call.d.ts +31 -0
- package/dist/types/client/events/chatstate.d.ts +9 -0
- package/dist/types/client/events/devices.d.ts +5 -4
- package/dist/types/client/{dirty.d.ts → events/dirty.d.ts} +4 -3
- package/dist/types/client/events/group.d.ts +2 -1
- package/dist/types/client/events/identity.d.ts +2 -1
- package/dist/types/client/{incoming.d.ts → events/incoming.d.ts} +27 -4
- package/dist/types/client/events/mex-notification.d.ts +6 -0
- package/dist/types/client/events/picture.d.ts +8 -0
- package/dist/types/client/events/presence.d.ts +28 -0
- package/dist/types/client/events/receipt.d.ts +14 -0
- package/dist/types/client/events/registration.d.ts +4 -3
- package/dist/types/client/index.d.ts +1 -1
- package/dist/types/client/media.d.ts +35 -1
- package/dist/types/client/messaging/fanout.d.ts +2 -2
- package/dist/types/client/messaging/group-metadata.d.ts +19 -0
- package/dist/types/client/messaging/ignore-key.d.ts +11 -0
- package/dist/types/client/messaging/key-protocol.d.ts +9 -7
- package/dist/types/client/messaging/link-preview.d.ts +19 -0
- package/dist/types/client/messaging/messages.d.ts +28 -0
- package/dist/types/client/newsletter/admin.d.ts +71 -0
- package/dist/types/client/newsletter/content.d.ts +42 -0
- package/dist/types/client/newsletter/discovery.d.ts +33 -0
- package/dist/types/client/newsletter/messaging.d.ts +66 -0
- package/dist/types/client/newsletter/mex.d.ts +14 -0
- package/dist/types/client/newsletter/parse.d.ts +19 -0
- package/dist/types/client/newsletter/types.d.ts +190 -0
- package/dist/types/client/persistence/WriteBehindPersistence.d.ts +12 -1
- package/dist/types/client/persistence/history-sync.d.ts +29 -0
- package/dist/types/client/{mailbox.d.ts → persistence/mailbox.d.ts} +4 -4
- package/dist/types/client/tokens/cs-token.d.ts +1 -3
- package/dist/types/client/types.d.ts +843 -71
- package/dist/types/crypto/core/hkdf.d.ts +10 -2
- package/dist/types/crypto/core/index.d.ts +2 -2
- package/dist/types/crypto/core/keys.d.ts +0 -4
- package/dist/types/crypto/core/nonce.d.ts +4 -5
- package/dist/types/crypto/core/primitives.d.ts +31 -20
- package/dist/types/crypto/core/random.d.ts +6 -0
- package/dist/types/crypto/core/xeddsa.d.ts +9 -0
- package/dist/types/crypto/curves/Ed25519.d.ts +7 -1
- package/dist/types/crypto/curves/X25519.d.ts +20 -1
- package/dist/types/crypto/curves/constants.d.ts +4 -3
- package/dist/types/crypto/curves/types.d.ts +0 -5
- package/dist/types/crypto/math/constants.d.ts +0 -1
- package/dist/types/crypto/math/mod.d.ts +0 -1
- package/dist/types/index.d.ts +32 -6
- package/dist/types/infra/log/ConsoleLogger.d.ts +18 -1
- package/dist/types/infra/log/PinoLogger.d.ts +55 -1
- package/dist/types/infra/log/types.d.ts +6 -0
- package/dist/types/infra/perf/BackgroundQueue.d.ts +19 -0
- package/dist/types/media/constants.d.ts +7 -2
- package/dist/types/media/crypto/WaMediaCrypto.d.ts +59 -0
- package/dist/types/media/index.d.ts +7 -5
- package/dist/types/media/processor.d.ts +27 -5
- package/dist/types/media/sticker/sticker-pack.d.ts +6 -0
- package/dist/types/media/{WaMediaTransferClient.d.ts → transfer/WaMediaTransferClient.d.ts} +30 -1
- package/dist/types/media/transfer/conn.d.ts +7 -0
- package/dist/types/media/types.d.ts +1 -2
- package/dist/types/message/WaMessageClient.d.ts +14 -0
- package/dist/types/message/addons/link-preview/builder.d.ts +13 -0
- package/dist/types/message/addons/link-preview/detect.d.ts +5 -0
- package/dist/types/message/addons/link-preview/fetcher.d.ts +13 -0
- package/dist/types/message/addons/link-preview/types.d.ts +51 -0
- package/dist/types/message/context-info.d.ts +66 -0
- package/dist/types/message/{addon-crypto.d.ts → crypto/addon-crypto.d.ts} +27 -5
- package/dist/types/message/{icdc.d.ts → crypto/icdc.d.ts} +4 -4
- package/dist/types/message/{phash.d.ts → crypto/phash.d.ts} +1 -1
- package/dist/types/message/{reporting-token.d.ts → crypto/reporting-token.d.ts} +2 -2
- package/dist/types/message/{use-case-secret.d.ts → crypto/use-case-secret.d.ts} +17 -1
- package/dist/types/message/encode/content.d.ts +43 -0
- package/dist/types/message/{device-sent.d.ts → encode/device-sent.d.ts} +1 -1
- package/dist/types/message/encode/media-payload.d.ts +12 -0
- package/dist/types/message/index.d.ts +2 -2
- package/dist/types/message/kinds/bot.d.ts +31 -0
- package/dist/types/message/kinds/newsletter.d.ts +12 -0
- package/dist/types/message/kinds/sticker-pack.d.ts +6 -0
- package/dist/types/message/{ack.d.ts → primitives/ack.d.ts} +1 -1
- package/dist/types/message/primitives/incoming.d.ts +21 -0
- package/dist/types/message/primitives/peer-data-operation.d.ts +23 -0
- package/dist/types/message/types.d.ts +208 -10
- package/dist/types/mex.d.ts +2 -0
- package/dist/types/proto.d.ts +2 -2
- package/dist/types/protocol/abprops.d.ts +9 -0
- package/dist/types/protocol/appstate.d.ts +4 -49
- package/dist/types/protocol/auth.d.ts +2 -2
- package/dist/types/protocol/bot.d.ts +45 -0
- package/dist/types/protocol/browser.d.ts +8 -0
- package/dist/types/protocol/business.d.ts +21 -0
- package/dist/types/protocol/call.d.ts +44 -0
- package/dist/types/protocol/constants.d.ts +16 -3
- package/dist/types/protocol/defaults.d.ts +3 -0
- package/dist/types/protocol/group.d.ts +1 -1
- package/dist/types/protocol/index.d.ts +2 -1
- package/dist/types/protocol/jid.d.ts +78 -0
- package/dist/types/protocol/media.d.ts +21 -13
- package/dist/types/protocol/message.d.ts +4 -0
- package/dist/types/protocol/newsletter.d.ts +65 -0
- package/dist/types/protocol/nodes.d.ts +20 -0
- package/dist/types/protocol/notification.d.ts +16 -0
- package/dist/types/protocol/presence.d.ts +16 -0
- package/dist/types/protocol/status.d.ts +7 -0
- package/dist/types/retry/codec.d.ts +5 -0
- package/dist/types/retry/index.d.ts +1 -1
- package/dist/types/retry/parse.d.ts +9 -0
- package/dist/types/retry/reason.d.ts +5 -0
- package/dist/types/retry/replay.d.ts +19 -5
- package/dist/types/retry/tracker.d.ts +10 -3
- package/dist/types/retry/types.d.ts +3 -8
- package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +20 -0
- package/dist/types/signal/api/SignalDigestSyncApi.d.ts +10 -0
- package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +9 -0
- package/dist/types/signal/api/SignalMissingPreKeysSyncApi.d.ts +8 -0
- package/dist/types/signal/api/SignalRotateKeyApi.d.ts +10 -0
- package/dist/types/signal/api/SignalSessionSyncApi.d.ts +13 -0
- package/dist/types/signal/api/codec.d.ts +20 -0
- package/dist/types/signal/api/constants.d.ts +1 -1
- package/dist/types/signal/api/prekeys.d.ts +4 -0
- package/dist/types/signal/{crypto → attestation}/WaAdvSignature.d.ts +2 -2
- package/dist/types/signal/attestation/constants.d.ts +4 -0
- package/dist/types/signal/constants.d.ts +7 -4
- package/dist/types/signal/encoding.d.ts +6 -68
- package/dist/types/signal/group/SenderKeyChain.d.ts +1 -1
- package/dist/types/signal/group/SenderKeyManager.d.ts +17 -0
- package/dist/types/signal/group/encoding.d.ts +25 -0
- package/dist/types/signal/index.d.ts +4 -1
- package/dist/types/signal/registration/encoding.d.ts +30 -0
- package/dist/types/signal/registration/keygen.d.ts +10 -0
- package/dist/types/signal/registration/utils.d.ts +5 -0
- package/dist/types/signal/session/SignalProtocol.d.ts +55 -0
- package/dist/types/signal/session/SignalRatchet.d.ts +2 -3
- package/dist/types/signal/session/SignalSession.d.ts +0 -1
- package/dist/types/signal/session/encoding.d.ts +28 -0
- package/dist/types/signal/session/resolver.d.ts +14 -0
- package/dist/types/store/cache/identity.cache.d.ts +15 -0
- package/dist/types/store/cache/privacy-token.cache.d.ts +15 -0
- package/dist/types/store/cache/sender-key.cache.d.ts +18 -0
- package/dist/types/store/cache/session.cache.d.ts +23 -0
- package/dist/types/store/contracts/contact.store.d.ts +14 -0
- package/dist/types/store/contracts/device-list.store.d.ts +13 -0
- package/dist/types/store/contracts/group-metadata.store.d.ts +14 -0
- package/dist/types/store/contracts/message.store.d.ts +0 -2
- package/dist/types/store/createStore.d.ts +54 -2
- package/dist/types/store/index.d.ts +17 -16
- package/dist/types/store/locks/group-metadata.lock.d.ts +2 -0
- package/dist/types/store/{providers/memory → memory}/appstate.store.d.ts +2 -2
- package/dist/types/store/memory/auth.store.d.ts +18 -0
- package/dist/types/store/{providers/memory → memory}/contact.store.d.ts +6 -1
- package/dist/types/store/{providers/memory → memory}/device-list.store.d.ts +15 -2
- package/dist/types/store/memory/group-metadata.store.d.ts +27 -0
- package/dist/types/store/{providers/memory → memory}/identity.store.d.ts +2 -2
- package/dist/types/store/{providers/memory → memory}/message-secret.store.d.ts +12 -2
- package/dist/types/store/{providers/memory → memory}/message.store.d.ts +1 -1
- package/dist/types/store/{providers/memory → memory}/pre-key.store.d.ts +2 -2
- package/dist/types/store/{providers/memory → memory}/privacy-token.store.d.ts +1 -1
- package/dist/types/store/{providers/memory → memory}/retry.store.d.ts +16 -3
- package/dist/types/store/{providers/memory → memory}/sender-key.store.d.ts +2 -2
- package/dist/types/store/{providers/memory → memory}/session.store.d.ts +2 -2
- package/dist/types/store/{providers/memory → memory}/signal.store.d.ts +2 -2
- package/dist/types/store/{providers/memory → memory}/thread.store.d.ts +1 -1
- package/dist/types/store/noop.store.d.ts +2 -2
- package/dist/types/store/types.d.ts +250 -6
- package/dist/types/transport/WaComms.d.ts +5 -0
- package/dist/types/transport/WaWebSocket.d.ts +5 -0
- package/dist/types/transport/binary/constants.d.ts +8 -2
- package/dist/types/transport/binary/decoder.d.ts +5 -0
- package/dist/types/transport/binary/encoder.d.ts +5 -0
- package/dist/types/transport/binary/tokens.d.ts +6 -6
- package/dist/types/transport/index.d.ts +3 -1
- package/dist/types/transport/keepalive/WaKeepAlive.d.ts +7 -0
- package/dist/types/transport/node/WaMobileTcpSocket.d.ts +6 -0
- package/dist/types/transport/node/WaNodeOrchestrator.d.ts +5 -0
- package/dist/types/transport/node/WaNodeTransport.d.ts +13 -0
- package/dist/types/transport/node/builders/account-sync.d.ts +1 -2
- package/dist/types/transport/node/builders/bot.d.ts +4 -0
- package/dist/types/transport/node/builders/business.d.ts +21 -4
- package/dist/types/transport/node/builders/chatstate.d.ts +11 -0
- package/dist/types/transport/node/builders/community.d.ts +17 -0
- package/dist/types/transport/node/builders/group.d.ts +44 -2
- package/dist/types/transport/node/builders/message.d.ts +11 -6
- package/dist/types/transport/node/builders/newsletter.d.ts +73 -0
- package/dist/types/transport/node/builders/passive.d.ts +3 -0
- package/dist/types/transport/node/builders/presence.d.ts +8 -1
- package/dist/types/transport/node/builders/profile.d.ts +3 -0
- package/dist/types/transport/node/builders/tos.d.ts +12 -0
- package/dist/types/transport/node/builders/usync.d.ts +16 -0
- package/dist/types/transport/node/helpers.d.ts +1 -2
- package/dist/types/transport/node/mex/client.d.ts +12 -1
- package/dist/types/transport/node/query.d.ts +19 -1
- package/dist/types/transport/node/usync.d.ts +3 -0
- package/dist/types/transport/noise/WaMobileClientPayload.d.ts +5 -0
- package/dist/types/transport/noise/WaNoiseCert.d.ts +5 -0
- package/dist/types/transport/noise/WaNoiseHandshake.d.ts +12 -6
- package/dist/types/transport/noise/WaNoiseSession.d.ts +0 -1
- package/dist/types/transport/noise/WaNoiseSocket.d.ts +12 -6
- package/dist/types/transport/noise/constants.d.ts +4 -5
- package/dist/types/transport/proxy.d.ts +5 -0
- package/dist/types/transport/types.d.ts +14 -7
- package/dist/types/transport/wa-web-version-fetcher.d.ts +44 -0
- package/dist/types/util/async.d.ts +4 -0
- package/dist/types/util/bytes.d.ts +36 -1
- package/dist/types/util/clock.d.ts +6 -0
- package/dist/types/util/coercion.d.ts +25 -0
- package/dist/types/util/collections.d.ts +8 -0
- package/dist/types/util/index.d.ts +2 -2
- package/dist/types/util/primitives.d.ts +11 -0
- package/dist/types/util/runtime.d.ts +5 -0
- package/dist/types/version-spec.d.ts +1 -0
- package/dist/util/async.js +4 -0
- package/dist/util/bytes.js +37 -2
- package/dist/util/clock.js +18 -0
- package/dist/util/coercion.js +48 -3
- package/dist/util/collections.js +12 -0
- package/dist/util/index.js +7 -1
- package/dist/util/primitives.js +20 -0
- package/dist/util/runtime.js +5 -0
- package/dist/version-spec.js +5 -0
- package/package.json +32 -8
- package/spec/appstate/index.d.ts +188 -0
- package/spec/appstate/index.js +850 -0
- package/spec/mex/index.d.ts +4172 -0
- package/spec/mex/index.js +261 -0
- package/spec/proto/index.d.ts +16305 -0
- package/spec/proto/index.js +1 -0
- package/spec/version/index.d.ts +4 -0
- package/spec/version/index.js +9 -0
- package/spec/version/version.json +3 -0
- package/dist/client/events/chat.js +0 -227
- package/dist/client/incoming.js +0 -306
- package/dist/client/mailbox.js +0 -66
- package/dist/client/messages.js +0 -305
- package/dist/esm/client/events/chat.js +0 -224
- package/dist/esm/client/incoming.js +0 -296
- package/dist/esm/client/mailbox.js +0 -63
- package/dist/esm/client/messages.js +0 -301
- package/dist/esm/media/WaMediaCrypto.js +0 -499
- package/dist/esm/message/phash.js +0 -47
- package/dist/esm/store/locks/participants.lock.js +0 -20
- package/dist/esm/store/providers/memory/contact.store.js +0 -28
- package/dist/esm/store/providers/memory/device-list.store.js +0 -67
- package/dist/esm/transport/node/mex/persist-ids.js +0 -10
- package/dist/media/WaMediaCrypto.js +0 -503
- package/dist/message/phash.js +0 -50
- package/dist/store/locks/participants.lock.js +0 -23
- package/dist/store/providers/memory/contact.store.js +0 -32
- package/dist/store/providers/memory/device-list.store.js +0 -71
- package/dist/transport/node/mex/persist-ids.js +0 -13
- package/dist/types/appstate/WaAppStateSyncClient.d.ts +0 -70
- package/dist/types/client/events/chat.d.ts +0 -3
- package/dist/types/client/history-sync.d.ts +0 -20
- package/dist/types/client/messages.d.ts +0 -18
- package/dist/types/client/messaging/participants.d.ts +0 -13
- package/dist/types/media/WaMediaCrypto.d.ts +0 -22
- package/dist/types/media/conn.d.ts +0 -3
- package/dist/types/message/content.d.ts +0 -14
- package/dist/types/message/incoming.d.ts +0 -18
- package/dist/types/signal/crypto/constants.d.ts +0 -4
- package/dist/types/store/contracts/participants.store.d.ts +0 -13
- package/dist/types/store/locks/participants.lock.d.ts +0 -2
- package/dist/types/store/providers/memory/participants.store.d.ts +0 -17
- package/dist/types/transport/node/mex/persist-ids.d.ts +0 -14
- package/proto/index.d.ts +0 -10903
- package/proto/index.js +0 -1
- /package/dist/{store/contracts/participants.store.js → client/newsletter/types.js} +0 -0
- /package/dist/esm/{store/contracts/participants.store.js → client/newsletter/types.js} +0 -0
- /package/dist/esm/message/{device-sent.js → encode/device-sent.js} +0 -0
- /package/dist/esm/signal/{crypto → attestation}/constants.js +0 -0
- /package/dist/esm/store/{providers/memory → memory}/signal.store.js +0 -0
- /package/dist/message/{device-sent.js → encode/device-sent.js} +0 -0
- /package/dist/signal/{crypto → attestation}/constants.js +0 -0
- /package/dist/store/{providers/memory → memory}/signal.store.js +0 -0
- /package/dist/types/message/{padding.d.ts → encode/padding.d.ts} +0 -0
|
@@ -1,70 +1,49 @@
|
|
|
1
1
|
import { randomBytesAsync, sha256 } from '../../crypto/index.js';
|
|
2
2
|
import { md5Bytes } from '../../crypto/core/primitives.js';
|
|
3
3
|
import { PromiseDedup } from '../../infra/perf/PromiseDedup.js';
|
|
4
|
-
import { ensureMessageSecret } from '../../message/index.js';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
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';
|
|
11
13
|
import { proto } from '../../proto.js';
|
|
12
14
|
import { WA_DEFAULTS } from '../../protocol/constants.js';
|
|
13
|
-
import { isGroupJid, isLidJid, normalizeDeviceJid, normalizeRecipientJid, parseJidFull, parseSignalAddressFromJid, signalAddressKey, toUserJid } 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,
|
|
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.
|
|
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.sessionStore = options.sessionStore;
|
|
35
|
-
this.identityStore = options.identityStore;
|
|
36
|
-
this.deviceListStore = options.deviceListStore;
|
|
37
|
-
this.messageSecretStore = options.messageSecretStore;
|
|
38
|
-
this.getCurrentMeJid = options.getCurrentMeJid;
|
|
39
|
-
this.getCurrentMeLid = options.getCurrentMeLid;
|
|
40
|
-
this.getCurrentSignedIdentity = options.getCurrentSignedIdentity;
|
|
41
|
-
this.resolvePrivacyTokenNode = options.resolvePrivacyTokenNode;
|
|
42
|
-
this.onDirectMessageSent = options.onDirectMessageSent;
|
|
43
|
-
this.getIcdcHashLength = options.getIcdcHashLength;
|
|
25
|
+
this.deps = options;
|
|
44
26
|
this.mobileMessageIdFormat = options.mobileMessageIdFormat ?? false;
|
|
27
|
+
this.serverClock = options.serverClock;
|
|
45
28
|
}
|
|
46
29
|
async publishMessageNode(node, options = {}) {
|
|
47
|
-
this.logger.
|
|
30
|
+
this.deps.logger.trace('wa client publish message node', {
|
|
48
31
|
tag: node.tag,
|
|
49
32
|
type: node.attrs.type,
|
|
50
33
|
to: node.attrs.to
|
|
51
34
|
});
|
|
52
|
-
const messageType = node.attrs.type ?? 'text';
|
|
53
35
|
const replayPayload = {
|
|
54
36
|
mode: 'opaque_node',
|
|
55
37
|
node: encodeBinaryNode(node)
|
|
56
38
|
};
|
|
57
|
-
return this.retryTracker.track({
|
|
39
|
+
return this.deps.retryTracker.track({
|
|
58
40
|
messageIdHint: node.attrs.id,
|
|
59
41
|
toJid: node.attrs.to,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
participantJid: node.attrs.participant,
|
|
63
|
-
recipientJid: node.attrs.recipient
|
|
64
|
-
}, async () => this.messageClient.publishNode(node, options));
|
|
42
|
+
replayPayload
|
|
43
|
+
}, async () => this.deps.messageClient.publishNode(node, options));
|
|
65
44
|
}
|
|
66
45
|
async publishEncryptedMessage(input, options = {}) {
|
|
67
|
-
this.logger.
|
|
46
|
+
this.deps.logger.trace('wa client publish encrypted message', {
|
|
68
47
|
to: input.to,
|
|
69
48
|
type: input.type,
|
|
70
49
|
encType: input.encType
|
|
@@ -77,14 +56,12 @@ export class WaMessageDispatchCoordinator {
|
|
|
77
56
|
ciphertext: input.ciphertext,
|
|
78
57
|
participant: input.participant
|
|
79
58
|
};
|
|
80
|
-
return this.retryTracker.track({
|
|
59
|
+
return this.deps.retryTracker.track({
|
|
81
60
|
messageIdHint: input.id,
|
|
82
61
|
toJid: input.to,
|
|
83
|
-
type: input.type ?? 'text',
|
|
84
62
|
replayPayload,
|
|
85
|
-
participantJid: input.participant,
|
|
86
63
|
eligibleRequesterDeviceJids: [input.to]
|
|
87
|
-
}, async () => this.messageClient.publishEncrypted(input, options));
|
|
64
|
+
}, async () => this.deps.messageClient.publishEncrypted(input, options));
|
|
88
65
|
}
|
|
89
66
|
async publishSignalMessage(input, options = {}) {
|
|
90
67
|
this.requireCurrentMeJid('publishSignalMessage');
|
|
@@ -92,30 +69,29 @@ export class WaMessageDispatchCoordinator {
|
|
|
92
69
|
if (address.server === WA_DEFAULTS.GROUP_SERVER) {
|
|
93
70
|
throw new Error('publishSignalMessage currently supports only direct chats; use sender-key flow for groups');
|
|
94
71
|
}
|
|
95
|
-
this.logger.
|
|
72
|
+
this.deps.logger.trace('wa client publish signal message', {
|
|
96
73
|
to: input.to,
|
|
97
74
|
type: input.type
|
|
98
75
|
});
|
|
99
76
|
const [paddedPlaintext] = await Promise.all([
|
|
100
77
|
writeRandomPadMax16(input.plaintext),
|
|
101
|
-
this.sessionResolver.ensureSession(address, input.to, input.expectedIdentity)
|
|
78
|
+
this.deps.sessionResolver.ensureSession(address, input.to, input.expectedIdentity)
|
|
102
79
|
]);
|
|
103
|
-
const encrypted = await this.signalProtocol.encryptMessage(address, paddedPlaintext, input.expectedIdentity);
|
|
80
|
+
const encrypted = await this.deps.signalProtocol.encryptMessage(address, paddedPlaintext, input.expectedIdentity);
|
|
104
81
|
const messageType = input.type ?? 'text';
|
|
82
|
+
const deviceIdentity = encrypted.type === 'pkmsg' ? this.getEncodedSignedDeviceIdentity() : undefined;
|
|
105
83
|
const replayPayload = {
|
|
106
84
|
mode: 'plaintext',
|
|
107
85
|
to: input.to,
|
|
108
86
|
type: messageType,
|
|
109
87
|
plaintext: paddedPlaintext
|
|
110
88
|
};
|
|
111
|
-
return this.retryTracker.track({
|
|
89
|
+
return this.deps.retryTracker.track({
|
|
112
90
|
messageIdHint: input.id,
|
|
113
91
|
toJid: input.to,
|
|
114
|
-
type: messageType,
|
|
115
92
|
replayPayload,
|
|
116
|
-
participantJid: input.participant,
|
|
117
93
|
eligibleRequesterDeviceJids: [input.to]
|
|
118
|
-
}, async () => this.messageClient.publishEncrypted({
|
|
94
|
+
}, async () => this.deps.messageClient.publishEncrypted({
|
|
119
95
|
to: input.to,
|
|
120
96
|
encType: encrypted.type,
|
|
121
97
|
ciphertext: encrypted.ciphertext,
|
|
@@ -124,33 +100,130 @@ export class WaMessageDispatchCoordinator {
|
|
|
124
100
|
category: input.category,
|
|
125
101
|
pushPriority: input.pushPriority,
|
|
126
102
|
participant: input.participant,
|
|
127
|
-
deviceFanout: input.deviceFanout
|
|
103
|
+
deviceFanout: input.deviceFanout,
|
|
104
|
+
deviceIdentity,
|
|
105
|
+
metaNode: input.metaNode
|
|
128
106
|
}, options));
|
|
129
107
|
}
|
|
130
108
|
async sendMessage(to, content, options = {}) {
|
|
131
109
|
const recipientJid = normalizeRecipientJid(to);
|
|
132
|
-
|
|
133
|
-
this.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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);
|
|
137
209
|
const rawSecret = messageWithSecret.messageContextInfo?.messageSecret;
|
|
138
210
|
if (rawSecret &&
|
|
139
211
|
rawSecret.length > 0 &&
|
|
140
212
|
sendOptions.id &&
|
|
141
213
|
needsSecretPersistence(messageWithSecret)) {
|
|
142
|
-
const meJid = this.
|
|
143
|
-
void this.messageSecretStore
|
|
214
|
+
const meJid = this.deps.getCurrentCredentials()?.meJid ?? '';
|
|
215
|
+
void this.deps.messageSecretStore
|
|
144
216
|
.set(sendOptions.id, { secret: rawSecret, senderJid: meJid })
|
|
145
217
|
.catch((error) => {
|
|
146
|
-
this.logger.warn('failed to persist outgoing message secret', {
|
|
218
|
+
this.deps.logger.warn('failed to persist outgoing message secret', {
|
|
147
219
|
id: sendOptions.id,
|
|
220
|
+
to: recipientJid,
|
|
148
221
|
message: toError(error).message
|
|
149
222
|
});
|
|
150
223
|
});
|
|
151
224
|
}
|
|
152
|
-
const meJid = this.
|
|
153
|
-
const regInfo = meJid ? await this.signalStore.getRegistrationInfo() : null;
|
|
225
|
+
const meJid = this.deps.getCurrentCredentials()?.meJid;
|
|
226
|
+
const regInfo = meJid ? await this.deps.signalStore.getRegistrationInfo() : null;
|
|
154
227
|
const localPubKey = regInfo?.identityKeyPair.pubKey;
|
|
155
228
|
const meParsed = meJid ? parseJidFull(meJid) : undefined;
|
|
156
229
|
const meUserJid = meParsed?.userJid;
|
|
@@ -162,67 +235,343 @@ export class WaMessageDispatchCoordinator {
|
|
|
162
235
|
]);
|
|
163
236
|
const messageWithIcdc = injectDeviceListMetadata(messageWithSecret, senderIcdc, recipientIcdc);
|
|
164
237
|
const plaintext = await writeRandomPadMax16(proto.Message.encode(messageWithIcdc).finish());
|
|
165
|
-
const
|
|
166
|
-
const
|
|
167
|
-
|
|
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);
|
|
168
248
|
const metaAttrs = resolveMetaAttrs(messageWithIcdc);
|
|
169
249
|
const metaNode = metaAttrs ? buildMetaNode(metaAttrs) : undefined;
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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);
|
|
173
258
|
}
|
|
174
|
-
return this.publishGroupSenderKeyMessage(recipientJid, messageWithIcdc, plaintext, type, sendOptions, {}, edit, mediatype, metaNode);
|
|
175
259
|
}
|
|
176
|
-
const
|
|
177
|
-
|
|
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;
|
|
178
312
|
}
|
|
179
313
|
async syncSignalSession(jid, reasonIdentity = false) {
|
|
180
314
|
const address = parseSignalAddressFromJid(jid);
|
|
181
315
|
if (address.server === WA_DEFAULTS.GROUP_SERVER) {
|
|
182
316
|
throw new Error('syncSignalSession supports only direct chats');
|
|
183
317
|
}
|
|
184
|
-
await this.sessionResolver.ensureSession(address, jid, undefined, reasonIdentity);
|
|
318
|
+
await this.deps.sessionResolver.ensureSession(address, jid, undefined, reasonIdentity);
|
|
185
319
|
}
|
|
186
320
|
async sendReceipt(input) {
|
|
187
|
-
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;
|
|
188
523
|
}
|
|
189
524
|
async requestAppStateSyncKeys(keyIds) {
|
|
190
|
-
return this.appStateSyncKeyProtocol.requestKeys(keyIds);
|
|
525
|
+
return this.deps.appStateSyncKeyProtocol.requestKeys(keyIds);
|
|
191
526
|
}
|
|
192
527
|
async sendAppStateSyncKeyShare(toDeviceJid, keys, missingKeyIds = []) {
|
|
193
|
-
await this.appStateSyncKeyProtocol.sendKeyShare(toDeviceJid, keys, missingKeyIds);
|
|
528
|
+
await this.deps.appStateSyncKeyProtocol.sendKeyShare(toDeviceJid, keys, missingKeyIds);
|
|
194
529
|
}
|
|
195
|
-
async
|
|
196
|
-
await this.
|
|
530
|
+
async mutateGroupMetadataCacheFromGroupEvent(event) {
|
|
531
|
+
await this.deps.groupMetadataCache.mutateFromGroupEvent(event);
|
|
197
532
|
}
|
|
533
|
+
// noop for now
|
|
198
534
|
shouldUseGroupDirectPath(message) {
|
|
199
|
-
|
|
200
|
-
if (protocolType === proto.Message.ProtocolMessage.Type.REVOKE ||
|
|
201
|
-
protocolType === proto.Message.ProtocolMessage.Type.MESSAGE_EDIT) {
|
|
202
|
-
return true;
|
|
203
|
-
}
|
|
204
|
-
return message.keepInChatMessage?.keepType === proto.KeepType.UNDO_KEEP_FOR_ALL;
|
|
535
|
+
return false;
|
|
205
536
|
}
|
|
206
|
-
async publishGroupDirectMessage(groupJid,
|
|
207
|
-
const sendOptions =
|
|
537
|
+
async publishGroupDirectMessage(groupJid, envelope, retryContext = {}) {
|
|
538
|
+
const { message, plaintext, type, edit, mediatype, sendOptions } = envelope;
|
|
208
539
|
const meJid = this.requireCurrentMeJid('sendMessage');
|
|
209
540
|
const participantUserJids = retryContext.forceRefreshParticipants
|
|
210
|
-
? await this.
|
|
211
|
-
: await this.
|
|
541
|
+
? await this.deps.groupMetadataCache.refreshParticipantUsers(groupJid)
|
|
542
|
+
: await this.deps.groupMetadataCache.resolveParticipantUsers(groupJid);
|
|
212
543
|
const addressingMode = retryContext.forceAddressingMode ??
|
|
213
544
|
this.resolveGroupAddressingMode(participantUserJids, groupJid);
|
|
214
545
|
const senderForPhash = this.resolveSenderForAddressingMode(addressingMode, meJid);
|
|
215
|
-
const fanoutDeviceJids = await this.fanoutResolver.resolveGroupParticipantDeviceJids(participantUserJids);
|
|
546
|
+
const fanoutDeviceJids = await this.deps.fanoutResolver.resolveGroupParticipantDeviceJids(participantUserJids);
|
|
216
547
|
if (fanoutDeviceJids.length === 0) {
|
|
217
548
|
throw new Error('group direct send resolved no target devices');
|
|
218
549
|
}
|
|
219
|
-
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
|
+
}
|
|
220
555
|
const uniqueNormalizedFanoutJids = new Set();
|
|
221
556
|
for (let index = 0; index < fanoutDeviceJids.length; index += 1) {
|
|
222
557
|
uniqueNormalizedFanoutJids.add(normalizeDeviceJid(fanoutDeviceJids[index]));
|
|
223
558
|
}
|
|
224
|
-
|
|
225
|
-
|
|
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');
|
|
226
575
|
}
|
|
227
576
|
const participantEncryptRequests = new Array(resolvedFanoutTargets.length);
|
|
228
577
|
for (let index = 0; index < resolvedFanoutTargets.length; index += 1) {
|
|
@@ -232,7 +581,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
232
581
|
plaintext
|
|
233
582
|
};
|
|
234
583
|
}
|
|
235
|
-
const encryptedParticipants = await this.signalProtocol.encryptMessagesBatch(participantEncryptRequests, resolvedFanoutTargets);
|
|
584
|
+
const encryptedParticipants = await this.deps.signalProtocol.encryptMessagesBatch(participantEncryptRequests, resolvedFanoutTargets);
|
|
236
585
|
const participants = new Array(resolvedFanoutTargets.length);
|
|
237
586
|
for (let index = 0; index < resolvedFanoutTargets.length; index += 1) {
|
|
238
587
|
const target = resolvedFanoutTargets[index];
|
|
@@ -250,20 +599,27 @@ export class WaMessageDispatchCoordinator {
|
|
|
250
599
|
}
|
|
251
600
|
}
|
|
252
601
|
const phashTargets = new Array(resolvedFanoutTargets.length + 1);
|
|
602
|
+
let phashTargetCount = 0;
|
|
253
603
|
for (let index = 0; index < resolvedFanoutTargets.length; index += 1) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
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);
|
|
267
623
|
const messageNode = buildDirectMessageFanoutNode({
|
|
268
624
|
to: groupJid,
|
|
269
625
|
type,
|
|
@@ -275,9 +631,10 @@ export class WaMessageDispatchCoordinator {
|
|
|
275
631
|
deviceIdentity: shouldAttachDeviceIdentity
|
|
276
632
|
? this.getEncodedSignedDeviceIdentity()
|
|
277
633
|
: undefined,
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
634
|
+
customNodes: customNodes.length > 0 ? customNodes : undefined,
|
|
635
|
+
mediatype,
|
|
636
|
+
decryptFail: envelope.decryptFail,
|
|
637
|
+
additionalAttributes: sendOptions.additionalAttributes
|
|
281
638
|
});
|
|
282
639
|
const replayPayload = {
|
|
283
640
|
mode: 'plaintext',
|
|
@@ -285,13 +642,12 @@ export class WaMessageDispatchCoordinator {
|
|
|
285
642
|
type,
|
|
286
643
|
plaintext
|
|
287
644
|
};
|
|
288
|
-
const result = await this.retryTracker.track({
|
|
289
|
-
messageIdHint:
|
|
645
|
+
const result = await this.deps.retryTracker.track({
|
|
646
|
+
messageIdHint: messageNode.attrs.id ?? sendOptions.id,
|
|
290
647
|
toJid: groupJid,
|
|
291
|
-
type,
|
|
292
648
|
replayPayload,
|
|
293
649
|
eligibleRequesterDeviceJids: undefined
|
|
294
|
-
}, async () => this.messageClient.publishNode(messageNode, sendOptions));
|
|
650
|
+
}, async () => this.deps.messageClient.publishNode(messageNode, sendOptions));
|
|
295
651
|
const ackError = result.ack.error;
|
|
296
652
|
const serverPhash = result.ack.phash;
|
|
297
653
|
const serverAddressingMode = result.ack.addressingMode;
|
|
@@ -300,7 +656,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
300
656
|
const hasAddressingError = ackError === 421;
|
|
301
657
|
if (!retryContext.retried &&
|
|
302
658
|
(hasPhashMismatch || hasAddressingMismatch || hasAddressingError)) {
|
|
303
|
-
this.logger.warn('group direct publish acknowledged with mismatch metadata', {
|
|
659
|
+
this.deps.logger.warn('group direct publish acknowledged with mismatch metadata', {
|
|
304
660
|
id: result.id,
|
|
305
661
|
groupJid,
|
|
306
662
|
localPhash,
|
|
@@ -309,28 +665,88 @@ export class WaMessageDispatchCoordinator {
|
|
|
309
665
|
serverAddressingMode,
|
|
310
666
|
ackError
|
|
311
667
|
});
|
|
312
|
-
return this.publishGroupDirectMessage(groupJid,
|
|
313
|
-
...
|
|
314
|
-
id: result.id
|
|
668
|
+
return this.publishGroupDirectMessage(groupJid, {
|
|
669
|
+
...envelope,
|
|
670
|
+
sendOptions: { ...sendOptions, id: result.id }
|
|
315
671
|
}, {
|
|
316
672
|
retried: true,
|
|
317
673
|
forceRefreshParticipants: true,
|
|
318
674
|
forceAddressingMode: serverAddressingMode
|
|
319
|
-
}
|
|
675
|
+
});
|
|
320
676
|
}
|
|
321
677
|
return result;
|
|
322
678
|
}
|
|
323
|
-
|
|
324
|
-
|
|
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;
|
|
325
741
|
const meJid = this.requireCurrentMeJid('sendMessage');
|
|
326
742
|
const participantUserJids = retryContext.forceRefreshParticipants
|
|
327
|
-
? await this.
|
|
328
|
-
: await this.
|
|
743
|
+
? await this.deps.groupMetadataCache.refreshParticipantUsers(groupJid)
|
|
744
|
+
: await this.deps.groupMetadataCache.resolveParticipantUsers(groupJid);
|
|
329
745
|
const addressingMode = retryContext.forceAddressingMode ??
|
|
330
746
|
this.resolveGroupAddressingMode(participantUserJids, groupJid);
|
|
331
747
|
const senderJid = this.resolveSenderForAddressingMode(addressingMode, meJid);
|
|
332
748
|
const sender = parseSignalAddressFromJid(senderJid);
|
|
333
|
-
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);
|
|
334
750
|
const distributionData = await this.distributionDedup.run(`dist:${groupJid}:${senderKeyId}`, () => this.encryptGroupDistributionParticipants(groupJid, senderKeyId, senderKeyDistributionMessage, participantUserJids));
|
|
335
751
|
const { fanoutDeviceJids, distributionParticipants } = distributionData;
|
|
336
752
|
let shouldAttachDeviceIdentity = false;
|
|
@@ -341,20 +757,28 @@ export class WaMessageDispatchCoordinator {
|
|
|
341
757
|
}
|
|
342
758
|
}
|
|
343
759
|
const phashTargets = new Array(fanoutDeviceJids.length + 1);
|
|
760
|
+
let phashTargetCount = 0;
|
|
344
761
|
for (let index = 0; index < fanoutDeviceJids.length; index += 1) {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
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);
|
|
358
782
|
const messageNode = buildGroupSenderKeyMessageNode({
|
|
359
783
|
to: groupJid,
|
|
360
784
|
type,
|
|
@@ -364,12 +788,14 @@ export class WaMessageDispatchCoordinator {
|
|
|
364
788
|
addressingMode,
|
|
365
789
|
groupCiphertext: groupCiphertext.ciphertext,
|
|
366
790
|
participants: distributionParticipants,
|
|
367
|
-
deviceIdentity: shouldAttachDeviceIdentity
|
|
791
|
+
deviceIdentity: shouldAttachDeviceIdentity || botSidecar?.encType === 'pkmsg'
|
|
368
792
|
? this.getEncodedSignedDeviceIdentity()
|
|
369
793
|
: undefined,
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
794
|
+
customNodes: customNodes.length > 0 ? customNodes : undefined,
|
|
795
|
+
mediatype,
|
|
796
|
+
decryptFail: envelope.decryptFail,
|
|
797
|
+
botParticipants: botSidecar ? [botSidecar] : undefined,
|
|
798
|
+
additionalAttributes: sendOptions.additionalAttributes
|
|
373
799
|
});
|
|
374
800
|
const replayPayload = {
|
|
375
801
|
mode: 'plaintext',
|
|
@@ -377,22 +803,21 @@ export class WaMessageDispatchCoordinator {
|
|
|
377
803
|
type,
|
|
378
804
|
plaintext
|
|
379
805
|
};
|
|
380
|
-
const result = await this.retryTracker.track({
|
|
381
|
-
messageIdHint:
|
|
806
|
+
const result = await this.deps.retryTracker.track({
|
|
807
|
+
messageIdHint: messageNode.attrs.id ?? sendOptions.id,
|
|
382
808
|
toJid: groupJid,
|
|
383
|
-
type,
|
|
384
809
|
replayPayload,
|
|
385
810
|
eligibleRequesterDeviceJids: undefined
|
|
386
|
-
}, async () => this.messageClient.publishNode(messageNode, sendOptions));
|
|
811
|
+
}, async () => this.deps.messageClient.publishNode(messageNode, sendOptions));
|
|
387
812
|
const distributedAddresses = new Array(distributionParticipants.length);
|
|
388
813
|
for (let index = 0; index < distributionParticipants.length; index += 1) {
|
|
389
814
|
distributedAddresses[index] = distributionParticipants[index].address;
|
|
390
815
|
}
|
|
391
816
|
try {
|
|
392
|
-
await this.senderKeyManager.markSenderKeyDistributed(groupJid, senderKeyId, distributedAddresses);
|
|
817
|
+
await this.deps.senderKeyManager.markSenderKeyDistributed(groupJid, senderKeyId, distributedAddresses);
|
|
393
818
|
}
|
|
394
819
|
catch (error) {
|
|
395
|
-
this.logger.warn('failed to mark sender key distribution targets', {
|
|
820
|
+
this.deps.logger.warn('failed to mark sender key distribution targets', {
|
|
396
821
|
groupJid,
|
|
397
822
|
participants: distributedAddresses.length,
|
|
398
823
|
message: toError(error).message
|
|
@@ -406,7 +831,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
406
831
|
const hasAddressingError = ackError === 421;
|
|
407
832
|
if (!retryContext.retried &&
|
|
408
833
|
(hasPhashMismatch || hasAddressingMismatch || hasAddressingError)) {
|
|
409
|
-
this.logger.warn('group message publish acknowledged with mismatch metadata', {
|
|
834
|
+
this.deps.logger.warn('group message publish acknowledged with mismatch metadata', {
|
|
410
835
|
id: result.id,
|
|
411
836
|
groupJid,
|
|
412
837
|
localPhash,
|
|
@@ -415,14 +840,14 @@ export class WaMessageDispatchCoordinator {
|
|
|
415
840
|
serverAddressingMode,
|
|
416
841
|
ackError
|
|
417
842
|
});
|
|
418
|
-
return this.publishGroupSenderKeyMessage(groupJid,
|
|
419
|
-
...
|
|
420
|
-
id: result.id
|
|
843
|
+
return this.publishGroupSenderKeyMessage(groupJid, {
|
|
844
|
+
...envelope,
|
|
845
|
+
sendOptions: { ...sendOptions, id: result.id }
|
|
421
846
|
}, {
|
|
422
847
|
retried: true,
|
|
423
848
|
forceRefreshParticipants: true,
|
|
424
849
|
forceAddressingMode: serverAddressingMode
|
|
425
|
-
}
|
|
850
|
+
});
|
|
426
851
|
}
|
|
427
852
|
return result;
|
|
428
853
|
}
|
|
@@ -432,7 +857,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
432
857
|
return 'lid';
|
|
433
858
|
}
|
|
434
859
|
}
|
|
435
|
-
this.logger.trace('group addressing mode resolved to pn (default)', {
|
|
860
|
+
this.deps.logger.trace('group addressing mode resolved to pn (default)', {
|
|
436
861
|
groupJid,
|
|
437
862
|
participants: participantUserJids.length
|
|
438
863
|
});
|
|
@@ -440,13 +865,13 @@ export class WaMessageDispatchCoordinator {
|
|
|
440
865
|
}
|
|
441
866
|
resolveSenderForAddressingMode(addressingMode, meJid) {
|
|
442
867
|
if (addressingMode === 'lid') {
|
|
443
|
-
const meLid = this.
|
|
868
|
+
const meLid = this.deps.getCurrentCredentials()?.meLid;
|
|
444
869
|
if (meLid && meLid.includes('@')) {
|
|
445
870
|
try {
|
|
446
871
|
return normalizeDeviceJid(meLid);
|
|
447
872
|
}
|
|
448
873
|
catch (error) {
|
|
449
|
-
this.logger.trace('ignoring malformed me lid jid', {
|
|
874
|
+
this.deps.logger.trace('ignoring malformed me lid jid', {
|
|
450
875
|
meLid,
|
|
451
876
|
message: toError(error).message
|
|
452
877
|
});
|
|
@@ -459,7 +884,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
459
884
|
const distributionPayload = await writeRandomPadMax16(proto.Message.encode({
|
|
460
885
|
senderKeyDistributionMessage
|
|
461
886
|
}).finish());
|
|
462
|
-
const fanoutDeviceJids = await this.fanoutResolver.resolveGroupParticipantDeviceJids(participantUserJids);
|
|
887
|
+
const fanoutDeviceJids = await this.deps.fanoutResolver.resolveGroupParticipantDeviceJids(participantUserJids);
|
|
463
888
|
if (fanoutDeviceJids.length === 0) {
|
|
464
889
|
return {
|
|
465
890
|
fanoutDeviceJids,
|
|
@@ -474,7 +899,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
474
899
|
fanoutAddresses[index] = address;
|
|
475
900
|
fanoutTargetsByAddressKey.set(signalAddressKey(address), { jid, address });
|
|
476
901
|
}
|
|
477
|
-
const pendingAddresses = await this.senderKeyManager.filterParticipantsNeedingDistribution(groupJid, senderKeyId, fanoutAddresses);
|
|
902
|
+
const pendingAddresses = await this.deps.senderKeyManager.filterParticipantsNeedingDistribution(groupJid, senderKeyId, fanoutAddresses);
|
|
478
903
|
if (pendingAddresses.length === 0) {
|
|
479
904
|
return {
|
|
480
905
|
fanoutDeviceJids,
|
|
@@ -507,7 +932,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
507
932
|
let availableTargets = [];
|
|
508
933
|
let prefetchedAvailableTargets;
|
|
509
934
|
try {
|
|
510
|
-
const resolvedTargets = await this.sessionResolver.ensureSessionsBatch(pendingTargetJids);
|
|
935
|
+
const resolvedTargets = await this.deps.sessionResolver.ensureSessionsBatch(pendingTargetJids);
|
|
511
936
|
availableTargets = resolvedTargets;
|
|
512
937
|
prefetchedAvailableTargets = resolvedTargets;
|
|
513
938
|
}
|
|
@@ -516,7 +941,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
516
941
|
if (normalized.message === 'identity mismatch') {
|
|
517
942
|
throw normalized;
|
|
518
943
|
}
|
|
519
|
-
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', {
|
|
520
945
|
groupJid,
|
|
521
946
|
requested: pendingTargetJids.length,
|
|
522
947
|
message: normalized.message
|
|
@@ -525,7 +950,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
525
950
|
for (let index = 0; index < pendingTargets.length; index += 1) {
|
|
526
951
|
pendingTargetAddresses[index] = pendingTargets[index].address;
|
|
527
952
|
}
|
|
528
|
-
const hasPendingSessions = await this.sessionStore.hasSessions(pendingTargetAddresses);
|
|
953
|
+
const hasPendingSessions = await this.deps.sessionStore.hasSessions(pendingTargetAddresses);
|
|
529
954
|
const nextAvailableTargets = [];
|
|
530
955
|
for (let index = 0; index < pendingTargets.length; index += 1) {
|
|
531
956
|
if (hasPendingSessions[index]) {
|
|
@@ -548,7 +973,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
548
973
|
plaintext: distributionPayload
|
|
549
974
|
};
|
|
550
975
|
}
|
|
551
|
-
const encryptedDistributionParticipants = await this.signalProtocol.encryptMessagesBatch(distributionEncryptRequests, prefetchedAvailableTargets);
|
|
976
|
+
const encryptedDistributionParticipants = await this.deps.signalProtocol.encryptMessagesBatch(distributionEncryptRequests, prefetchedAvailableTargets);
|
|
552
977
|
const distributionParticipants = new Array(availableTargets.length);
|
|
553
978
|
for (let index = 0; index < availableTargets.length; index += 1) {
|
|
554
979
|
const target = availableTargets[index];
|
|
@@ -564,12 +989,12 @@ export class WaMessageDispatchCoordinator {
|
|
|
564
989
|
distributionParticipants
|
|
565
990
|
};
|
|
566
991
|
}
|
|
567
|
-
async publishDirectSignalMessageWithFanout(recipientJid,
|
|
568
|
-
const sendOptions =
|
|
992
|
+
async publishDirectSignalMessageWithFanout(recipientJid, envelope) {
|
|
993
|
+
const { message, plaintext, type, edit, mediatype, sendOptions } = envelope;
|
|
569
994
|
const meJid = this.requireCurrentMeJid('sendMessage');
|
|
570
|
-
const meLid = this.
|
|
571
|
-
const selfDeviceJidForRecipient = this.fanoutResolver.resolveSelfDeviceJidForRecipient(recipientJid, meJid, meLid);
|
|
572
|
-
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);
|
|
573
998
|
const targets = new Array(deviceJids.length);
|
|
574
999
|
for (let index = 0; index < deviceJids.length; index += 1) {
|
|
575
1000
|
const jid = deviceJids[index];
|
|
@@ -582,7 +1007,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
582
1007
|
}
|
|
583
1008
|
const recipientUserJid = toUserJid(recipientJid);
|
|
584
1009
|
const meUserJid = toUserJid(selfDeviceJidForRecipient);
|
|
585
|
-
this.logger.
|
|
1010
|
+
this.deps.logger.trace('wa client publish signal fanout', {
|
|
586
1011
|
to: recipientJid,
|
|
587
1012
|
devices: deviceJids.length,
|
|
588
1013
|
type
|
|
@@ -596,20 +1021,42 @@ export class WaMessageDispatchCoordinator {
|
|
|
596
1021
|
}
|
|
597
1022
|
}
|
|
598
1023
|
}
|
|
599
|
-
const resolvedFanoutTargets = await this.sessionResolver.ensureSessionsBatch(deviceJids, expectedIdentityByJid);
|
|
1024
|
+
const resolvedFanoutTargets = await this.deps.sessionResolver.ensureSessionsBatch(deviceJids, expectedIdentityByJid);
|
|
600
1025
|
const resolvedFanoutTargetsByJid = new Map();
|
|
601
1026
|
for (let index = 0; index < resolvedFanoutTargets.length; index += 1) {
|
|
602
1027
|
const target = resolvedFanoutTargets[index];
|
|
603
1028
|
resolvedFanoutTargetsByJid.set(normalizeDeviceJid(target.jid), target);
|
|
604
1029
|
}
|
|
1030
|
+
const liveTargets = [];
|
|
1031
|
+
const droppedSecondaryDevices = [];
|
|
605
1032
|
for (let index = 0; index < targets.length; index += 1) {
|
|
606
|
-
|
|
607
|
-
|
|
1033
|
+
const target = targets[index];
|
|
1034
|
+
if (resolvedFanoutTargetsByJid.has(target.normalizedJid)) {
|
|
1035
|
+
liveTargets.push(target);
|
|
1036
|
+
continue;
|
|
608
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');
|
|
609
1056
|
}
|
|
610
1057
|
let hasSelfDeviceFanout = false;
|
|
611
|
-
for (let index = 0; index <
|
|
612
|
-
if (
|
|
1058
|
+
for (let index = 0; index < liveTargets.length; index += 1) {
|
|
1059
|
+
if (liveTargets[index].userJid === meUserJid) {
|
|
613
1060
|
hasSelfDeviceFanout = true;
|
|
614
1061
|
break;
|
|
615
1062
|
}
|
|
@@ -617,13 +1064,10 @@ export class WaMessageDispatchCoordinator {
|
|
|
617
1064
|
const selfDevicePlaintext = hasSelfDeviceFanout
|
|
618
1065
|
? await writeRandomPadMax16(proto.Message.encode(wrapDeviceSentMessage(message, recipientUserJid)).finish())
|
|
619
1066
|
: null;
|
|
620
|
-
const participantRequests = new Array(
|
|
621
|
-
for (let index = 0; index <
|
|
622
|
-
const target =
|
|
1067
|
+
const participantRequests = new Array(liveTargets.length);
|
|
1068
|
+
for (let index = 0; index < liveTargets.length; index += 1) {
|
|
1069
|
+
const target = liveTargets[index];
|
|
623
1070
|
const resolvedTarget = resolvedFanoutTargetsByJid.get(target.normalizedJid);
|
|
624
|
-
if (!resolvedTarget) {
|
|
625
|
-
throw new Error('direct fanout missing signal session for target');
|
|
626
|
-
}
|
|
627
1071
|
participantRequests[index] = {
|
|
628
1072
|
target,
|
|
629
1073
|
address: resolvedTarget.address,
|
|
@@ -648,15 +1092,20 @@ export class WaMessageDispatchCoordinator {
|
|
|
648
1092
|
session: request.session
|
|
649
1093
|
};
|
|
650
1094
|
}
|
|
651
|
-
const encryptedParticipants = await this.signalProtocol.encryptMessagesBatch(encryptRequests, prefetchedSessions);
|
|
652
|
-
const
|
|
1095
|
+
const encryptedParticipants = await this.deps.signalProtocol.encryptMessagesBatch(encryptRequests, prefetchedSessions);
|
|
1096
|
+
const isBotRecipient = isBotJid(recipientJid);
|
|
1097
|
+
const participants = [];
|
|
653
1098
|
for (let index = 0; index < participantRequests.length; index += 1) {
|
|
654
1099
|
const request = participantRequests[index];
|
|
655
|
-
|
|
1100
|
+
const entry = {
|
|
656
1101
|
jid: request.target.jid,
|
|
657
1102
|
encType: encryptedParticipants[index].type,
|
|
658
1103
|
ciphertext: encryptedParticipants[index].ciphertext
|
|
659
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);
|
|
660
1109
|
}
|
|
661
1110
|
let shouldAttachDeviceIdentity = false;
|
|
662
1111
|
for (let index = 0; index < participants.length; index += 1) {
|
|
@@ -676,16 +1125,23 @@ export class WaMessageDispatchCoordinator {
|
|
|
676
1125
|
context: 'direct_fanout'
|
|
677
1126
|
});
|
|
678
1127
|
let privacyTokenNode;
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
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
|
+
}
|
|
688
1139
|
}
|
|
1140
|
+
const customNodes = envelope.customNodes ? [...envelope.customNodes] : [];
|
|
1141
|
+
if (reportingArtifacts?.node)
|
|
1142
|
+
customNodes.push(reportingArtifacts.node);
|
|
1143
|
+
if (privacyTokenNode)
|
|
1144
|
+
customNodes.push(privacyTokenNode);
|
|
689
1145
|
const messageNode = buildDirectMessageFanoutNode({
|
|
690
1146
|
to: recipientJid,
|
|
691
1147
|
type,
|
|
@@ -693,10 +1149,10 @@ export class WaMessageDispatchCoordinator {
|
|
|
693
1149
|
edit,
|
|
694
1150
|
participants,
|
|
695
1151
|
deviceIdentity,
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
1152
|
+
customNodes: customNodes.length > 0 ? customNodes : undefined,
|
|
1153
|
+
mediatype,
|
|
1154
|
+
decryptFail: envelope.decryptFail,
|
|
1155
|
+
additionalAttributes: sendOptions.additionalAttributes
|
|
700
1156
|
});
|
|
701
1157
|
const replayPayload = {
|
|
702
1158
|
mode: 'plaintext',
|
|
@@ -704,14 +1160,13 @@ export class WaMessageDispatchCoordinator {
|
|
|
704
1160
|
type,
|
|
705
1161
|
plaintext
|
|
706
1162
|
};
|
|
707
|
-
const result = await this.retryTracker.track({
|
|
708
|
-
messageIdHint:
|
|
1163
|
+
const result = await this.deps.retryTracker.track({
|
|
1164
|
+
messageIdHint: messageNode.attrs.id ?? sendOptions.id,
|
|
709
1165
|
toJid: recipientJid,
|
|
710
|
-
type,
|
|
711
1166
|
replayPayload,
|
|
712
1167
|
eligibleRequesterDeviceJids: deviceJids
|
|
713
|
-
}, async () => this.messageClient.publishNode(messageNode, sendOptions));
|
|
714
|
-
this.onDirectMessageSent(recipientUserJid);
|
|
1168
|
+
}, async () => this.deps.messageClient.publishNode(messageNode, sendOptions));
|
|
1169
|
+
this.deps.onDirectMessageSent(recipientUserJid);
|
|
715
1170
|
return result;
|
|
716
1171
|
}
|
|
717
1172
|
async withResolvedMessageId(options) {
|
|
@@ -737,26 +1192,24 @@ export class WaMessageDispatchCoordinator {
|
|
|
737
1192
|
const dv = new DataView(timestampBytes.buffer, timestampBytes.byteOffset, timestampBytes.byteLength);
|
|
738
1193
|
if (this.mobileMessageIdFormat) {
|
|
739
1194
|
dv.setBigUint64(0, BigInt(Date.now()), false);
|
|
740
|
-
const
|
|
1195
|
+
const digest = md5Bytes([
|
|
741
1196
|
timestampBytes,
|
|
742
1197
|
TEXT_ENCODER.encode(meUserJid),
|
|
743
1198
|
await randomBytesAsync(16)
|
|
744
1199
|
]);
|
|
745
|
-
const digest = md5Bytes(entropy);
|
|
746
1200
|
digest[0] = 0xac;
|
|
747
1201
|
return bytesToHex(digest).toUpperCase();
|
|
748
1202
|
}
|
|
749
1203
|
dv.setBigUint64(0, BigInt(Math.floor(Date.now() / 1000)), false);
|
|
750
|
-
const
|
|
1204
|
+
const digest = sha256([
|
|
751
1205
|
timestampBytes,
|
|
752
1206
|
TEXT_ENCODER.encode(meUserJid),
|
|
753
1207
|
await randomBytesAsync(8)
|
|
754
1208
|
]);
|
|
755
|
-
const digest = await sha256(entropy);
|
|
756
1209
|
return `3EB0${bytesToHex(digest.subarray(0, 9)).toUpperCase()}`;
|
|
757
1210
|
}
|
|
758
1211
|
catch (error) {
|
|
759
|
-
this.logger.warn('failed to generate message id, falling back to random', {
|
|
1212
|
+
this.deps.logger.warn('failed to generate message id, falling back to random', {
|
|
760
1213
|
message: toError(error).message
|
|
761
1214
|
});
|
|
762
1215
|
if (this.mobileMessageIdFormat) {
|
|
@@ -780,7 +1233,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
780
1233
|
});
|
|
781
1234
|
}
|
|
782
1235
|
catch (error) {
|
|
783
|
-
this.logger.warn('failed to generate reporting token', {
|
|
1236
|
+
this.deps.logger.warn('failed to generate reporting token', {
|
|
784
1237
|
context: input.context,
|
|
785
1238
|
id: input.stanzaId,
|
|
786
1239
|
remoteJid: input.remoteJid,
|
|
@@ -790,7 +1243,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
790
1243
|
}
|
|
791
1244
|
}
|
|
792
1245
|
getEncodedSignedDeviceIdentity() {
|
|
793
|
-
const signedIdentity = this.
|
|
1246
|
+
const signedIdentity = this.deps.getCurrentCredentials()?.signedIdentity;
|
|
794
1247
|
if (!signedIdentity) {
|
|
795
1248
|
return undefined;
|
|
796
1249
|
}
|
|
@@ -799,15 +1252,15 @@ export class WaMessageDispatchCoordinator {
|
|
|
799
1252
|
resolveUserIcdc(userJid, localIdentity) {
|
|
800
1253
|
return this.icdcDedup.run(`icdc:${userJid}:${localIdentity ? '1' : '0'}`, async () => {
|
|
801
1254
|
try {
|
|
802
|
-
const snapshots = await this.deviceListStore.getUserDevicesBatch([userJid]);
|
|
1255
|
+
const snapshots = await this.deps.deviceListStore.getUserDevicesBatch([userJid]);
|
|
803
1256
|
const snapshot = snapshots[0];
|
|
804
1257
|
if (!snapshot || snapshot.deviceJids.length === 0) {
|
|
805
1258
|
return null;
|
|
806
1259
|
}
|
|
807
|
-
return resolveIcdcMeta(snapshot.deviceJids, this.identityStore, snapshot.updatedAtMs, localIdentity, this.getIcdcHashLength?.());
|
|
1260
|
+
return resolveIcdcMeta(snapshot.deviceJids, this.deps.identityStore, snapshot.updatedAtMs, localIdentity, this.deps.getIcdcHashLength?.());
|
|
808
1261
|
}
|
|
809
1262
|
catch (error) {
|
|
810
|
-
this.logger.trace('icdc resolution failed', {
|
|
1263
|
+
this.deps.logger.trace('icdc resolution failed', {
|
|
811
1264
|
userJid,
|
|
812
1265
|
message: toError(error).message
|
|
813
1266
|
});
|
|
@@ -816,10 +1269,35 @@ export class WaMessageDispatchCoordinator {
|
|
|
816
1269
|
});
|
|
817
1270
|
}
|
|
818
1271
|
requireCurrentMeJid(context) {
|
|
819
|
-
const meJid = this.
|
|
1272
|
+
const meJid = this.deps.getCurrentCredentials()?.meJid;
|
|
820
1273
|
if (meJid) {
|
|
821
1274
|
return meJid;
|
|
822
1275
|
}
|
|
823
1276
|
throw new Error(`${context} requires registered meJid`);
|
|
824
1277
|
}
|
|
825
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
|
+
}
|