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
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { WA_DEFAULTS } from '../../../protocol/defaults.js';
|
|
2
|
+
import { WA_EMAIL_LIMITS, WA_EMAIL_TAGS, WA_EMAIL_XMLNS } from '../../../protocol/email.js';
|
|
3
|
+
import { buildIqNode } from '../../node/query.js';
|
|
4
|
+
export function buildGetEmailIq() {
|
|
5
|
+
return buildIqNode('get', WA_DEFAULTS.HOST_DOMAIN, WA_EMAIL_XMLNS, [
|
|
6
|
+
{ tag: WA_EMAIL_TAGS.EMAIL, attrs: {} }
|
|
7
|
+
]);
|
|
8
|
+
}
|
|
9
|
+
export function buildSetEmailIq(email, context) {
|
|
10
|
+
if (email.length === 0 || email.length > WA_EMAIL_LIMITS.EMAIL_MAX_LENGTH) {
|
|
11
|
+
throw new Error(`email length must be between 1 and ${WA_EMAIL_LIMITS.EMAIL_MAX_LENGTH} chars`);
|
|
12
|
+
}
|
|
13
|
+
const emailChildren = [];
|
|
14
|
+
if (context !== undefined) {
|
|
15
|
+
emailChildren.push({ tag: WA_EMAIL_TAGS.CONTEXT, attrs: {}, content: context });
|
|
16
|
+
}
|
|
17
|
+
emailChildren.push({ tag: WA_EMAIL_TAGS.EMAIL_ADDRESS, attrs: {}, content: email });
|
|
18
|
+
return buildIqNode('set', WA_DEFAULTS.HOST_DOMAIN, WA_EMAIL_XMLNS, [
|
|
19
|
+
{ tag: WA_EMAIL_TAGS.EMAIL, attrs: {}, content: emailChildren }
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
22
|
+
export function buildRequestEmailVerificationCodeIq(input) {
|
|
23
|
+
assertLocaleField('languageCode', input.languageCode);
|
|
24
|
+
assertLocaleField('localeCode', input.localeCode);
|
|
25
|
+
return buildIqNode('set', WA_DEFAULTS.HOST_DOMAIN, WA_EMAIL_XMLNS, [
|
|
26
|
+
{
|
|
27
|
+
tag: WA_EMAIL_TAGS.VERIFY_EMAIL,
|
|
28
|
+
attrs: {},
|
|
29
|
+
content: [
|
|
30
|
+
{ tag: WA_EMAIL_TAGS.LG, attrs: {}, content: input.languageCode },
|
|
31
|
+
{ tag: WA_EMAIL_TAGS.LC, attrs: {}, content: input.localeCode }
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
]);
|
|
35
|
+
}
|
|
36
|
+
export function buildVerifyEmailCodeIq(code) {
|
|
37
|
+
if (code.length !== WA_EMAIL_LIMITS.CODE_LENGTH) {
|
|
38
|
+
throw new Error(`verification code must be exactly ${WA_EMAIL_LIMITS.CODE_LENGTH} chars`);
|
|
39
|
+
}
|
|
40
|
+
return buildIqNode('set', WA_DEFAULTS.HOST_DOMAIN, WA_EMAIL_XMLNS, [
|
|
41
|
+
{
|
|
42
|
+
tag: WA_EMAIL_TAGS.VERIFY_EMAIL,
|
|
43
|
+
attrs: {},
|
|
44
|
+
content: [{ tag: WA_EMAIL_TAGS.CODE, attrs: {}, content: code }]
|
|
45
|
+
}
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
export function buildConfirmEmailIq(context) {
|
|
49
|
+
const children = context !== undefined
|
|
50
|
+
? [{ tag: WA_EMAIL_TAGS.CONTEXT, attrs: {}, content: context }]
|
|
51
|
+
: undefined;
|
|
52
|
+
return buildIqNode('set', WA_DEFAULTS.HOST_DOMAIN, WA_EMAIL_XMLNS, [
|
|
53
|
+
{
|
|
54
|
+
tag: WA_EMAIL_TAGS.CONFIRM_EMAIL,
|
|
55
|
+
attrs: {},
|
|
56
|
+
...(children !== undefined ? { content: children } : {})
|
|
57
|
+
}
|
|
58
|
+
]);
|
|
59
|
+
}
|
|
60
|
+
function assertLocaleField(field, value) {
|
|
61
|
+
if (value.length < WA_EMAIL_LIMITS.LOCALE_MIN_LENGTH ||
|
|
62
|
+
value.length > WA_EMAIL_LIMITS.LOCALE_MAX_LENGTH) {
|
|
63
|
+
throw new Error(`${field} must be between ${WA_EMAIL_LIMITS.LOCALE_MIN_LENGTH} and ${WA_EMAIL_LIMITS.LOCALE_MAX_LENGTH} chars`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { WA_NODE_TAGS } from '../../../protocol/constants.js';
|
|
2
|
+
export function buildOfflineBatchNode(count) {
|
|
3
|
+
return {
|
|
4
|
+
tag: WA_NODE_TAGS.INFO_BULLETIN,
|
|
5
|
+
attrs: {},
|
|
6
|
+
content: [
|
|
7
|
+
{
|
|
8
|
+
tag: 'offline_batch',
|
|
9
|
+
attrs: { count: String(count) },
|
|
10
|
+
content: undefined
|
|
11
|
+
}
|
|
12
|
+
]
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { toRawPubKey } from '../../../crypto/core/keys.js';
|
|
1
2
|
import { WA_DEFAULTS, WA_NODE_TAGS, WA_XMLNS } from '../../../protocol/constants.js';
|
|
2
3
|
import { SIGNAL_KEY_BUNDLE_TYPE_BYTES } from '../../../signal/api/constants.js';
|
|
3
4
|
import { buildIqNode } from '../../node/query.js';
|
|
4
|
-
import { intToBytes
|
|
5
|
+
import { intToBytes } from '../../../util/bytes.js';
|
|
5
6
|
function buildSignedPreKeyNode(signedPreKey) {
|
|
6
7
|
return {
|
|
7
8
|
tag: WA_NODE_TAGS.SKEY,
|
|
@@ -15,55 +16,51 @@ function buildSignedPreKeyNode(signedPreKey) {
|
|
|
15
16
|
{
|
|
16
17
|
tag: WA_NODE_TAGS.VALUE,
|
|
17
18
|
attrs: {},
|
|
18
|
-
content:
|
|
19
|
+
content: toRawPubKey(signedPreKey.keyPair.pubKey)
|
|
19
20
|
},
|
|
20
21
|
{
|
|
21
22
|
tag: WA_NODE_TAGS.SIGNATURE,
|
|
22
23
|
attrs: {},
|
|
23
|
-
content:
|
|
24
|
+
content: signedPreKey.signature
|
|
24
25
|
}
|
|
25
26
|
]
|
|
26
27
|
};
|
|
27
28
|
}
|
|
28
29
|
export function buildPreKeyUploadIq(registrationInfo, signedPreKey, preKeys) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
{
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
tag: WA_NODE_TAGS.
|
|
30
|
+
const children = [];
|
|
31
|
+
children.push({
|
|
32
|
+
tag: WA_NODE_TAGS.IDENTITY,
|
|
33
|
+
attrs: {},
|
|
34
|
+
content: toRawPubKey(registrationInfo.identityKeyPair.pubKey)
|
|
35
|
+
}, {
|
|
36
|
+
tag: WA_NODE_TAGS.REGISTRATION,
|
|
37
|
+
attrs: {},
|
|
38
|
+
content: intToBytes(4, registrationInfo.registrationId)
|
|
39
|
+
}, {
|
|
40
|
+
tag: WA_NODE_TAGS.TYPE,
|
|
41
|
+
attrs: {},
|
|
42
|
+
content: SIGNAL_KEY_BUNDLE_TYPE_BYTES
|
|
43
|
+
}, {
|
|
44
|
+
tag: WA_NODE_TAGS.LIST,
|
|
45
|
+
attrs: {},
|
|
46
|
+
content: preKeys.map((record) => ({
|
|
47
|
+
tag: WA_NODE_TAGS.KEY,
|
|
47
48
|
attrs: {},
|
|
48
|
-
content:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}))
|
|
64
|
-
},
|
|
65
|
-
buildSignedPreKeyNode(signedPreKey)
|
|
66
|
-
]);
|
|
49
|
+
content: [
|
|
50
|
+
{
|
|
51
|
+
tag: WA_NODE_TAGS.ID,
|
|
52
|
+
attrs: {},
|
|
53
|
+
content: intToBytes(3, record.keyId)
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
tag: WA_NODE_TAGS.VALUE,
|
|
57
|
+
attrs: {},
|
|
58
|
+
content: toRawPubKey(record.keyPair.pubKey)
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}))
|
|
62
|
+
}, buildSignedPreKeyNode(signedPreKey));
|
|
63
|
+
return buildIqNode('set', WA_DEFAULTS.HOST_DOMAIN, WA_XMLNS.SIGNAL, children);
|
|
67
64
|
}
|
|
68
65
|
export function buildSignedPreKeyRotateIq(signedPreKey) {
|
|
69
66
|
return buildIqNode('set', WA_DEFAULTS.HOST_DOMAIN, WA_XMLNS.SIGNAL, [
|
|
@@ -1,29 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { WA_DEFAULTS } from '../../../protocol/defaults.js';
|
|
2
|
+
import { toUserJid } from '../../../protocol/jid.js';
|
|
3
|
+
import { WA_XMLNS } from '../../../protocol/nodes.js';
|
|
2
4
|
import { WA_PRIVACY_TOKEN_TAGS, WA_PRIVACY_TOKEN_TYPES } from '../../../protocol/privacy-token.js';
|
|
5
|
+
import { buildIqNode } from '../../node/query.js';
|
|
3
6
|
export function buildPrivacyTokenIqNode(input) {
|
|
4
|
-
return
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
{
|
|
16
|
-
tag: WA_PRIVACY_TOKEN_TAGS.TOKEN,
|
|
17
|
-
attrs: {
|
|
18
|
-
jid: input.jid,
|
|
19
|
-
t: String(input.timestampS),
|
|
20
|
-
type: input.type ?? WA_PRIVACY_TOKEN_TYPES.TRUSTED_CONTACT
|
|
21
|
-
}
|
|
7
|
+
return buildIqNode('set', WA_DEFAULTS.HOST_DOMAIN, WA_XMLNS.PRIVACY, [
|
|
8
|
+
{
|
|
9
|
+
tag: WA_PRIVACY_TOKEN_TAGS.TOKENS,
|
|
10
|
+
attrs: {},
|
|
11
|
+
content: [
|
|
12
|
+
{
|
|
13
|
+
tag: WA_PRIVACY_TOKEN_TAGS.TOKEN,
|
|
14
|
+
attrs: {
|
|
15
|
+
jid: toUserJid(input.jid),
|
|
16
|
+
t: String(input.timestampS),
|
|
17
|
+
type: input.type ?? WA_PRIVACY_TOKEN_TYPES.TRUSTED_CONTACT
|
|
22
18
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
]);
|
|
27
23
|
}
|
|
28
24
|
export function buildTcTokenMessageNode(token) {
|
|
29
25
|
return {
|
|
@@ -126,6 +126,14 @@ export function decodeNodeContentUtf8OrBytes(value, field) {
|
|
|
126
126
|
}
|
|
127
127
|
throw new Error(`node ${field} has no binary content`);
|
|
128
128
|
}
|
|
129
|
+
export function getNodeTextContent(node) {
|
|
130
|
+
const content = node.content;
|
|
131
|
+
if (content instanceof Uint8Array)
|
|
132
|
+
return TEXT_DECODER.decode(content);
|
|
133
|
+
if (typeof content === 'string')
|
|
134
|
+
return content;
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
129
137
|
export function decodeNodeContentBase64OrBytes(value, field) {
|
|
130
138
|
if (value === null || value === undefined) {
|
|
131
139
|
throw new Error(`missing binary node content for ${field}`);
|
|
@@ -155,3 +163,19 @@ export async function createNodeIdGenerator() {
|
|
|
155
163
|
}
|
|
156
164
|
};
|
|
157
165
|
}
|
|
166
|
+
export function createMobileNodeIdGenerator() {
|
|
167
|
+
let featureCounter = 0;
|
|
168
|
+
let systemCounter = 0;
|
|
169
|
+
return {
|
|
170
|
+
prefix: '0',
|
|
171
|
+
next() {
|
|
172
|
+
const id = `0${featureCounter.toString(16)}`;
|
|
173
|
+
featureCounter = (featureCounter + 1) & 0xffff;
|
|
174
|
+
return id;
|
|
175
|
+
},
|
|
176
|
+
nextSystem() {
|
|
177
|
+
systemCounter = (systemCounter + 1) & 0xffff;
|
|
178
|
+
return systemCounter.toString(16);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { TEXT_DECODER } from '../../../util/bytes.js';
|
|
2
|
+
let cachedArgo;
|
|
3
|
+
async function loadArgo() {
|
|
4
|
+
if (cachedArgo !== undefined)
|
|
5
|
+
return cachedArgo;
|
|
6
|
+
try {
|
|
7
|
+
cachedArgo = (await import('argo-codec'));
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
cachedArgo = null;
|
|
11
|
+
}
|
|
12
|
+
return cachedArgo;
|
|
13
|
+
}
|
|
14
|
+
export async function isMexArgoDecoderAvailable() {
|
|
15
|
+
return (await loadArgo()) !== null;
|
|
16
|
+
}
|
|
17
|
+
const LABEL_NULL = -1;
|
|
18
|
+
const LABEL_ABSENT = -2;
|
|
19
|
+
const BACKREF_BASE = -4;
|
|
20
|
+
const DESC_NULL = -1;
|
|
21
|
+
const DESC_FALSE = 0;
|
|
22
|
+
const DESC_TRUE = 1;
|
|
23
|
+
const DESC_OBJECT = 2;
|
|
24
|
+
const DESC_LIST = 3;
|
|
25
|
+
const DESC_STRING = 4;
|
|
26
|
+
const DESC_BYTES = 5;
|
|
27
|
+
const DESC_INT = 6;
|
|
28
|
+
const DESC_FLOAT = 7;
|
|
29
|
+
const FLAG_INLINE_EVERYTHING = 1 << 0;
|
|
30
|
+
const FLAG_HAS_USER_FLAGS = 1 << 6;
|
|
31
|
+
export async function decodeMexArgoResponse(bytes) {
|
|
32
|
+
const argo = await loadArgo();
|
|
33
|
+
if (!argo)
|
|
34
|
+
throw new Error('argo-codec not installed');
|
|
35
|
+
const r = new argo.Reader(bytes);
|
|
36
|
+
const flags = r.bitset();
|
|
37
|
+
const inline = (flags & FLAG_INLINE_EVERYTHING) !== 0;
|
|
38
|
+
if (flags & FLAG_HAS_USER_FLAGS)
|
|
39
|
+
r.bitset();
|
|
40
|
+
const segments = [];
|
|
41
|
+
if (!inline) {
|
|
42
|
+
while (r.pos < r.end) {
|
|
43
|
+
const len = r.label();
|
|
44
|
+
segments.push(new argo.Reader(r.bytes(len)));
|
|
45
|
+
}
|
|
46
|
+
if (segments.length === 0)
|
|
47
|
+
throw new Error('mex argo: missing core segment');
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
segments.push(r);
|
|
51
|
+
}
|
|
52
|
+
const core = segments[segments.length - 1];
|
|
53
|
+
const blocks = inline ? new Map() : indexBlocks(segments.slice(0, -1));
|
|
54
|
+
const ctx = { core, blocks, stringSeen: [] };
|
|
55
|
+
const data = readDesc(ctx);
|
|
56
|
+
const errors = [];
|
|
57
|
+
if (core.pos < core.end) {
|
|
58
|
+
const errCount = core.label();
|
|
59
|
+
for (let i = 0; i < errCount; i++)
|
|
60
|
+
errors.push(readError(ctx));
|
|
61
|
+
}
|
|
62
|
+
return { data, errors };
|
|
63
|
+
}
|
|
64
|
+
function indexBlocks(slices) {
|
|
65
|
+
const m = new Map();
|
|
66
|
+
const keys = ['String', 'Int', 'Float', 'Bytes'];
|
|
67
|
+
for (let i = 0; i < slices.length && i < keys.length; i++)
|
|
68
|
+
m.set(keys[i], slices[i]);
|
|
69
|
+
return m;
|
|
70
|
+
}
|
|
71
|
+
function getBlock(ctx, key) {
|
|
72
|
+
const b = ctx.blocks.get(key);
|
|
73
|
+
if (!b)
|
|
74
|
+
throw new Error(`mex argo: block '${key}' missing`);
|
|
75
|
+
return b;
|
|
76
|
+
}
|
|
77
|
+
function readStringFromBlock(ctx) {
|
|
78
|
+
const lab = ctx.core.label();
|
|
79
|
+
if (lab < BACKREF_BASE + 1) {
|
|
80
|
+
const idx = -lab + BACKREF_BASE;
|
|
81
|
+
return ctx.stringSeen[idx];
|
|
82
|
+
}
|
|
83
|
+
const block = getBlock(ctx, 'String');
|
|
84
|
+
const s = TEXT_DECODER.decode(block.bytes(lab));
|
|
85
|
+
ctx.stringSeen.push(s);
|
|
86
|
+
return s;
|
|
87
|
+
}
|
|
88
|
+
function readDesc(ctx) {
|
|
89
|
+
const m = ctx.core.label();
|
|
90
|
+
switch (m) {
|
|
91
|
+
case DESC_NULL:
|
|
92
|
+
return null;
|
|
93
|
+
case DESC_FALSE:
|
|
94
|
+
return false;
|
|
95
|
+
case DESC_TRUE:
|
|
96
|
+
return true;
|
|
97
|
+
case DESC_STRING:
|
|
98
|
+
return readStringFromBlock(ctx);
|
|
99
|
+
case DESC_INT:
|
|
100
|
+
return getBlock(ctx, 'Int').label();
|
|
101
|
+
case DESC_FLOAT:
|
|
102
|
+
throw new Error('mex argo: DESC_FLOAT not implemented');
|
|
103
|
+
case DESC_BYTES:
|
|
104
|
+
throw new Error('mex argo: DESC_BYTES not implemented');
|
|
105
|
+
case DESC_LIST: {
|
|
106
|
+
const n = ctx.core.label();
|
|
107
|
+
const out = [];
|
|
108
|
+
for (let i = 0; i < n; i++)
|
|
109
|
+
out.push(readDesc(ctx));
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
112
|
+
case DESC_OBJECT: {
|
|
113
|
+
const n = ctx.core.label();
|
|
114
|
+
const out = {};
|
|
115
|
+
for (let i = 0; i < n; i++) {
|
|
116
|
+
const key = readStringFromBlock(ctx);
|
|
117
|
+
out[key] = readDesc(ctx);
|
|
118
|
+
}
|
|
119
|
+
return out;
|
|
120
|
+
}
|
|
121
|
+
default:
|
|
122
|
+
throw new Error(`mex argo: unknown DESC marker ${m}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function readError(ctx) {
|
|
126
|
+
const message = readStringFromBlock(ctx);
|
|
127
|
+
skipOptional(ctx); // location — never observed in MEX errors so far
|
|
128
|
+
const path = readPath(ctx);
|
|
129
|
+
const extensions = readOptionalDesc(ctx);
|
|
130
|
+
return { message, path, extensions };
|
|
131
|
+
}
|
|
132
|
+
function skipOptional(ctx) {
|
|
133
|
+
const lab = ctx.core.label();
|
|
134
|
+
if (lab !== LABEL_ABSENT && lab !== LABEL_NULL) {
|
|
135
|
+
// Present but not yet structurally decoded; would need a typed inner read here.
|
|
136
|
+
// For locations specifically we have no observed sample; bail loudly if hit.
|
|
137
|
+
throw new Error(`mex argo: unexpected optional present (lab=${lab}); add support`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function readPath(ctx) {
|
|
141
|
+
const lab = ctx.core.label();
|
|
142
|
+
if (lab === LABEL_ABSENT || lab === LABEL_NULL)
|
|
143
|
+
return null;
|
|
144
|
+
return lab;
|
|
145
|
+
}
|
|
146
|
+
function readOptionalDesc(ctx) {
|
|
147
|
+
const lab = ctx.core.label();
|
|
148
|
+
if (lab === LABEL_ABSENT || lab === LABEL_NULL)
|
|
149
|
+
return null;
|
|
150
|
+
const v = readDesc(ctx);
|
|
151
|
+
return typeof v === 'object' && v !== null ? v : null;
|
|
152
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { WA_DEFAULTS, WA_IQ_TYPES, WA_NODE_TAGS, WA_XMLNS } from '../../../protocol/constants.js';
|
|
2
|
+
import { decodeNodeContentUtf8OrBytes, findNodeChild } from '../../node/helpers.js';
|
|
3
|
+
import { decodeMexArgoResponse, isMexArgoDecoderAvailable } from '../../node/mex/argo-decoder.js';
|
|
4
|
+
import { assertIqResult } from '../../node/query.js';
|
|
5
|
+
import { TEXT_DECODER } from '../../../util/bytes.js';
|
|
6
|
+
import { toError } from '../../../util/primitives.js';
|
|
7
|
+
const MEX_DEFAULT_TIMEOUT_MS = 32000;
|
|
8
|
+
export async function dispatchMexQuery(socket, args) {
|
|
9
|
+
const body = JSON.stringify({
|
|
10
|
+
queryId: args.clientDocId,
|
|
11
|
+
variables: args.variables
|
|
12
|
+
});
|
|
13
|
+
const node = {
|
|
14
|
+
tag: WA_NODE_TAGS.IQ,
|
|
15
|
+
attrs: {
|
|
16
|
+
...(args.iqId ? { id: args.iqId } : {}),
|
|
17
|
+
to: WA_DEFAULTS.HOST_DOMAIN,
|
|
18
|
+
type: WA_IQ_TYPES.GET,
|
|
19
|
+
xmlns: WA_XMLNS.MEX
|
|
20
|
+
},
|
|
21
|
+
content: [
|
|
22
|
+
{
|
|
23
|
+
tag: 'query',
|
|
24
|
+
attrs: { query_id: args.docId },
|
|
25
|
+
content: body
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
};
|
|
29
|
+
const response = await socket.query(node, args.timeoutMs ?? MEX_DEFAULT_TIMEOUT_MS);
|
|
30
|
+
assertIqResult(response, `mex/${args.opName}`);
|
|
31
|
+
const data = await parseMexResultPayload(response, args.opName);
|
|
32
|
+
return { raw: response, data };
|
|
33
|
+
}
|
|
34
|
+
async function parseMexResultPayload(node, opName) {
|
|
35
|
+
const result = findNodeChild(node, 'result');
|
|
36
|
+
if (!result) {
|
|
37
|
+
throw new Error(`mex/${opName} response missing <result>`);
|
|
38
|
+
}
|
|
39
|
+
const format = result.attrs.format ?? 'json';
|
|
40
|
+
const rawBytes = decodeNodeContentUtf8OrBytes(result.content, `mex/${opName}/result`);
|
|
41
|
+
if (format === 'argo') {
|
|
42
|
+
if (!(await isMexArgoDecoderAvailable())) {
|
|
43
|
+
throw new Error(`mex/${opName} argo response received but 'argo-codec' not installed; ${rawBytes.length}B; ` +
|
|
44
|
+
`strings: ${extractVisibleStrings(rawBytes)}`);
|
|
45
|
+
}
|
|
46
|
+
let decoded;
|
|
47
|
+
try {
|
|
48
|
+
decoded = await decodeMexArgoResponse(rawBytes);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
throw new Error(`mex/${opName} argo decode failed: ${toError(error).message}; ` +
|
|
52
|
+
`${rawBytes.length}B; strings: ${extractVisibleStrings(rawBytes)}`);
|
|
53
|
+
}
|
|
54
|
+
if (decoded.errors.length > 0) {
|
|
55
|
+
const summary = decoded.errors
|
|
56
|
+
.map((e) => {
|
|
57
|
+
const code = e.extensions?.error_code ?? e.extensions?.code ?? '?';
|
|
58
|
+
const sev = e.extensions?.severity;
|
|
59
|
+
return `${code}${sev ? `/${String(sev)}` : ''}: ${e.message} @${e.path ?? ''}`;
|
|
60
|
+
})
|
|
61
|
+
.join('; ');
|
|
62
|
+
throw new Error(`mex/${opName} errors: ${summary}`);
|
|
63
|
+
}
|
|
64
|
+
return decoded.data;
|
|
65
|
+
}
|
|
66
|
+
return extractGraphQlData(JSON.parse(TEXT_DECODER.decode(rawBytes)), opName);
|
|
67
|
+
}
|
|
68
|
+
function extractVisibleStrings(bytes) {
|
|
69
|
+
return TEXT_DECODER.decode(bytes)
|
|
70
|
+
.replace(/[\x00-\x1f\x7f-\xff]+/g, ' ')
|
|
71
|
+
.replace(/\s+/g, ' ')
|
|
72
|
+
.trim();
|
|
73
|
+
}
|
|
74
|
+
function extractGraphQlData(payload, opName) {
|
|
75
|
+
const json = (payload ?? {});
|
|
76
|
+
if (json.errors && json.errors.length > 0) {
|
|
77
|
+
const summary = json.errors
|
|
78
|
+
.map((e) => `${e.extensions?.error_code ?? '?'}: ${e.message ?? '?'} @${(e.path ?? []).join('.')}`)
|
|
79
|
+
.join('; ');
|
|
80
|
+
throw new Error(`mex/${opName} errors: ${summary}`);
|
|
81
|
+
}
|
|
82
|
+
return json.data ?? null;
|
|
83
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const WA_MEX_PERSIST_IDS = Object.freeze({
|
|
2
|
+
WWWGetCertificates: Object.freeze({
|
|
3
|
+
docId: '25094190163544446',
|
|
4
|
+
clientDocId: '16428758503015954638431529919'
|
|
5
|
+
}),
|
|
6
|
+
WWWCreateUser: Object.freeze({
|
|
7
|
+
docId: '8548056818544135',
|
|
8
|
+
clientDocId: '25777518041400352865446016972'
|
|
9
|
+
})
|
|
10
|
+
});
|
|
@@ -2,7 +2,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
2
2
|
import { md5Bytes } from '../../crypto/core/primitives.js';
|
|
3
3
|
import { proto } from '../../proto.js';
|
|
4
4
|
import { DEFAULT_VERSION_BASE } from '../noise/constants.js';
|
|
5
|
-
import { intToBytes
|
|
5
|
+
import { intToBytes } from '../../util/bytes.js';
|
|
6
6
|
function parseVersion(versionBase) {
|
|
7
7
|
const [p = '2', s = '3000', t = '0'] = versionBase.split('.');
|
|
8
8
|
const primary = Number.parseInt(p, 10);
|
|
@@ -15,13 +15,20 @@ function parseVersion(versionBase) {
|
|
|
15
15
|
}
|
|
16
16
|
return { primary, secondary, tertiary };
|
|
17
17
|
}
|
|
18
|
+
let cachedLocale = null;
|
|
18
19
|
function resolveLocale() {
|
|
20
|
+
// The first `Intl.DateTimeFormat()` call triggers V8's lazy ICU init
|
|
21
|
+
// (tens of ms). The process locale does not change at runtime, so
|
|
22
|
+
// memoize after the first resolve.
|
|
23
|
+
if (cachedLocale !== null)
|
|
24
|
+
return cachedLocale;
|
|
19
25
|
const locale = Intl.DateTimeFormat().resolvedOptions().locale || 'en-US';
|
|
20
26
|
const [language = 'en', country = 'US'] = locale.split('-');
|
|
21
|
-
|
|
27
|
+
cachedLocale = Object.freeze({
|
|
22
28
|
lg: language.toLowerCase(),
|
|
23
29
|
lc: country.toUpperCase()
|
|
24
|
-
};
|
|
30
|
+
});
|
|
31
|
+
return cachedLocale;
|
|
25
32
|
}
|
|
26
33
|
function defaultWebSubPlatform() {
|
|
27
34
|
return proto.ClientPayload.WebInfo.WebSubPlatform.WEB_BROWSER;
|
|
@@ -144,16 +151,14 @@ export function buildRegistrationPayload(config) {
|
|
|
144
151
|
const version = parseVersion(versionBase);
|
|
145
152
|
const common = buildCommonPayload(config, version);
|
|
146
153
|
const devicePairingData = {
|
|
147
|
-
buildHash: config.buildHash
|
|
148
|
-
deviceProps: config.deviceProps
|
|
149
|
-
? toBytesView(config.deviceProps)
|
|
150
|
-
: defaultDeviceProps(versionBase, config, version),
|
|
154
|
+
buildHash: config.buildHash ?? md5Bytes(versionBase),
|
|
155
|
+
deviceProps: config.deviceProps ?? defaultDeviceProps(versionBase, config, version),
|
|
151
156
|
eRegid: intToBytes(4, registrationId),
|
|
152
157
|
eKeytype: intToBytes(1, 5),
|
|
153
|
-
eIdent:
|
|
158
|
+
eIdent: config.registrationInfo.identityKeyPair.pubKey,
|
|
154
159
|
eSkeyId: intToBytes(3, signedPreKeyId),
|
|
155
|
-
eSkeyVal:
|
|
156
|
-
eSkeySig:
|
|
160
|
+
eSkeyVal: config.signedPreKey.keyPair.pubKey,
|
|
161
|
+
eSkeySig: config.signedPreKey.signature
|
|
157
162
|
};
|
|
158
163
|
return proto.ClientPayload.encode({
|
|
159
164
|
...common,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EMPTY_BYTES
|
|
1
|
+
import { EMPTY_BYTES } from '../../util/bytes.js';
|
|
2
2
|
const WA_MAX_FRAME_LENGTH = (1 << 24) - 1;
|
|
3
3
|
function frameLength(header) {
|
|
4
4
|
return (header[0] << 16) | (header[1] << 8) | header[2];
|
|
@@ -11,7 +11,7 @@ export class WaFrameCodec {
|
|
|
11
11
|
if (maxFrameLength >= 1 << 24) {
|
|
12
12
|
throw new Error('maxFrameLength must be lower than protocol limit (16777216)');
|
|
13
13
|
}
|
|
14
|
-
this.introFrame = introFrame && introFrame.length > 0 ?
|
|
14
|
+
this.introFrame = introFrame && introFrame.length > 0 ? introFrame : null;
|
|
15
15
|
this.maxFrameLength = maxFrameLength;
|
|
16
16
|
this.introSent = false;
|
|
17
17
|
this.buffered = EMPTY_BYTES;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { proto } from '../../proto.js';
|
|
3
|
+
function parseAppVersion(version) {
|
|
4
|
+
const parts = version.split('.');
|
|
5
|
+
const at = (i) => {
|
|
6
|
+
const n = Number(parts[i]);
|
|
7
|
+
return Number.isFinite(n) ? n : undefined;
|
|
8
|
+
};
|
|
9
|
+
return {
|
|
10
|
+
primary: at(0) ?? 2,
|
|
11
|
+
secondary: at(1) ?? 0,
|
|
12
|
+
tertiary: at(2) ?? 0,
|
|
13
|
+
quaternary: at(3)
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export function buildMobileLoginPayload(config) {
|
|
17
|
+
if (!Number.isSafeInteger(config.username) || config.username <= 0) {
|
|
18
|
+
throw new Error('mobile login payload requires a valid numeric username');
|
|
19
|
+
}
|
|
20
|
+
const info = config.deviceInfo;
|
|
21
|
+
const version = parseAppVersion(info.appVersion);
|
|
22
|
+
const userAgent = {
|
|
23
|
+
platform: proto.ClientPayload.UserAgent.Platform.ANDROID,
|
|
24
|
+
releaseChannel: proto.ClientPayload.UserAgent.ReleaseChannel.RELEASE,
|
|
25
|
+
appVersion: version,
|
|
26
|
+
mcc: info.mcc ?? '000',
|
|
27
|
+
mnc: info.mnc ?? '000',
|
|
28
|
+
osVersion: info.osVersion,
|
|
29
|
+
manufacturer: info.manufacturer,
|
|
30
|
+
device: info.device,
|
|
31
|
+
osBuildNumber: info.osBuildNumber,
|
|
32
|
+
phoneId: info.phoneId ?? randomUUID(),
|
|
33
|
+
localeLanguageIso6391: info.localeLanguageIso6391 ?? 'en',
|
|
34
|
+
localeCountryIso31661Alpha2: info.localeCountryIso31661Alpha2 ?? 'US',
|
|
35
|
+
deviceType: proto.ClientPayload.UserAgent.DeviceType.PHONE,
|
|
36
|
+
deviceBoard: info.deviceBoard,
|
|
37
|
+
deviceModelType: info.deviceModelType
|
|
38
|
+
};
|
|
39
|
+
return proto.ClientPayload.encode({
|
|
40
|
+
passive: config.passive === true,
|
|
41
|
+
pull: config.pull ?? true,
|
|
42
|
+
product: proto.ClientPayload.Product.WHATSAPP,
|
|
43
|
+
connectType: config.connectType ?? proto.ClientPayload.ConnectType.CELLULAR_UNKNOWN,
|
|
44
|
+
connectReason: config.connectReason ?? proto.ClientPayload.ConnectReason.USER_ACTIVATED,
|
|
45
|
+
userAgent,
|
|
46
|
+
username: config.username,
|
|
47
|
+
device: config.device ?? 0,
|
|
48
|
+
lidDbMigrated: config.lidDbMigrated === true,
|
|
49
|
+
pushName: config.pushName,
|
|
50
|
+
yearClass: config.yearClass,
|
|
51
|
+
memClass: config.memClass
|
|
52
|
+
}).finish();
|
|
53
|
+
}
|