zapo-js 1.6.2 → 1.7.1
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 +26 -12
- package/dist/abprops-spec.d.ts +10 -0
- package/dist/abprops-spec.js +25 -0
- package/dist/appstate/crypto/WaAppStateCrypto.js +4 -6
- package/dist/auth/WaAuthClient.d.ts +14 -1
- package/dist/auth/WaAuthClient.js +22 -1
- package/dist/auth/credentials-flow.d.ts +3 -1
- package/dist/auth/credentials-flow.js +3 -0
- package/dist/auth/pairing/WaPairingFlow.d.ts +5 -0
- package/dist/auth/pairing/WaPairingFlow.js +66 -14
- package/dist/auth/types.d.ts +13 -0
- package/dist/client/WaClient.d.ts +11 -0
- package/dist/client/WaClient.js +60 -0
- package/dist/client/WaClientFactory.d.ts +2 -2
- package/dist/client/WaClientFactory.js +53 -13
- package/dist/client/coordinators/WaAbPropsCoordinator.d.ts +2 -2
- package/dist/client/coordinators/WaAbPropsCoordinator.js +16 -4
- package/dist/client/coordinators/WaIncomingNodeCoordinator.d.ts +2 -1
- package/dist/client/coordinators/WaIncomingNodeCoordinator.js +4 -0
- package/dist/client/coordinators/WaMessageCoordinator.d.ts +96 -0
- package/dist/client/coordinators/WaMessageCoordinator.js +163 -8
- package/dist/client/coordinators/WaMessageDispatchCoordinator.d.ts +64 -0
- package/dist/client/coordinators/WaMessageDispatchCoordinator.js +252 -57
- package/dist/client/coordinators/WaPrivacyCoordinator.d.ts +97 -19
- package/dist/client/coordinators/WaPrivacyCoordinator.js +152 -101
- package/dist/client/coordinators/WaRetryCoordinator.d.ts +22 -0
- package/dist/client/coordinators/WaRetryCoordinator.js +74 -11
- package/dist/client/events/dirty.d.ts +3 -0
- package/dist/client/events/dirty.js +12 -7
- package/dist/client/events/offline.d.ts +9 -0
- package/dist/client/events/offline.js +95 -0
- package/dist/client/events/privacy.d.ts +45 -0
- package/dist/client/events/privacy.js +130 -0
- package/dist/client/messaging/group-metadata.d.ts +12 -0
- package/dist/client/messaging/group-metadata.js +24 -8
- package/dist/client/messaging/link-preview.d.ts +7 -0
- package/dist/client/messaging/link-preview.js +27 -0
- package/dist/client/messaging/messages.js +16 -12
- package/dist/client/newsletter/content.d.ts +4 -1
- package/dist/client/newsletter/content.js +43 -18
- package/dist/client/newsletter/discovery.js +4 -2
- package/dist/client/newsletter/messaging.d.ts +2 -0
- package/dist/client/newsletter/messaging.js +2 -1
- package/dist/client/newsletter/mex.d.ts +2 -2
- package/dist/client/persistence/WriteBehindPersistence.js +2 -1
- package/dist/client/persistence/ephemeral-setting.d.ts +42 -0
- package/dist/client/persistence/ephemeral-setting.js +120 -0
- package/dist/client/persistence/group-history.d.ts +29 -0
- package/dist/client/persistence/group-history.js +149 -0
- package/dist/client/persistence/history-blob.d.ts +25 -0
- package/dist/client/persistence/history-blob.js +38 -0
- package/dist/client/persistence/history-sync.d.ts +20 -0
- package/dist/client/persistence/history-sync.js +165 -71
- package/dist/client/plugins/types.d.ts +10 -2
- package/dist/client/types.d.ts +150 -16
- package/dist/crypto/core/index.d.ts +1 -1
- package/dist/crypto/core/index.js +2 -1
- package/dist/crypto/core/primitives.d.ts +19 -0
- package/dist/crypto/core/primitives.js +48 -0
- package/dist/crypto/core/xeddsa.js +35 -4
- package/dist/crypto/curves/X25519.js +29 -2
- package/dist/crypto/nativeBackend.d.ts +20 -0
- package/dist/crypto/nativeBackend.js +95 -0
- package/dist/esm/abprops-spec.js +15 -0
- package/dist/esm/appstate/crypto/WaAppStateCrypto.js +4 -6
- package/dist/esm/auth/WaAuthClient.js +22 -1
- package/dist/esm/auth/credentials-flow.js +3 -0
- package/dist/esm/auth/pairing/WaPairingFlow.js +67 -15
- package/dist/esm/client/WaClient.js +60 -0
- package/dist/esm/client/WaClientFactory.js +54 -14
- package/dist/esm/client/coordinators/WaAbPropsCoordinator.js +17 -5
- package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +4 -0
- package/dist/esm/client/coordinators/WaMessageCoordinator.js +166 -11
- package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +254 -60
- package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +145 -94
- package/dist/esm/client/coordinators/WaRetryCoordinator.js +74 -11
- package/dist/esm/client/events/dirty.js +12 -7
- package/dist/esm/client/events/offline.js +92 -0
- package/dist/esm/client/events/privacy.js +123 -0
- package/dist/esm/client/messaging/group-metadata.js +25 -9
- package/dist/esm/client/messaging/link-preview.js +29 -2
- package/dist/esm/client/messaging/messages.js +16 -12
- package/dist/esm/client/newsletter/content.js +44 -19
- package/dist/esm/client/newsletter/discovery.js +4 -2
- package/dist/esm/client/newsletter/messaging.js +2 -1
- package/dist/esm/client/persistence/WriteBehindPersistence.js +2 -1
- package/dist/esm/client/persistence/ephemeral-setting.js +116 -0
- package/dist/esm/client/persistence/group-history.js +145 -0
- package/dist/esm/client/persistence/history-blob.js +34 -0
- package/dist/esm/client/persistence/history-sync.js +157 -65
- package/dist/esm/crypto/core/index.js +1 -1
- package/dist/esm/crypto/core/primitives.js +47 -0
- package/dist/esm/crypto/core/xeddsa.js +36 -5
- package/dist/esm/crypto/curves/X25519.js +29 -2
- package/dist/esm/crypto/nativeBackend.js +93 -0
- package/dist/esm/index.js +3 -1
- package/dist/esm/media/crypto/WaMediaCrypto.js +38 -19
- package/dist/esm/message/context-info.js +39 -0
- package/dist/esm/message/crypto/reporting-token.js +38 -216
- package/dist/esm/message/encode/content.js +73 -12
- package/dist/esm/message/encode/media-payload.js +3 -1
- package/dist/esm/message/kinds/group-history.js +36 -0
- package/dist/esm/message/primitives/incoming.js +32 -13
- package/dist/esm/protocol/abprops.js +18 -162
- package/dist/esm/protocol/constants.js +4 -3
- package/dist/esm/protocol/defaults.js +7 -0
- package/dist/esm/protocol/device-identity.js +10 -5
- package/dist/esm/protocol/jid.js +83 -36
- package/dist/esm/protocol/media.js +1 -0
- package/dist/esm/protocol/message.js +8 -0
- package/dist/esm/protocol/notification.js +1 -0
- package/dist/esm/protocol/privacy.js +70 -4
- package/dist/esm/signal/group/SenderKeyChain.js +1 -2
- package/dist/esm/signal/group/SenderKeyManager.js +1 -7
- package/dist/esm/signal/session/SignalProtocol.js +22 -21
- package/dist/esm/signal/session/SignalRatchet.js +20 -17
- package/dist/esm/signal/session/encoding.js +25 -3
- package/dist/esm/signal/session/resolver.js +11 -5
- package/dist/esm/store/contracts/chat-metadata.store.js +1 -0
- package/dist/esm/store/createStore.js +19 -2
- package/dist/esm/store/index.js +1 -0
- package/dist/esm/store/memory/chat-metadata.store.js +66 -0
- package/dist/esm/store/noop.store.js +8 -0
- package/dist/esm/transport/binary/constants.js +19 -0
- package/dist/esm/transport/binary/decoder.js +17 -19
- package/dist/esm/transport/binary/encoder.js +61 -18
- package/dist/esm/transport/node/builders/global.js +20 -0
- package/dist/esm/transport/node/builders/message.js +32 -15
- package/dist/esm/transport/node/builders/privacy.js +63 -4
- package/dist/esm/transport/noise/WaClientPayload.js +43 -22
- package/dist/esm/transport/noise/WaFrameCodec.js +14 -4
- package/dist/esm/util/coercion.js +12 -4
- package/dist/esm/util/index.js +1 -1
- package/dist/esm/util/protoscan.js +181 -0
- package/dist/esm/util/runtime.js +34 -0
- package/dist/index.d.ts +11 -6
- package/dist/index.js +15 -2
- package/dist/media/crypto/WaMediaCrypto.js +36 -17
- package/dist/media/types.d.ts +1 -1
- package/dist/message/context-info.d.ts +10 -0
- package/dist/message/context-info.js +40 -0
- package/dist/message/crypto/reporting-token.d.ts +3 -1
- package/dist/message/crypto/reporting-token.js +38 -216
- package/dist/message/encode/content.d.ts +24 -4
- package/dist/message/encode/content.js +74 -12
- package/dist/message/encode/media-payload.d.ts +5 -2
- package/dist/message/encode/media-payload.js +3 -1
- package/dist/message/kinds/group-history.d.ts +30 -0
- package/dist/message/kinds/group-history.js +40 -0
- package/dist/message/primitives/incoming.d.ts +5 -0
- package/dist/message/primitives/incoming.js +32 -13
- package/dist/message/types.d.ts +10 -0
- package/dist/protocol/abprops.d.ts +27 -140
- package/dist/protocol/abprops.js +18 -163
- package/dist/protocol/constants.d.ts +4 -3
- package/dist/protocol/constants.js +10 -3
- package/dist/protocol/defaults.d.ts +7 -0
- package/dist/protocol/defaults.js +7 -0
- package/dist/protocol/device-identity.d.ts +14 -4
- package/dist/protocol/device-identity.js +9 -4
- package/dist/protocol/jid.d.ts +4 -1
- package/dist/protocol/jid.js +83 -36
- package/dist/protocol/media.d.ts +1 -0
- package/dist/protocol/media.js +1 -0
- package/dist/protocol/message.d.ts +6 -0
- package/dist/protocol/message.js +9 -0
- package/dist/protocol/notification.d.ts +1 -0
- package/dist/protocol/notification.js +1 -0
- package/dist/protocol/privacy.d.ts +52 -0
- package/dist/protocol/privacy.js +71 -5
- package/dist/signal/group/SenderKeyChain.d.ts +1 -1
- package/dist/signal/group/SenderKeyChain.js +1 -2
- package/dist/signal/group/SenderKeyManager.js +1 -7
- package/dist/signal/session/SignalProtocol.d.ts +13 -0
- package/dist/signal/session/SignalProtocol.js +22 -21
- package/dist/signal/session/SignalRatchet.d.ts +4 -4
- package/dist/signal/session/SignalRatchet.js +19 -16
- package/dist/signal/session/SignalSession.d.ts +8 -1
- package/dist/signal/session/encoding.d.ts +5 -0
- package/dist/signal/session/encoding.js +25 -3
- package/dist/signal/session/resolver.js +11 -5
- package/dist/store/contracts/chat-metadata.store.d.ts +34 -0
- package/dist/store/contracts/chat-metadata.store.js +2 -0
- package/dist/store/contracts/group-metadata.store.d.ts +7 -0
- package/dist/store/contracts/thread.store.d.ts +6 -0
- package/dist/store/createStore.d.ts +10 -2
- package/dist/store/createStore.js +18 -1
- package/dist/store/index.d.ts +3 -1
- package/dist/store/index.js +3 -1
- package/dist/store/memory/chat-metadata.store.d.ts +26 -0
- package/dist/store/memory/chat-metadata.store.js +70 -0
- package/dist/store/noop.store.d.ts +2 -0
- package/dist/store/noop.store.js +9 -1
- package/dist/store/types.d.ts +190 -39
- package/dist/transport/binary/constants.d.ts +8 -0
- package/dist/transport/binary/constants.js +20 -1
- package/dist/transport/binary/decoder.js +17 -19
- package/dist/transport/binary/encoder.js +60 -17
- package/dist/transport/node/builders/global.d.ts +8 -0
- package/dist/transport/node/builders/global.js +21 -0
- package/dist/transport/node/builders/message.js +32 -15
- package/dist/transport/node/builders/privacy.d.ts +26 -2
- package/dist/transport/node/builders/privacy.js +63 -3
- package/dist/transport/noise/WaClientPayload.js +43 -22
- package/dist/transport/noise/WaFrameCodec.d.ts +1 -0
- package/dist/transport/noise/WaFrameCodec.js +14 -4
- package/dist/transport/noise/types.d.ts +17 -0
- package/dist/util/coercion.d.ts +6 -0
- package/dist/util/coercion.js +13 -4
- package/dist/util/index.d.ts +1 -1
- package/dist/util/index.js +2 -1
- package/dist/util/protoscan.d.ts +33 -0
- package/dist/util/protoscan.js +186 -0
- package/dist/util/runtime.d.ts +12 -0
- package/dist/util/runtime.js +35 -0
- package/package.json +3 -1
- package/spec/abprops/index.d.ts +4402 -0
- package/spec/abprops/index.js +4372 -0
|
@@ -17,11 +17,13 @@ import type { SenderKeyManager } from '../../signal/group/SenderKeyManager';
|
|
|
17
17
|
import type { SignalSessionResolver } from '../../signal/session/resolver';
|
|
18
18
|
import type { SignalProtocol } from '../../signal/session/SignalProtocol';
|
|
19
19
|
import type { SignalAddress } from '../../signal/types';
|
|
20
|
+
import type { WaChatMetadataStore } from '../../store/contracts/chat-metadata.store';
|
|
20
21
|
import type { WaDeviceListStore } from '../../store/contracts/device-list.store';
|
|
21
22
|
import type { WaIdentityStore } from '../../store/contracts/identity.store';
|
|
22
23
|
import type { WaMessageSecretStore } from '../../store/contracts/message-secret.store';
|
|
23
24
|
import type { WaSessionStore } from '../../store/contracts/session.store';
|
|
24
25
|
import type { WaSignalStore } from '../../store/contracts/signal.store';
|
|
26
|
+
import type { WaThreadStore } from '../../store/contracts/thread.store';
|
|
25
27
|
import type { BinaryNode } from '../../transport/types';
|
|
26
28
|
import type { ServerClock } from '../../util/clock';
|
|
27
29
|
interface WaMessageDispatchCoordinatorOptions {
|
|
@@ -45,6 +47,8 @@ interface WaMessageDispatchCoordinatorOptions {
|
|
|
45
47
|
readonly sessionStore: WaSessionStore;
|
|
46
48
|
readonly identityStore: WaIdentityStore;
|
|
47
49
|
readonly deviceListStore: WaDeviceListStore;
|
|
50
|
+
readonly threadStore: WaThreadStore;
|
|
51
|
+
readonly chatMetadataStore: WaChatMetadataStore;
|
|
48
52
|
readonly signalDeviceSync: SignalDeviceSyncApi;
|
|
49
53
|
readonly messageSecretStore: WaMessageSecretStore;
|
|
50
54
|
/**
|
|
@@ -66,6 +70,32 @@ interface WaMessageDispatchCoordinatorOptions {
|
|
|
66
70
|
readonly mobileMessageIdFormat?: () => boolean;
|
|
67
71
|
readonly serverClock: ServerClock;
|
|
68
72
|
}
|
|
73
|
+
/** Membership split behind a group-history share, in the group's addressing mode. */
|
|
74
|
+
export interface WaGroupHistoryAudience {
|
|
75
|
+
/** Members the bundle is addressed to. */
|
|
76
|
+
readonly historyReceivers: readonly string[];
|
|
77
|
+
/** Members in the group who are not receiving it. */
|
|
78
|
+
readonly nonHistoryReceivers: readonly string[];
|
|
79
|
+
/** Requested JIDs that are not current members of the group. */
|
|
80
|
+
readonly unknownJids: readonly string[];
|
|
81
|
+
/** Whether the caller asked to share with this account itself. */
|
|
82
|
+
readonly requestedSelf: boolean;
|
|
83
|
+
readonly addressingMode: 'pn' | 'lid';
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Narrows a group's participant list to the members a group-history bundle is
|
|
87
|
+
* addressed to, plus the sender so its own devices keep a copy. Receivers are
|
|
88
|
+
* intersected with the live participant list, so a stale receiver entry cannot
|
|
89
|
+
* pull a non-member into the fanout. Any other message keeps the full list.
|
|
90
|
+
*
|
|
91
|
+
* Receivers must be written in the group's addressing mode - a PN entry for a
|
|
92
|
+
* LID-addressed group does not match and is reported through `onDropped`.
|
|
93
|
+
*
|
|
94
|
+
* @throws when no receiver matches a current member. Sending to the sender's
|
|
95
|
+
* own devices alone counts as no match: it would look like a delivered share
|
|
96
|
+
* while nobody received anything.
|
|
97
|
+
*/
|
|
98
|
+
export declare function restrictGroupHistoryTargets(message: Proto.IMessage, participantUserJids: readonly string[], senderJid: string, onDropped?: (droppedJids: readonly string[], totalExpected: number) => void): readonly string[];
|
|
69
99
|
export declare class WaMessageDispatchCoordinator {
|
|
70
100
|
private readonly deps;
|
|
71
101
|
private readonly mobileMessageIdFormat;
|
|
@@ -74,6 +104,24 @@ export declare class WaMessageDispatchCoordinator {
|
|
|
74
104
|
private readonly privacyTokenDedup;
|
|
75
105
|
private readonly distributionDedup;
|
|
76
106
|
constructor(options: WaMessageDispatchCoordinatorOptions);
|
|
107
|
+
/**
|
|
108
|
+
* Per-chat disappearing settings from the cache, falling back to the
|
|
109
|
+
* durable thread record on a cold miss and warming the cache with it. A
|
|
110
|
+
* chat with no disappearing mode is cached as expiration `0` rather than
|
|
111
|
+
* left absent, so the archive is not re-read on every send to it; the
|
|
112
|
+
* incoming writers overwrite that entry the moment the chat turns it on.
|
|
113
|
+
* A failing archive degrades the send to "no ephemeral fields" instead of
|
|
114
|
+
* rejecting it - the store is opt-in persistence, not a send dependency.
|
|
115
|
+
*/
|
|
116
|
+
private resolveChatMetadata;
|
|
117
|
+
/**
|
|
118
|
+
* Disappearing-message fields for a send into a chat with the mode on, or
|
|
119
|
+
* `{}` when nothing resolves. Both chat kinds report initiator
|
|
120
|
+
* `CHANGED_IN_CHAT` when nothing more specific is stored; the trigger comes
|
|
121
|
+
* from the group metadata for a group and defaults to `CHAT_SETTING` for
|
|
122
|
+
* 1:1, and is omitted when a group reports none.
|
|
123
|
+
*/
|
|
124
|
+
private resolveChatEphemeral;
|
|
77
125
|
publishMessageNode(node: BinaryNode, options?: WaMessagePublishOptions): Promise<WaMessagePublishResult>;
|
|
78
126
|
publishEncryptedMessage(input: WaEncryptedMessageInput, options?: WaMessagePublishOptions): Promise<WaMessagePublishResult>;
|
|
79
127
|
publishSignalMessage(input: WaSignalMessagePublishInput, options?: WaMessagePublishOptions): Promise<WaMessagePublishResult>;
|
|
@@ -119,6 +167,22 @@ export declare class WaMessageDispatchCoordinator {
|
|
|
119
167
|
requestAppStateSyncKeys(keyIds: readonly Uint8Array[]): Promise<readonly string[]>;
|
|
120
168
|
sendAppStateSyncKeyShare(toDeviceJid: string, keys: readonly WaAppStateSyncKey[], missingKeyIds?: readonly Uint8Array[]): Promise<void>;
|
|
121
169
|
mutateGroupMetadataCacheFromGroupEvent(event: WaGroupEvent): Promise<void>;
|
|
170
|
+
/**
|
|
171
|
+
* Splits a group's members into the ones a history bundle is being shared
|
|
172
|
+
* with and the rest, normalizing everything to the group's addressing mode
|
|
173
|
+
* so the receiver list written into the proto matches what the fanout can
|
|
174
|
+
* actually resolve. This account is excluded from both lists.
|
|
175
|
+
*
|
|
176
|
+
* Requested JIDs that are not current members come back in `unknownJids`
|
|
177
|
+
* instead of being silently dropped - sharing history with a non-member is
|
|
178
|
+
* a caller mistake worth surfacing.
|
|
179
|
+
*/
|
|
180
|
+
resolveGroupHistoryAudience(groupJid: string, requestedJids: readonly string[]): Promise<WaGroupHistoryAudience>;
|
|
181
|
+
/**
|
|
182
|
+
* A group-history bundle goes to the members named in `historyReceivers`
|
|
183
|
+
* rather than to the whole group, so it takes the per-device direct fanout
|
|
184
|
+
* instead of the group sender key.
|
|
185
|
+
*/
|
|
122
186
|
private shouldUseGroupDirectPath;
|
|
123
187
|
private publishGroupDirectMessage;
|
|
124
188
|
private buildBotSidecarParticipant;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WaMessageDispatchCoordinator = void 0;
|
|
4
|
+
exports.restrictGroupHistoryTargets = restrictGroupHistoryTargets;
|
|
4
5
|
const _crypto_1 = require("../../crypto");
|
|
5
6
|
const primitives_1 = require("../../crypto/core/primitives");
|
|
6
7
|
const PromiseDedup_1 = require("../../infra/perf/PromiseDedup");
|
|
@@ -20,6 +21,58 @@ const binary_1 = require("../../transport/binary");
|
|
|
20
21
|
const message_1 = require("../../transport/node/builders/message");
|
|
21
22
|
const bytes_1 = require("../../util/bytes");
|
|
22
23
|
const primitives_2 = require("../../util/primitives");
|
|
24
|
+
/**
|
|
25
|
+
* Members a group-history bundle is addressed to. Empty for every other
|
|
26
|
+
* message, which is what keeps the restricted fanout scoped to bundles.
|
|
27
|
+
*/
|
|
28
|
+
function resolveGroupHistoryReceivers(message) {
|
|
29
|
+
const metadata = (0, content_1.unwrapMessage)(message).messageHistoryBundle?.messageHistoryMetadata;
|
|
30
|
+
return metadata?.historyReceivers ?? [];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Narrows a group's participant list to the members a group-history bundle is
|
|
34
|
+
* addressed to, plus the sender so its own devices keep a copy. Receivers are
|
|
35
|
+
* intersected with the live participant list, so a stale receiver entry cannot
|
|
36
|
+
* pull a non-member into the fanout. Any other message keeps the full list.
|
|
37
|
+
*
|
|
38
|
+
* Receivers must be written in the group's addressing mode - a PN entry for a
|
|
39
|
+
* LID-addressed group does not match and is reported through `onDropped`.
|
|
40
|
+
*
|
|
41
|
+
* @throws when no receiver matches a current member. Sending to the sender's
|
|
42
|
+
* own devices alone counts as no match: it would look like a delivered share
|
|
43
|
+
* while nobody received anything.
|
|
44
|
+
*/
|
|
45
|
+
function restrictGroupHistoryTargets(message, participantUserJids, senderJid, onDropped) {
|
|
46
|
+
const receivers = resolveGroupHistoryReceivers(message);
|
|
47
|
+
if (receivers.length === 0) {
|
|
48
|
+
return participantUserJids;
|
|
49
|
+
}
|
|
50
|
+
const pending = new Set();
|
|
51
|
+
for (let index = 0; index < receivers.length; index += 1) {
|
|
52
|
+
pending.add((0, jid_1.toUserJid)(receivers[index]));
|
|
53
|
+
}
|
|
54
|
+
const senderUserJid = (0, jid_1.toUserJid)(senderJid);
|
|
55
|
+
const targets = [];
|
|
56
|
+
let matchedReceivers = 0;
|
|
57
|
+
for (let index = 0; index < participantUserJids.length; index += 1) {
|
|
58
|
+
const participant = participantUserJids[index];
|
|
59
|
+
const participantUserJid = (0, jid_1.toUserJid)(participant);
|
|
60
|
+
if (pending.delete(participantUserJid)) {
|
|
61
|
+
matchedReceivers += 1;
|
|
62
|
+
targets[targets.length] = participant;
|
|
63
|
+
}
|
|
64
|
+
else if (participantUserJid === senderUserJid) {
|
|
65
|
+
targets[targets.length] = participant;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (pending.size > 0 && onDropped) {
|
|
69
|
+
onDropped([...pending], receivers.length);
|
|
70
|
+
}
|
|
71
|
+
if (matchedReceivers === 0) {
|
|
72
|
+
throw new Error('group history bundle resolved no receivers in the group');
|
|
73
|
+
}
|
|
74
|
+
return targets;
|
|
75
|
+
}
|
|
23
76
|
class WaMessageDispatchCoordinator {
|
|
24
77
|
constructor(options) {
|
|
25
78
|
this.icdcDedup = new PromiseDedup_1.PromiseDedup();
|
|
@@ -29,6 +82,82 @@ class WaMessageDispatchCoordinator {
|
|
|
29
82
|
this.mobileMessageIdFormat = options.mobileMessageIdFormat ?? (() => false);
|
|
30
83
|
this.serverClock = options.serverClock;
|
|
31
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Per-chat disappearing settings from the cache, falling back to the
|
|
87
|
+
* durable thread record on a cold miss and warming the cache with it. A
|
|
88
|
+
* chat with no disappearing mode is cached as expiration `0` rather than
|
|
89
|
+
* left absent, so the archive is not re-read on every send to it; the
|
|
90
|
+
* incoming writers overwrite that entry the moment the chat turns it on.
|
|
91
|
+
* A failing archive degrades the send to "no ephemeral fields" instead of
|
|
92
|
+
* rejecting it - the store is opt-in persistence, not a send dependency.
|
|
93
|
+
*/
|
|
94
|
+
async resolveChatMetadata(chatJid) {
|
|
95
|
+
try {
|
|
96
|
+
const cached = await this.deps.chatMetadataStore.getChatMetadata(chatJid);
|
|
97
|
+
if (cached) {
|
|
98
|
+
return cached;
|
|
99
|
+
}
|
|
100
|
+
const thread = await this.deps.threadStore.getByJid(chatJid);
|
|
101
|
+
const expiration = thread?.ephemeralExpiration ?? 0;
|
|
102
|
+
const settingTimestamp = expiration > 0 ? thread?.ephemeralSettingTimestamp : undefined;
|
|
103
|
+
const snapshot = {
|
|
104
|
+
chatJid,
|
|
105
|
+
ephemeralExpiration: expiration,
|
|
106
|
+
...(settingTimestamp !== undefined
|
|
107
|
+
? { ephemeralSettingTimestamp: settingTimestamp }
|
|
108
|
+
: {}),
|
|
109
|
+
updatedAtMs: Date.now()
|
|
110
|
+
};
|
|
111
|
+
await this.deps.chatMetadataStore.upsertChatMetadata(snapshot);
|
|
112
|
+
return snapshot;
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
this.deps.logger.debug('chat metadata lookup failed, sending without ephemeral fields', {
|
|
116
|
+
jid: chatJid,
|
|
117
|
+
message: (0, primitives_2.toError)(error).message
|
|
118
|
+
});
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Disappearing-message fields for a send into a chat with the mode on, or
|
|
124
|
+
* `{}` when nothing resolves. Both chat kinds report initiator
|
|
125
|
+
* `CHANGED_IN_CHAT` when nothing more specific is stored; the trigger comes
|
|
126
|
+
* from the group metadata for a group and defaults to `CHAT_SETTING` for
|
|
127
|
+
* 1:1, and is omitted when a group reports none.
|
|
128
|
+
*/
|
|
129
|
+
async resolveChatEphemeral(recipientJid) {
|
|
130
|
+
if ((0, jid_1.isGroupJid)(recipientJid)) {
|
|
131
|
+
const settings = await this.deps.groupMetadataCache.resolveEphemeralSettings(recipientJid);
|
|
132
|
+
if (!settings) {
|
|
133
|
+
return {};
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
expirationSeconds: settings.expirationSeconds,
|
|
137
|
+
disappearingModeInitiator: _proto_1.proto.DisappearingMode.Initiator.CHANGED_IN_CHAT,
|
|
138
|
+
...(settings.trigger !== undefined
|
|
139
|
+
? {
|
|
140
|
+
disappearingModeTrigger: settings.trigger
|
|
141
|
+
}
|
|
142
|
+
: {})
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
const chat = await this.resolveChatMetadata(recipientJid);
|
|
146
|
+
const expiration = chat?.ephemeralExpiration;
|
|
147
|
+
if (expiration === undefined || expiration <= 0) {
|
|
148
|
+
return {};
|
|
149
|
+
}
|
|
150
|
+
const stored = chat?.ephemeralSettingTimestamp;
|
|
151
|
+
const settingTimestamp = stored !== undefined ? (0, constants_1.normalizeEphemeralSettingSeconds)(stored) : undefined;
|
|
152
|
+
return {
|
|
153
|
+
expirationSeconds: expiration,
|
|
154
|
+
disappearingModeInitiator: _proto_1.proto.DisappearingMode.Initiator.CHANGED_IN_CHAT,
|
|
155
|
+
disappearingModeTrigger: _proto_1.proto.DisappearingMode.Trigger.CHAT_SETTING,
|
|
156
|
+
...(settingTimestamp !== undefined
|
|
157
|
+
? { ephemeralSettingTimestamp: settingTimestamp }
|
|
158
|
+
: {})
|
|
159
|
+
};
|
|
160
|
+
}
|
|
32
161
|
async publishMessageNode(node, options = {}) {
|
|
33
162
|
this.deps.logger.trace('wa client publish message node', {
|
|
34
163
|
tag: node.tag,
|
|
@@ -149,17 +278,34 @@ class WaMessageDispatchCoordinator {
|
|
|
149
278
|
this.withResolvedMessageId(options)
|
|
150
279
|
]);
|
|
151
280
|
}
|
|
281
|
+
const isGroupRecipient = (0, jid_1.isGroupJid)(recipientJid);
|
|
282
|
+
const directRecipientJid = isGroupRecipient
|
|
283
|
+
? recipientJid
|
|
284
|
+
: await this.resolveDirectRecipientLid((0, jid_1.toUserJid)(recipientJid));
|
|
152
285
|
let optionsCtx = options.contextInfo;
|
|
153
286
|
if (options.expirationSeconds !== undefined) {
|
|
154
287
|
optionsCtx = { ...optionsCtx, expirationSeconds: options.expirationSeconds };
|
|
155
288
|
}
|
|
156
|
-
if (
|
|
157
|
-
optionsCtx
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
289
|
+
if (options.ephemeralSettingTimestamp !== undefined) {
|
|
290
|
+
optionsCtx = {
|
|
291
|
+
...optionsCtx,
|
|
292
|
+
ephemeralSettingTimestamp: options.ephemeralSettingTimestamp
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
if (options.disappearingModeTrigger !== undefined) {
|
|
296
|
+
optionsCtx = {
|
|
297
|
+
...optionsCtx,
|
|
298
|
+
disappearingModeTrigger: options.disappearingModeTrigger
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
const autoInjectDisabled = isGroupRecipient
|
|
302
|
+
? options.disableGroupEphemeralAutoInject
|
|
303
|
+
: options.disableDirectEphemeralAutoInject;
|
|
304
|
+
if (optionsCtx?.expirationSeconds === undefined && !autoInjectDisabled) {
|
|
305
|
+
optionsCtx = {
|
|
306
|
+
...(await this.resolveChatEphemeral(directRecipientJid)),
|
|
307
|
+
...optionsCtx
|
|
308
|
+
};
|
|
163
309
|
}
|
|
164
310
|
const ctx = (0, context_info_1.resolveSendContextInfo)({
|
|
165
311
|
contentLevel: pickContentContextInfo(content),
|
|
@@ -252,17 +398,16 @@ class WaMessageDispatchCoordinator {
|
|
|
252
398
|
]);
|
|
253
399
|
const messageWithIcdc = (0, icdc_1.injectDeviceListMetadata)(messageWithSecret, senderIcdc, recipientIcdc);
|
|
254
400
|
const plaintext = await (0, padding_1.writeRandomPadMax16)(_proto_1.proto.Message.encode(messageWithIcdc).finish());
|
|
255
|
-
const
|
|
401
|
+
const outboundAttrs = (0, content_1.resolveOutboundMessageAttrs)(messageWithIcdc);
|
|
402
|
+
const buttonAddonKind = outboundAttrs.buttonAddonKind;
|
|
256
403
|
const buttonAddonNode = buttonAddonKind ? (0, message_1.buildButtonAddonNode)(buttonAddonKind) : undefined;
|
|
257
404
|
// when a <biz> companion is attached the stanza must advertise type=text and
|
|
258
405
|
// omit enc.mediatype; sending type=media + mediatype=list/button alongside the
|
|
259
406
|
// companion is rejected by the server as SMAX_INVALID (479).
|
|
260
|
-
const type = buttonAddonKind ? 'text' :
|
|
261
|
-
const edit =
|
|
262
|
-
const mediatype = buttonAddonKind
|
|
263
|
-
|
|
264
|
-
: ((0, content_1.resolveEncMediaType)(messageWithIcdc) ?? undefined);
|
|
265
|
-
const metaAttrs = (0, content_1.resolveMetaAttrs)(messageWithIcdc);
|
|
407
|
+
const type = buttonAddonKind ? 'text' : outboundAttrs.typeAttr;
|
|
408
|
+
const edit = outboundAttrs.edit ?? undefined;
|
|
409
|
+
const mediatype = buttonAddonKind ? undefined : (outboundAttrs.mediatype ?? undefined);
|
|
410
|
+
const metaAttrs = outboundAttrs.metaAttrs;
|
|
266
411
|
const metaNode = metaAttrs ? (0, message_1.buildMetaNode)(metaAttrs) : undefined;
|
|
267
412
|
const customNodes = [];
|
|
268
413
|
if (metaNode)
|
|
@@ -274,7 +419,7 @@ class WaMessageDispatchCoordinator {
|
|
|
274
419
|
customNodes.push(node);
|
|
275
420
|
}
|
|
276
421
|
}
|
|
277
|
-
const decryptFail =
|
|
422
|
+
const decryptFail = outboundAttrs.decryptFail;
|
|
278
423
|
const envelope = {
|
|
279
424
|
message: messageWithIcdc,
|
|
280
425
|
plaintext,
|
|
@@ -285,9 +430,6 @@ class WaMessageDispatchCoordinator {
|
|
|
285
430
|
customNodes: customNodes.length > 0 ? customNodes : undefined,
|
|
286
431
|
sendOptions
|
|
287
432
|
};
|
|
288
|
-
const directRecipientJid = isGroup
|
|
289
|
-
? recipientJid
|
|
290
|
-
: await this.resolveDirectRecipientLid((0, jid_1.toUserJid)(recipientJid));
|
|
291
433
|
const peerRecipientPn = isGroup
|
|
292
434
|
? undefined
|
|
293
435
|
: await this.resolvePeerRecipientPn((0, jid_1.toUserJid)(recipientJid), directRecipientJid);
|
|
@@ -397,7 +539,7 @@ class WaMessageDispatchCoordinator {
|
|
|
397
539
|
replayStatusSetting: statusSetting,
|
|
398
540
|
// Bare `<to jid=user>` ack hints route the skmsg through primary
|
|
399
541
|
// devices that already hold the sender key.
|
|
400
|
-
customize:
|
|
542
|
+
customize: ({ fanoutDeviceJids, distributionParticipants, messageWithSecret, sendOptions }) => {
|
|
401
543
|
const distributedAddressKeys = new Set();
|
|
402
544
|
for (let i = 0; i < distributionParticipants.length; i += 1) {
|
|
403
545
|
distributedAddressKeys.add((0, jid_1.signalAddressKey)(distributionParticipants[i].address));
|
|
@@ -417,7 +559,7 @@ class WaMessageDispatchCoordinator {
|
|
|
417
559
|
seenAck.add(userJid);
|
|
418
560
|
ackHints.push({ jid: userJid });
|
|
419
561
|
}
|
|
420
|
-
const reportingArtifacts =
|
|
562
|
+
const reportingArtifacts = this.tryBuildReportingTokenArtifacts({
|
|
421
563
|
message: messageWithSecret,
|
|
422
564
|
stanzaId: sendOptions.id,
|
|
423
565
|
senderUserJid: (0, jid_1.toUserJid)(senderJid),
|
|
@@ -495,14 +637,15 @@ class WaMessageDispatchCoordinator {
|
|
|
495
637
|
participants.push(entry);
|
|
496
638
|
}
|
|
497
639
|
}
|
|
640
|
+
const outboundAttrs = (0, content_1.resolveOutboundMessageAttrs)(messageWithSecret);
|
|
498
641
|
const messageNode = (0, message_1.buildGroupSenderKeyMessageNode)({
|
|
499
642
|
to: input.groupJid,
|
|
500
|
-
type:
|
|
643
|
+
type: outboundAttrs.typeAttr,
|
|
501
644
|
id: sendOptions.id,
|
|
502
645
|
phash: extras.phash,
|
|
503
|
-
edit:
|
|
504
|
-
mediatype:
|
|
505
|
-
decryptFail:
|
|
646
|
+
edit: outboundAttrs.edit ?? undefined,
|
|
647
|
+
mediatype: outboundAttrs.mediatype ?? undefined,
|
|
648
|
+
decryptFail: outboundAttrs.decryptFail,
|
|
506
649
|
groupCiphertext: groupCiphertext.ciphertext,
|
|
507
650
|
participants,
|
|
508
651
|
deviceIdentity: shouldAttachDeviceIdentity
|
|
@@ -550,9 +693,59 @@ class WaMessageDispatchCoordinator {
|
|
|
550
693
|
async mutateGroupMetadataCacheFromGroupEvent(event) {
|
|
551
694
|
await this.deps.groupMetadataCache.mutateFromGroupEvent(event);
|
|
552
695
|
}
|
|
553
|
-
|
|
696
|
+
/**
|
|
697
|
+
* Splits a group's members into the ones a history bundle is being shared
|
|
698
|
+
* with and the rest, normalizing everything to the group's addressing mode
|
|
699
|
+
* so the receiver list written into the proto matches what the fanout can
|
|
700
|
+
* actually resolve. This account is excluded from both lists.
|
|
701
|
+
*
|
|
702
|
+
* Requested JIDs that are not current members come back in `unknownJids`
|
|
703
|
+
* instead of being silently dropped - sharing history with a non-member is
|
|
704
|
+
* a caller mistake worth surfacing.
|
|
705
|
+
*/
|
|
706
|
+
async resolveGroupHistoryAudience(groupJid, requestedJids) {
|
|
707
|
+
const participants = await this.deps.groupMetadataCache.resolveParticipantUsers(groupJid);
|
|
708
|
+
const meJid = this.requireCurrentMeJid('shareGroupHistory');
|
|
709
|
+
const addressingMode = this.resolveGroupAddressingMode(participants, groupJid);
|
|
710
|
+
const meUserJid = (0, jid_1.toUserJid)(this.resolveSenderForAddressingMode(addressingMode, meJid));
|
|
711
|
+
const pending = new Set();
|
|
712
|
+
for (let index = 0; index < requestedJids.length; index += 1) {
|
|
713
|
+
pending.add((0, jid_1.toUserJid)((0, jid_1.normalizeRecipientJid)(requestedJids[index])));
|
|
714
|
+
}
|
|
715
|
+
const historyReceivers = [];
|
|
716
|
+
const nonHistoryReceivers = [];
|
|
717
|
+
for (let index = 0; index < participants.length; index += 1) {
|
|
718
|
+
const participantUserJid = (0, jid_1.toUserJid)(participants[index]);
|
|
719
|
+
if (participantUserJid === meUserJid) {
|
|
720
|
+
continue;
|
|
721
|
+
}
|
|
722
|
+
if (pending.delete(participantUserJid)) {
|
|
723
|
+
historyReceivers[historyReceivers.length] = participantUserJid;
|
|
724
|
+
}
|
|
725
|
+
else {
|
|
726
|
+
nonHistoryReceivers[nonHistoryReceivers.length] = participantUserJid;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
const requestedSelf = pending.delete(meUserJid);
|
|
730
|
+
const unknownJids = [];
|
|
731
|
+
for (const jid of pending) {
|
|
732
|
+
unknownJids[unknownJids.length] = jid;
|
|
733
|
+
}
|
|
734
|
+
return {
|
|
735
|
+
historyReceivers,
|
|
736
|
+
nonHistoryReceivers,
|
|
737
|
+
unknownJids,
|
|
738
|
+
requestedSelf,
|
|
739
|
+
addressingMode
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* A group-history bundle goes to the members named in `historyReceivers`
|
|
744
|
+
* rather than to the whole group, so it takes the per-device direct fanout
|
|
745
|
+
* instead of the group sender key.
|
|
746
|
+
*/
|
|
554
747
|
shouldUseGroupDirectPath(message) {
|
|
555
|
-
return
|
|
748
|
+
return resolveGroupHistoryReceivers(message).length > 0;
|
|
556
749
|
}
|
|
557
750
|
async publishGroupDirectMessage(groupJid, envelope, retryContext = {}) {
|
|
558
751
|
const { message, plaintext, type, edit, mediatype, sendOptions } = envelope;
|
|
@@ -562,8 +755,16 @@ class WaMessageDispatchCoordinator {
|
|
|
562
755
|
: await this.deps.groupMetadataCache.resolveParticipantUsers(groupJid);
|
|
563
756
|
const addressingMode = retryContext.forceAddressingMode ??
|
|
564
757
|
this.resolveGroupAddressingMode(participantUserJids, groupJid);
|
|
565
|
-
const
|
|
566
|
-
const
|
|
758
|
+
const senderJid = this.resolveSenderForAddressingMode(addressingMode, meJid);
|
|
759
|
+
const targetUserJids = restrictGroupHistoryTargets(message, participantUserJids, senderJid, (droppedJids, totalExpected) => {
|
|
760
|
+
this.deps.logger.warn('group history receivers missing from the participant list', {
|
|
761
|
+
groupJid,
|
|
762
|
+
droppedCount: droppedJids.length,
|
|
763
|
+
totalExpected,
|
|
764
|
+
sample: droppedJids.slice(0, 3)
|
|
765
|
+
});
|
|
766
|
+
});
|
|
767
|
+
const fanoutDeviceJids = await this.deps.fanoutResolver.resolveGroupParticipantDeviceJids(targetUserJids);
|
|
567
768
|
if (fanoutDeviceJids.length === 0) {
|
|
568
769
|
throw new Error('group direct send resolved no target devices');
|
|
569
770
|
}
|
|
@@ -618,22 +819,11 @@ class WaMessageDispatchCoordinator {
|
|
|
618
819
|
break;
|
|
619
820
|
}
|
|
620
821
|
}
|
|
621
|
-
const
|
|
622
|
-
let phashTargetCount = 0;
|
|
623
|
-
for (let index = 0; index < resolvedFanoutTargets.length; index += 1) {
|
|
624
|
-
const candidate = resolvedFanoutTargets[index].jid;
|
|
625
|
-
if ((0, jid_1.isHostedDeviceJid)(candidate))
|
|
626
|
-
continue;
|
|
627
|
-
phashTargets[phashTargetCount] = candidate;
|
|
628
|
-
phashTargetCount += 1;
|
|
629
|
-
}
|
|
630
|
-
phashTargets[phashTargetCount] = senderForPhash;
|
|
631
|
-
phashTargets.length = phashTargetCount + 1;
|
|
632
|
-
const localPhash = (0, phash_1.computePhashV2)(phashTargets);
|
|
633
|
-
const reportingArtifacts = await this.tryBuildReportingTokenArtifacts({
|
|
822
|
+
const reportingArtifacts = this.tryBuildReportingTokenArtifacts({
|
|
634
823
|
message,
|
|
824
|
+
messageBytes: (0, padding_1.unpadPkcs7)(plaintext),
|
|
635
825
|
stanzaId: sendOptions.id,
|
|
636
|
-
senderUserJid: (0, jid_1.toUserJid)(
|
|
826
|
+
senderUserJid: (0, jid_1.toUserJid)(senderJid),
|
|
637
827
|
remoteJid: groupJid,
|
|
638
828
|
context: 'group_direct'
|
|
639
829
|
});
|
|
@@ -645,7 +835,6 @@ class WaMessageDispatchCoordinator {
|
|
|
645
835
|
type,
|
|
646
836
|
id: sendOptions.id,
|
|
647
837
|
edit,
|
|
648
|
-
phash: localPhash,
|
|
649
838
|
addressingMode,
|
|
650
839
|
participants,
|
|
651
840
|
deviceIdentity: shouldAttachDeviceIdentity
|
|
@@ -671,7 +860,7 @@ class WaMessageDispatchCoordinator {
|
|
|
671
860
|
const ackError = result.ack.error;
|
|
672
861
|
const serverPhash = result.ack.phash;
|
|
673
862
|
const serverAddressingMode = result.ack.addressingMode;
|
|
674
|
-
const hasPhashMismatch = !!serverPhash
|
|
863
|
+
const hasPhashMismatch = !!serverPhash;
|
|
675
864
|
const hasAddressingMismatch = !!serverAddressingMode && serverAddressingMode !== addressingMode;
|
|
676
865
|
const hasAddressingError = ackError === constants_1.WA_NACK_REASONS.STALE_GROUP_ADDRESSING_MODE;
|
|
677
866
|
if (!retryContext.retried &&
|
|
@@ -679,7 +868,6 @@ class WaMessageDispatchCoordinator {
|
|
|
679
868
|
this.deps.logger.warn('group direct publish acknowledged with mismatch metadata', {
|
|
680
869
|
id: result.id,
|
|
681
870
|
groupJid,
|
|
682
|
-
localPhash,
|
|
683
871
|
serverPhash,
|
|
684
872
|
localAddressingMode: addressingMode,
|
|
685
873
|
serverAddressingMode,
|
|
@@ -788,8 +976,9 @@ class WaMessageDispatchCoordinator {
|
|
|
788
976
|
phashTargets[phashTargetCount] = senderJid;
|
|
789
977
|
phashTargets.length = phashTargetCount + 1;
|
|
790
978
|
const localPhash = (0, phash_1.computePhashV2)(phashTargets);
|
|
791
|
-
const reportingArtifacts =
|
|
979
|
+
const reportingArtifacts = this.tryBuildReportingTokenArtifacts({
|
|
792
980
|
message,
|
|
981
|
+
messageBytes: (0, padding_1.unpadPkcs7)(plaintext),
|
|
793
982
|
stanzaId: sendOptions.id,
|
|
794
983
|
senderUserJid: (0, jid_1.toUserJid)(senderJid),
|
|
795
984
|
remoteJid: groupJid,
|
|
@@ -901,9 +1090,6 @@ class WaMessageDispatchCoordinator {
|
|
|
901
1090
|
return (0, jid_1.normalizeDeviceJid)(meJid);
|
|
902
1091
|
}
|
|
903
1092
|
async encryptGroupDistributionParticipants(groupJid, senderKeyId, senderKeyDistributionMessage, participantUserJids) {
|
|
904
|
-
const distributionPayload = await (0, padding_1.writeRandomPadMax16)(_proto_1.proto.Message.encode({
|
|
905
|
-
senderKeyDistributionMessage
|
|
906
|
-
}).finish());
|
|
907
1093
|
const fanoutDeviceJids = await this.deps.fanoutResolver.resolveGroupParticipantDeviceJids(participantUserJids);
|
|
908
1094
|
if (fanoutDeviceJids.length === 0) {
|
|
909
1095
|
return {
|
|
@@ -911,13 +1097,9 @@ class WaMessageDispatchCoordinator {
|
|
|
911
1097
|
distributionParticipants: []
|
|
912
1098
|
};
|
|
913
1099
|
}
|
|
914
|
-
const fanoutTargetsByAddressKey = new Map();
|
|
915
1100
|
const fanoutAddresses = new Array(fanoutDeviceJids.length);
|
|
916
1101
|
for (let index = 0; index < fanoutDeviceJids.length; index += 1) {
|
|
917
|
-
|
|
918
|
-
const address = (0, jid_1.parseSignalAddressFromJid)(jid);
|
|
919
|
-
fanoutAddresses[index] = address;
|
|
920
|
-
fanoutTargetsByAddressKey.set((0, jid_1.signalAddressKey)(address), { jid, address });
|
|
1102
|
+
fanoutAddresses[index] = (0, jid_1.parseSignalAddressFromJid)(fanoutDeviceJids[index]);
|
|
921
1103
|
}
|
|
922
1104
|
const pendingAddresses = await this.deps.senderKeyManager.filterParticipantsNeedingDistribution(groupJid, senderKeyId, fanoutAddresses);
|
|
923
1105
|
if (pendingAddresses.length === 0) {
|
|
@@ -926,6 +1108,14 @@ class WaMessageDispatchCoordinator {
|
|
|
926
1108
|
distributionParticipants: []
|
|
927
1109
|
};
|
|
928
1110
|
}
|
|
1111
|
+
const fanoutTargetsByAddressKey = new Map();
|
|
1112
|
+
for (let index = 0; index < fanoutAddresses.length; index += 1) {
|
|
1113
|
+
const address = fanoutAddresses[index];
|
|
1114
|
+
fanoutTargetsByAddressKey.set((0, jid_1.signalAddressKey)(address), {
|
|
1115
|
+
jid: fanoutDeviceJids[index],
|
|
1116
|
+
address
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
929
1119
|
const pendingAddressKeys = new Set();
|
|
930
1120
|
const pendingTargets = [];
|
|
931
1121
|
for (let index = 0; index < pendingAddresses.length; index += 1) {
|
|
@@ -985,6 +1175,9 @@ class WaMessageDispatchCoordinator {
|
|
|
985
1175
|
distributionParticipants: []
|
|
986
1176
|
};
|
|
987
1177
|
}
|
|
1178
|
+
const distributionPayload = await (0, padding_1.writeRandomPadMax16)(_proto_1.proto.Message.encode({
|
|
1179
|
+
senderKeyDistributionMessage
|
|
1180
|
+
}).finish());
|
|
988
1181
|
const distributionEncryptRequests = new Array(availableTargets.length);
|
|
989
1182
|
for (let index = 0; index < availableTargets.length; index += 1) {
|
|
990
1183
|
const target = availableTargets[index];
|
|
@@ -1137,8 +1330,9 @@ class WaMessageDispatchCoordinator {
|
|
|
1137
1330
|
const deviceIdentity = shouldAttachDeviceIdentity
|
|
1138
1331
|
? this.getEncodedSignedDeviceIdentity()
|
|
1139
1332
|
: undefined;
|
|
1140
|
-
const reportingArtifacts =
|
|
1333
|
+
const reportingArtifacts = this.tryBuildReportingTokenArtifacts({
|
|
1141
1334
|
message,
|
|
1335
|
+
messageBytes: (0, padding_1.unpadPkcs7)(plaintext),
|
|
1142
1336
|
stanzaId: sendOptions.id,
|
|
1143
1337
|
senderUserJid: meUserJid,
|
|
1144
1338
|
remoteJid: recipientUserJid,
|
|
@@ -1241,13 +1435,14 @@ class WaMessageDispatchCoordinator {
|
|
|
1241
1435
|
return `3EB0${(0, bytes_1.bytesToHex)(await (0, _crypto_1.randomBytesAsync)(8)).toUpperCase()}`;
|
|
1242
1436
|
}
|
|
1243
1437
|
}
|
|
1244
|
-
|
|
1438
|
+
tryBuildReportingTokenArtifacts(input) {
|
|
1245
1439
|
if (!input.stanzaId) {
|
|
1246
1440
|
return null;
|
|
1247
1441
|
}
|
|
1248
1442
|
try {
|
|
1249
|
-
return
|
|
1443
|
+
return (0, reporting_token_1.buildReportingTokenArtifacts)({
|
|
1250
1444
|
message: input.message,
|
|
1445
|
+
messageBytes: input.messageBytes,
|
|
1251
1446
|
stanzaId: input.stanzaId,
|
|
1252
1447
|
senderUserJid: input.senderUserJid,
|
|
1253
1448
|
remoteJid: input.remoteJid
|