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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { proto } from '../../proto.js';
|
|
2
2
|
import { WA_MESSAGE_TAGS } from '../../protocol/constants.js';
|
|
3
|
-
import { isGroupOrBroadcastJid, normalizeDeviceJid, parseSignalAddressFromJid
|
|
3
|
+
import { isGroupOrBroadcastJid, normalizeDeviceJid, parseSignalAddressFromJid } from '../../protocol/jid.js';
|
|
4
4
|
import { MAX_RETRY_ATTEMPTS, RETRY_KEYS_MIN_COUNT, RETRY_OUTBOUND_TTL_MS, RETRY_REASON } from '../../retry/constants.js';
|
|
5
5
|
import { pickRetryStateMax } from '../../retry/outbound.js';
|
|
6
6
|
import { parseRetryReceiptRequest } from '../../retry/parse.js';
|
|
@@ -10,12 +10,16 @@ import { generatePreKeyPair } from '../../signal/registration/keygen.js';
|
|
|
10
10
|
import { buildInboundRetryReceiptAckNode } from '../../transport/node/builders/message.js';
|
|
11
11
|
import { buildRetryReceiptNode } from '../../transport/node/builders/retry.js';
|
|
12
12
|
import { toError } from '../../util/primitives.js';
|
|
13
|
+
const RETRY_CLEANUP_INTERVAL_MS = 30000;
|
|
13
14
|
function getRetryReasonName(code) {
|
|
14
15
|
if (code === undefined) {
|
|
15
16
|
return undefined;
|
|
16
17
|
}
|
|
17
|
-
const
|
|
18
|
-
|
|
18
|
+
for (const reasonName in RETRY_REASON) {
|
|
19
|
+
if (RETRY_REASON[reasonName] === code)
|
|
20
|
+
return reasonName;
|
|
21
|
+
}
|
|
22
|
+
return 'unknown';
|
|
19
23
|
}
|
|
20
24
|
function getRemoteRetryReasonLogFields(reason) {
|
|
21
25
|
return {
|
|
@@ -26,6 +30,7 @@ function getRemoteRetryReasonLogFields(reason) {
|
|
|
26
30
|
}
|
|
27
31
|
export class WaRetryCoordinator {
|
|
28
32
|
constructor(options) {
|
|
33
|
+
this.nextRetryCleanupAtMs = 0;
|
|
29
34
|
this.logger = options.logger;
|
|
30
35
|
this.retryStore = options.retryStore;
|
|
31
36
|
this.retryTtlMs = this.retryStore.getTtlMs?.() ?? RETRY_OUTBOUND_TTL_MS;
|
|
@@ -72,7 +77,7 @@ export class WaRetryCoordinator {
|
|
|
72
77
|
return;
|
|
73
78
|
}
|
|
74
79
|
try {
|
|
75
|
-
await this.
|
|
80
|
+
await this.maybeCleanupRetryStore(Date.now());
|
|
76
81
|
const request = parseRetryReceiptRequest(receiptNode);
|
|
77
82
|
if (!request) {
|
|
78
83
|
return;
|
|
@@ -97,10 +102,7 @@ export class WaRetryCoordinator {
|
|
|
97
102
|
}
|
|
98
103
|
async prepareDecryptFailureRetry(context, error) {
|
|
99
104
|
const nowMs = Date.now();
|
|
100
|
-
const
|
|
101
|
-
this.retryStore.cleanupExpired(nowMs),
|
|
102
|
-
this.signalStore.getRegistrationInfo()
|
|
103
|
-
]);
|
|
105
|
+
const registrationInfo = await this.signalStore.getRegistrationInfo();
|
|
104
106
|
if (!registrationInfo) {
|
|
105
107
|
this.logger.warn('retry receipt skipped: missing local registration info', {
|
|
106
108
|
id: context.stanzaId,
|
|
@@ -195,6 +197,21 @@ export class WaRetryCoordinator {
|
|
|
195
197
|
});
|
|
196
198
|
return null;
|
|
197
199
|
}
|
|
200
|
+
let requesterAddress;
|
|
201
|
+
let requesterNormalizedDeviceJid;
|
|
202
|
+
try {
|
|
203
|
+
requesterAddress = parseSignalAddressFromJid(requesterJid);
|
|
204
|
+
requesterNormalizedDeviceJid = normalizeDeviceJid(requesterJid);
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
this.logger.info('retry request rejected: invalid requester jid', {
|
|
208
|
+
id: request.stanzaId,
|
|
209
|
+
originalMsgId: request.originalMsgId,
|
|
210
|
+
requester: requesterJid,
|
|
211
|
+
message: toError(error).message
|
|
212
|
+
});
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
198
215
|
if (request.retryCount >= MAX_RETRY_ATTEMPTS) {
|
|
199
216
|
this.logger.info('retry request rejected: retry count exceeded', {
|
|
200
217
|
id: request.stanzaId,
|
|
@@ -214,7 +231,7 @@ export class WaRetryCoordinator {
|
|
|
214
231
|
});
|
|
215
232
|
return null;
|
|
216
233
|
}
|
|
217
|
-
const sessionReady = await this.updateLocalSessionFromRetryRequest(request, requesterJid);
|
|
234
|
+
const sessionReady = await this.updateLocalSessionFromRetryRequest(request, requesterJid, requesterAddress, requesterNormalizedDeviceJid);
|
|
218
235
|
if (!sessionReady) {
|
|
219
236
|
this.logger.info('retry request rejected: missing compatible session', {
|
|
220
237
|
id: request.stanzaId,
|
|
@@ -225,7 +242,7 @@ export class WaRetryCoordinator {
|
|
|
225
242
|
});
|
|
226
243
|
return null;
|
|
227
244
|
}
|
|
228
|
-
const authorization = await this.authorizeRetryRequest(request, outbound, requesterJid);
|
|
245
|
+
const authorization = await this.authorizeRetryRequest(request, outbound, requesterJid, requesterAddress, requesterNormalizedDeviceJid);
|
|
229
246
|
if (!authorization.authorized) {
|
|
230
247
|
this.logger.info('retry request rejected', {
|
|
231
248
|
id: request.stanzaId,
|
|
@@ -239,6 +256,8 @@ export class WaRetryCoordinator {
|
|
|
239
256
|
}
|
|
240
257
|
return {
|
|
241
258
|
requesterJid,
|
|
259
|
+
requesterAddress,
|
|
260
|
+
requesterNormalizedDeviceJid,
|
|
242
261
|
outbound
|
|
243
262
|
};
|
|
244
263
|
}
|
|
@@ -271,7 +290,7 @@ export class WaRetryCoordinator {
|
|
|
271
290
|
}
|
|
272
291
|
async runRetryTaskSerialized(messageId, task) {
|
|
273
292
|
const previous = this.retryProcessingByMessageId.get(messageId) ?? Promise.resolve();
|
|
274
|
-
const current = previous.
|
|
293
|
+
const current = previous.then(task, task);
|
|
275
294
|
const tracker = current.then(() => undefined, () => undefined);
|
|
276
295
|
this.retryProcessingByMessageId.set(messageId, tracker);
|
|
277
296
|
try {
|
|
@@ -311,18 +330,17 @@ export class WaRetryCoordinator {
|
|
|
311
330
|
: undefined
|
|
312
331
|
};
|
|
313
332
|
}
|
|
314
|
-
async updateLocalSessionFromRetryRequest(request, requesterJid) {
|
|
315
|
-
await this.markRetryRequesterSenderKeyAsStale(request, requesterJid);
|
|
316
|
-
const
|
|
317
|
-
const currentSession = await this.signalStore.getSession(address);
|
|
333
|
+
async updateLocalSessionFromRetryRequest(request, requesterJid, requesterAddress, requesterNormalizedDeviceJid) {
|
|
334
|
+
await this.markRetryRequesterSenderKeyAsStale(request, requesterJid, requesterAddress);
|
|
335
|
+
const currentSession = await this.signalStore.getSession(requesterAddress);
|
|
318
336
|
if (currentSession && request.regId > 0 && currentSession.remote.regId !== request.regId) {
|
|
319
|
-
await this.signalStore.deleteSession(
|
|
337
|
+
await this.signalStore.deleteSession(requesterAddress);
|
|
320
338
|
}
|
|
321
339
|
if (request.keyBundle) {
|
|
322
|
-
if (!request.keyBundle.key) {
|
|
340
|
+
if (!request.keyBundle.key || !request.keyBundle.skey.signature) {
|
|
323
341
|
return false;
|
|
324
342
|
}
|
|
325
|
-
await this.signalProtocol.establishOutgoingSession(
|
|
343
|
+
await this.signalProtocol.establishOutgoingSession(requesterAddress, {
|
|
326
344
|
regId: request.regId,
|
|
327
345
|
identity: request.keyBundle.identity,
|
|
328
346
|
signedKey: {
|
|
@@ -337,23 +355,22 @@ export class WaRetryCoordinator {
|
|
|
337
355
|
});
|
|
338
356
|
return true;
|
|
339
357
|
}
|
|
340
|
-
const hasSession = await this.signalProtocol.hasSession(
|
|
358
|
+
const hasSession = await this.signalProtocol.hasSession(requesterAddress);
|
|
341
359
|
if (hasSession) {
|
|
342
360
|
return true;
|
|
343
361
|
}
|
|
344
|
-
const fetched = await this.fetchMissingPreKeysSession(requesterJid, request.regId);
|
|
362
|
+
const fetched = await this.fetchMissingPreKeysSession(requesterJid, requesterAddress, requesterNormalizedDeviceJid, request.regId);
|
|
345
363
|
if (!fetched) {
|
|
346
364
|
return false;
|
|
347
365
|
}
|
|
348
|
-
await this.signalProtocol.establishOutgoingSession(
|
|
366
|
+
await this.signalProtocol.establishOutgoingSession(requesterAddress, fetched);
|
|
349
367
|
return true;
|
|
350
368
|
}
|
|
351
|
-
async markRetryRequesterSenderKeyAsStale(request, requesterJid) {
|
|
369
|
+
async markRetryRequesterSenderKeyAsStale(request, requesterJid, requesterAddress) {
|
|
352
370
|
if (!isGroupOrBroadcastJid(request.from)) {
|
|
353
371
|
return;
|
|
354
372
|
}
|
|
355
373
|
try {
|
|
356
|
-
const requesterAddress = parseSignalAddressFromJid(requesterJid);
|
|
357
374
|
const deleted = await this.senderKeyStore.markForgetSenderKey(request.from, [
|
|
358
375
|
requesterAddress
|
|
359
376
|
]);
|
|
@@ -371,12 +388,11 @@ export class WaRetryCoordinator {
|
|
|
371
388
|
});
|
|
372
389
|
}
|
|
373
390
|
}
|
|
374
|
-
async fetchMissingPreKeysSession(requesterJid, requesterRegistrationId) {
|
|
391
|
+
async fetchMissingPreKeysSession(requesterJid, requesterAddress, requesterNormalizedDeviceJid, requesterRegistrationId) {
|
|
375
392
|
try {
|
|
376
|
-
const requesterAddress = parseSignalAddressFromJid(requesterJid);
|
|
377
393
|
const results = await this.signalMissingPreKeysSync.fetchMissingPreKeys([
|
|
378
394
|
{
|
|
379
|
-
userJid:
|
|
395
|
+
userJid: `${requesterAddress.user}@${requesterAddress.server}`,
|
|
380
396
|
devices: [
|
|
381
397
|
{
|
|
382
398
|
deviceId: requesterAddress.device,
|
|
@@ -393,8 +409,7 @@ export class WaRetryCoordinator {
|
|
|
393
409
|
});
|
|
394
410
|
return null;
|
|
395
411
|
}
|
|
396
|
-
const
|
|
397
|
-
const matched = first.devices.find((device) => normalizeDeviceJid(device.deviceJid) === requesterDeviceJid);
|
|
412
|
+
const matched = first.devices.find((device) => normalizeDeviceJid(device.deviceJid) === requesterNormalizedDeviceJid);
|
|
398
413
|
if (!matched) {
|
|
399
414
|
this.logger.warn('missing prekeys fetch did not return requested device', {
|
|
400
415
|
requester: requesterJid,
|
|
@@ -412,7 +427,7 @@ export class WaRetryCoordinator {
|
|
|
412
427
|
return null;
|
|
413
428
|
}
|
|
414
429
|
}
|
|
415
|
-
async authorizeRetryRequest(request, outbound, requesterJid) {
|
|
430
|
+
async authorizeRetryRequest(request, outbound, requesterJid, requesterAddress, requesterNormalizedDeviceJid) {
|
|
416
431
|
if (outbound.state === 'ineligible') {
|
|
417
432
|
return { authorized: false, reason: `state_${outbound.state}` };
|
|
418
433
|
}
|
|
@@ -420,25 +435,29 @@ export class WaRetryCoordinator {
|
|
|
420
435
|
if (!isGroupOutbound && (outbound.state === 'read' || outbound.state === 'played')) {
|
|
421
436
|
return { authorized: false, reason: `state_${outbound.state}` };
|
|
422
437
|
}
|
|
423
|
-
const requesterAuthorized = await this.isRequesterAuthorizedDevice(requesterJid);
|
|
438
|
+
const requesterAuthorized = await this.isRequesterAuthorizedDevice(requesterJid, requesterAddress, requesterNormalizedDeviceJid);
|
|
424
439
|
if (!requesterAuthorized) {
|
|
425
440
|
return { authorized: false, reason: 'requester_device_not_authorized' };
|
|
426
441
|
}
|
|
427
442
|
return { authorized: true };
|
|
428
443
|
}
|
|
429
|
-
async isRequesterAuthorizedDevice(requesterJid) {
|
|
444
|
+
async isRequesterAuthorizedDevice(requesterJid, requesterAddress, requesterNormalizedDeviceJid) {
|
|
430
445
|
try {
|
|
431
|
-
const requesterUser =
|
|
446
|
+
const requesterUser = `${requesterAddress.user}@${requesterAddress.server}`;
|
|
447
|
+
if (requesterNormalizedDeviceJid === normalizeDeviceJid(requesterUser)) {
|
|
448
|
+
return true;
|
|
449
|
+
}
|
|
432
450
|
const synced = await this.signalDeviceSync.syncDeviceList([requesterUser]);
|
|
433
451
|
const target = synced.find((entry) => entry.jid === requesterUser);
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
452
|
+
if (!target) {
|
|
453
|
+
return false;
|
|
454
|
+
}
|
|
455
|
+
for (let index = 0; index < target.deviceJids.length; index += 1) {
|
|
456
|
+
if (normalizeDeviceJid(target.deviceJids[index]) === requesterNormalizedDeviceJid) {
|
|
457
|
+
return true;
|
|
439
458
|
}
|
|
440
459
|
}
|
|
441
|
-
return
|
|
460
|
+
return false;
|
|
442
461
|
}
|
|
443
462
|
catch (error) {
|
|
444
463
|
this.logger.warn('retry authorization failed while syncing requester device list', {
|
|
@@ -487,4 +506,18 @@ export class WaRetryCoordinator {
|
|
|
487
506
|
});
|
|
488
507
|
}
|
|
489
508
|
}
|
|
509
|
+
async maybeCleanupRetryStore(nowMs) {
|
|
510
|
+
if (nowMs < this.nextRetryCleanupAtMs) {
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
this.nextRetryCleanupAtMs = nowMs + RETRY_CLEANUP_INTERVAL_MS;
|
|
514
|
+
try {
|
|
515
|
+
await this.retryStore.cleanupExpired(nowMs);
|
|
516
|
+
}
|
|
517
|
+
catch (error) {
|
|
518
|
+
this.logger.warn('retry store cleanup failed', {
|
|
519
|
+
message: toError(error).message
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
}
|
|
490
523
|
}
|
package/dist/esm/client/dirty.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { randomBytesAsync } from '../crypto/index.js';
|
|
2
1
|
import { WA_ACCOUNT_SYNC_PROTOCOLS, WA_DEFAULTS, WA_DIRTY_PROTOCOLS, WA_DIRTY_TYPES, WA_IQ_TYPES, WA_SUPPORTED_DIRTY_TYPES } from '../protocol/constants.js';
|
|
3
2
|
import { toUserJid } from '../protocol/jid.js';
|
|
4
|
-
import { buildAccountBlocklistSyncIq, buildAccountDevicesSyncIq, buildAccountPictureSyncIq, buildAccountPrivacySyncIq, buildClearDirtyBitsIq, buildGroupsDirtySyncIq, buildNewsletterMetadataSyncIq } from '../transport/node/builders/
|
|
5
|
-
import {
|
|
3
|
+
import { buildAccountBlocklistSyncIq, buildAccountDevicesSyncIq, buildAccountPictureSyncIq, buildAccountPrivacySyncIq, buildClearDirtyBitsIq, buildGroupsDirtySyncIq, buildNewsletterMetadataSyncIq } from '../transport/node/builders/account-sync.js';
|
|
4
|
+
import { getNodeChildrenTags } from '../transport/node/helpers.js';
|
|
6
5
|
import { assertIqResult, parseIqError } from '../transport/node/query.js';
|
|
7
|
-
import { bytesToHex } from '../util/bytes.js';
|
|
8
6
|
import { toError } from '../util/primitives.js';
|
|
9
7
|
const SUPPORTED_DIRTY_TYPES = new Set(WA_SUPPORTED_DIRTY_TYPES);
|
|
10
8
|
const ACCOUNT_SYNC_PROTOCOL_SET = new Set(WA_ACCOUNT_SYNC_PROTOCOLS);
|
|
@@ -18,19 +16,13 @@ function parseDirtyBitNode(node, logger) {
|
|
|
18
16
|
});
|
|
19
17
|
return null;
|
|
20
18
|
}
|
|
21
|
-
const protocols =
|
|
19
|
+
const protocols = getNodeChildrenTags(node);
|
|
22
20
|
return {
|
|
23
21
|
type,
|
|
24
22
|
timestamp,
|
|
25
23
|
protocols
|
|
26
24
|
};
|
|
27
25
|
}
|
|
28
|
-
function splitDirtyBitsBySupport(dirtyBits) {
|
|
29
|
-
return {
|
|
30
|
-
supported: dirtyBits.filter((dirtyBit) => SUPPORTED_DIRTY_TYPES.has(dirtyBit.type)),
|
|
31
|
-
unsupported: dirtyBits.filter((dirtyBit) => !SUPPORTED_DIRTY_TYPES.has(dirtyBit.type))
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
26
|
function resolveAccountSyncProtocols(protocols) {
|
|
35
27
|
const selected = protocols.filter((protocol) => ACCOUNT_SYNC_PROTOCOL_SET.has(protocol));
|
|
36
28
|
if (selected.length > 0) {
|
|
@@ -39,9 +31,15 @@ function resolveAccountSyncProtocols(protocols) {
|
|
|
39
31
|
return WA_ACCOUNT_SYNC_PROTOCOLS;
|
|
40
32
|
}
|
|
41
33
|
export function parseDirtyBits(nodes, logger) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
const parsed = [];
|
|
35
|
+
for (const node of nodes) {
|
|
36
|
+
const dirtyBit = parseDirtyBitNode(node, logger);
|
|
37
|
+
if (!dirtyBit) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
parsed.push(dirtyBit);
|
|
41
|
+
}
|
|
42
|
+
return parsed;
|
|
45
43
|
}
|
|
46
44
|
export async function handleDirtyBits(runtime, dirtyBits) {
|
|
47
45
|
const meJid = runtime.getCurrentCredentials()?.meJid ?? null;
|
|
@@ -49,22 +47,33 @@ export async function handleDirtyBits(runtime, dirtyBits) {
|
|
|
49
47
|
runtime.logger.trace('dirty bits skipped: session is not registered');
|
|
50
48
|
return;
|
|
51
49
|
}
|
|
52
|
-
const
|
|
50
|
+
const supported = [];
|
|
51
|
+
const unsupported = [];
|
|
52
|
+
for (const dirtyBit of dirtyBits) {
|
|
53
|
+
if (SUPPORTED_DIRTY_TYPES.has(dirtyBit.type)) {
|
|
54
|
+
supported.push(dirtyBit);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
unsupported.push(dirtyBit);
|
|
58
|
+
}
|
|
53
59
|
runtime.logger.info('handling dirty bits from info bulletin', {
|
|
54
60
|
supported: supported.map((entry) => entry.type).join(','),
|
|
55
61
|
unsupported: unsupported.map((entry) => entry.type).join(',')
|
|
56
62
|
});
|
|
57
|
-
const
|
|
63
|
+
const clearableDirtyBits = [...unsupported];
|
|
64
|
+
const settledSupported = await Promise.allSettled(supported.map(async (dirtyBit) => handleDirtyBit(runtime, dirtyBit)));
|
|
65
|
+
for (let index = 0; index < settledSupported.length; index += 1) {
|
|
66
|
+
const result = settledSupported[index];
|
|
58
67
|
if (result.status === 'fulfilled') {
|
|
59
|
-
|
|
68
|
+
clearableDirtyBits.push(supported[index]);
|
|
69
|
+
continue;
|
|
60
70
|
}
|
|
61
71
|
runtime.logger.warn('failed handling dirty bit', {
|
|
62
72
|
type: supported[index].type,
|
|
63
73
|
message: toError(result.reason).message
|
|
64
74
|
});
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
await clearDirtyBits(runtime, unsupported.concat(handledSupported));
|
|
75
|
+
}
|
|
76
|
+
await clearDirtyBits(runtime, clearableDirtyBits);
|
|
68
77
|
}
|
|
69
78
|
async function handleDirtyBit(runtime, dirtyBit) {
|
|
70
79
|
switch (dirtyBit.type) {
|
|
@@ -149,7 +158,7 @@ async function syncAccountDevicesDirtyBit(runtime) {
|
|
|
149
158
|
}
|
|
150
159
|
await runSyncQuery(runtime, {
|
|
151
160
|
queryContext: 'account_sync.devices',
|
|
152
|
-
node: buildAccountDevicesSyncIq(userJids, await generateUsyncSid()),
|
|
161
|
+
node: buildAccountDevicesSyncIq(userJids, await runtime.generateUsyncSid()),
|
|
153
162
|
logMessage: 'account_sync devices synchronized',
|
|
154
163
|
contextData: { meJid, targets: userJids.join(',') }
|
|
155
164
|
});
|
|
@@ -213,9 +222,6 @@ async function syncNewsletterMetadataDirtyBit(runtime) {
|
|
|
213
222
|
runtime.logger.info('newsletter_metadata dirty bit received (GraphQL/MEX sync intentionally disabled)');
|
|
214
223
|
await runtime.queryWithContext('dirty.newsletter_metadata', buildNewsletterMetadataSyncIq(), WA_DEFAULTS.IQ_TIMEOUT_MS);
|
|
215
224
|
}
|
|
216
|
-
async function generateUsyncSid() {
|
|
217
|
-
return bytesToHex(await randomBytesAsync(8));
|
|
218
|
-
}
|
|
219
225
|
function resolveAccountSyncDeviceTargets(credentials) {
|
|
220
226
|
if (!credentials?.meJid) {
|
|
221
227
|
return [];
|
|
@@ -75,8 +75,7 @@ export function parseChatEventFromAppStateMutation(mutation) {
|
|
|
75
75
|
...pickOptionalPrimitive('deviceAgentId', value.chatAssignment.deviceAgentID, 'string')
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
|
-
const fallbackAction = normalizeIndexAction(parsedIndex?.action) ??
|
|
79
|
-
normalizeValueActionKey(syncActionValueKey);
|
|
78
|
+
const fallbackAction = normalizeIndexAction(parsedIndex?.action) ?? normalizeValueActionKey(syncActionValueKey);
|
|
80
79
|
if (!fallbackAction) {
|
|
81
80
|
return null;
|
|
82
81
|
}
|
|
@@ -201,10 +200,12 @@ function extractChatJid(parts) {
|
|
|
201
200
|
return undefined;
|
|
202
201
|
}
|
|
203
202
|
function findPresentSyncActionValueKey(value) {
|
|
204
|
-
|
|
203
|
+
const valueRecord = value;
|
|
204
|
+
for (const key in valueRecord) {
|
|
205
205
|
if (key === 'timestamp') {
|
|
206
206
|
continue;
|
|
207
207
|
}
|
|
208
|
+
const keyValue = valueRecord[key];
|
|
208
209
|
if (keyValue === null || keyValue === undefined) {
|
|
209
210
|
continue;
|
|
210
211
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { WA_GROUP_NOTIFICATION_TAGS, WA_NOTIFICATION_TYPES } from '../../protocol/constants.js';
|
|
2
2
|
import { WA_NODE_TAGS } from '../../protocol/nodes.js';
|
|
3
3
|
import { findNodeChild, getNodeChildren, getNodeChildrenByTag } from '../../transport/node/helpers.js';
|
|
4
|
-
import { parseOptionalInt } from '../../transport/stream/parse.js';
|
|
5
4
|
import { TEXT_DECODER } from '../../util/bytes.js';
|
|
5
|
+
import { parseOptionalInt } from '../../util/primitives.js';
|
|
6
6
|
function readNodeTextContent(node) {
|
|
7
7
|
if (!node) {
|
|
8
8
|
return undefined;
|
|
@@ -15,31 +15,43 @@ function readNodeTextContent(node) {
|
|
|
15
15
|
}
|
|
16
16
|
return undefined;
|
|
17
17
|
}
|
|
18
|
-
function parseParticipants(node) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
export function parseParticipants(node) {
|
|
19
|
+
const participants = [];
|
|
20
|
+
for (const participantNode of getNodeChildrenByTag(node, WA_NODE_TAGS.PARTICIPANT)) {
|
|
21
|
+
participants.push({
|
|
22
|
+
jid: participantNode.attrs.jid,
|
|
23
|
+
role: participantNode.attrs.type,
|
|
24
|
+
lidJid: participantNode.attrs.lid,
|
|
25
|
+
phoneJid: participantNode.attrs.phone_number,
|
|
26
|
+
displayName: participantNode.attrs.display_name,
|
|
27
|
+
username: participantNode.attrs.username,
|
|
28
|
+
expirationSeconds: parseOptionalInt(participantNode.attrs.expiration)
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return participants;
|
|
28
32
|
}
|
|
29
33
|
function parseLinkedGroups(node) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
const groups = [];
|
|
35
|
+
for (const groupNode of getNodeChildrenByTag(node, WA_NODE_TAGS.GROUP)) {
|
|
36
|
+
groups.push({
|
|
37
|
+
jid: groupNode.attrs.jid,
|
|
38
|
+
subject: groupNode.attrs.subject,
|
|
39
|
+
subjectTimestampSeconds: parseOptionalInt(groupNode.attrs.s_t),
|
|
40
|
+
hiddenSubgroup: findNodeChild(groupNode, 'hidden_group') !== undefined
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return groups;
|
|
36
44
|
}
|
|
37
45
|
function parseMembershipRequests(node) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
46
|
+
const requests = [];
|
|
47
|
+
for (const requestNode of getNodeChildrenByTag(node, 'requested_user')) {
|
|
48
|
+
requests.push({
|
|
49
|
+
jid: requestNode.attrs.jid,
|
|
50
|
+
username: requestNode.attrs.username,
|
|
51
|
+
phoneJid: requestNode.attrs.phone_number
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return requests;
|
|
43
55
|
}
|
|
44
56
|
function parseSubgroupSuggestion(node) {
|
|
45
57
|
const subjectNode = findNodeChild(node, WA_NODE_TAGS.SUBJECT);
|
|
@@ -65,9 +77,15 @@ function parseSubgroupSuggestion(node) {
|
|
|
65
77
|
};
|
|
66
78
|
}
|
|
67
79
|
function parseSubgroupSuggestions(node) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
80
|
+
const suggestions = [];
|
|
81
|
+
for (const suggestionNode of getNodeChildrenByTag(node, 'sub_group_suggestion')) {
|
|
82
|
+
const suggestion = parseSubgroupSuggestion(suggestionNode);
|
|
83
|
+
if (!suggestion) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
suggestions.push(suggestion);
|
|
87
|
+
}
|
|
88
|
+
return suggestions;
|
|
71
89
|
}
|
|
72
90
|
function createBaseGroupEvent(notificationNode, actionNode) {
|
|
73
91
|
return {
|
|
@@ -136,8 +154,7 @@ function parseCreateGroupAction(notificationNode, actionNode) {
|
|
|
136
154
|
ephemeralDuration: parseOptionalInt(findNodeChild(groupNode, WA_NODE_TAGS.EPHEMERAL)?.attrs.expiration),
|
|
137
155
|
disappearingTrigger: findNodeChild(groupNode, WA_NODE_TAGS.EPHEMERAL)?.attrs.trigger,
|
|
138
156
|
membershipApprovalEnabled: groupJoinNode?.attrs.state === 'on',
|
|
139
|
-
allowNonAdminSubGroupCreation: findNodeChild(groupNode, WA_GROUP_NOTIFICATION_TAGS.ALLOW_NON_ADMIN_SUB_GROUP_CREATION) !==
|
|
140
|
-
undefined,
|
|
157
|
+
allowNonAdminSubGroupCreation: findNodeChild(groupNode, WA_GROUP_NOTIFICATION_TAGS.ALLOW_NON_ADMIN_SUB_GROUP_CREATION) !== undefined,
|
|
141
158
|
linkedParentGroupJid: findNodeChild(groupNode, 'linked_parent')?.attrs.jid ??
|
|
142
159
|
findNodeChild(groupNode, 'parent')?.attrs.jid
|
|
143
160
|
}
|
|
@@ -224,7 +241,12 @@ function parseGroupActionNode(notificationNode, actionNode) {
|
|
|
224
241
|
};
|
|
225
242
|
}
|
|
226
243
|
case WA_GROUP_NOTIFICATION_TAGS.LOCKED:
|
|
227
|
-
return {
|
|
244
|
+
return {
|
|
245
|
+
...baseEvent,
|
|
246
|
+
action: 'restrict',
|
|
247
|
+
enabled: true,
|
|
248
|
+
mode: actionNode.attrs.threshold
|
|
249
|
+
};
|
|
228
250
|
case WA_GROUP_NOTIFICATION_TAGS.UNLOCKED:
|
|
229
251
|
return { ...baseEvent, action: 'restrict', enabled: false };
|
|
230
252
|
case WA_GROUP_NOTIFICATION_TAGS.ANNOUNCEMENT:
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { promisify } from 'node:util';
|
|
2
2
|
import { unzip } from 'node:zlib';
|
|
3
3
|
import { proto } from '../proto.js';
|
|
4
|
-
import { decodeProtoBytes } from '../util/
|
|
5
|
-
import { toBytesView } from '../util/bytes.js';
|
|
4
|
+
import { decodeProtoBytes, toBytesView } from '../util/bytes.js';
|
|
6
5
|
import { longToNumber } from '../util/primitives.js';
|
|
7
6
|
const unzipAsync = promisify(unzip);
|
|
8
7
|
const HANDLED_SYNC_TYPES = new Set([
|
|
@@ -28,15 +27,58 @@ export async function processHistorySyncNotification(deps, notification) {
|
|
|
28
27
|
pushnames: historySync.pushnames.length
|
|
29
28
|
});
|
|
30
29
|
const nowMs = Date.now();
|
|
30
|
+
const contacts = [];
|
|
31
|
+
for (const pn of historySync.pushnames) {
|
|
32
|
+
if (!pn.id) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
contacts.push({
|
|
36
|
+
jid: pn.id,
|
|
37
|
+
pushName: pn.pushname ?? undefined,
|
|
38
|
+
lastUpdatedMs: nowMs
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
const threads = [];
|
|
42
|
+
const messages = [];
|
|
31
43
|
let messagesCount = 0;
|
|
32
|
-
const conversationPromises = [];
|
|
33
44
|
for (const conversation of historySync.conversations) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
45
|
+
const threadJid = conversation.id;
|
|
46
|
+
if (!threadJid) {
|
|
47
|
+
deps.logger.debug('skipping history sync conversation without thread jid');
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
threads.push({
|
|
51
|
+
jid: threadJid,
|
|
52
|
+
name: conversation.name ?? undefined,
|
|
53
|
+
unreadCount: conversation.unreadCount ?? undefined,
|
|
54
|
+
archived: conversation.archived ?? undefined,
|
|
55
|
+
pinned: conversation.pinned ?? undefined,
|
|
56
|
+
muteEndMs: longToNumber(conversation.muteEndTime) || undefined,
|
|
57
|
+
markedAsUnread: conversation.markedAsUnread ?? undefined,
|
|
58
|
+
ephemeralExpiration: conversation.ephemeralExpiration ?? undefined
|
|
59
|
+
});
|
|
60
|
+
for (const histMsg of conversation.messages ?? []) {
|
|
61
|
+
const webMsg = histMsg.message;
|
|
62
|
+
if (!webMsg?.key?.id) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const timestampMs = longToNumber(webMsg.messageTimestamp) * 1000;
|
|
66
|
+
messages.push({
|
|
67
|
+
id: webMsg.key.id,
|
|
68
|
+
threadJid,
|
|
69
|
+
senderJid: webMsg.key.participant ?? undefined,
|
|
70
|
+
fromMe: webMsg.key.fromMe === true,
|
|
71
|
+
timestampMs: timestampMs || undefined,
|
|
72
|
+
messageBytes: webMsg.message
|
|
73
|
+
? proto.Message.encode(webMsg.message).finish()
|
|
74
|
+
: undefined
|
|
75
|
+
});
|
|
76
|
+
messagesCount += 1;
|
|
77
|
+
}
|
|
37
78
|
}
|
|
38
|
-
|
|
39
|
-
await
|
|
79
|
+
await deps.contactStore.upsertBatch(contacts);
|
|
80
|
+
await deps.threadStore.upsertBatch(threads);
|
|
81
|
+
await deps.messageStore.upsertBatch(messages);
|
|
40
82
|
const event = {
|
|
41
83
|
syncType,
|
|
42
84
|
messagesCount,
|
|
@@ -65,55 +107,3 @@ async function downloadHistorySyncBlob(deps, notification) {
|
|
|
65
107
|
fileEncSha256
|
|
66
108
|
});
|
|
67
109
|
}
|
|
68
|
-
async function persistConversation(deps, conversation, _nowMs) {
|
|
69
|
-
const threadJid = conversation.id;
|
|
70
|
-
if (!threadJid) {
|
|
71
|
-
deps.logger.debug('skipping history sync conversation without thread jid');
|
|
72
|
-
return 0;
|
|
73
|
-
}
|
|
74
|
-
const messages = conversation.messages ?? [];
|
|
75
|
-
const messageRecords = [];
|
|
76
|
-
for (const histMsg of messages) {
|
|
77
|
-
const webMsg = histMsg.message;
|
|
78
|
-
if (!webMsg?.key?.id) {
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
const timestampMs = longToNumber(webMsg.messageTimestamp) * 1000;
|
|
82
|
-
const messageBytes = webMsg.message
|
|
83
|
-
? proto.Message.encode(webMsg.message).finish()
|
|
84
|
-
: undefined;
|
|
85
|
-
messageRecords.push({
|
|
86
|
-
id: webMsg.key.id,
|
|
87
|
-
threadJid,
|
|
88
|
-
senderJid: webMsg.key.participant ?? undefined,
|
|
89
|
-
fromMe: webMsg.key.fromMe === true,
|
|
90
|
-
timestampMs: timestampMs || undefined,
|
|
91
|
-
messageBytes
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
const threadPromise = deps.threadStore.upsert({
|
|
95
|
-
jid: threadJid,
|
|
96
|
-
name: conversation.name ?? undefined,
|
|
97
|
-
unreadCount: conversation.unreadCount ?? undefined,
|
|
98
|
-
archived: conversation.archived ?? undefined,
|
|
99
|
-
pinned: conversation.pinned ?? undefined,
|
|
100
|
-
muteEndMs: longToNumber(conversation.muteEndTime) || undefined,
|
|
101
|
-
markedAsUnread: conversation.markedAsUnread ?? undefined,
|
|
102
|
-
ephemeralExpiration: conversation.ephemeralExpiration ?? undefined
|
|
103
|
-
});
|
|
104
|
-
const messagePromises = messageRecords.map((record) => deps.messageStore.upsert(record));
|
|
105
|
-
await Promise.all([threadPromise, ...messagePromises]);
|
|
106
|
-
return messageRecords.length;
|
|
107
|
-
}
|
|
108
|
-
async function persistPushnames(deps, pushnames, nowMs) {
|
|
109
|
-
if (pushnames.length === 0) {
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
await Promise.all(pushnames
|
|
113
|
-
.filter((pn) => !!pn.id)
|
|
114
|
-
.map((pn) => deps.contactStore.upsert({
|
|
115
|
-
jid: pn.id,
|
|
116
|
-
pushName: pn.pushname ?? undefined,
|
|
117
|
-
lastUpdatedMs: nowMs
|
|
118
|
-
})));
|
|
119
|
-
}
|