zapo-js 0.2.0 → 0.3.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/README.md +7 -3
- package/dist/appstate/WaAppStateCrypto.js +49 -41
- package/dist/appstate/WaAppStateSyncClient.js +79 -42
- package/dist/appstate/index.js +2 -2
- package/dist/auth/WaAuthClient.js +20 -11
- package/dist/auth/{flow/WaAuthCredentialsFlow.js → credentials-flow.js} +83 -18
- package/dist/auth/pairing/WaPairingFlow.js +26 -29
- package/dist/auth/pairing/{WaPairingCodeCrypto.js → pairing-code-crypto.js} +29 -13
- package/dist/client/WaClient.js +115 -75
- package/dist/client/WaClientFactory.js +113 -30
- package/dist/client/connection/WaConnectionManager.js +4 -1
- package/dist/client/coordinators/WaAbPropsCoordinator.js +141 -0
- package/dist/client/coordinators/WaBusinessCoordinator.js +3 -12
- package/dist/client/coordinators/WaEmailCoordinator.js +63 -0
- package/dist/client/coordinators/WaIncomingNodeCoordinator.js +33 -8
- package/dist/client/coordinators/WaMessageDispatchCoordinator.js +55 -25
- package/dist/client/coordinators/WaOfflineResumeCoordinator.js +114 -0
- package/dist/client/coordinators/WaPassiveTasksCoordinator.js +38 -20
- package/dist/client/coordinators/WaProfileCoordinator.js +3 -1
- package/dist/client/coordinators/WaRetryCoordinator.js +11 -9
- package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +22 -4
- package/dist/client/dirty.js +1 -1
- package/dist/client/events/abprops.js +43 -0
- package/dist/client/events/privacy-token.js +1 -2
- package/dist/client/events/registration.js +42 -0
- package/dist/client/incoming.js +37 -0
- package/dist/client/mailbox.js +17 -1
- package/dist/client/media.js +243 -0
- package/dist/client/messages.js +163 -86
- package/dist/crypto/core/index.js +4 -1
- package/dist/crypto/core/random.js +3 -9
- package/dist/crypto/core/xeddsa.js +57 -0
- package/dist/crypto/curves/X25519.js +18 -0
- package/dist/crypto/curves/constants.js +2 -1
- package/dist/esm/appstate/WaAppStateCrypto.js +39 -31
- package/dist/esm/appstate/WaAppStateSyncClient.js +68 -31
- package/dist/esm/appstate/index.js +1 -1
- package/dist/esm/appstate/{WaAppStateSyncResponseParser.js → response-parser.js} +1 -1
- package/dist/esm/auth/WaAuthClient.js +17 -8
- package/dist/esm/auth/{flow/WaAuthCredentialsFlow.js → credentials-flow.js} +83 -18
- package/dist/esm/auth/pairing/WaPairingFlow.js +25 -28
- package/dist/esm/auth/pairing/{WaPairingCodeCrypto.js → pairing-code-crypto.js} +20 -6
- package/dist/esm/client/WaClient.js +116 -76
- package/dist/esm/client/WaClientFactory.js +114 -31
- package/dist/esm/client/connection/WaConnectionManager.js +4 -1
- package/dist/esm/client/coordinators/WaAbPropsCoordinator.js +137 -0
- package/dist/esm/client/coordinators/WaBusinessCoordinator.js +4 -13
- package/dist/esm/client/coordinators/WaEmailCoordinator.js +60 -0
- package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +35 -10
- package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +47 -17
- package/dist/esm/client/coordinators/WaOfflineResumeCoordinator.js +110 -0
- package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +38 -20
- package/dist/esm/client/coordinators/WaProfileCoordinator.js +3 -1
- package/dist/esm/client/coordinators/WaRetryCoordinator.js +11 -9
- package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +24 -6
- package/dist/esm/client/dirty.js +1 -1
- package/dist/esm/client/events/abprops.js +40 -0
- package/dist/esm/client/events/privacy-token.js +1 -2
- package/dist/esm/client/events/registration.js +39 -0
- package/dist/esm/client/incoming.js +36 -0
- package/dist/esm/client/mailbox.js +17 -1
- package/dist/esm/client/media.js +234 -0
- package/dist/esm/client/messages.js +162 -85
- package/dist/esm/crypto/core/index.js +1 -0
- package/dist/esm/crypto/core/random.js +2 -7
- package/dist/esm/crypto/core/xeddsa.js +53 -0
- package/dist/esm/crypto/curves/X25519.js +20 -2
- package/dist/esm/crypto/curves/constants.js +1 -0
- package/dist/esm/infra/perf/StoreLock.js +7 -4
- package/dist/esm/media/WaMediaCrypto.js +257 -62
- package/dist/esm/media/WaMediaTransferClient.js +47 -190
- package/dist/esm/media/constants.js +2 -0
- package/dist/esm/media/processor.js +1 -0
- package/dist/esm/message/addon-crypto.js +130 -3
- package/dist/esm/message/content.js +12 -6
- package/dist/esm/message/icdc.js +8 -8
- package/dist/esm/message/incoming.js +14 -12
- package/dist/esm/message/phash.js +32 -12
- package/dist/esm/message/reporting-token.js +3 -3
- package/dist/esm/message/use-case-secret.js +1 -1
- package/dist/esm/protocol/abprops.js +159 -0
- package/dist/esm/protocol/browser.js +14 -0
- package/dist/esm/protocol/constants.js +3 -1
- package/dist/esm/protocol/email.js +30 -0
- package/dist/esm/protocol/jid.js +44 -10
- package/dist/esm/protocol/nodes.js +6 -2
- package/dist/esm/protocol/notification.js +7 -1
- package/dist/esm/retry/reason.js +1 -1
- package/dist/esm/signal/api/SignalDeviceSyncApi.js +5 -2
- package/dist/esm/signal/api/SignalDigestSyncApi.js +8 -6
- package/dist/esm/signal/api/SignalIdentitySyncApi.js +4 -4
- package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +1 -1
- package/dist/esm/signal/api/SignalSessionSyncApi.js +1 -1
- package/dist/esm/signal/crypto/WaAdvSignature.js +5 -51
- package/dist/esm/signal/crypto/constants.js +0 -4
- package/dist/esm/signal/encoding.js +11 -54
- package/dist/esm/signal/group/SenderKeyChain.js +3 -3
- package/dist/esm/signal/group/SenderKeyCodec.js +5 -6
- package/dist/esm/signal/group/SenderKeyManager.js +13 -10
- package/dist/esm/signal/registration/keygen.js +2 -3
- package/dist/esm/signal/registration/utils.js +2 -2
- package/dist/esm/signal/session/SignalProtocol.js +18 -17
- package/dist/esm/signal/session/SignalRatchet.js +21 -10
- package/dist/esm/signal/session/SignalSerializer.js +5 -6
- package/dist/esm/signal/session/SignalSession.js +11 -9
- package/dist/esm/signal/session/resolver.js +6 -6
- package/dist/esm/store/contracts/identity.store.js +1 -0
- package/dist/esm/store/contracts/message-secret.store.js +1 -0
- package/dist/esm/store/contracts/pre-key.store.js +1 -0
- package/dist/esm/store/contracts/session.store.js +1 -0
- package/dist/esm/store/createStore.js +48 -12
- package/dist/esm/store/index.js +4 -0
- package/dist/esm/store/locks/identity.lock.js +16 -0
- package/dist/esm/store/locks/message-secret.lock.js +17 -0
- package/dist/esm/store/locks/pre-key.lock.js +27 -0
- package/dist/esm/store/locks/session.lock.js +19 -0
- package/dist/esm/store/locks/signal.lock.js +0 -24
- package/dist/esm/store/noop.store.js +20 -0
- package/dist/esm/store/providers/memory/device-list.store.js +3 -0
- package/dist/esm/store/providers/memory/identity.store.js +31 -0
- package/dist/esm/store/providers/memory/message-secret.store.js +81 -0
- package/dist/esm/store/providers/memory/participants.store.js +3 -0
- package/dist/esm/store/providers/memory/pre-key.store.js +97 -0
- package/dist/esm/store/providers/memory/retry.store.js +25 -11
- package/dist/esm/store/providers/memory/session.store.js +45 -0
- package/dist/esm/store/providers/memory/signal.store.js +1 -164
- package/dist/esm/transport/WaComms.js +4 -3
- package/dist/esm/transport/WaWebSocket.js +9 -1
- package/dist/esm/transport/index.js +6 -0
- package/dist/esm/transport/keepalive/WaKeepAlive.js +17 -8
- package/dist/esm/transport/node/WaMobileTcpSocket.js +114 -0
- package/dist/esm/transport/node/WaNodeOrchestrator.js +17 -8
- package/dist/esm/transport/node/builders/abprops.js +20 -0
- package/dist/esm/transport/node/builders/device.js +11 -0
- package/dist/esm/transport/node/builders/email.js +65 -0
- package/dist/esm/transport/node/builders/offline.js +14 -0
- package/dist/esm/transport/node/builders/prekeys.js +37 -40
- package/dist/esm/transport/node/builders/presence.js +13 -0
- package/dist/esm/transport/node/builders/privacy-token.js +19 -23
- package/dist/esm/transport/node/builders/retry.js +1 -1
- package/dist/esm/transport/node/helpers.js +24 -0
- package/dist/esm/transport/node/mex/argo-decoder.js +152 -0
- package/dist/esm/transport/node/mex/client.js +83 -0
- package/dist/esm/transport/node/mex/persist-ids.js +10 -0
- package/dist/esm/transport/noise/WaClientPayload.js +15 -10
- package/dist/esm/transport/noise/WaFrameCodec.js +2 -2
- package/dist/esm/transport/noise/WaMobileClientPayload.js +53 -0
- package/dist/esm/transport/noise/WaNoiseCert.js +9 -27
- package/dist/esm/transport/noise/WaNoiseSession.js +12 -11
- package/dist/infra/perf/StoreLock.js +7 -4
- package/dist/media/WaMediaCrypto.js +253 -58
- package/dist/media/WaMediaTransferClient.js +50 -223
- package/dist/media/constants.js +3 -1
- package/dist/media/processor.js +2 -0
- package/dist/message/addon-crypto.js +131 -0
- package/dist/message/content.js +13 -5
- package/dist/message/icdc.js +8 -8
- package/dist/message/incoming.js +14 -12
- package/dist/message/phash.js +32 -12
- package/dist/message/reporting-token.js +2 -2
- package/dist/message/use-case-secret.js +1 -1
- package/dist/protocol/abprops.js +163 -0
- package/dist/protocol/browser.js +15 -0
- package/dist/protocol/constants.js +14 -2
- package/dist/protocol/email.js +33 -0
- package/dist/protocol/jid.js +45 -10
- package/dist/protocol/nodes.js +6 -2
- package/dist/protocol/notification.js +8 -2
- package/dist/retry/reason.js +1 -1
- package/dist/signal/api/SignalDeviceSyncApi.js +5 -2
- package/dist/signal/api/SignalDigestSyncApi.js +8 -6
- package/dist/signal/api/SignalIdentitySyncApi.js +4 -4
- package/dist/signal/crypto/WaAdvSignature.js +2 -50
- package/dist/signal/crypto/constants.js +1 -5
- package/dist/signal/encoding.js +11 -49
- package/dist/signal/group/SenderKeyChain.js +2 -2
- package/dist/signal/group/SenderKeyCodec.js +4 -5
- package/dist/signal/group/SenderKeyManager.js +12 -9
- package/dist/signal/registration/keygen.js +1 -2
- package/dist/signal/registration/utils.js +2 -2
- package/dist/signal/session/SignalProtocol.js +18 -17
- package/dist/signal/session/SignalRatchet.js +19 -8
- package/dist/signal/session/SignalSerializer.js +5 -6
- package/dist/signal/session/SignalSession.js +11 -9
- package/dist/signal/session/resolver.js +6 -6
- package/dist/store/contracts/identity.store.js +2 -0
- package/dist/store/contracts/message-secret.store.js +2 -0
- package/dist/store/contracts/pre-key.store.js +2 -0
- package/dist/store/contracts/session.store.js +2 -0
- package/dist/store/createStore.js +47 -11
- package/dist/store/index.js +9 -1
- package/dist/store/locks/identity.lock.js +19 -0
- package/dist/store/locks/message-secret.lock.js +20 -0
- package/dist/store/locks/pre-key.lock.js +30 -0
- package/dist/store/locks/session.lock.js +22 -0
- package/dist/store/locks/signal.lock.js +0 -24
- package/dist/store/noop.store.js +21 -1
- package/dist/store/providers/memory/device-list.store.js +3 -0
- package/dist/store/providers/memory/identity.store.js +35 -0
- package/dist/store/providers/memory/message-secret.store.js +85 -0
- package/dist/store/providers/memory/participants.store.js +3 -0
- package/dist/store/providers/memory/pre-key.store.js +101 -0
- package/dist/store/providers/memory/retry.store.js +24 -10
- package/dist/store/providers/memory/session.store.js +49 -0
- package/dist/store/providers/memory/signal.store.js +1 -164
- package/dist/transport/WaComms.js +4 -3
- package/dist/transport/WaWebSocket.js +9 -1
- package/dist/transport/index.js +17 -1
- package/dist/transport/keepalive/WaKeepAlive.js +17 -8
- package/dist/transport/node/WaMobileTcpSocket.js +118 -0
- package/dist/transport/node/WaNodeOrchestrator.js +16 -7
- package/dist/transport/node/builders/abprops.js +23 -0
- package/dist/transport/node/builders/device.js +14 -0
- package/dist/transport/node/builders/email.js +72 -0
- package/dist/transport/node/builders/offline.js +17 -0
- package/dist/transport/node/builders/prekeys.js +36 -39
- package/dist/transport/node/builders/presence.js +16 -0
- package/dist/transport/node/builders/privacy-token.js +18 -22
- package/dist/transport/node/builders/retry.js +1 -1
- package/dist/transport/node/helpers.js +26 -0
- package/dist/transport/node/mex/argo-decoder.js +189 -0
- package/dist/transport/node/mex/client.js +86 -0
- package/dist/transport/node/mex/persist-ids.js +13 -0
- package/dist/transport/noise/WaClientPayload.js +14 -9
- package/dist/transport/noise/WaFrameCodec.js +1 -1
- package/dist/transport/noise/WaMobileClientPayload.js +56 -0
- package/dist/transport/noise/WaNoiseCert.js +8 -26
- package/dist/transport/noise/WaNoiseSession.js +11 -10
- package/dist/types/appstate/WaAppStateCrypto.d.ts +11 -8
- package/dist/types/appstate/WaAppStateSyncClient.d.ts +6 -2
- package/dist/types/appstate/index.d.ts +1 -1
- package/dist/types/appstate/{WaAppStateSyncResponseParser.d.ts → response-parser.d.ts} +1 -1
- package/dist/types/appstate/types.d.ts +1 -1
- package/dist/types/auth/WaAuthClient.d.ts +9 -3
- package/dist/types/auth/credentials-flow.d.ts +20 -0
- package/dist/types/auth/pairing/WaPairingFlow.d.ts +3 -2
- package/dist/types/auth/pairing/{WaPairingCodeCrypto.d.ts → pairing-code-crypto.d.ts} +6 -1
- package/dist/types/auth/types.d.ts +40 -0
- package/dist/types/client/WaClient.d.ts +19 -8
- package/dist/types/client/WaClientFactory.d.ts +10 -4
- package/dist/types/client/coordinators/WaAbPropsCoordinator.d.ts +26 -0
- package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +1 -1
- package/dist/types/client/coordinators/WaEmailCoordinator.d.ts +24 -0
- package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +6 -1
- package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +15 -2
- package/dist/types/client/coordinators/WaOfflineResumeCoordinator.d.ts +31 -0
- package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +13 -2
- package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +1 -1
- package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +4 -2
- package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +6 -0
- package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +11 -1
- package/dist/types/client/dirty.d.ts +3 -1
- package/dist/types/client/events/abprops.d.ts +14 -0
- package/dist/types/client/events/registration.d.ts +17 -0
- package/dist/types/client/incoming.d.ts +6 -1
- package/dist/types/client/mailbox.d.ts +2 -0
- package/dist/types/client/media.d.ts +31 -0
- package/dist/types/client/messages.d.ts +2 -0
- package/dist/types/client/persistence/WriteBehindPersistence.d.ts +1 -1
- package/dist/types/client/types.d.ts +100 -1
- package/dist/types/crypto/core/index.d.ts +1 -0
- package/dist/types/crypto/core/primitives.d.ts +1 -1
- package/dist/types/crypto/core/random.d.ts +1 -1
- package/dist/types/crypto/core/xeddsa.d.ts +2 -0
- package/dist/types/crypto/curves/constants.d.ts +1 -0
- package/dist/types/crypto/index.d.ts +1 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/infra/log/ConsoleLogger.d.ts +1 -1
- package/dist/types/infra/log/PinoLogger.d.ts +1 -1
- package/dist/types/infra/perf/StoreLock.d.ts +1 -0
- package/dist/types/media/WaMediaCrypto.d.ts +15 -6
- package/dist/types/media/WaMediaTransferClient.d.ts +3 -11
- package/dist/types/media/constants.d.ts +2 -0
- package/dist/types/media/index.d.ts +1 -0
- package/dist/types/media/processor.d.ts +28 -0
- package/dist/types/media/types.d.ts +9 -3
- package/dist/types/message/addon-crypto.d.ts +34 -3
- package/dist/types/message/content.d.ts +3 -1
- package/dist/types/message/icdc.d.ts +4 -4
- package/dist/types/message/types.d.ts +16 -24
- package/dist/types/protocol/abprops.d.ts +142 -0
- package/dist/types/protocol/browser.d.ts +1 -0
- package/dist/types/protocol/constants.d.ts +5 -1
- package/dist/types/protocol/email.d.ts +32 -0
- package/dist/types/protocol/jid.d.ts +1 -0
- package/dist/types/protocol/nodes.d.ts +4 -0
- package/dist/types/protocol/notification.d.ts +6 -0
- package/dist/types/protocol/stream.d.ts +1 -0
- package/dist/types/retry/reason.d.ts +1 -1
- package/dist/types/signal/api/SignalDigestSyncApi.d.ts +3 -0
- package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +3 -3
- package/dist/types/signal/crypto/WaAdvSignature.d.ts +0 -2
- package/dist/types/signal/crypto/constants.d.ts +0 -1
- package/dist/types/signal/encoding.d.ts +7 -1
- package/dist/types/signal/group/SenderKeyChain.d.ts +1 -1
- package/dist/types/signal/group/SenderKeyManager.d.ts +7 -2
- package/dist/types/signal/registration/utils.d.ts +2 -1
- package/dist/types/signal/session/SignalProtocol.d.ts +11 -2
- package/dist/types/signal/session/SignalSerializer.d.ts +2 -1
- package/dist/types/signal/session/resolver.d.ts +4 -2
- package/dist/types/signal/types.d.ts +16 -4
- package/dist/types/store/contracts/identity.store.d.ts +11 -0
- package/dist/types/store/contracts/message-secret.store.d.ts +16 -0
- package/dist/types/store/contracts/pre-key.store.d.ts +13 -0
- package/dist/types/store/contracts/session.store.d.ts +14 -0
- package/dist/types/store/contracts/signal.store.d.ts +1 -34
- package/dist/types/store/index.d.ts +9 -1
- package/dist/types/store/locks/identity.lock.d.ts +3 -0
- package/dist/types/store/locks/message-secret.lock.d.ts +3 -0
- package/dist/types/store/locks/pre-key.lock.d.ts +3 -0
- package/dist/types/store/locks/session.lock.d.ts +3 -0
- package/dist/types/store/noop.store.d.ts +4 -0
- package/dist/types/store/providers/memory/identity.store.d.ts +18 -0
- package/dist/types/store/providers/memory/message-secret.store.d.ts +21 -0
- package/dist/types/store/providers/memory/pre-key.store.d.ts +23 -0
- package/dist/types/store/providers/memory/retry.store.d.ts +7 -1
- package/dist/types/store/providers/memory/session.store.d.ts +21 -0
- package/dist/types/store/providers/memory/signal.store.d.ts +3 -45
- package/dist/types/store/providers/memory/thread.store.d.ts +1 -1
- package/dist/types/store/types.d.ts +21 -1
- package/dist/types/transport/WaWebSocket.d.ts +1 -0
- package/dist/types/transport/index.d.ts +8 -1
- package/dist/types/transport/keepalive/WaKeepAlive.d.ts +4 -1
- package/dist/types/transport/node/WaMobileTcpSocket.d.ts +18 -0
- package/dist/types/transport/node/WaNodeOrchestrator.d.ts +6 -2
- package/dist/types/transport/node/builders/abprops.d.ts +5 -0
- package/dist/types/transport/node/builders/device.d.ts +2 -0
- package/dist/types/transport/node/builders/email.d.ts +11 -0
- package/dist/types/transport/node/builders/offline.d.ts +2 -0
- package/dist/types/transport/node/builders/prekeys.d.ts +4 -3
- package/dist/types/transport/node/builders/presence.d.ts +6 -0
- package/dist/types/transport/node/helpers.d.ts +3 -0
- package/dist/types/transport/node/mex/argo-decoder.d.ts +11 -0
- package/dist/types/transport/node/mex/client.d.ts +18 -0
- package/dist/types/transport/node/mex/persist-ids.d.ts +14 -0
- package/dist/types/transport/noise/WaMobileClientPayload.d.ts +29 -0
- package/dist/types/transport/noise/WaNoiseCert.d.ts +7 -1
- package/dist/types/transport/noise/WaNoiseSession.d.ts +1 -0
- package/dist/types/transport/types.d.ts +8 -0
- package/package.json +6 -4
- package/dist/auth/pairing/constants.js +0 -5
- package/dist/client/connection/WaKeyShareCoordinator.js +0 -63
- package/dist/esm/auth/pairing/constants.js +0 -2
- package/dist/esm/client/connection/WaKeyShareCoordinator.js +0 -59
- package/dist/esm/transport/node/builders/index.js +0 -11
- package/dist/transport/node/builders/index.js +0 -51
- package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +0 -14
- package/dist/types/auth/pairing/constants.d.ts +0 -2
- package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +0 -14
- package/dist/types/transport/node/builders/index.d.ts +0 -11
- /package/dist/appstate/{WaAppStateSyncResponseParser.js → response-parser.js} +0 -0
|
@@ -200,7 +200,10 @@ export class WaConnectionManager {
|
|
|
200
200
|
this.logger.debug('starting comms with credentials', {
|
|
201
201
|
registered: credentials.meJid !== null && credentials.meJid !== undefined
|
|
202
202
|
});
|
|
203
|
-
const commsConfig = this.authClient.buildCommsConfig(this.options
|
|
203
|
+
const commsConfig = this.authClient.buildCommsConfig(this.options, {
|
|
204
|
+
noiseTrustedRootCa: this.options.testHooks?.noiseRootCa,
|
|
205
|
+
disableNoiseCertificateChainVerification: this.options.dangerous?.disableNoiseCertificateChainVerification
|
|
206
|
+
});
|
|
204
207
|
const comms = new WaComms(commsConfig, this.logger);
|
|
205
208
|
this.pendingComms = comms;
|
|
206
209
|
this.mediaConnCache = null;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { parseAbPropsIqResult } from '../events/abprops.js';
|
|
2
|
+
import { AB_PROP_CONFIGS, resolveAbPropNameByCode, WA_ABPROPS_REFRESH_BOUNDS } from '../../protocol/abprops.js';
|
|
3
|
+
import { WA_DEFAULTS } from '../../protocol/constants.js';
|
|
4
|
+
import { buildGetAbPropsIq } from '../../transport/node/builders/abprops.js';
|
|
5
|
+
import { toError } from '../../util/primitives.js';
|
|
6
|
+
export class WaAbPropsCoordinator {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.logger = options.logger;
|
|
9
|
+
this.runtime = options.runtime;
|
|
10
|
+
this.cache = new Map();
|
|
11
|
+
this.syncState = { hash: null, abKey: null, refreshId: null };
|
|
12
|
+
this.syncPromise = null;
|
|
13
|
+
this.syncEpoch = 0;
|
|
14
|
+
this.pendingSync = false;
|
|
15
|
+
}
|
|
16
|
+
getConfigValue(name) {
|
|
17
|
+
const cached = this.cache.get(name);
|
|
18
|
+
if (cached !== undefined) {
|
|
19
|
+
return cached;
|
|
20
|
+
}
|
|
21
|
+
return AB_PROP_CONFIGS[name].defaultValue;
|
|
22
|
+
}
|
|
23
|
+
sync() {
|
|
24
|
+
if (this.syncPromise) {
|
|
25
|
+
this.pendingSync = true;
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
this.startSync();
|
|
29
|
+
}
|
|
30
|
+
reset() {
|
|
31
|
+
this.cache.clear();
|
|
32
|
+
this.syncState.hash = null;
|
|
33
|
+
this.syncState.abKey = null;
|
|
34
|
+
this.syncState.refreshId = null;
|
|
35
|
+
this.syncPromise = null;
|
|
36
|
+
this.pendingSync = false;
|
|
37
|
+
this.syncEpoch += 1;
|
|
38
|
+
}
|
|
39
|
+
startSync() {
|
|
40
|
+
const epoch = this.syncEpoch;
|
|
41
|
+
this.pendingSync = false;
|
|
42
|
+
this.syncPromise = this.executeSyncWithRetry(epoch)
|
|
43
|
+
.catch((error) => {
|
|
44
|
+
this.logger.warn('ab props sync failed', {
|
|
45
|
+
message: toError(error).message
|
|
46
|
+
});
|
|
47
|
+
})
|
|
48
|
+
.finally(() => {
|
|
49
|
+
if (this.syncEpoch !== epoch) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
this.syncPromise = null;
|
|
53
|
+
if (this.pendingSync) {
|
|
54
|
+
this.startSync();
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async executeSyncWithRetry(epoch) {
|
|
59
|
+
const maxRetries = 3;
|
|
60
|
+
for (let attempt = 0; attempt < maxRetries; attempt += 1) {
|
|
61
|
+
if (this.syncEpoch !== epoch) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
await this.executeSync(epoch);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
if (attempt === maxRetries - 1) {
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
this.logger.debug('ab props sync retrying', {
|
|
73
|
+
attempt: attempt + 1,
|
|
74
|
+
message: toError(error).message
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async executeSync(epoch) {
|
|
80
|
+
const iqNode = buildGetAbPropsIq({
|
|
81
|
+
hash: this.syncState.hash,
|
|
82
|
+
refreshId: this.syncState.refreshId
|
|
83
|
+
});
|
|
84
|
+
const response = await this.runtime.queryWithContext('abprops.sync', iqNode, WA_DEFAULTS.IQ_TIMEOUT_MS);
|
|
85
|
+
if (this.syncEpoch !== epoch) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const result = parseAbPropsIqResult(response);
|
|
89
|
+
if (result.abKey !== null) {
|
|
90
|
+
this.syncState.abKey = result.abKey;
|
|
91
|
+
}
|
|
92
|
+
if (result.hash !== null) {
|
|
93
|
+
this.syncState.hash = result.hash;
|
|
94
|
+
}
|
|
95
|
+
if (result.refreshId !== null) {
|
|
96
|
+
this.syncState.refreshId = result.refreshId;
|
|
97
|
+
}
|
|
98
|
+
if (!result.isDeltaUpdate) {
|
|
99
|
+
this.cache.clear();
|
|
100
|
+
}
|
|
101
|
+
let applied = 0;
|
|
102
|
+
for (let i = 0; i < result.props.length; i += 1) {
|
|
103
|
+
const entry = result.props[i];
|
|
104
|
+
const name = resolveAbPropNameByCode(entry.configCode);
|
|
105
|
+
if (!name) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const config = AB_PROP_CONFIGS[name];
|
|
109
|
+
const parsed = parseConfigValue(entry.configValue, config.type, config.defaultValue);
|
|
110
|
+
this.cache.set(name, parsed);
|
|
111
|
+
applied += 1;
|
|
112
|
+
}
|
|
113
|
+
this.logger.info('ab props synced', {
|
|
114
|
+
received: result.props.length,
|
|
115
|
+
applied,
|
|
116
|
+
isDelta: result.isDeltaUpdate,
|
|
117
|
+
abKey: result.abKey,
|
|
118
|
+
refresh: result.refresh !== null ? clampRefresh(result.refresh) : null
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function parseConfigValue(value, type, defaultValue) {
|
|
123
|
+
if (value === null) {
|
|
124
|
+
return defaultValue;
|
|
125
|
+
}
|
|
126
|
+
if (type === 'bool') {
|
|
127
|
+
return value === '1' || value === 'true' || value === 'True';
|
|
128
|
+
}
|
|
129
|
+
if (type === 'int') {
|
|
130
|
+
const parsed = Number.parseInt(value, 10);
|
|
131
|
+
return Number.isSafeInteger(parsed) ? parsed : defaultValue;
|
|
132
|
+
}
|
|
133
|
+
return value;
|
|
134
|
+
}
|
|
135
|
+
function clampRefresh(seconds) {
|
|
136
|
+
return Math.max(WA_ABPROPS_REFRESH_BOUNDS.MIN_S, Math.min(WA_ABPROPS_REFRESH_BOUNDS.MAX_S, seconds));
|
|
137
|
+
}
|
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
import { proto } from '../../proto.js';
|
|
2
2
|
import { buildDeleteCoverPhotoIq, buildEditBusinessProfileIq, buildGetBusinessProfileIq, buildGetVerifiedNameIq, buildUpdateCoverPhotoIq } from '../../transport/node/builders/business.js';
|
|
3
|
-
import { findNodeChild, getNodeChildren } from '../../transport/node/helpers.js';
|
|
3
|
+
import { findNodeChild, getNodeChildren, getNodeTextContent } from '../../transport/node/helpers.js';
|
|
4
4
|
import { assertIqResult } from '../../transport/node/query.js';
|
|
5
|
-
import { TEXT_DECODER } from '../../util/bytes.js';
|
|
6
5
|
import { longToNumber } from '../../util/primitives.js';
|
|
7
|
-
function readTextContent(node) {
|
|
8
|
-
const content = node.content;
|
|
9
|
-
if (content instanceof Uint8Array)
|
|
10
|
-
return TEXT_DECODER.decode(content);
|
|
11
|
-
if (typeof content === 'string')
|
|
12
|
-
return content;
|
|
13
|
-
return undefined;
|
|
14
|
-
}
|
|
15
6
|
function parseBusinessProfiles(result) {
|
|
16
7
|
const bizNode = findNodeChild(result, 'business_profile');
|
|
17
8
|
if (!bizNode) {
|
|
@@ -40,7 +31,7 @@ function parseBusinessProfiles(result) {
|
|
|
40
31
|
const websites = [];
|
|
41
32
|
for (let j = 0; j < children.length; j += 1) {
|
|
42
33
|
const child = children[j];
|
|
43
|
-
const text =
|
|
34
|
+
const text = getNodeTextContent(child);
|
|
44
35
|
switch (child.tag) {
|
|
45
36
|
case 'description':
|
|
46
37
|
if (text !== undefined)
|
|
@@ -102,7 +93,7 @@ function parseBusinessCategories(node) {
|
|
|
102
93
|
const id = child.attrs.id;
|
|
103
94
|
if (!id)
|
|
104
95
|
continue;
|
|
105
|
-
categories[count] = { id, name:
|
|
96
|
+
categories[count] = { id, name: getNodeTextContent(child) ?? '' };
|
|
106
97
|
count += 1;
|
|
107
98
|
}
|
|
108
99
|
categories.length = count;
|
|
@@ -139,7 +130,7 @@ function parseProfileOptions(node) {
|
|
|
139
130
|
const options = {};
|
|
140
131
|
for (let i = 0; i < children.length; i += 1) {
|
|
141
132
|
const child = children[i];
|
|
142
|
-
const text =
|
|
133
|
+
const text = getNodeTextContent(child);
|
|
143
134
|
if (text !== undefined) {
|
|
144
135
|
options[child.tag] = text;
|
|
145
136
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { WA_EMAIL_TAGS } from '../../protocol/email.js';
|
|
2
|
+
import { buildConfirmEmailIq, buildGetEmailIq, buildRequestEmailVerificationCodeIq, buildSetEmailIq, buildVerifyEmailCodeIq } from '../../transport/node/builders/email.js';
|
|
3
|
+
import { findNodeChild, getNodeTextContent } from '../../transport/node/helpers.js';
|
|
4
|
+
import { assertIqResult } from '../../transport/node/query.js';
|
|
5
|
+
export function createEmailCoordinator(options) {
|
|
6
|
+
const { queryWithContext } = options;
|
|
7
|
+
return {
|
|
8
|
+
getStatus: async () => {
|
|
9
|
+
const result = await queryWithContext('email.getStatus', buildGetEmailIq());
|
|
10
|
+
assertIqResult(result, 'email.getStatus');
|
|
11
|
+
return parseEmailStatus(result);
|
|
12
|
+
},
|
|
13
|
+
setEmail: async (email, context) => {
|
|
14
|
+
const result = await queryWithContext('email.set', buildSetEmailIq(email, context), undefined, context !== undefined ? { context } : {});
|
|
15
|
+
assertIqResult(result, 'email.set');
|
|
16
|
+
return parseEmailStatus(result);
|
|
17
|
+
},
|
|
18
|
+
requestVerificationCode: async (input) => {
|
|
19
|
+
const result = await queryWithContext('email.requestCode', buildRequestEmailVerificationCodeIq(input), undefined, { languageCode: input.languageCode, localeCode: input.localeCode });
|
|
20
|
+
assertIqResult(result, 'email.requestCode');
|
|
21
|
+
},
|
|
22
|
+
verifyCode: async (code) => {
|
|
23
|
+
const result = await queryWithContext('email.verifyCode', buildVerifyEmailCodeIq(code));
|
|
24
|
+
assertIqResult(result, 'email.verifyCode');
|
|
25
|
+
return parseVerifyCodeResult(result);
|
|
26
|
+
},
|
|
27
|
+
confirm: async (context) => {
|
|
28
|
+
const result = await queryWithContext('email.confirm', buildConfirmEmailIq(context), undefined, context !== undefined ? { context } : {});
|
|
29
|
+
assertIqResult(result, 'email.confirm');
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function parseEmailStatus(result) {
|
|
34
|
+
const emailNode = findNodeChild(result, WA_EMAIL_TAGS.EMAIL);
|
|
35
|
+
if (!emailNode) {
|
|
36
|
+
return { email: null, verified: false, confirmed: false };
|
|
37
|
+
}
|
|
38
|
+
const verifiedAttr = emailNode.attrs.verified;
|
|
39
|
+
const addressNode = findNodeChild(emailNode, WA_EMAIL_TAGS.EMAIL_ADDRESS);
|
|
40
|
+
const confirmedNode = findNodeChild(emailNode, WA_EMAIL_TAGS.CONFIRMED);
|
|
41
|
+
return {
|
|
42
|
+
email: addressNode ? (getNodeTextContent(addressNode) ?? null) : null,
|
|
43
|
+
verified: verifiedAttr === 'true',
|
|
44
|
+
confirmed: confirmedNode ? getNodeTextContent(confirmedNode) === 'true' : false
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function parseVerifyCodeResult(result) {
|
|
48
|
+
const emailNode = findNodeChild(result, WA_EMAIL_TAGS.EMAIL);
|
|
49
|
+
if (!emailNode) {
|
|
50
|
+
return { verified: false, autoVerifyFailed: false, email: null };
|
|
51
|
+
}
|
|
52
|
+
const doVerify = emailNode.attrs.do_verify;
|
|
53
|
+
const autoVerifyNode = findNodeChild(emailNode, WA_EMAIL_TAGS.AUTO_VERIFY);
|
|
54
|
+
const addressNode = findNodeChild(emailNode, WA_EMAIL_TAGS.EMAIL_ADDRESS);
|
|
55
|
+
return {
|
|
56
|
+
verified: doVerify === 'true',
|
|
57
|
+
autoVerifyFailed: autoVerifyNode ? getNodeTextContent(autoVerifyNode) === 'fail' : false,
|
|
58
|
+
email: addressNode ? (getNodeTextContent(addressNode) ?? null) : null
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createIncomingBaseEvent, createIncomingFailureHandler, createIncomingGroupNotificationHandler, createIncomingNotificationHandler, createIncomingReceiptHandler, createInfoBulletinNotificationEvent, createUnhandledIncomingNodeEvent } from '../incoming.js';
|
|
1
|
+
import { createIncomingBaseEvent, createIncomingFailureHandler, createIncomingGroupNotificationHandler, createIncomingNotificationHandler, createIncomingReceiptHandler, createIncomingRegistrationNotificationHandler, createInfoBulletinNotificationEvent, createUnhandledIncomingNodeEvent } from '../incoming.js';
|
|
2
2
|
import { WA_IQ_TYPES, WA_MESSAGE_TAGS, WA_NODE_TAGS, WA_NOTIFICATION_TYPES, WA_SIGNALING } from '../../protocol/constants.js';
|
|
3
|
-
import { decodeNodeContentBase64OrBytes, findNodeChild, getNodeChildrenByTag } from '../../transport/node/helpers.js';
|
|
3
|
+
import { decodeNodeContentBase64OrBytes, findNodeChild, getNodeChildren, getNodeChildrenByTag } from '../../transport/node/helpers.js';
|
|
4
4
|
import { parseStreamControlNode, parseSuccessPersistAttributes } from '../../transport/stream/parse.js';
|
|
5
5
|
import { parseOptionalInt, toError } from '../../util/primitives.js';
|
|
6
|
-
const
|
|
6
|
+
const INFO_BULLETIN_CHILD_TAGS = new Set([
|
|
7
7
|
'offline',
|
|
8
8
|
'offline_preview',
|
|
9
9
|
'priority_offline_complete',
|
|
@@ -15,6 +15,7 @@ export class WaIncomingNodeCoordinator {
|
|
|
15
15
|
constructor(options) {
|
|
16
16
|
this.logger = options.logger;
|
|
17
17
|
this.runtime = options.runtime;
|
|
18
|
+
this.offlineResume = options.offlineResume;
|
|
18
19
|
this.nodeHandlerRegistry = new Map();
|
|
19
20
|
this.registerDefaultIncomingHandlers();
|
|
20
21
|
this.mediaConnWarmupPromise = null;
|
|
@@ -25,6 +26,9 @@ export class WaIncomingNodeCoordinator {
|
|
|
25
26
|
id: node.attrs.id,
|
|
26
27
|
type: node.attrs.type
|
|
27
28
|
});
|
|
29
|
+
if (node.attrs.offline !== undefined) {
|
|
30
|
+
this.offlineResume.trackOfflineStanza();
|
|
31
|
+
}
|
|
28
32
|
const streamControlResult = parseStreamControlNode(node);
|
|
29
33
|
if (streamControlResult) {
|
|
30
34
|
await this.runtime.handleStreamControlResult(streamControlResult);
|
|
@@ -144,6 +148,16 @@ export class WaIncomingNodeCoordinator {
|
|
|
144
148
|
emitUnhandledStanza: runtime.emitUnhandledIncomingNode
|
|
145
149
|
})
|
|
146
150
|
});
|
|
151
|
+
this.registerIncomingHandler({
|
|
152
|
+
tag: WA_NODE_TAGS.NOTIFICATION,
|
|
153
|
+
subtype: WA_NOTIFICATION_TYPES.REGISTRATION,
|
|
154
|
+
handler: createIncomingRegistrationNotificationHandler({
|
|
155
|
+
logger: this.logger,
|
|
156
|
+
sendNode: runtime.sendNode,
|
|
157
|
+
emitRegistrationCode: runtime.emitRegistrationCode,
|
|
158
|
+
emitAccountTakeoverNotice: runtime.emitAccountTakeoverNotice
|
|
159
|
+
})
|
|
160
|
+
});
|
|
147
161
|
this.registerIncomingHandler({
|
|
148
162
|
tag: WA_NODE_TAGS.NOTIFICATION,
|
|
149
163
|
handler: createIncomingNotificationHandler({
|
|
@@ -263,13 +277,24 @@ export class WaIncomingNodeCoordinator {
|
|
|
263
277
|
return false;
|
|
264
278
|
}
|
|
265
279
|
let handled = false;
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
280
|
+
const children = getNodeChildren(node);
|
|
281
|
+
for (const child of children) {
|
|
282
|
+
if (INFO_BULLETIN_CHILD_TAGS.has(child.tag)) {
|
|
283
|
+
this.runtime.emitIncomingNotification(createInfoBulletinNotificationEvent(node, child.tag, {
|
|
284
|
+
count: parseOptionalInt(child.attrs.count),
|
|
285
|
+
message: parseOptionalInt(child.attrs.message),
|
|
286
|
+
receipt: parseOptionalInt(child.attrs.receipt),
|
|
287
|
+
notification: parseOptionalInt(child.attrs.notification),
|
|
288
|
+
t: parseOptionalInt(child.attrs.t)
|
|
289
|
+
}));
|
|
290
|
+
if (child.tag === 'offline_preview') {
|
|
291
|
+
this.offlineResume.handleOfflinePreview(parseOptionalInt(child.attrs.count) ?? 0);
|
|
292
|
+
}
|
|
293
|
+
if (child.tag === 'offline') {
|
|
294
|
+
this.offlineResume.handleOfflineComplete(parseOptionalInt(child.attrs.count) ?? 0);
|
|
295
|
+
}
|
|
296
|
+
handled = true;
|
|
297
|
+
}
|
|
273
298
|
}
|
|
274
299
|
const edgeRoutingNode = findNodeChild(node, WA_NODE_TAGS.EDGE_ROUTING);
|
|
275
300
|
if (edgeRoutingNode) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { randomBytesAsync, sha256 } from '../../crypto/index.js';
|
|
2
|
+
import { md5Bytes } from '../../crypto/core/primitives.js';
|
|
2
3
|
import { PromiseDedup } from '../../infra/perf/PromiseDedup.js';
|
|
3
4
|
import { ensureMessageSecret } from '../../message/index.js';
|
|
4
|
-
import { resolveEditAttr, resolveEncMediaType, resolveMessageTypeAttr, resolveMetaAttrs } from '../../message/content.js';
|
|
5
|
+
import { needsSecretPersistence, resolveEditAttr, resolveEncMediaType, resolveMessageTypeAttr, resolveMetaAttrs } from '../../message/content.js';
|
|
5
6
|
import { wrapDeviceSentMessage } from '../../message/device-sent.js';
|
|
6
7
|
import { injectDeviceListMetadata, resolveIcdcMeta } from '../../message/icdc.js';
|
|
7
8
|
import { writeRandomPadMax16 } from '../../message/padding.js';
|
|
@@ -9,8 +10,7 @@ import { computePhashV2 } from '../../message/phash.js';
|
|
|
9
10
|
import { buildReportingTokenArtifacts } from '../../message/reporting-token.js';
|
|
10
11
|
import { proto } from '../../proto.js';
|
|
11
12
|
import { WA_DEFAULTS } from '../../protocol/constants.js';
|
|
12
|
-
import { isGroupJid, normalizeDeviceJid, normalizeRecipientJid, parseJidFull, parseSignalAddressFromJid,
|
|
13
|
-
import { signalAddressKey } from '../../protocol/jid.js';
|
|
13
|
+
import { isGroupJid, isLidJid, normalizeDeviceJid, normalizeRecipientJid, parseJidFull, parseSignalAddressFromJid, signalAddressKey, toUserJid } from '../../protocol/jid.js';
|
|
14
14
|
import { encodeBinaryNode } from '../../transport/binary/index.js';
|
|
15
15
|
import { buildDirectMessageFanoutNode, buildGroupSenderKeyMessageNode, buildMetaNode } from '../../transport/node/builders/message.js';
|
|
16
16
|
import { bytesToHex, concatBytes, TEXT_ENCODER } from '../../util/bytes.js';
|
|
@@ -31,12 +31,17 @@ export class WaMessageDispatchCoordinator {
|
|
|
31
31
|
this.senderKeyManager = options.senderKeyManager;
|
|
32
32
|
this.signalProtocol = options.signalProtocol;
|
|
33
33
|
this.signalStore = options.signalStore;
|
|
34
|
+
this.sessionStore = options.sessionStore;
|
|
35
|
+
this.identityStore = options.identityStore;
|
|
34
36
|
this.deviceListStore = options.deviceListStore;
|
|
37
|
+
this.messageSecretStore = options.messageSecretStore;
|
|
35
38
|
this.getCurrentMeJid = options.getCurrentMeJid;
|
|
36
39
|
this.getCurrentMeLid = options.getCurrentMeLid;
|
|
37
40
|
this.getCurrentSignedIdentity = options.getCurrentSignedIdentity;
|
|
38
41
|
this.resolvePrivacyTokenNode = options.resolvePrivacyTokenNode;
|
|
39
42
|
this.onDirectMessageSent = options.onDirectMessageSent;
|
|
43
|
+
this.getIcdcHashLength = options.getIcdcHashLength;
|
|
44
|
+
this.mobileMessageIdFormat = options.mobileMessageIdFormat ?? false;
|
|
40
45
|
}
|
|
41
46
|
async publishMessageNode(node, options = {}) {
|
|
42
47
|
this.logger.debug('wa client publish message node', {
|
|
@@ -129,6 +134,21 @@ export class WaMessageDispatchCoordinator {
|
|
|
129
134
|
this.withResolvedMessageId(options)
|
|
130
135
|
]);
|
|
131
136
|
const messageWithSecret = await ensureMessageSecret(message);
|
|
137
|
+
const rawSecret = messageWithSecret.messageContextInfo?.messageSecret;
|
|
138
|
+
if (rawSecret &&
|
|
139
|
+
rawSecret.length > 0 &&
|
|
140
|
+
sendOptions.id &&
|
|
141
|
+
needsSecretPersistence(messageWithSecret)) {
|
|
142
|
+
const meJid = this.getCurrentMeJid() ?? '';
|
|
143
|
+
void this.messageSecretStore
|
|
144
|
+
.set(sendOptions.id, { secret: rawSecret, senderJid: meJid })
|
|
145
|
+
.catch((error) => {
|
|
146
|
+
this.logger.warn('failed to persist outgoing message secret', {
|
|
147
|
+
id: sendOptions.id,
|
|
148
|
+
message: toError(error).message
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
}
|
|
132
152
|
const meJid = this.getCurrentMeJid();
|
|
133
153
|
const regInfo = meJid ? await this.signalStore.getRegistrationInfo() : null;
|
|
134
154
|
const localPubKey = regInfo?.identityKeyPair.pubKey;
|
|
@@ -408,14 +428,8 @@ export class WaMessageDispatchCoordinator {
|
|
|
408
428
|
}
|
|
409
429
|
resolveGroupAddressingMode(participantUserJids, groupJid) {
|
|
410
430
|
for (let index = 0; index < participantUserJids.length; index += 1) {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
if (splitJid(participantJid).server === 'lid') {
|
|
414
|
-
return 'lid';
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
catch (error) {
|
|
418
|
-
this.logger.trace('ignoring malformed participant jid in addressing mode resolution', { participantJid, message: toError(error).message });
|
|
431
|
+
if (isLidJid(participantUserJids[index])) {
|
|
432
|
+
return 'lid';
|
|
419
433
|
}
|
|
420
434
|
}
|
|
421
435
|
this.logger.trace('group addressing mode resolved to pn (default)', {
|
|
@@ -511,7 +525,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
511
525
|
for (let index = 0; index < pendingTargets.length; index += 1) {
|
|
512
526
|
pendingTargetAddresses[index] = pendingTargets[index].address;
|
|
513
527
|
}
|
|
514
|
-
const hasPendingSessions = await this.
|
|
528
|
+
const hasPendingSessions = await this.sessionStore.hasSessions(pendingTargetAddresses);
|
|
515
529
|
const nextAvailableTargets = [];
|
|
516
530
|
for (let index = 0; index < pendingTargets.length; index += 1) {
|
|
517
531
|
if (hasPendingSessions[index]) {
|
|
@@ -719,9 +733,20 @@ export class WaMessageDispatchCoordinator {
|
|
|
719
733
|
async generateOutgoingMessageId() {
|
|
720
734
|
try {
|
|
721
735
|
const meUserJid = toUserJid(this.requireCurrentMeJid('sendMessage'));
|
|
722
|
-
const timestampSeconds = Math.floor(Date.now() / 1000);
|
|
723
736
|
const timestampBytes = new Uint8Array(8);
|
|
724
|
-
new DataView(timestampBytes.buffer, timestampBytes.byteOffset, timestampBytes.byteLength)
|
|
737
|
+
const dv = new DataView(timestampBytes.buffer, timestampBytes.byteOffset, timestampBytes.byteLength);
|
|
738
|
+
if (this.mobileMessageIdFormat) {
|
|
739
|
+
dv.setBigUint64(0, BigInt(Date.now()), false);
|
|
740
|
+
const entropy = concatBytes([
|
|
741
|
+
timestampBytes,
|
|
742
|
+
TEXT_ENCODER.encode(meUserJid),
|
|
743
|
+
await randomBytesAsync(16)
|
|
744
|
+
]);
|
|
745
|
+
const digest = md5Bytes(entropy);
|
|
746
|
+
digest[0] = 0xac;
|
|
747
|
+
return bytesToHex(digest).toUpperCase();
|
|
748
|
+
}
|
|
749
|
+
dv.setBigUint64(0, BigInt(Math.floor(Date.now() / 1000)), false);
|
|
725
750
|
const entropy = concatBytes([
|
|
726
751
|
timestampBytes,
|
|
727
752
|
TEXT_ENCODER.encode(meUserJid),
|
|
@@ -731,9 +756,14 @@ export class WaMessageDispatchCoordinator {
|
|
|
731
756
|
return `3EB0${bytesToHex(digest.subarray(0, 9)).toUpperCase()}`;
|
|
732
757
|
}
|
|
733
758
|
catch (error) {
|
|
734
|
-
this.logger.warn('failed to generate
|
|
759
|
+
this.logger.warn('failed to generate message id, falling back to random', {
|
|
735
760
|
message: toError(error).message
|
|
736
761
|
});
|
|
762
|
+
if (this.mobileMessageIdFormat) {
|
|
763
|
+
const bytes = await randomBytesAsync(16);
|
|
764
|
+
bytes[0] = 0xac;
|
|
765
|
+
return bytesToHex(bytes).toUpperCase();
|
|
766
|
+
}
|
|
737
767
|
return `3EB0${bytesToHex(await randomBytesAsync(8)).toUpperCase()}`;
|
|
738
768
|
}
|
|
739
769
|
}
|
|
@@ -762,7 +792,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
762
792
|
getEncodedSignedDeviceIdentity() {
|
|
763
793
|
const signedIdentity = this.getCurrentSignedIdentity();
|
|
764
794
|
if (!signedIdentity) {
|
|
765
|
-
|
|
795
|
+
return undefined;
|
|
766
796
|
}
|
|
767
797
|
return proto.ADVSignedDeviceIdentity.encode(signedIdentity).finish();
|
|
768
798
|
}
|
|
@@ -774,7 +804,7 @@ export class WaMessageDispatchCoordinator {
|
|
|
774
804
|
if (!snapshot || snapshot.deviceJids.length === 0) {
|
|
775
805
|
return null;
|
|
776
806
|
}
|
|
777
|
-
return resolveIcdcMeta(snapshot.deviceJids, this.
|
|
807
|
+
return resolveIcdcMeta(snapshot.deviceJids, this.identityStore, snapshot.updatedAtMs, localIdentity, this.getIcdcHashLength?.());
|
|
778
808
|
}
|
|
779
809
|
catch (error) {
|
|
780
810
|
this.logger.trace('icdc resolution failed', {
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { buildOfflineBatchNode } from '../../transport/node/builders/offline.js';
|
|
2
|
+
import { toError } from '../../util/primitives.js';
|
|
3
|
+
const WA_OFFLINE_RESUME = Object.freeze({
|
|
4
|
+
BATCH_SIZE: 200,
|
|
5
|
+
STANZA_TIMEOUT_MS: 60000
|
|
6
|
+
});
|
|
7
|
+
const WA_OFFLINE_RESUME_STATE = Object.freeze({
|
|
8
|
+
INIT: 'init',
|
|
9
|
+
RESUMING: 'resuming',
|
|
10
|
+
COMPLETE: 'complete'
|
|
11
|
+
});
|
|
12
|
+
export class WaOfflineResumeCoordinator {
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.logger = options.logger;
|
|
15
|
+
this.runtime = options.runtime;
|
|
16
|
+
this.state = WA_OFFLINE_RESUME_STATE.INIT;
|
|
17
|
+
this.totalStanzas = 0;
|
|
18
|
+
this.pendingStanzas = 0;
|
|
19
|
+
this.stanzaTimeout = null;
|
|
20
|
+
}
|
|
21
|
+
get isComplete() {
|
|
22
|
+
return this.state === WA_OFFLINE_RESUME_STATE.COMPLETE;
|
|
23
|
+
}
|
|
24
|
+
get isResuming() {
|
|
25
|
+
return this.state === WA_OFFLINE_RESUME_STATE.RESUMING;
|
|
26
|
+
}
|
|
27
|
+
handleOfflinePreview(stanzaCount) {
|
|
28
|
+
this.clearTimers();
|
|
29
|
+
this.state = WA_OFFLINE_RESUME_STATE.RESUMING;
|
|
30
|
+
this.totalStanzas = stanzaCount;
|
|
31
|
+
this.pendingStanzas = stanzaCount;
|
|
32
|
+
this.logger.info('offline resume started', {
|
|
33
|
+
totalStanzas: stanzaCount
|
|
34
|
+
});
|
|
35
|
+
this.runtime.emitOfflineResume({
|
|
36
|
+
status: 'resuming',
|
|
37
|
+
totalStanzas: stanzaCount,
|
|
38
|
+
remainingStanzas: stanzaCount,
|
|
39
|
+
forced: false
|
|
40
|
+
});
|
|
41
|
+
void this.sendOfflineBatch();
|
|
42
|
+
this.resetStanzaTimeout();
|
|
43
|
+
}
|
|
44
|
+
handleOfflineComplete(serverStanzaCount) {
|
|
45
|
+
if (this.state !== WA_OFFLINE_RESUME_STATE.RESUMING) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
this.completeResume(false, serverStanzaCount);
|
|
49
|
+
}
|
|
50
|
+
trackOfflineStanza() {
|
|
51
|
+
if (this.state !== WA_OFFLINE_RESUME_STATE.RESUMING) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this.pendingStanzas = Math.max(0, this.pendingStanzas - 1);
|
|
55
|
+
this.resetStanzaTimeout();
|
|
56
|
+
}
|
|
57
|
+
reset() {
|
|
58
|
+
this.clearTimers();
|
|
59
|
+
this.state = WA_OFFLINE_RESUME_STATE.INIT;
|
|
60
|
+
this.totalStanzas = 0;
|
|
61
|
+
this.pendingStanzas = 0;
|
|
62
|
+
}
|
|
63
|
+
completeResume(forced, serverStanzaCount) {
|
|
64
|
+
this.clearTimers();
|
|
65
|
+
this.state = WA_OFFLINE_RESUME_STATE.COMPLETE;
|
|
66
|
+
this.logger.info('offline resume complete', {
|
|
67
|
+
totalStanzas: this.totalStanzas,
|
|
68
|
+
remainingStanzas: this.pendingStanzas,
|
|
69
|
+
serverStanzaCount,
|
|
70
|
+
forced
|
|
71
|
+
});
|
|
72
|
+
this.runtime.emitOfflineResume({
|
|
73
|
+
status: 'complete',
|
|
74
|
+
totalStanzas: this.totalStanzas,
|
|
75
|
+
remainingStanzas: this.pendingStanzas,
|
|
76
|
+
forced
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
async sendOfflineBatch() {
|
|
80
|
+
try {
|
|
81
|
+
await this.runtime.sendNode(buildOfflineBatchNode(WA_OFFLINE_RESUME.BATCH_SIZE));
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
this.logger.warn('offline batch request failed', {
|
|
85
|
+
message: toError(err).message
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
resetStanzaTimeout() {
|
|
90
|
+
if (this.stanzaTimeout !== null) {
|
|
91
|
+
clearTimeout(this.stanzaTimeout);
|
|
92
|
+
}
|
|
93
|
+
this.stanzaTimeout = setTimeout(() => {
|
|
94
|
+
this.stanzaTimeout = null;
|
|
95
|
+
if (this.state === WA_OFFLINE_RESUME_STATE.RESUMING) {
|
|
96
|
+
this.logger.warn('offline resume forced complete due to stanza timeout', {
|
|
97
|
+
totalStanzas: this.totalStanzas,
|
|
98
|
+
remainingStanzas: this.pendingStanzas
|
|
99
|
+
});
|
|
100
|
+
this.completeResume(true);
|
|
101
|
+
}
|
|
102
|
+
}, WA_OFFLINE_RESUME.STANZA_TIMEOUT_MS);
|
|
103
|
+
}
|
|
104
|
+
clearTimers() {
|
|
105
|
+
if (this.stanzaTimeout !== null) {
|
|
106
|
+
clearTimeout(this.stanzaTimeout);
|
|
107
|
+
this.stanzaTimeout = null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|