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
|
@@ -4,7 +4,6 @@ exports.processHistorySyncNotification = processHistorySyncNotification;
|
|
|
4
4
|
const node_util_1 = require("node:util");
|
|
5
5
|
const node_zlib_1 = require("node:zlib");
|
|
6
6
|
const _proto_1 = require("../proto.js");
|
|
7
|
-
const base64_1 = require("../util/base64");
|
|
8
7
|
const bytes_1 = require("../util/bytes");
|
|
9
8
|
const primitives_1 = require("../util/primitives");
|
|
10
9
|
const unzipAsync = (0, node_util_1.promisify)(node_zlib_1.unzip);
|
|
@@ -31,15 +30,58 @@ async function processHistorySyncNotification(deps, notification) {
|
|
|
31
30
|
pushnames: historySync.pushnames.length
|
|
32
31
|
});
|
|
33
32
|
const nowMs = Date.now();
|
|
33
|
+
const contacts = [];
|
|
34
|
+
for (const pn of historySync.pushnames) {
|
|
35
|
+
if (!pn.id) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
contacts.push({
|
|
39
|
+
jid: pn.id,
|
|
40
|
+
pushName: pn.pushname ?? undefined,
|
|
41
|
+
lastUpdatedMs: nowMs
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const threads = [];
|
|
45
|
+
const messages = [];
|
|
34
46
|
let messagesCount = 0;
|
|
35
|
-
const conversationPromises = [];
|
|
36
47
|
for (const conversation of historySync.conversations) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
48
|
+
const threadJid = conversation.id;
|
|
49
|
+
if (!threadJid) {
|
|
50
|
+
deps.logger.debug('skipping history sync conversation without thread jid');
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
threads.push({
|
|
54
|
+
jid: threadJid,
|
|
55
|
+
name: conversation.name ?? undefined,
|
|
56
|
+
unreadCount: conversation.unreadCount ?? undefined,
|
|
57
|
+
archived: conversation.archived ?? undefined,
|
|
58
|
+
pinned: conversation.pinned ?? undefined,
|
|
59
|
+
muteEndMs: (0, primitives_1.longToNumber)(conversation.muteEndTime) || undefined,
|
|
60
|
+
markedAsUnread: conversation.markedAsUnread ?? undefined,
|
|
61
|
+
ephemeralExpiration: conversation.ephemeralExpiration ?? undefined
|
|
62
|
+
});
|
|
63
|
+
for (const histMsg of conversation.messages ?? []) {
|
|
64
|
+
const webMsg = histMsg.message;
|
|
65
|
+
if (!webMsg?.key?.id) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const timestampMs = (0, primitives_1.longToNumber)(webMsg.messageTimestamp) * 1000;
|
|
69
|
+
messages.push({
|
|
70
|
+
id: webMsg.key.id,
|
|
71
|
+
threadJid,
|
|
72
|
+
senderJid: webMsg.key.participant ?? undefined,
|
|
73
|
+
fromMe: webMsg.key.fromMe === true,
|
|
74
|
+
timestampMs: timestampMs || undefined,
|
|
75
|
+
messageBytes: webMsg.message
|
|
76
|
+
? _proto_1.proto.Message.encode(webMsg.message).finish()
|
|
77
|
+
: undefined
|
|
78
|
+
});
|
|
79
|
+
messagesCount += 1;
|
|
80
|
+
}
|
|
40
81
|
}
|
|
41
|
-
|
|
42
|
-
await
|
|
82
|
+
await deps.contactStore.upsertBatch(contacts);
|
|
83
|
+
await deps.threadStore.upsertBatch(threads);
|
|
84
|
+
await deps.messageStore.upsertBatch(messages);
|
|
43
85
|
const event = {
|
|
44
86
|
syncType,
|
|
45
87
|
messagesCount,
|
|
@@ -52,14 +94,14 @@ async function processHistorySyncNotification(deps, notification) {
|
|
|
52
94
|
}
|
|
53
95
|
async function downloadHistorySyncBlob(deps, notification) {
|
|
54
96
|
if (notification.initialHistBootstrapInlinePayload) {
|
|
55
|
-
return (0,
|
|
97
|
+
return (0, bytes_1.decodeProtoBytes)(notification.initialHistBootstrapInlinePayload, 'initialHistBootstrapInlinePayload');
|
|
56
98
|
}
|
|
57
99
|
if (!notification.directPath) {
|
|
58
100
|
throw new Error('history sync notification missing directPath');
|
|
59
101
|
}
|
|
60
|
-
const mediaKey = (0,
|
|
61
|
-
const fileSha256 = (0,
|
|
62
|
-
const fileEncSha256 = (0,
|
|
102
|
+
const mediaKey = (0, bytes_1.decodeProtoBytes)(notification.mediaKey, 'history sync mediaKey');
|
|
103
|
+
const fileSha256 = (0, bytes_1.decodeProtoBytes)(notification.fileSha256, 'history sync fileSha256');
|
|
104
|
+
const fileEncSha256 = (0, bytes_1.decodeProtoBytes)(notification.fileEncSha256, 'history sync fileEncSha256');
|
|
63
105
|
return deps.mediaTransfer.downloadAndDecrypt({
|
|
64
106
|
directPath: notification.directPath,
|
|
65
107
|
mediaType: 'history',
|
|
@@ -68,55 +110,3 @@ async function downloadHistorySyncBlob(deps, notification) {
|
|
|
68
110
|
fileEncSha256
|
|
69
111
|
});
|
|
70
112
|
}
|
|
71
|
-
async function persistConversation(deps, conversation, _nowMs) {
|
|
72
|
-
const threadJid = conversation.id;
|
|
73
|
-
if (!threadJid) {
|
|
74
|
-
deps.logger.debug('skipping history sync conversation without thread jid');
|
|
75
|
-
return 0;
|
|
76
|
-
}
|
|
77
|
-
const messages = conversation.messages ?? [];
|
|
78
|
-
const messageRecords = [];
|
|
79
|
-
for (const histMsg of messages) {
|
|
80
|
-
const webMsg = histMsg.message;
|
|
81
|
-
if (!webMsg?.key?.id) {
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
const timestampMs = (0, primitives_1.longToNumber)(webMsg.messageTimestamp) * 1000;
|
|
85
|
-
const messageBytes = webMsg.message
|
|
86
|
-
? _proto_1.proto.Message.encode(webMsg.message).finish()
|
|
87
|
-
: undefined;
|
|
88
|
-
messageRecords.push({
|
|
89
|
-
id: webMsg.key.id,
|
|
90
|
-
threadJid,
|
|
91
|
-
senderJid: webMsg.key.participant ?? undefined,
|
|
92
|
-
fromMe: webMsg.key.fromMe === true,
|
|
93
|
-
timestampMs: timestampMs || undefined,
|
|
94
|
-
messageBytes
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
const threadPromise = deps.threadStore.upsert({
|
|
98
|
-
jid: threadJid,
|
|
99
|
-
name: conversation.name ?? undefined,
|
|
100
|
-
unreadCount: conversation.unreadCount ?? undefined,
|
|
101
|
-
archived: conversation.archived ?? undefined,
|
|
102
|
-
pinned: conversation.pinned ?? undefined,
|
|
103
|
-
muteEndMs: (0, primitives_1.longToNumber)(conversation.muteEndTime) || undefined,
|
|
104
|
-
markedAsUnread: conversation.markedAsUnread ?? undefined,
|
|
105
|
-
ephemeralExpiration: conversation.ephemeralExpiration ?? undefined
|
|
106
|
-
});
|
|
107
|
-
const messagePromises = messageRecords.map((record) => deps.messageStore.upsert(record));
|
|
108
|
-
await Promise.all([threadPromise, ...messagePromises]);
|
|
109
|
-
return messageRecords.length;
|
|
110
|
-
}
|
|
111
|
-
async function persistPushnames(deps, pushnames, nowMs) {
|
|
112
|
-
if (pushnames.length === 0) {
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
await Promise.all(pushnames
|
|
116
|
-
.filter((pn) => !!pn.id)
|
|
117
|
-
.map((pn) => deps.contactStore.upsert({
|
|
118
|
-
jid: pn.id,
|
|
119
|
-
pushName: pn.pushname ?? undefined,
|
|
120
|
-
lastUpdatedMs: nowMs
|
|
121
|
-
})));
|
|
122
|
-
}
|
package/dist/client/incoming.js
CHANGED
|
@@ -12,7 +12,6 @@ const constants_1 = require("../protocol/constants");
|
|
|
12
12
|
const message_1 = require("../transport/node/builders/message");
|
|
13
13
|
const pairing_1 = require("../transport/node/builders/pairing");
|
|
14
14
|
const helpers_1 = require("../transport/node/helpers");
|
|
15
|
-
const parse_1 = require("../transport/stream/parse");
|
|
16
15
|
const primitives_1 = require("../util/primitives");
|
|
17
16
|
const LOGOUT_FAILURE_REASONS = new Set([401, 403, 406]);
|
|
18
17
|
const DISCONNECT_FAILURE_REASONS = new Set([405, 409, 503]);
|
|
@@ -128,8 +127,8 @@ function createIncomingReceiptHandler(options) {
|
|
|
128
127
|
}
|
|
129
128
|
function createIncomingFailureHandler(options) {
|
|
130
129
|
return async (node) => {
|
|
131
|
-
const reason = (0,
|
|
132
|
-
const code = (0,
|
|
130
|
+
const reason = (0, primitives_1.parseOptionalInt)(node.attrs.reason);
|
|
131
|
+
const code = (0, primitives_1.parseOptionalInt)(node.attrs.code);
|
|
133
132
|
options.emitIncomingFailure({
|
|
134
133
|
...createIncomingBaseEvent(node),
|
|
135
134
|
failureReason: reason,
|
|
@@ -150,47 +149,50 @@ function createIncomingNotificationHandler(options) {
|
|
|
150
149
|
const notificationType = node.attrs.type ?? '';
|
|
151
150
|
const classification = classifyNotificationType(notificationType);
|
|
152
151
|
const firstChildTag = (0, helpers_1.getFirstNodeChild)(node)?.tag;
|
|
152
|
+
const baseEvent = createIncomingBaseEvent(node);
|
|
153
153
|
const serverSyncCollections = notificationType === 'server_sync'
|
|
154
|
-
? (0, helpers_1.
|
|
155
|
-
.map((collectionNode) => collectionNode.attrs.name)
|
|
156
|
-
.filter((name) => typeof name === 'string' && name.length > 0)
|
|
154
|
+
? (0, helpers_1.getNodeChildrenNonEmptyAttrValuesByTag)(node, constants_1.WA_NODE_TAGS.COLLECTION, 'name')
|
|
157
155
|
: [];
|
|
156
|
+
let details;
|
|
157
|
+
if (firstChildTag || serverSyncCollections.length > 0) {
|
|
158
|
+
details = {};
|
|
159
|
+
if (firstChildTag) {
|
|
160
|
+
details.firstChildTag = firstChildTag;
|
|
161
|
+
}
|
|
162
|
+
if (serverSyncCollections.length > 0) {
|
|
163
|
+
details.collections = serverSyncCollections;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
158
166
|
options.emitIncomingNotification({
|
|
159
|
-
...
|
|
167
|
+
...baseEvent,
|
|
160
168
|
notificationType,
|
|
161
169
|
classification,
|
|
162
|
-
details
|
|
163
|
-
? {
|
|
164
|
-
...(firstChildTag ? { firstChildTag } : {}),
|
|
165
|
-
...(serverSyncCollections.length > 0
|
|
166
|
-
? { collections: serverSyncCollections }
|
|
167
|
-
: {})
|
|
168
|
-
}
|
|
169
|
-
: undefined
|
|
170
|
+
details
|
|
170
171
|
});
|
|
171
172
|
if (classification === 'out_of_scope') {
|
|
172
173
|
options.emitUnhandledStanza({
|
|
173
|
-
...
|
|
174
|
+
...baseEvent,
|
|
174
175
|
reason: `notification.${notificationType}.out_of_scope`
|
|
175
176
|
});
|
|
176
177
|
}
|
|
177
178
|
else if (classification === 'unknown') {
|
|
178
179
|
options.emitUnhandledStanza({
|
|
179
|
-
...
|
|
180
|
+
...baseEvent,
|
|
180
181
|
reason: `notification.${notificationType || 'unknown'}.not_supported`
|
|
181
182
|
});
|
|
182
183
|
}
|
|
183
184
|
await sendSafeAck(options.logger, options.sendNode, (0, pairing_1.buildNotificationAckNode)(node));
|
|
184
185
|
if (notificationType === 'server_sync' && serverSyncCollections.length > 0) {
|
|
186
|
+
const collectionsCsv = serverSyncCollections.join(',');
|
|
185
187
|
if (!options.syncAppState) {
|
|
186
188
|
options.logger.warn('received server_sync notification without app-state sync runtime', {
|
|
187
|
-
collections:
|
|
189
|
+
collections: collectionsCsv
|
|
188
190
|
});
|
|
189
191
|
return true;
|
|
190
192
|
}
|
|
191
193
|
void options.syncAppState().catch((error) => {
|
|
192
194
|
options.logger.warn('failed to sync app-state after server_sync notification', {
|
|
193
|
-
collections:
|
|
195
|
+
collections: collectionsCsv,
|
|
194
196
|
message: (0, primitives_1.toError)(error).message
|
|
195
197
|
});
|
|
196
198
|
});
|
|
@@ -203,6 +205,7 @@ function createIncomingGroupNotificationHandler(options) {
|
|
|
203
205
|
if (node.attrs.type !== constants_1.WA_NOTIFICATION_TYPES.GROUP) {
|
|
204
206
|
return false;
|
|
205
207
|
}
|
|
208
|
+
const baseEvent = createIncomingBaseEvent(node);
|
|
206
209
|
const parsed = (0, group_1.parseGroupNotificationEvents)(node);
|
|
207
210
|
for (const event of parsed.events) {
|
|
208
211
|
options.emitGroupEvent(event);
|
|
@@ -212,7 +215,7 @@ function createIncomingGroupNotificationHandler(options) {
|
|
|
212
215
|
}
|
|
213
216
|
if (parsed.events.length === 0 && parsed.unhandled.length === 0) {
|
|
214
217
|
options.emitUnhandledStanza({
|
|
215
|
-
...
|
|
218
|
+
...baseEvent,
|
|
216
219
|
reason: `notification.${constants_1.WA_NOTIFICATION_TYPES.GROUP}.empty`
|
|
217
220
|
});
|
|
218
221
|
}
|
package/dist/client/mailbox.js
CHANGED
|
@@ -4,14 +4,12 @@ exports.persistIncomingMailboxEntities = persistIncomingMailboxEntities;
|
|
|
4
4
|
const _proto_1 = require("../proto.js");
|
|
5
5
|
const primitives_1 = require("../util/primitives");
|
|
6
6
|
async function persistContacts(contactStore, event, nowMs) {
|
|
7
|
-
const candidateJids =
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
if (event.rawNode.attrs.participant) {
|
|
12
|
-
candidateJids.add(event.rawNode.attrs.participant);
|
|
7
|
+
const candidateJids = [event.senderJid, event.rawNode.attrs.participant].filter((jid) => !!jid);
|
|
8
|
+
if (candidateJids.length === 0) {
|
|
9
|
+
return;
|
|
13
10
|
}
|
|
14
|
-
|
|
11
|
+
const contacts = [...new Set(candidateJids)].map((jid) => ({ jid, lastUpdatedMs: nowMs }));
|
|
12
|
+
await contactStore.upsertBatch(contacts);
|
|
15
13
|
}
|
|
16
14
|
async function persistIncomingMailboxEntities(options) {
|
|
17
15
|
const { logger, contactStore, messageStore, event } = options;
|
|
@@ -31,7 +29,9 @@ async function persistIncomingMailboxEntities(options) {
|
|
|
31
29
|
senderJid: event.senderJid,
|
|
32
30
|
participantJid: event.rawNode.attrs.participant,
|
|
33
31
|
fromMe: false,
|
|
34
|
-
timestampMs: event.timestampSeconds === undefined
|
|
32
|
+
timestampMs: event.timestampSeconds === undefined
|
|
33
|
+
? undefined
|
|
34
|
+
: event.timestampSeconds * 1000,
|
|
35
35
|
encType: event.encryptionType,
|
|
36
36
|
plaintext: event.plaintext,
|
|
37
37
|
messageBytes
|
package/dist/client/messages.js
CHANGED
|
@@ -8,8 +8,8 @@ const WaMediaCrypto_1 = require("../media/WaMediaCrypto");
|
|
|
8
8
|
const content_1 = require("../message/content");
|
|
9
9
|
const constants_2 = require("../protocol/constants");
|
|
10
10
|
const media_1 = require("../transport/node/builders/media");
|
|
11
|
-
const base64_1 = require("../util/base64");
|
|
12
11
|
const bytes_1 = require("../util/bytes");
|
|
12
|
+
const bytes_2 = require("../util/bytes");
|
|
13
13
|
const primitives_1 = require("../util/primitives");
|
|
14
14
|
async function buildMediaMessageContent(options, content) {
|
|
15
15
|
if (typeof content === 'string') {
|
|
@@ -36,7 +36,7 @@ async function getMediaConn(options, forceRefresh = false) {
|
|
|
36
36
|
return mediaConn;
|
|
37
37
|
}
|
|
38
38
|
async function buildMediaMessage(options, content) {
|
|
39
|
-
const mediaBytes = (0,
|
|
39
|
+
const mediaBytes = (0, bytes_2.toBytesView)(content.media);
|
|
40
40
|
const uploaded = await uploadMedia(options, content, mediaBytes);
|
|
41
41
|
const mediaKeyTimestamp = Math.floor(Date.now() / 1000);
|
|
42
42
|
const common = {
|
|
@@ -113,7 +113,7 @@ async function uploadMedia(options, content, mediaBytes) {
|
|
|
113
113
|
]);
|
|
114
114
|
const selectedHost = mediaConn.hosts.find((host) => !host.isFallback)?.hostname ?? mediaConn.hosts[0].hostname;
|
|
115
115
|
const uploadPath = constants_1.MEDIA_UPLOAD_PATHS[uploadType];
|
|
116
|
-
const hashToken = (0,
|
|
116
|
+
const hashToken = (0, bytes_1.bytesToBase64UrlSafe)(encrypted.fileEncSha256);
|
|
117
117
|
const uploadUrl = `https://${selectedHost}${uploadPath}/${hashToken}?auth=${encodeURIComponent(mediaConn.auth)}&token=${encodeURIComponent(hashToken)}`;
|
|
118
118
|
options.logger.debug('sending media upload request', {
|
|
119
119
|
mediaType: content.type,
|
|
@@ -133,7 +133,7 @@ async function uploadMedia(options, content, mediaBytes) {
|
|
|
133
133
|
}
|
|
134
134
|
let parsedBody;
|
|
135
135
|
try {
|
|
136
|
-
parsedBody = JSON.parse(
|
|
136
|
+
parsedBody = JSON.parse(bytes_2.TEXT_DECODER.decode(uploadBody));
|
|
137
137
|
}
|
|
138
138
|
catch (error) {
|
|
139
139
|
throw new Error(`media upload returned invalid json: ${(0, primitives_1.toError)(error).message}`);
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDeviceFanoutResolver = createDeviceFanoutResolver;
|
|
4
|
+
const jid_1 = require("../../protocol/jid");
|
|
5
|
+
const primitives_1 = require("../../util/primitives");
|
|
6
|
+
function createDeviceFanoutResolver(options) {
|
|
7
|
+
const { signalDeviceSync, getCurrentMeJid, getCurrentMeLid, logger } = options;
|
|
8
|
+
const requireCurrentMeJid = (context) => {
|
|
9
|
+
const meJid = getCurrentMeJid();
|
|
10
|
+
if (meJid) {
|
|
11
|
+
return meJid;
|
|
12
|
+
}
|
|
13
|
+
throw new Error(`${context} requires registered meJid`);
|
|
14
|
+
};
|
|
15
|
+
const resolveDirectFanoutDeviceJids = async (recipientJid, selfDeviceJidForRecipient) => {
|
|
16
|
+
const recipientUserJid = (0, jid_1.toUserJid)(recipientJid);
|
|
17
|
+
const meUserJid = (0, jid_1.toUserJid)(selfDeviceJidForRecipient);
|
|
18
|
+
const targets = recipientUserJid === meUserJid ? [recipientUserJid] : [recipientUserJid, meUserJid];
|
|
19
|
+
try {
|
|
20
|
+
const synced = await signalDeviceSync.syncDeviceList(targets);
|
|
21
|
+
const byUser = new Map(synced.map((entry) => [(0, jid_1.toUserJid)(entry.jid), entry.deviceJids]));
|
|
22
|
+
const fanout = new Set();
|
|
23
|
+
const recipientDevices = byUser.get(recipientUserJid) ?? [];
|
|
24
|
+
if (recipientDevices.length === 0) {
|
|
25
|
+
fanout.add(recipientUserJid);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
for (let index = 0; index < recipientDevices.length; index += 1) {
|
|
29
|
+
fanout.add(recipientDevices[index]);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const meDevices = byUser.get(meUserJid) ?? [];
|
|
33
|
+
const normalizedMeJid = (0, jid_1.normalizeDeviceJid)(selfDeviceJidForRecipient);
|
|
34
|
+
for (let index = 0; index < meDevices.length; index += 1) {
|
|
35
|
+
const deviceJid = meDevices[index];
|
|
36
|
+
if ((0, jid_1.normalizeDeviceJid)(deviceJid) === normalizedMeJid) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
fanout.add(deviceJid);
|
|
40
|
+
}
|
|
41
|
+
return [...fanout];
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
logger.warn('signal device fanout sync failed, falling back to direct recipient', {
|
|
45
|
+
to: recipientJid,
|
|
46
|
+
message: (0, primitives_1.toError)(error).message
|
|
47
|
+
});
|
|
48
|
+
return [recipientUserJid];
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const resolveGroupParticipantDeviceJids = async (participantUserJids) => {
|
|
52
|
+
const meDeviceJids = new Set();
|
|
53
|
+
const meJid = getCurrentMeJid();
|
|
54
|
+
if (meJid) {
|
|
55
|
+
try {
|
|
56
|
+
meDeviceJids.add((0, jid_1.normalizeDeviceJid)(meJid));
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
logger.trace('ignoring malformed me jid', {
|
|
60
|
+
meJid,
|
|
61
|
+
message: (0, primitives_1.toError)(error).message
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const meLid = getCurrentMeLid();
|
|
66
|
+
if (meLid && meLid.includes('@')) {
|
|
67
|
+
try {
|
|
68
|
+
meDeviceJids.add((0, jid_1.normalizeDeviceJid)(meLid));
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
logger.trace('ignoring malformed me lid jid', {
|
|
72
|
+
meLid,
|
|
73
|
+
message: (0, primitives_1.toError)(error).message
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const candidateUsers = [...new Set(participantUserJids)];
|
|
78
|
+
if (candidateUsers.length === 0) {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const synced = await signalDeviceSync.syncDeviceList(candidateUsers);
|
|
83
|
+
const fanout = new Set();
|
|
84
|
+
for (const entry of synced) {
|
|
85
|
+
if (entry.deviceJids.length === 0) {
|
|
86
|
+
const normalizedEntryJid = (0, jid_1.normalizeDeviceJid)(entry.jid);
|
|
87
|
+
if (meDeviceJids.has(normalizedEntryJid)) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
fanout.add(normalizedEntryJid);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
for (const deviceJid of entry.deviceJids) {
|
|
94
|
+
const normalizedDeviceJid = (0, jid_1.normalizeDeviceJid)(deviceJid);
|
|
95
|
+
if (meDeviceJids.has(normalizedDeviceJid)) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
fanout.add(normalizedDeviceJid);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return [...fanout];
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
logger.warn('group participant device sync failed, falling back to participant user jids', {
|
|
105
|
+
participants: candidateUsers.length,
|
|
106
|
+
message: (0, primitives_1.toError)(error).message
|
|
107
|
+
});
|
|
108
|
+
const fallbackJids = new Set();
|
|
109
|
+
for (const candidateJid of candidateUsers) {
|
|
110
|
+
try {
|
|
111
|
+
const normalizedCandidateJid = (0, jid_1.normalizeDeviceJid)(candidateJid);
|
|
112
|
+
if (meDeviceJids.has(normalizedCandidateJid)) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
fallbackJids.add(normalizedCandidateJid);
|
|
116
|
+
}
|
|
117
|
+
catch (fallbackError) {
|
|
118
|
+
logger.trace('ignoring malformed participant jid in fallback fanout resolution', {
|
|
119
|
+
participantJid: candidateJid,
|
|
120
|
+
message: (0, primitives_1.toError)(fallbackError).message
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return [...fallbackJids];
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
const resolveOwnPeerDeviceJids = async () => {
|
|
128
|
+
const meJid = requireCurrentMeJid('resolveOwnPeerDeviceJids');
|
|
129
|
+
const meUserJid = (0, jid_1.toUserJid)(meJid);
|
|
130
|
+
const meDevices = new Set();
|
|
131
|
+
meDevices.add((0, jid_1.normalizeDeviceJid)(meJid));
|
|
132
|
+
const meLid = getCurrentMeLid();
|
|
133
|
+
if (meLid && meLid.includes('@')) {
|
|
134
|
+
try {
|
|
135
|
+
meDevices.add((0, jid_1.normalizeDeviceJid)(meLid));
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
logger.trace('ignoring malformed me lid jid while resolving peer devices', {
|
|
139
|
+
meLid,
|
|
140
|
+
message: (0, primitives_1.toError)(error).message
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
const synced = await signalDeviceSync.syncDeviceList([meUserJid]);
|
|
146
|
+
const peerDevices = new Set();
|
|
147
|
+
for (const entry of synced) {
|
|
148
|
+
const sourceDevices = entry.deviceJids.length > 0 ? entry.deviceJids : [entry.jid];
|
|
149
|
+
for (const deviceJid of sourceDevices) {
|
|
150
|
+
try {
|
|
151
|
+
const normalized = (0, jid_1.normalizeDeviceJid)(deviceJid);
|
|
152
|
+
if (meDevices.has(normalized)) {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
peerDevices.add(normalized);
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
logger.trace('ignoring malformed peer device jid while resolving app-state peers', {
|
|
159
|
+
deviceJid,
|
|
160
|
+
message: (0, primitives_1.toError)(error).message
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return [...peerDevices];
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
logger.warn('failed to resolve peer devices for app-state key request', {
|
|
169
|
+
message: (0, primitives_1.toError)(error).message
|
|
170
|
+
});
|
|
171
|
+
return [];
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
const resolveSelfDeviceJidForRecipient = (recipientJid, meJid, meLid) => {
|
|
175
|
+
if ((0, jid_1.splitJid)(recipientJid).server !== 'lid') {
|
|
176
|
+
return meJid;
|
|
177
|
+
}
|
|
178
|
+
if (!meLid || !meLid.includes('@')) {
|
|
179
|
+
return meJid;
|
|
180
|
+
}
|
|
181
|
+
return meLid;
|
|
182
|
+
};
|
|
183
|
+
return {
|
|
184
|
+
resolveDirectFanoutDeviceJids,
|
|
185
|
+
resolveGroupParticipantDeviceJids,
|
|
186
|
+
resolveOwnPeerDeviceJids,
|
|
187
|
+
resolveSelfDeviceJidForRecipient
|
|
188
|
+
};
|
|
189
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAppStateSyncKeyProtocol = createAppStateSyncKeyProtocol;
|
|
4
|
+
const padding_1 = require("../../message/padding");
|
|
5
|
+
const _proto_1 = require("../../proto.js");
|
|
6
|
+
const jid_1 = require("../../protocol/jid");
|
|
7
|
+
const bytes_1 = require("../../util/bytes");
|
|
8
|
+
function createAppStateSyncKeyProtocol(options) {
|
|
9
|
+
const { publishSignalMessage, fanoutResolver, getCurrentMeJid, getCurrentMeLid, logger } = options;
|
|
10
|
+
const requireCurrentIdentity = (context) => {
|
|
11
|
+
const meJid = getCurrentMeJid();
|
|
12
|
+
const meLid = getCurrentMeLid();
|
|
13
|
+
if (meJid || meLid) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
throw new Error(`${context} requires registered identity`);
|
|
17
|
+
};
|
|
18
|
+
const publishProtocolMessageToDevice = async (deviceJid, protocolMessage) => {
|
|
19
|
+
const plaintext = await (0, padding_1.writeRandomPadMax16)(_proto_1.proto.Message.encode({
|
|
20
|
+
protocolMessage
|
|
21
|
+
}).finish());
|
|
22
|
+
await publishSignalMessage({
|
|
23
|
+
to: deviceJid,
|
|
24
|
+
plaintext,
|
|
25
|
+
type: 'protocol',
|
|
26
|
+
category: 'peer',
|
|
27
|
+
pushPriority: 'high'
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
const requestKeys = async (keyIds) => {
|
|
31
|
+
requireCurrentIdentity('requestKeys');
|
|
32
|
+
const normalizedKeyIds = [];
|
|
33
|
+
const seenKeyIds = new Set();
|
|
34
|
+
for (const keyId of keyIds) {
|
|
35
|
+
if (keyId.byteLength === 0) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const keyHex = (0, bytes_1.bytesToHex)(keyId);
|
|
39
|
+
if (seenKeyIds.has(keyHex)) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
seenKeyIds.add(keyHex);
|
|
43
|
+
normalizedKeyIds.push(keyId);
|
|
44
|
+
}
|
|
45
|
+
if (normalizedKeyIds.length === 0) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
const peerDeviceJids = await fanoutResolver.resolveOwnPeerDeviceJids();
|
|
49
|
+
if (peerDeviceJids.length === 0) {
|
|
50
|
+
logger.warn('app-state sync key request skipped: no peer devices available', {
|
|
51
|
+
keys: normalizedKeyIds.length
|
|
52
|
+
});
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
const protocolMessage = {
|
|
56
|
+
type: _proto_1.proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_REQUEST,
|
|
57
|
+
appStateSyncKeyRequest: {
|
|
58
|
+
keyIds: normalizedKeyIds.map((keyId) => ({
|
|
59
|
+
keyId
|
|
60
|
+
}))
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const publishResults = await Promise.allSettled(peerDeviceJids.map((deviceJid) => publishProtocolMessageToDevice(deviceJid, protocolMessage)));
|
|
64
|
+
const failedPublishes = publishResults.filter((result) => result.status === 'rejected').length;
|
|
65
|
+
if (failedPublishes > 0) {
|
|
66
|
+
logger.warn('some app-state sync key requests failed', {
|
|
67
|
+
total: peerDeviceJids.length,
|
|
68
|
+
failed: failedPublishes
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
logger.info('app-state sync key request sent to peer devices', {
|
|
72
|
+
devices: peerDeviceJids.length,
|
|
73
|
+
keys: normalizedKeyIds.length,
|
|
74
|
+
keyIds: normalizedKeyIds.map((keyId) => (0, bytes_1.bytesToHex)(keyId)).join(',')
|
|
75
|
+
});
|
|
76
|
+
return peerDeviceJids;
|
|
77
|
+
};
|
|
78
|
+
const sendKeyShare = async (toDeviceJid, keys, missingKeyIds = []) => {
|
|
79
|
+
requireCurrentIdentity('sendKeyShare');
|
|
80
|
+
const normalizedTo = (0, jid_1.normalizeDeviceJid)(toDeviceJid);
|
|
81
|
+
const seenKeyIds = new Set();
|
|
82
|
+
const keyShareEntries = [];
|
|
83
|
+
let sharedKeyCount = 0;
|
|
84
|
+
for (const key of keys) {
|
|
85
|
+
const keyHex = (0, bytes_1.bytesToHex)(key.keyId);
|
|
86
|
+
if (seenKeyIds.has(keyHex)) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
seenKeyIds.add(keyHex);
|
|
90
|
+
sharedKeyCount += 1;
|
|
91
|
+
keyShareEntries.push({
|
|
92
|
+
keyId: { keyId: key.keyId },
|
|
93
|
+
keyData: {
|
|
94
|
+
keyData: key.keyData,
|
|
95
|
+
timestamp: key.timestamp,
|
|
96
|
+
...(key.fingerprint ? { fingerprint: key.fingerprint } : {})
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
for (const keyId of missingKeyIds) {
|
|
101
|
+
if (keyId.byteLength === 0) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const keyHex = (0, bytes_1.bytesToHex)(keyId);
|
|
105
|
+
if (seenKeyIds.has(keyHex)) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
seenKeyIds.add(keyHex);
|
|
109
|
+
keyShareEntries.push({
|
|
110
|
+
keyId: { keyId }
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
const protocolMessage = {
|
|
114
|
+
type: _proto_1.proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_SHARE,
|
|
115
|
+
appStateSyncKeyShare: {
|
|
116
|
+
keys: keyShareEntries
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
await publishProtocolMessageToDevice(normalizedTo, protocolMessage);
|
|
120
|
+
logger.info('app-state sync key share sent', {
|
|
121
|
+
to: normalizedTo,
|
|
122
|
+
keys: sharedKeyCount,
|
|
123
|
+
orphanKeys: keyShareEntries.length - sharedKeyCount
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
return {
|
|
127
|
+
requestKeys,
|
|
128
|
+
sendKeyShare
|
|
129
|
+
};
|
|
130
|
+
}
|