zapo-js 0.1.0 → 0.1.2
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 +12 -7
- package/dist/appstate/WaAppStateCrypto.js +18 -25
- package/dist/appstate/WaAppStateSyncClient.js +181 -114
- package/dist/appstate/WaAppStateSyncResponseParser.js +16 -5
- package/dist/appstate/constants.js +4 -3
- package/dist/appstate/utils.js +10 -30
- package/dist/auth/WaAuthClient.js +48 -55
- package/dist/auth/flow/WaAuthCredentialsFlow.js +21 -14
- package/dist/auth/index.js +1 -3
- package/dist/auth/pairing/WaPairingFlow.js +21 -23
- package/dist/auth/pairing/WaQrFlow.js +37 -24
- package/dist/client/WaClient.js +103 -276
- package/dist/client/WaClientFactory.js +227 -110
- package/dist/client/connection/WaConnectionManager.js +292 -0
- package/dist/client/connection/WaKeyShareCoordinator.js +63 -0
- package/dist/client/connection/WaReceiptQueue.js +51 -0
- package/dist/client/coordinators/WaAppStateMutationCoordinator.js +471 -0
- package/dist/client/coordinators/WaGroupCoordinator.js +27 -17
- package/dist/client/coordinators/WaIncomingNodeCoordinator.js +20 -27
- package/dist/client/coordinators/WaMessageDispatchCoordinator.js +231 -686
- package/dist/client/coordinators/WaRetryCoordinator.js +70 -37
- package/dist/client/dirty.js +35 -29
- package/dist/client/events/chat.js +4 -3
- package/dist/client/events/group.js +59 -36
- package/dist/client/history-sync.js +53 -63
- package/dist/client/incoming.js +23 -20
- package/dist/client/mailbox.js +8 -8
- package/dist/client/messages.js +4 -4
- package/dist/client/messaging/fanout.js +189 -0
- package/dist/client/messaging/key-protocol.js +130 -0
- package/dist/client/messaging/participants.js +191 -0
- package/dist/crypto/core/hkdf.js +3 -8
- package/dist/crypto/core/index.js +1 -4
- package/dist/crypto/core/keys.js +2 -3
- package/dist/crypto/core/primitives.js +12 -15
- package/dist/crypto/core/random.js +7 -26
- package/dist/crypto/curves/Ed25519.js +7 -8
- package/dist/crypto/curves/X25519.js +13 -16
- package/dist/crypto/index.js +0 -5
- package/dist/esm/appstate/WaAppStateCrypto.js +6 -13
- package/dist/esm/appstate/WaAppStateSyncClient.js +174 -107
- package/dist/esm/appstate/WaAppStateSyncResponseParser.js +17 -6
- package/dist/esm/appstate/constants.js +3 -2
- package/dist/esm/appstate/utils.js +8 -27
- package/dist/esm/auth/WaAuthClient.js +48 -55
- package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +21 -14
- package/dist/esm/auth/index.js +0 -1
- package/dist/esm/auth/pairing/WaPairingFlow.js +14 -16
- package/dist/esm/auth/pairing/WaQrFlow.js +37 -24
- package/dist/esm/client/WaClient.js +103 -276
- package/dist/esm/client/WaClientFactory.js +227 -110
- package/dist/esm/client/connection/WaConnectionManager.js +288 -0
- package/dist/esm/client/connection/WaKeyShareCoordinator.js +59 -0
- package/dist/esm/client/connection/WaReceiptQueue.js +47 -0
- package/dist/esm/client/coordinators/WaAppStateMutationCoordinator.js +467 -0
- package/dist/esm/client/coordinators/WaGroupCoordinator.js +20 -10
- package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +20 -27
- package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +232 -687
- package/dist/esm/client/coordinators/WaRetryCoordinator.js +71 -38
- package/dist/esm/client/dirty.js +30 -24
- package/dist/esm/client/events/chat.js +4 -3
- package/dist/esm/client/events/group.js +50 -28
- package/dist/esm/client/history-sync.js +50 -60
- package/dist/esm/client/incoming.js +23 -20
- package/dist/esm/client/mailbox.js +8 -8
- package/dist/esm/client/messages.js +1 -1
- package/dist/esm/client/messaging/fanout.js +186 -0
- package/dist/esm/client/messaging/key-protocol.js +127 -0
- package/dist/esm/client/messaging/participants.js +188 -0
- package/dist/esm/crypto/core/hkdf.js +3 -8
- package/dist/esm/crypto/core/index.js +0 -1
- package/dist/esm/crypto/core/keys.js +2 -3
- package/dist/esm/crypto/core/primitives.js +12 -15
- package/dist/esm/crypto/core/random.js +6 -25
- package/dist/esm/crypto/curves/Ed25519.js +4 -5
- package/dist/esm/crypto/curves/X25519.js +10 -13
- package/dist/esm/crypto/index.js +0 -2
- package/dist/esm/infra/log/ConsoleLogger.js +18 -17
- package/dist/esm/infra/log/PinoLogger.js +15 -9
- package/dist/esm/infra/log/types.js +11 -1
- package/dist/esm/infra/perf/BoundedTaskQueue.js +13 -17
- package/dist/esm/media/WaMediaCrypto.js +2 -4
- package/dist/esm/media/WaMediaTransferClient.js +226 -58
- package/dist/esm/media/conn.js +10 -6
- package/dist/esm/media/constants.js +4 -1
- package/dist/esm/message/WaMessageClient.js +4 -13
- package/dist/esm/message/ack.js +6 -6
- package/dist/esm/message/addon-crypto.js +59 -0
- package/dist/esm/message/incoming.js +106 -111
- package/dist/esm/message/index.js +2 -0
- package/dist/esm/message/reporting-token.js +438 -0
- package/dist/esm/message/use-case-secret.js +49 -0
- package/dist/esm/protocol/appstate.js +58 -0
- package/dist/esm/protocol/constants.js +2 -1
- package/dist/esm/protocol/index.js +2 -10
- package/dist/esm/protocol/jid.js +63 -51
- package/dist/esm/protocol/media.js +3 -3
- package/dist/esm/protocol/nodes.js +2 -0
- package/dist/esm/protocol/usync.js +11 -0
- package/dist/esm/retry/index.js +1 -0
- package/dist/esm/retry/outbound.js +4 -5
- package/dist/esm/retry/parse.js +58 -76
- package/dist/esm/retry/replay.js +48 -49
- package/dist/esm/retry/tracker.js +56 -0
- package/dist/esm/signal/api/SignalDeviceSyncApi.js +249 -82
- package/dist/esm/signal/api/SignalDigestSyncApi.js +6 -1
- package/dist/esm/signal/api/SignalIdentitySyncApi.js +49 -34
- package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +70 -62
- package/dist/esm/signal/api/SignalSessionSyncApi.js +23 -30
- package/dist/esm/signal/crypto/WaAdvSignature.js +3 -5
- package/dist/esm/signal/group/SenderKeyChain.js +28 -23
- package/dist/esm/signal/group/SenderKeyCodec.js +2 -4
- package/dist/esm/signal/group/SenderKeyManager.js +26 -16
- package/dist/esm/signal/index.js +1 -0
- package/dist/esm/signal/session/SignalProtocol.js +49 -14
- package/dist/esm/signal/session/SignalRatchet.js +24 -15
- package/dist/esm/signal/session/SignalSession.js +14 -9
- package/dist/esm/signal/session/resolver.js +186 -0
- package/dist/esm/signal/store/sqlite.js +16 -37
- package/dist/esm/store/createStore.js +16 -18
- package/dist/esm/store/noop.store.js +3 -6
- package/dist/esm/store/providers/memory/appstate.store.js +30 -6
- package/dist/esm/store/providers/memory/contact.store.js +5 -0
- package/dist/esm/store/providers/memory/device-list.store.js +3 -30
- package/dist/esm/store/providers/memory/message.store.js +11 -5
- package/dist/esm/store/providers/memory/participants.store.js +1 -8
- package/dist/esm/store/providers/memory/sender-key.store.js +5 -7
- package/dist/esm/store/providers/memory/signal.store.js +13 -1
- package/dist/esm/store/providers/memory/thread.store.js +5 -0
- package/dist/esm/store/providers/sqlite/appstate.store.js +82 -1
- package/dist/esm/store/providers/sqlite/connection.js +18 -13
- package/dist/esm/store/providers/sqlite/contact.store.js +31 -18
- package/dist/esm/store/providers/sqlite/device-list.store.js +7 -35
- package/dist/esm/store/providers/sqlite/message.store.js +45 -32
- package/dist/esm/store/providers/sqlite/migrations.js +1 -1
- package/dist/esm/store/providers/sqlite/participants.store.js +1 -9
- package/dist/esm/store/providers/sqlite/retry.store.js +8 -11
- package/dist/esm/store/providers/sqlite/sender-key.store.js +25 -30
- package/dist/esm/store/providers/sqlite/signal.store.js +104 -22
- package/dist/esm/store/providers/sqlite/table-names.js +107 -0
- package/dist/esm/store/providers/sqlite/thread.store.js +35 -22
- package/dist/esm/transport/WaComms.js +25 -23
- package/dist/esm/transport/WaWebSocket.js +115 -12
- package/dist/esm/transport/binary/decoder.js +4 -4
- package/dist/esm/transport/binary/encoder.js +12 -4
- package/dist/esm/transport/index.js +1 -0
- package/dist/esm/transport/keepalive/WaKeepAlive.js +2 -8
- package/dist/esm/transport/node/WaNodeOrchestrator.js +2 -4
- package/dist/esm/transport/node/WaNodeTransport.js +0 -3
- package/dist/esm/transport/node/builders/{accountSync.js → account-sync.js} +16 -36
- package/dist/esm/transport/node/builders/index.js +2 -1
- package/dist/esm/transport/node/builders/message.js +9 -0
- package/dist/esm/transport/node/builders/pairing.js +4 -5
- package/dist/esm/transport/node/builders/usync.js +41 -0
- package/dist/esm/transport/node/helpers.js +107 -5
- package/dist/esm/transport/node/usync.js +35 -0
- package/dist/esm/transport/noise/WaFrameCodec.js +48 -33
- package/dist/esm/transport/noise/WaNoiseCert.js +3 -6
- package/dist/esm/transport/noise/WaNoiseSession.js +17 -10
- package/dist/esm/transport/proxy.js +27 -0
- package/dist/esm/transport/stream/parse.js +13 -48
- package/dist/esm/util/bytes.js +50 -32
- package/dist/esm/util/coercion.js +6 -14
- package/dist/esm/util/primitives.js +39 -14
- package/dist/infra/log/ConsoleLogger.js +18 -17
- package/dist/infra/log/PinoLogger.js +15 -9
- package/dist/infra/log/types.js +12 -0
- package/dist/infra/perf/BoundedTaskQueue.js +13 -17
- package/dist/media/WaMediaCrypto.js +1 -3
- package/dist/media/WaMediaTransferClient.js +259 -58
- package/dist/media/conn.js +10 -6
- package/dist/media/constants.js +4 -1
- package/dist/message/WaMessageClient.js +5 -14
- package/dist/message/ack.js +6 -6
- package/dist/message/addon-crypto.js +65 -0
- package/dist/message/incoming.js +104 -109
- package/dist/message/index.js +2 -0
- package/dist/message/reporting-token.js +443 -0
- package/dist/message/use-case-secret.js +55 -0
- package/dist/protocol/appstate.js +59 -1
- package/dist/protocol/constants.js +7 -1
- package/dist/protocol/index.js +20 -42
- package/dist/protocol/jid.js +64 -51
- package/dist/protocol/media.js +3 -3
- package/dist/protocol/nodes.js +2 -0
- package/dist/protocol/usync.js +14 -0
- package/dist/retry/index.js +3 -1
- package/dist/retry/outbound.js +6 -7
- package/dist/retry/parse.js +57 -75
- package/dist/retry/replay.js +46 -47
- package/dist/retry/tracker.js +59 -0
- package/dist/signal/api/SignalDeviceSyncApi.js +247 -80
- package/dist/signal/api/SignalDigestSyncApi.js +6 -1
- package/dist/signal/api/SignalIdentitySyncApi.js +49 -34
- package/dist/signal/api/SignalMissingPreKeysSyncApi.js +67 -59
- package/dist/signal/api/SignalSessionSyncApi.js +23 -30
- package/dist/signal/crypto/WaAdvSignature.js +2 -4
- package/dist/signal/group/SenderKeyChain.js +27 -22
- package/dist/signal/group/SenderKeyCodec.js +1 -3
- package/dist/signal/group/SenderKeyManager.js +26 -16
- package/dist/signal/index.js +3 -1
- package/dist/signal/session/SignalProtocol.js +49 -14
- package/dist/signal/session/SignalRatchet.js +24 -15
- package/dist/signal/session/SignalSession.js +14 -9
- package/dist/signal/session/resolver.js +189 -0
- package/dist/signal/store/sqlite.js +16 -37
- package/dist/store/createStore.js +16 -18
- package/dist/store/noop.store.js +3 -6
- package/dist/store/providers/memory/appstate.store.js +28 -4
- package/dist/store/providers/memory/contact.store.js +5 -0
- package/dist/store/providers/memory/device-list.store.js +3 -30
- package/dist/store/providers/memory/message.store.js +11 -5
- package/dist/store/providers/memory/participants.store.js +1 -8
- package/dist/store/providers/memory/sender-key.store.js +8 -10
- package/dist/store/providers/memory/signal.store.js +21 -9
- package/dist/store/providers/memory/thread.store.js +5 -0
- package/dist/store/providers/sqlite/appstate.store.js +81 -0
- package/dist/store/providers/sqlite/connection.js +18 -13
- package/dist/store/providers/sqlite/contact.store.js +31 -18
- package/dist/store/providers/sqlite/device-list.store.js +7 -35
- package/dist/store/providers/sqlite/message.store.js +45 -32
- package/dist/store/providers/sqlite/migrations.js +1 -1
- package/dist/store/providers/sqlite/participants.store.js +1 -9
- package/dist/store/providers/sqlite/retry.store.js +8 -11
- package/dist/store/providers/sqlite/sender-key.store.js +24 -29
- package/dist/store/providers/sqlite/signal.store.js +105 -23
- package/dist/store/providers/sqlite/table-names.js +113 -0
- package/dist/store/providers/sqlite/thread.store.js +35 -22
- package/dist/transport/WaComms.js +27 -25
- package/dist/transport/WaWebSocket.js +148 -12
- package/dist/transport/binary/decoder.js +4 -4
- package/dist/transport/binary/encoder.js +12 -4
- package/dist/transport/index.js +7 -1
- package/dist/transport/keepalive/WaKeepAlive.js +1 -7
- package/dist/transport/node/WaNodeOrchestrator.js +2 -4
- package/dist/transport/node/WaNodeTransport.js +0 -3
- package/dist/transport/node/builders/{accountSync.js → account-sync.js} +15 -35
- package/dist/transport/node/builders/index.js +12 -9
- package/dist/transport/node/builders/message.js +9 -0
- package/dist/transport/node/builders/pairing.js +4 -5
- package/dist/transport/node/builders/usync.js +45 -0
- package/dist/transport/node/helpers.js +112 -4
- package/dist/transport/node/usync.js +38 -0
- package/dist/transport/noise/WaFrameCodec.js +47 -32
- package/dist/transport/noise/WaNoiseCert.js +5 -8
- package/dist/transport/noise/WaNoiseSession.js +17 -10
- package/dist/transport/proxy.js +34 -0
- package/dist/transport/stream/parse.js +17 -53
- package/dist/types/appstate/WaAppStateCrypto.d.ts +0 -1
- package/dist/types/appstate/WaAppStateSyncClient.d.ts +5 -2
- package/dist/types/appstate/constants.d.ts +1 -0
- package/dist/types/appstate/store/sqlite.d.ts +4 -18
- package/dist/types/appstate/utils.d.ts +0 -1
- package/dist/types/auth/WaAuthClient.d.ts +10 -12
- package/dist/types/auth/index.d.ts +0 -2
- package/dist/types/auth/pairing/WaQrFlow.d.ts +1 -1
- package/dist/types/auth/types.d.ts +6 -9
- package/dist/types/client/WaClient.d.ts +27 -25
- package/dist/types/client/WaClientFactory.d.ts +22 -23
- package/dist/types/client/connection/WaConnectionManager.d.ts +64 -0
- package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +14 -0
- package/dist/types/client/connection/WaReceiptQueue.d.ts +13 -0
- package/dist/types/client/coordinators/WaAppStateMutationCoordinator.d.ts +46 -0
- package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +0 -1
- package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +18 -41
- package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +2 -0
- package/dist/types/client/dirty.d.ts +1 -0
- package/dist/types/client/events/group.d.ts +2 -1
- package/dist/types/client/index.d.ts +1 -1
- package/dist/types/client/messaging/fanout.d.ts +14 -0
- package/dist/types/client/messaging/key-protocol.d.ts +18 -0
- package/dist/types/client/messaging/participants.d.ts +13 -0
- package/dist/types/client/types.d.ts +24 -1
- package/dist/types/crypto/core/hkdf.d.ts +0 -6
- package/dist/types/crypto/core/index.d.ts +0 -1
- package/dist/types/crypto/core/random.d.ts +1 -7
- package/dist/types/crypto/index.d.ts +0 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/infra/log/ConsoleLogger.d.ts +2 -1
- package/dist/types/infra/log/PinoLogger.d.ts +1 -1
- package/dist/types/infra/log/types.d.ts +1 -0
- package/dist/types/infra/perf/BoundedTaskQueue.d.ts +1 -1
- package/dist/types/media/WaMediaTransferClient.d.ts +13 -3
- package/dist/types/media/types.d.ts +5 -0
- package/dist/types/message/addon-crypto.d.ts +25 -0
- package/dist/types/message/index.d.ts +2 -0
- package/dist/types/message/reporting-token.d.ts +19 -0
- package/dist/types/message/use-case-secret.d.ts +20 -0
- package/dist/types/protocol/appstate.d.ts +58 -0
- package/dist/types/protocol/constants.d.ts +2 -1
- package/dist/types/protocol/index.d.ts +2 -10
- package/dist/types/protocol/jid.d.ts +3 -3
- package/dist/types/protocol/nodes.d.ts +2 -0
- package/dist/types/protocol/usync.d.ts +11 -0
- package/dist/types/retry/index.d.ts +1 -0
- package/dist/types/retry/replay.d.ts +0 -4
- package/dist/types/retry/tracker.d.ts +19 -0
- package/dist/types/retry/types.d.ts +4 -3
- package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +13 -1
- package/dist/types/signal/group/SenderKeyCodec.d.ts +4 -6
- package/dist/types/signal/index.d.ts +1 -0
- package/dist/types/signal/session/SignalProtocol.d.ts +9 -0
- package/dist/types/signal/session/resolver.d.ts +17 -0
- package/dist/types/store/contracts/appstate.store.d.ts +3 -0
- package/dist/types/store/contracts/contact.store.d.ts +1 -0
- package/dist/types/store/contracts/device-list.store.d.ts +0 -3
- package/dist/types/store/contracts/message.store.d.ts +1 -0
- package/dist/types/store/contracts/participants.store.d.ts +0 -1
- package/dist/types/store/contracts/sender-key.store.d.ts +0 -1
- package/dist/types/store/contracts/signal.store.d.ts +6 -0
- package/dist/types/store/contracts/thread.store.d.ts +1 -0
- package/dist/types/store/index.d.ts +1 -1
- package/dist/types/store/providers/memory/appstate.store.d.ts +2 -0
- package/dist/types/store/providers/memory/contact.store.d.ts +1 -0
- package/dist/types/store/providers/memory/device-list.store.d.ts +0 -3
- package/dist/types/store/providers/memory/message.store.d.ts +1 -0
- package/dist/types/store/providers/memory/participants.store.d.ts +0 -1
- package/dist/types/store/providers/memory/sender-key.store.d.ts +0 -1
- package/dist/types/store/providers/memory/signal.store.d.ts +6 -0
- package/dist/types/store/providers/memory/thread.store.d.ts +1 -0
- package/dist/types/store/providers/sqlite/appstate.store.d.ts +2 -0
- package/dist/types/store/providers/sqlite/contact.store.d.ts +2 -0
- package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -3
- package/dist/types/store/providers/sqlite/message.store.d.ts +2 -0
- package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -1
- package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -1
- package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -1
- package/dist/types/store/providers/sqlite/signal.store.d.ts +7 -0
- package/dist/types/store/providers/sqlite/table-names.d.ts +5 -0
- package/dist/types/store/providers/sqlite/thread.store.d.ts +2 -0
- package/dist/types/store/types.d.ts +3 -0
- package/dist/types/transport/WaWebSocket.d.ts +3 -0
- package/dist/types/transport/index.d.ts +2 -1
- package/dist/types/transport/keepalive/WaKeepAlive.d.ts +0 -1
- package/dist/types/transport/node/WaNodeTransport.d.ts +0 -9
- package/dist/types/transport/node/builders/group.d.ts +4 -6
- package/dist/types/transport/node/builders/index.d.ts +2 -1
- package/dist/types/transport/node/builders/message.d.ts +14 -25
- package/dist/types/transport/node/builders/retry.d.ts +2 -4
- package/dist/types/transport/node/builders/usync.d.ts +21 -0
- package/dist/types/transport/node/helpers.d.ts +8 -0
- package/dist/types/transport/node/usync.d.ts +2 -0
- package/dist/types/transport/noise/WaFrameCodec.d.ts +3 -0
- package/dist/types/transport/noise/WaNoiseSession.d.ts +1 -0
- package/dist/types/transport/proxy.d.ts +6 -0
- package/dist/types/transport/stream/parse.d.ts +0 -1
- package/dist/types/transport/types.d.ts +18 -1
- package/dist/types/util/bytes.d.ts +5 -0
- package/dist/types/util/primitives.d.ts +3 -0
- package/dist/util/bytes.js +55 -33
- package/dist/util/coercion.js +6 -14
- package/dist/util/primitives.js +42 -14
- package/package.json +27 -9
- package/proto/index.d.ts +1090 -1048
- package/proto/index.js +1 -1
- package/scripts/check-node-version.cjs +0 -1
- package/dist/crypto/core/encoding.js +0 -29
- package/dist/esm/crypto/core/encoding.js +0 -25
- package/dist/esm/util/base64.js +0 -18
- package/dist/esm/util/signal-address.js +0 -5
- package/dist/types/crypto/core/encoding.d.ts +0 -11
- package/dist/types/util/base64.d.ts +0 -4
- package/dist/types/util/signal-address.d.ts +0 -2
- package/dist/util/base64.js +0 -24
- package/dist/util/signal-address.js +0 -8
- /package/dist/types/transport/node/builders/{accountSync.d.ts → account-sync.d.ts} +0 -0
package/dist/esm/protocol/jid.js
CHANGED
|
@@ -1,33 +1,53 @@
|
|
|
1
1
|
import { WA_DEFAULTS } from './constants.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
function scanJid(jid) {
|
|
3
|
+
let atIndex = -1;
|
|
4
|
+
let colonIndex = -1;
|
|
5
|
+
let dotIndex = -1;
|
|
6
|
+
for (let index = 0; index < jid.length; index++) {
|
|
7
|
+
const code = jid.charCodeAt(index);
|
|
8
|
+
if (code === 64) {
|
|
9
|
+
atIndex = index;
|
|
10
|
+
break;
|
|
11
|
+
}
|
|
12
|
+
if (code === 58 && colonIndex === -1)
|
|
13
|
+
colonIndex = index;
|
|
14
|
+
else if (code === 46 && dotIndex === -1 && colonIndex === -1)
|
|
15
|
+
dotIndex = index;
|
|
6
16
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
17
|
+
if (atIndex < 1 || atIndex >= jid.length - 1)
|
|
18
|
+
throw new Error(`invalid jid: ${jid}`);
|
|
19
|
+
return { atIndex, colonIndex, dotIndex };
|
|
20
|
+
}
|
|
21
|
+
export function splitJid(jid) {
|
|
22
|
+
const { atIndex } = scanJid(jid);
|
|
23
|
+
return { user: jid.slice(0, atIndex), server: jid.slice(atIndex + 1) };
|
|
11
24
|
}
|
|
12
25
|
export function normalizeRecipientJid(to) {
|
|
13
26
|
const input = to.trim();
|
|
14
|
-
if (input.length === 0)
|
|
27
|
+
if (input.length === 0)
|
|
15
28
|
throw new Error('recipient cannot be empty');
|
|
29
|
+
let hasDash = false;
|
|
30
|
+
let digits = '';
|
|
31
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
32
|
+
const code = input.charCodeAt(index);
|
|
33
|
+
if (code === 64)
|
|
34
|
+
return input;
|
|
35
|
+
if (code === 45) {
|
|
36
|
+
hasDash = true;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (code >= 48 && code <= 57)
|
|
40
|
+
digits += input[index];
|
|
16
41
|
}
|
|
17
|
-
if (
|
|
18
|
-
return input;
|
|
19
|
-
}
|
|
20
|
-
if (input.includes('-')) {
|
|
42
|
+
if (hasDash)
|
|
21
43
|
return `${input}@${WA_DEFAULTS.GROUP_SERVER}`;
|
|
22
|
-
|
|
23
|
-
const digits = input.replace(/\D/g, '');
|
|
24
|
-
if (digits.length === 0) {
|
|
44
|
+
if (digits.length === 0)
|
|
25
45
|
throw new Error(`invalid recipient: ${to}`);
|
|
26
|
-
}
|
|
27
46
|
return `${digits}@${WA_DEFAULTS.HOST_DOMAIN}`;
|
|
28
47
|
}
|
|
29
48
|
export function isJidType(jid, type) {
|
|
30
|
-
|
|
49
|
+
const atIndex = jid.length - type.length - 1;
|
|
50
|
+
return atIndex >= 1 && jid.charCodeAt(atIndex) === 64 && jid.endsWith(type);
|
|
31
51
|
}
|
|
32
52
|
export function isGroupJid(jid) {
|
|
33
53
|
return isJidType(jid, WA_DEFAULTS.GROUP_SERVER);
|
|
@@ -39,26 +59,14 @@ export function isGroupOrBroadcastJid(jid) {
|
|
|
39
59
|
return isGroupJid(jid) || isBroadcastJid(jid);
|
|
40
60
|
}
|
|
41
61
|
export function parseSignalAddressFromJid(jid) {
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
if (colonIndex === -1)
|
|
45
|
-
return {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
device: 0
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
const user = parsed.user.slice(0, colonIndex);
|
|
52
|
-
const deviceRaw = parsed.user.slice(colonIndex + 1);
|
|
53
|
-
const device = Number.parseInt(deviceRaw, 10);
|
|
54
|
-
if (!Number.isFinite(device) || device < 0) {
|
|
62
|
+
const { atIndex, colonIndex } = scanJid(jid);
|
|
63
|
+
const server = jid.slice(atIndex + 1);
|
|
64
|
+
if (colonIndex === -1)
|
|
65
|
+
return { user: jid.slice(0, atIndex), server, device: 0 };
|
|
66
|
+
const device = Number.parseInt(jid.slice(colonIndex + 1, atIndex), 10);
|
|
67
|
+
if (!Number.isFinite(device) || device < 0)
|
|
55
68
|
throw new Error(`invalid jid device: ${jid}`);
|
|
56
|
-
}
|
|
57
|
-
return {
|
|
58
|
-
user,
|
|
59
|
-
server: parsed.server,
|
|
60
|
-
device
|
|
61
|
-
};
|
|
69
|
+
return { user: jid.slice(0, colonIndex), server, device };
|
|
62
70
|
}
|
|
63
71
|
export function toUserJid(jid) {
|
|
64
72
|
const address = parseSignalAddressFromJid(jid);
|
|
@@ -66,29 +74,33 @@ export function toUserJid(jid) {
|
|
|
66
74
|
}
|
|
67
75
|
export function normalizeDeviceJid(jid) {
|
|
68
76
|
const address = parseSignalAddressFromJid(jid);
|
|
69
|
-
if (address.device === 0)
|
|
77
|
+
if (address.device === 0)
|
|
70
78
|
return `${address.user}@${address.server}`;
|
|
71
|
-
}
|
|
72
79
|
return `${address.user}:${address.device}@${address.server}`;
|
|
73
80
|
}
|
|
74
81
|
export function getLoginIdentity(meJid) {
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
if (!Number.isSafeInteger(username) || username <= 0) {
|
|
82
|
+
const { atIndex, colonIndex, dotIndex } = scanJid(meJid);
|
|
83
|
+
const userEndIndex = dotIndex === -1 ? (colonIndex === -1 ? atIndex : colonIndex) : dotIndex;
|
|
84
|
+
const username = Number.parseInt(meJid.slice(0, userEndIndex), 10);
|
|
85
|
+
const device = colonIndex === -1 ? 0 : Number.parseInt(meJid.slice(colonIndex + 1, atIndex), 10);
|
|
86
|
+
if (!Number.isSafeInteger(username) || username <= 0)
|
|
81
87
|
throw new Error(`invalid numeric username from ${meJid}`);
|
|
82
|
-
|
|
83
|
-
if (!Number.isSafeInteger(device) || device < 0) {
|
|
88
|
+
if (!Number.isSafeInteger(device) || device < 0)
|
|
84
89
|
throw new Error(`invalid device from ${meJid}`);
|
|
85
|
-
}
|
|
86
90
|
return { username, device };
|
|
87
91
|
}
|
|
88
92
|
export function parsePhoneJid(input) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
93
|
+
let digits = '';
|
|
94
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
95
|
+
const code = input.charCodeAt(index);
|
|
96
|
+
if (code >= 48 && code <= 57)
|
|
97
|
+
digits += input[index];
|
|
92
98
|
}
|
|
99
|
+
if (!digits)
|
|
100
|
+
throw new Error('phone number is empty after normalization');
|
|
93
101
|
return `${digits}@${WA_DEFAULTS.HOST_DOMAIN}`;
|
|
94
102
|
}
|
|
103
|
+
export function signalAddressKey(address) {
|
|
104
|
+
const server = address.server ?? WA_DEFAULTS.HOST_DOMAIN;
|
|
105
|
+
return `${address.user}|${server}|${address.device}`;
|
|
106
|
+
}
|
|
@@ -13,8 +13,8 @@ export const WA_MEDIA_HKDF_INFO = Object.freeze({
|
|
|
13
13
|
});
|
|
14
14
|
export const WA_PREVIEW_MEDIA_HKDF_INFO = 'Messenger Preview Keys';
|
|
15
15
|
export function getWaMediaHkdfInfo(mediaType) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const info = WA_MEDIA_HKDF_INFO[mediaType];
|
|
17
|
+
if (info !== undefined)
|
|
18
|
+
return info;
|
|
19
19
|
throw new Error(`unsupported media type: ${mediaType}`);
|
|
20
20
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const WA_USYNC_MODES = Object.freeze({
|
|
2
|
+
QUERY: 'query'
|
|
3
|
+
});
|
|
4
|
+
export const WA_USYNC_CONTEXTS = Object.freeze({
|
|
5
|
+
INTERACTIVE: 'interactive',
|
|
6
|
+
NOTIFICATION: 'notification'
|
|
7
|
+
});
|
|
8
|
+
export const WA_USYNC_DEFAULTS = Object.freeze({
|
|
9
|
+
INDEX: '0',
|
|
10
|
+
LAST: 'true'
|
|
11
|
+
});
|
package/dist/esm/retry/index.js
CHANGED
|
@@ -3,3 +3,4 @@ export { mapRetryReasonFromError } from './reason.js';
|
|
|
3
3
|
export { parseRetryReceiptRequest } from './parse.js';
|
|
4
4
|
export { decodeRetryReplayPayload, encodeRetryReplayPayload, pickRetryStateMax } from './outbound.js';
|
|
5
5
|
export { WaRetryReplayService } from './replay.js';
|
|
6
|
+
export { createOutboundRetryTracker } from './tracker.js';
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { TEXT_DECODER, TEXT_ENCODER } from '../util/bytes.js';
|
|
1
|
+
import { base64ToBytesChecked, bytesToBase64, TEXT_DECODER, TEXT_ENCODER } from '../util/bytes.js';
|
|
3
2
|
function requireObject(value) {
|
|
4
3
|
if (!value || typeof value !== 'object') {
|
|
5
4
|
throw new Error('invalid retry replay payload');
|
|
@@ -44,7 +43,7 @@ export function decodeRetryReplayPayload(raw) {
|
|
|
44
43
|
mode,
|
|
45
44
|
to: requireString(parsed.to, 'to'),
|
|
46
45
|
type: requireString(parsed.type, 'type'),
|
|
47
|
-
plaintext:
|
|
46
|
+
plaintext: base64ToBytesChecked(requireString(parsed.plaintext, 'plaintext'), 'retry.plaintext')
|
|
48
47
|
};
|
|
49
48
|
}
|
|
50
49
|
if (mode === 'encrypted') {
|
|
@@ -57,7 +56,7 @@ export function decodeRetryReplayPayload(raw) {
|
|
|
57
56
|
to: requireString(parsed.to, 'to'),
|
|
58
57
|
type: requireString(parsed.type, 'type'),
|
|
59
58
|
encType,
|
|
60
|
-
ciphertext:
|
|
59
|
+
ciphertext: base64ToBytesChecked(requireString(parsed.ciphertext, 'ciphertext'), 'retry.ciphertext'),
|
|
61
60
|
participant: parsed.participant === undefined
|
|
62
61
|
? undefined
|
|
63
62
|
: requireString(parsed.participant, 'participant')
|
|
@@ -66,7 +65,7 @@ export function decodeRetryReplayPayload(raw) {
|
|
|
66
65
|
if (mode === 'opaque_node') {
|
|
67
66
|
return {
|
|
68
67
|
mode,
|
|
69
|
-
node:
|
|
68
|
+
node: base64ToBytesChecked(requireString(parsed.node, 'node'), 'retry.node')
|
|
70
69
|
};
|
|
71
70
|
}
|
|
72
71
|
throw new Error(`invalid retry replay payload mode: ${mode}`);
|
package/dist/esm/retry/parse.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { WA_MESSAGE_TAGS, WA_NODE_TAGS } from '../protocol/constants.js';
|
|
2
2
|
import { SIGNAL_KEY_DATA_LENGTH, SIGNAL_KEY_ID_LENGTH, SIGNAL_REGISTRATION_ID_LENGTH, SIGNAL_SIGNATURE_LENGTH } from '../signal/api/constants.js';
|
|
3
|
-
import { decodeNodeContentBase64OrBytes,
|
|
4
|
-
import { parseOptionalInt } from '../
|
|
3
|
+
import { decodeNodeContentBase64OrBytes, findNodeChildrenByTags } from '../transport/node/helpers.js';
|
|
4
|
+
import { parseOptionalInt } from '../util/primitives.js';
|
|
5
5
|
function parseFixedLengthBytes(value, byteLength, field) {
|
|
6
6
|
const out = decodeNodeContentBase64OrBytes(value, field);
|
|
7
7
|
if (out.byteLength !== byteLength) {
|
|
@@ -10,81 +10,62 @@ function parseFixedLengthBytes(value, byteLength, field) {
|
|
|
10
10
|
return out;
|
|
11
11
|
}
|
|
12
12
|
function parseBigEndianUint(bytes, field) {
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
switch (bytes.byteLength) {
|
|
14
|
+
case 1:
|
|
15
|
+
return bytes[0];
|
|
16
|
+
case 2:
|
|
17
|
+
return (bytes[0] << 8) | bytes[1];
|
|
18
|
+
case 3:
|
|
19
|
+
return ((bytes[0] << 16) | (bytes[1] << 8) | bytes[2]) >>> 0;
|
|
20
|
+
case 4:
|
|
21
|
+
return ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0;
|
|
22
|
+
default:
|
|
23
|
+
throw new Error(`${field} has invalid byte length`);
|
|
15
24
|
}
|
|
16
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
17
|
-
if (bytes.byteLength === 1) {
|
|
18
|
-
return view.getUint8(0);
|
|
19
|
-
}
|
|
20
|
-
if (bytes.byteLength === 2) {
|
|
21
|
-
return view.getUint16(0);
|
|
22
|
-
}
|
|
23
|
-
return bytes.byteLength === 3 ? (view.getUint16(0) << 8) | view.getUint8(2) : view.getUint32(0);
|
|
24
|
-
}
|
|
25
|
-
function parseRetryType(value) {
|
|
26
|
-
if (value === 'retry' || value === 'enc_rekey_retry') {
|
|
27
|
-
return value;
|
|
28
|
-
}
|
|
29
|
-
return null;
|
|
30
25
|
}
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return 0;
|
|
35
|
-
}
|
|
36
|
-
if (parsed < 0) {
|
|
37
|
-
throw new Error('retry count must be >= 0');
|
|
38
|
-
}
|
|
39
|
-
return parsed;
|
|
40
|
-
}
|
|
41
|
-
function parseRetryReason(value) {
|
|
42
|
-
const parsed = parseOptionalInt(value);
|
|
43
|
-
if (parsed === undefined) {
|
|
44
|
-
return undefined;
|
|
45
|
-
}
|
|
46
|
-
if (parsed < 0) {
|
|
47
|
-
throw new Error('retry reason must be >= 0');
|
|
26
|
+
function requireNode(node, message) {
|
|
27
|
+
if (!node) {
|
|
28
|
+
throw new Error(message);
|
|
48
29
|
}
|
|
49
|
-
return
|
|
30
|
+
return node;
|
|
50
31
|
}
|
|
51
32
|
function parseRetryKeyBundle(node) {
|
|
52
33
|
if (!node) {
|
|
53
34
|
return undefined;
|
|
54
35
|
}
|
|
55
|
-
const identityNode =
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
36
|
+
const [identityNode, signedKeyNode, keyNode, deviceIdentityNode] = findNodeChildrenByTags(node, [WA_NODE_TAGS.IDENTITY, WA_NODE_TAGS.SKEY, WA_NODE_TAGS.KEY, WA_NODE_TAGS.DEVICE_IDENTITY]);
|
|
37
|
+
const identity = requireNode(identityNode, 'retry keys section missing identity or skey');
|
|
38
|
+
const signedKey = requireNode(signedKeyNode, 'retry keys section missing identity or skey');
|
|
39
|
+
const [signedKeyIdNode, signedKeyValueNode, signedKeySignatureNode] = findNodeChildrenByTags(signedKey, [WA_NODE_TAGS.ID, WA_NODE_TAGS.VALUE, WA_NODE_TAGS.SIGNATURE]);
|
|
40
|
+
const signedKeyId = requireNode(signedKeyIdNode, 'retry keys section has incomplete skey');
|
|
41
|
+
const signedKeyValue = requireNode(signedKeyValueNode, 'retry keys section has incomplete skey');
|
|
42
|
+
const signedKeySignature = requireNode(signedKeySignatureNode, 'retry keys section has incomplete skey');
|
|
43
|
+
let keyIdNode;
|
|
44
|
+
let keyValueNode;
|
|
45
|
+
if (keyNode) {
|
|
46
|
+
const keyNodes = findNodeChildrenByTags(keyNode, [WA_NODE_TAGS.ID, WA_NODE_TAGS.VALUE]);
|
|
47
|
+
keyIdNode = keyNodes[0];
|
|
48
|
+
keyValueNode = keyNodes[1];
|
|
49
|
+
}
|
|
50
|
+
const keyId = keyNode ? requireNode(keyIdNode, 'retry keys section has incomplete key') : null;
|
|
51
|
+
const keyValue = keyNode
|
|
52
|
+
? requireNode(keyValueNode, 'retry keys section has incomplete key')
|
|
53
|
+
: null;
|
|
73
54
|
return {
|
|
74
|
-
identity: parseFixedLengthBytes(
|
|
55
|
+
identity: parseFixedLengthBytes(identity.content, SIGNAL_KEY_DATA_LENGTH, 'retry.keys.identity'),
|
|
75
56
|
deviceIdentity: deviceIdentityNode
|
|
76
57
|
? decodeNodeContentBase64OrBytes(deviceIdentityNode.content, 'retry.keys.device-identity')
|
|
77
58
|
: undefined,
|
|
78
|
-
key:
|
|
59
|
+
key: keyId && keyValue
|
|
79
60
|
? {
|
|
80
|
-
id: parseBigEndianUint(parseFixedLengthBytes(
|
|
81
|
-
publicKey: parseFixedLengthBytes(
|
|
61
|
+
id: parseBigEndianUint(parseFixedLengthBytes(keyId.content, SIGNAL_KEY_ID_LENGTH, 'retry.keys.key.id'), 'retry.keys.key.id'),
|
|
62
|
+
publicKey: parseFixedLengthBytes(keyValue.content, SIGNAL_KEY_DATA_LENGTH, 'retry.keys.key.value')
|
|
82
63
|
}
|
|
83
64
|
: undefined,
|
|
84
65
|
skey: {
|
|
85
|
-
id: parseBigEndianUint(parseFixedLengthBytes(
|
|
86
|
-
publicKey: parseFixedLengthBytes(
|
|
87
|
-
signature: parseFixedLengthBytes(
|
|
66
|
+
id: parseBigEndianUint(parseFixedLengthBytes(signedKeyId.content, SIGNAL_KEY_ID_LENGTH, 'retry.keys.skey.id'), 'retry.keys.skey.id'),
|
|
67
|
+
publicKey: parseFixedLengthBytes(signedKeyValue.content, SIGNAL_KEY_DATA_LENGTH, 'retry.keys.skey.value'),
|
|
68
|
+
signature: parseFixedLengthBytes(signedKeySignature.content, SIGNAL_SIGNATURE_LENGTH, 'retry.keys.skey.signature')
|
|
88
69
|
}
|
|
89
70
|
};
|
|
90
71
|
}
|
|
@@ -92,7 +73,9 @@ export function parseRetryReceiptRequest(node) {
|
|
|
92
73
|
if (node.tag !== WA_MESSAGE_TAGS.RECEIPT) {
|
|
93
74
|
return null;
|
|
94
75
|
}
|
|
95
|
-
const receiptType =
|
|
76
|
+
const receiptType = node.attrs.type === 'retry' || node.attrs.type === 'enc_rekey_retry'
|
|
77
|
+
? node.attrs.type
|
|
78
|
+
: null;
|
|
96
79
|
if (!receiptType) {
|
|
97
80
|
return null;
|
|
98
81
|
}
|
|
@@ -101,19 +84,18 @@ export function parseRetryReceiptRequest(node) {
|
|
|
101
84
|
if (!stanzaId || !from) {
|
|
102
85
|
throw new Error('retry receipt is missing id/from attrs');
|
|
103
86
|
}
|
|
104
|
-
const retryNode =
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const originalMsgId = retryNode.attrs.id;
|
|
87
|
+
const [retryNode, registrationNode, keysNode] = findNodeChildrenByTags(node, [
|
|
88
|
+
'retry',
|
|
89
|
+
WA_NODE_TAGS.REGISTRATION,
|
|
90
|
+
'keys'
|
|
91
|
+
]);
|
|
92
|
+
const retry = requireNode(retryNode, 'retry receipt is missing retry child');
|
|
93
|
+
const registrationNodeValue = requireNode(registrationNode, 'retry receipt is missing registration child');
|
|
94
|
+
const originalMsgId = retry.attrs.id;
|
|
113
95
|
if (!originalMsgId) {
|
|
114
96
|
throw new Error('retry receipt is missing retry.id');
|
|
115
97
|
}
|
|
116
|
-
const registration = parseFixedLengthBytes(
|
|
98
|
+
const registration = parseFixedLengthBytes(registrationNodeValue.content, SIGNAL_REGISTRATION_ID_LENGTH, 'retry.registration');
|
|
117
99
|
return {
|
|
118
100
|
type: receiptType,
|
|
119
101
|
stanzaId,
|
|
@@ -121,10 +103,10 @@ export function parseRetryReceiptRequest(node) {
|
|
|
121
103
|
participant: node.attrs.participant,
|
|
122
104
|
recipient: node.attrs.recipient,
|
|
123
105
|
originalMsgId,
|
|
124
|
-
retryCount:
|
|
125
|
-
retryReason:
|
|
126
|
-
t:
|
|
106
|
+
retryCount: parseOptionalInt(retry.attrs.count) ?? 0,
|
|
107
|
+
retryReason: parseOptionalInt(retry.attrs.error ?? node.attrs.error),
|
|
108
|
+
t: retry.attrs.t ?? node.attrs.t,
|
|
127
109
|
regId: parseBigEndianUint(registration, 'retry.registration'),
|
|
128
|
-
keyBundle: parseRetryKeyBundle(
|
|
110
|
+
keyBundle: parseRetryKeyBundle(keysNode)
|
|
129
111
|
};
|
|
130
112
|
}
|
package/dist/esm/retry/replay.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { wrapDeviceSentMessage } from '../message/device-sent.js';
|
|
2
2
|
import { unpadPkcs7, writeRandomPadMax16 } from '../message/padding.js';
|
|
3
3
|
import { proto } from '../proto.js';
|
|
4
|
-
import { isGroupOrBroadcastJid, normalizeDeviceJid, parseSignalAddressFromJid,
|
|
4
|
+
import { isGroupOrBroadcastJid, normalizeDeviceJid, parseSignalAddressFromJid, toUserJid } from '../protocol/jid.js';
|
|
5
5
|
import { decodeRetryReplayPayload } from './outbound.js';
|
|
6
6
|
import { decodeBinaryNode } from '../transport/binary/index.js';
|
|
7
7
|
import { buildGroupRetryMessageNode } from '../transport/node/builders/message.js';
|
|
8
|
-
import { findNodeChild
|
|
8
|
+
import { findNodeChild } from '../transport/node/helpers.js';
|
|
9
9
|
import { toError } from '../util/primitives.js';
|
|
10
10
|
export class WaRetryReplayService {
|
|
11
11
|
constructor(options) {
|
|
@@ -13,17 +13,19 @@ export class WaRetryReplayService {
|
|
|
13
13
|
}
|
|
14
14
|
async resendOutboundMessage(outbound, requesterJid, retryCount) {
|
|
15
15
|
const payload = decodeRetryReplayPayload(outbound.replayPayload);
|
|
16
|
+
const requesterAddress = parseSignalAddressFromJid(requesterJid);
|
|
17
|
+
const normalizedRequesterJid = normalizeDeviceJid(requesterJid);
|
|
16
18
|
if (payload.mode === 'plaintext') {
|
|
17
|
-
return this.resendPlaintextPayload(outbound, payload, requesterJid, retryCount);
|
|
19
|
+
return this.resendPlaintextPayload(outbound, payload, requesterJid, requesterAddress, retryCount);
|
|
18
20
|
}
|
|
19
21
|
if (payload.mode === 'encrypted') {
|
|
20
|
-
return this.resendEncryptedPayload(outbound, payload, requesterJid, retryCount);
|
|
22
|
+
return this.resendEncryptedPayload(outbound, payload, requesterJid, normalizedRequesterJid, retryCount);
|
|
21
23
|
}
|
|
22
|
-
return this.resendOpaquePayload(outbound, payload,
|
|
24
|
+
return this.resendOpaquePayload(outbound, payload, normalizedRequesterJid);
|
|
23
25
|
}
|
|
24
|
-
async resendPlaintextPayload(outbound, payload, requesterJid, retryCount) {
|
|
26
|
+
async resendPlaintextPayload(outbound, payload, requesterJid, requesterAddress, retryCount) {
|
|
25
27
|
if (isGroupOrBroadcastJid(payload.to)) {
|
|
26
|
-
return this.resendGroupPlaintextPayload(outbound, payload, requesterJid);
|
|
28
|
+
return this.resendGroupPlaintextPayload(outbound, payload, requesterJid, requesterAddress);
|
|
27
29
|
}
|
|
28
30
|
let payloadUserJid;
|
|
29
31
|
let requesterUserJid;
|
|
@@ -37,8 +39,8 @@ export class WaRetryReplayService {
|
|
|
37
39
|
if (payloadUserJid !== requesterUserJid) {
|
|
38
40
|
return 'ineligible';
|
|
39
41
|
}
|
|
40
|
-
const encrypted = await this.signalProtocol.encryptMessage(
|
|
41
|
-
await this.messageClient.sendEncrypted({
|
|
42
|
+
const encrypted = await this.options.signalProtocol.encryptMessage(requesterAddress, payload.plaintext);
|
|
43
|
+
await this.options.messageClient.sendEncrypted({
|
|
42
44
|
to: requesterJid,
|
|
43
45
|
encType: encrypted.type,
|
|
44
46
|
ciphertext: encrypted.ciphertext,
|
|
@@ -48,15 +50,15 @@ export class WaRetryReplayService {
|
|
|
48
50
|
});
|
|
49
51
|
return 'resent';
|
|
50
52
|
}
|
|
51
|
-
async resendGroupPlaintextPayload(outbound, payload, requesterJid) {
|
|
53
|
+
async resendGroupPlaintextPayload(outbound, payload, requesterJid, requesterAddress) {
|
|
52
54
|
const plaintext = (await this.maybeWrapGroupRetryPlaintextForSelfDevice(payload, requesterJid)) ??
|
|
53
55
|
payload.plaintext;
|
|
54
|
-
const encrypted = await this.signalProtocol.encryptMessage(
|
|
56
|
+
const encrypted = await this.options.signalProtocol.encryptMessage(requesterAddress, plaintext);
|
|
55
57
|
let deviceIdentity;
|
|
56
58
|
if (encrypted.type === 'pkmsg') {
|
|
57
|
-
const signedIdentity = this.getCurrentSignedIdentity();
|
|
59
|
+
const signedIdentity = this.options.getCurrentSignedIdentity();
|
|
58
60
|
if (!signedIdentity) {
|
|
59
|
-
this.logger.warn('retry request rejected: missing signed identity for pkmsg group retry');
|
|
61
|
+
this.options.logger.warn('retry request rejected: missing signed identity for pkmsg group retry');
|
|
60
62
|
return 'ineligible';
|
|
61
63
|
}
|
|
62
64
|
deviceIdentity = proto.ADVSignedDeviceIdentity.encode(signedIdentity).finish();
|
|
@@ -66,22 +68,22 @@ export class WaRetryReplayService {
|
|
|
66
68
|
type: payload.type,
|
|
67
69
|
id: outbound.messageId,
|
|
68
70
|
requesterJid,
|
|
69
|
-
addressingMode:
|
|
71
|
+
addressingMode: requesterAddress.server === 'lid' ? 'lid' : 'pn',
|
|
70
72
|
encType: encrypted.type,
|
|
71
73
|
ciphertext: encrypted.ciphertext,
|
|
72
74
|
deviceIdentity
|
|
73
75
|
});
|
|
74
|
-
await this.messageClient.sendMessageNode(retryNode);
|
|
76
|
+
await this.options.messageClient.sendMessageNode(retryNode);
|
|
75
77
|
return 'resent';
|
|
76
78
|
}
|
|
77
|
-
async resendEncryptedPayload(outbound, payload, requesterJid, retryCount) {
|
|
79
|
+
async resendEncryptedPayload(outbound, payload, requesterJid, normalizedRequesterJid, retryCount) {
|
|
78
80
|
if (payload.encType === 'skmsg') {
|
|
79
81
|
return 'ineligible';
|
|
80
82
|
}
|
|
81
|
-
if (normalizeDeviceJid(payload.to) !==
|
|
83
|
+
if (normalizeDeviceJid(payload.to) !== normalizedRequesterJid) {
|
|
82
84
|
return 'ineligible';
|
|
83
85
|
}
|
|
84
|
-
await this.messageClient.sendEncrypted({
|
|
86
|
+
await this.options.messageClient.sendEncrypted({
|
|
85
87
|
to: requesterJid,
|
|
86
88
|
encType: payload.encType,
|
|
87
89
|
ciphertext: payload.ciphertext,
|
|
@@ -92,8 +94,11 @@ export class WaRetryReplayService {
|
|
|
92
94
|
});
|
|
93
95
|
return 'resent';
|
|
94
96
|
}
|
|
95
|
-
async resendOpaquePayload(outbound, payload,
|
|
97
|
+
async resendOpaquePayload(outbound, payload, normalizedRequesterJid) {
|
|
96
98
|
const decoded = decodeBinaryNode(payload.node);
|
|
99
|
+
if (!this.isOpaqueReplayCompatible(decoded, normalizedRequesterJid)) {
|
|
100
|
+
return 'ineligible';
|
|
101
|
+
}
|
|
97
102
|
const replayNode = decoded.attrs.id === outbound.messageId
|
|
98
103
|
? decoded
|
|
99
104
|
: {
|
|
@@ -103,10 +108,7 @@ export class WaRetryReplayService {
|
|
|
103
108
|
id: outbound.messageId
|
|
104
109
|
}
|
|
105
110
|
};
|
|
106
|
-
|
|
107
|
-
return 'ineligible';
|
|
108
|
-
}
|
|
109
|
-
await this.messageClient.sendMessageNode(replayNode);
|
|
111
|
+
await this.options.messageClient.sendMessageNode(replayNode);
|
|
110
112
|
return 'resent';
|
|
111
113
|
}
|
|
112
114
|
async maybeWrapGroupRetryPlaintextForSelfDevice(payload, requesterJid) {
|
|
@@ -120,7 +122,7 @@ export class WaRetryReplayService {
|
|
|
120
122
|
return writeRandomPadMax16(proto.Message.encode(wrapped).finish());
|
|
121
123
|
}
|
|
122
124
|
catch (error) {
|
|
123
|
-
this.logger.warn('retry request failed to wrap deviceSent payload for self requester', {
|
|
125
|
+
this.options.logger.warn('retry request failed to wrap deviceSent payload for self requester', {
|
|
124
126
|
requester: requesterJid,
|
|
125
127
|
to: payload.to,
|
|
126
128
|
message: toError(error).message
|
|
@@ -140,38 +142,35 @@ export class WaRetryReplayService {
|
|
|
140
142
|
}
|
|
141
143
|
return false;
|
|
142
144
|
}
|
|
143
|
-
|
|
144
|
-
return this.options.logger;
|
|
145
|
-
}
|
|
146
|
-
get messageClient() {
|
|
147
|
-
return this.options.messageClient;
|
|
148
|
-
}
|
|
149
|
-
get signalProtocol() {
|
|
150
|
-
return this.options.signalProtocol;
|
|
151
|
-
}
|
|
152
|
-
getCurrentSignedIdentity() {
|
|
153
|
-
return this.options.getCurrentSignedIdentity();
|
|
154
|
-
}
|
|
155
|
-
isOpaqueReplayCompatible(node, requesterJid) {
|
|
156
|
-
const requester = normalizeDeviceJid(requesterJid);
|
|
145
|
+
isOpaqueReplayCompatible(node, normalizedRequesterJid) {
|
|
157
146
|
const participantsNode = findNodeChild(node, 'participants');
|
|
158
147
|
if (participantsNode) {
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
148
|
+
const participantsContent = Array.isArray(participantsNode.content)
|
|
149
|
+
? participantsNode.content
|
|
150
|
+
: [];
|
|
151
|
+
let participantNode;
|
|
152
|
+
let participantCount = 0;
|
|
153
|
+
for (let index = 0; index < participantsContent.length; index++) {
|
|
154
|
+
const child = participantsContent[index];
|
|
155
|
+
if (child.tag !== 'to')
|
|
156
|
+
continue;
|
|
157
|
+
participantCount++;
|
|
158
|
+
if (participantCount > 1)
|
|
159
|
+
return false;
|
|
160
|
+
participantNode = child;
|
|
162
161
|
}
|
|
163
|
-
|
|
164
|
-
if (!participantJid) {
|
|
162
|
+
if (participantCount !== 1 || !participantNode)
|
|
165
163
|
return false;
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
const participantJid = participantNode.attrs.jid;
|
|
165
|
+
if (!participantJid)
|
|
166
|
+
return false;
|
|
167
|
+
return normalizeDeviceJid(participantJid) === normalizedRequesterJid;
|
|
168
168
|
}
|
|
169
169
|
if (node.attrs.participant) {
|
|
170
|
-
return normalizeDeviceJid(node.attrs.participant) ===
|
|
171
|
-
}
|
|
172
|
-
if (node.attrs.to) {
|
|
173
|
-
return normalizeDeviceJid(node.attrs.to) === requester;
|
|
170
|
+
return normalizeDeviceJid(node.attrs.participant) === normalizedRequesterJid;
|
|
174
171
|
}
|
|
172
|
+
if (node.attrs.to)
|
|
173
|
+
return normalizeDeviceJid(node.attrs.to) === normalizedRequesterJid;
|
|
175
174
|
return false;
|
|
176
175
|
}
|
|
177
176
|
}
|