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
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scanHistorySyncBlob = scanHistorySyncBlob;
|
|
4
|
+
exports.scanConversationJidPair = scanConversationJidPair;
|
|
3
5
|
exports.runHistorySyncNotification = runHistorySyncNotification;
|
|
4
6
|
exports.processHistorySyncNotification = processHistorySyncNotification;
|
|
5
7
|
const node_util_1 = require("node:util");
|
|
6
8
|
const node_zlib_1 = require("node:zlib");
|
|
9
|
+
const history_blob_1 = require("../persistence/history-blob");
|
|
7
10
|
const _proto_1 = require("../../proto");
|
|
8
11
|
const jid_1 = require("../../protocol/jid");
|
|
12
|
+
const message_1 = require("../../protocol/message");
|
|
9
13
|
const bytes_1 = require("../../util/bytes");
|
|
10
14
|
const primitives_1 = require("../../util/primitives");
|
|
15
|
+
const protoscan_1 = require("../../util/protoscan");
|
|
11
16
|
const unzipAsync = (0, node_util_1.promisify)(node_zlib_1.unzip);
|
|
12
17
|
const HANDLED_SYNC_TYPES = new Set([
|
|
13
18
|
_proto_1.proto.Message.HistorySyncType.INITIAL_BOOTSTRAP,
|
|
@@ -18,6 +23,90 @@ const HANDLED_SYNC_TYPES = new Set([
|
|
|
18
23
|
_proto_1.proto.Message.HistorySyncType.NON_BLOCKING_DATA
|
|
19
24
|
]);
|
|
20
25
|
const HISTORY_SYNC_MAX_PENDING_WRITES = 1024;
|
|
26
|
+
const HISTORY_SYNC_FIELDS = Object.freeze({
|
|
27
|
+
CONVERSATIONS: 2,
|
|
28
|
+
CHUNK_ORDER: 5,
|
|
29
|
+
PROGRESS: 6,
|
|
30
|
+
PUSHNAMES: 7,
|
|
31
|
+
PHONE_NUMBER_TO_LID_MAPPINGS: 15,
|
|
32
|
+
NCT_SALT: 19,
|
|
33
|
+
INLINE_CONTACTS: 20
|
|
34
|
+
});
|
|
35
|
+
const CONVERSATION_JID_FIELDS = Object.freeze({
|
|
36
|
+
PN_JID: 39,
|
|
37
|
+
LID_JID: 42,
|
|
38
|
+
ACCOUNT_LID: 49
|
|
39
|
+
});
|
|
40
|
+
function scanHistorySyncBlob(bytes) {
|
|
41
|
+
const conversationRanges = [];
|
|
42
|
+
const pushnames = [];
|
|
43
|
+
const inlineContacts = [];
|
|
44
|
+
const phoneNumberToLidMappings = [];
|
|
45
|
+
let nctSalt = null;
|
|
46
|
+
let chunkOrder = null;
|
|
47
|
+
let progress = null;
|
|
48
|
+
(0, protoscan_1.scanProtoFields)(bytes, 0, bytes.length, (field) => {
|
|
49
|
+
if (field.wireType === protoscan_1.PROTO_WIRE_TYPES.LEN) {
|
|
50
|
+
if (field.fieldNumber === HISTORY_SYNC_FIELDS.CONVERSATIONS) {
|
|
51
|
+
conversationRanges[conversationRanges.length] = {
|
|
52
|
+
start: field.valueStart,
|
|
53
|
+
end: field.valueEnd
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
else if (field.fieldNumber === HISTORY_SYNC_FIELDS.PUSHNAMES) {
|
|
57
|
+
pushnames[pushnames.length] = _proto_1.proto.Pushname.decode(bytes.subarray(field.valueStart, field.valueEnd));
|
|
58
|
+
}
|
|
59
|
+
else if (field.fieldNumber === HISTORY_SYNC_FIELDS.PHONE_NUMBER_TO_LID_MAPPINGS) {
|
|
60
|
+
phoneNumberToLidMappings[phoneNumberToLidMappings.length] =
|
|
61
|
+
_proto_1.proto.PhoneNumberToLIDMapping.decode(bytes.subarray(field.valueStart, field.valueEnd));
|
|
62
|
+
}
|
|
63
|
+
else if (field.fieldNumber === HISTORY_SYNC_FIELDS.INLINE_CONTACTS) {
|
|
64
|
+
inlineContacts[inlineContacts.length] = _proto_1.proto.InlineContact.decode(bytes.subarray(field.valueStart, field.valueEnd));
|
|
65
|
+
}
|
|
66
|
+
else if (field.fieldNumber === HISTORY_SYNC_FIELDS.NCT_SALT) {
|
|
67
|
+
nctSalt = bytes.slice(field.valueStart, field.valueEnd);
|
|
68
|
+
}
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (field.wireType === protoscan_1.PROTO_WIRE_TYPES.VARINT) {
|
|
72
|
+
if (field.fieldNumber === HISTORY_SYNC_FIELDS.CHUNK_ORDER) {
|
|
73
|
+
chunkOrder = field.varintValue;
|
|
74
|
+
}
|
|
75
|
+
else if (field.fieldNumber === HISTORY_SYNC_FIELDS.PROGRESS) {
|
|
76
|
+
progress = field.varintValue;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return {
|
|
81
|
+
conversationRanges,
|
|
82
|
+
pushnames,
|
|
83
|
+
inlineContacts,
|
|
84
|
+
phoneNumberToLidMappings,
|
|
85
|
+
nctSalt,
|
|
86
|
+
chunkOrder,
|
|
87
|
+
progress
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function scanConversationJidPair(bytes, range) {
|
|
91
|
+
let pnJid = null;
|
|
92
|
+
let lidJid = null;
|
|
93
|
+
let accountLid = null;
|
|
94
|
+
(0, protoscan_1.scanProtoFields)(bytes, range.start, range.end, (field) => {
|
|
95
|
+
if (field.wireType !== protoscan_1.PROTO_WIRE_TYPES.LEN) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (field.fieldNumber === CONVERSATION_JID_FIELDS.PN_JID) {
|
|
99
|
+
pnJid = bytes_1.TEXT_DECODER.decode(bytes.subarray(field.valueStart, field.valueEnd));
|
|
100
|
+
}
|
|
101
|
+
else if (field.fieldNumber === CONVERSATION_JID_FIELDS.LID_JID) {
|
|
102
|
+
lidJid = bytes_1.TEXT_DECODER.decode(bytes.subarray(field.valueStart, field.valueEnd));
|
|
103
|
+
}
|
|
104
|
+
else if (field.fieldNumber === CONVERSATION_JID_FIELDS.ACCOUNT_LID) {
|
|
105
|
+
accountLid = bytes_1.TEXT_DECODER.decode(bytes.subarray(field.valueStart, field.valueEnd));
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
return { pnJid, lidJid: lidJid ?? accountLid };
|
|
109
|
+
}
|
|
21
110
|
async function runHistorySyncNotification(deps, notification) {
|
|
22
111
|
try {
|
|
23
112
|
await processHistorySyncNotification(deps, notification);
|
|
@@ -47,14 +136,17 @@ async function processHistorySyncNotification(deps, notification) {
|
|
|
47
136
|
}
|
|
48
137
|
const blob = await downloadHistorySyncBlob(deps, notification);
|
|
49
138
|
const decompressed = (0, bytes_1.toBytesView)(await unzipAsync(blob));
|
|
50
|
-
|
|
139
|
+
// Conversations are decoded one record at a time in the loop below so the
|
|
140
|
+
// full message graph never coexists in memory; the scan only records their
|
|
141
|
+
// byte ranges and decodes the small metadata fields.
|
|
142
|
+
const scan = scanHistorySyncBlob(decompressed);
|
|
51
143
|
deps.logger.info('decoded history sync chunk', {
|
|
52
144
|
syncType,
|
|
53
|
-
chunkOrder:
|
|
54
|
-
progress:
|
|
55
|
-
conversations:
|
|
56
|
-
pushnames:
|
|
57
|
-
inlineContacts:
|
|
145
|
+
chunkOrder: scan.chunkOrder,
|
|
146
|
+
progress: scan.progress,
|
|
147
|
+
conversations: scan.conversationRanges.length,
|
|
148
|
+
pushnames: scan.pushnames.length,
|
|
149
|
+
inlineContacts: scan.inlineContacts.length
|
|
58
150
|
});
|
|
59
151
|
const nowMs = Date.now();
|
|
60
152
|
const pendingWrites = [];
|
|
@@ -63,24 +155,23 @@ async function processHistorySyncNotification(deps, notification) {
|
|
|
63
155
|
// pushnames and mappings land on a single canonical (LID-form) contact
|
|
64
156
|
// row instead of two mirror rows (one keyed by PN, one keyed by LID).
|
|
65
157
|
const pnToLid = new Map();
|
|
66
|
-
for (const map of
|
|
158
|
+
for (const map of scan.phoneNumberToLidMappings) {
|
|
67
159
|
if (map.pnJid && map.lidJid) {
|
|
68
160
|
pnToLid.set(map.pnJid, map.lidJid);
|
|
69
161
|
}
|
|
70
162
|
}
|
|
71
|
-
for (const c of
|
|
163
|
+
for (const c of scan.inlineContacts) {
|
|
72
164
|
if (c.pnJid && c.lidJid) {
|
|
73
165
|
pnToLid.set(c.pnJid, c.lidJid);
|
|
74
166
|
}
|
|
75
167
|
}
|
|
76
|
-
for (const
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
pnToLid.set(pnJid, lidJid);
|
|
168
|
+
for (const range of scan.conversationRanges) {
|
|
169
|
+
const pair = scanConversationJidPair(decompressed, range);
|
|
170
|
+
if (pair.pnJid && pair.lidJid) {
|
|
171
|
+
pnToLid.set(pair.pnJid, pair.lidJid);
|
|
81
172
|
}
|
|
82
173
|
}
|
|
83
|
-
for (const pn of
|
|
174
|
+
for (const pn of scan.pushnames) {
|
|
84
175
|
if (!pn.id) {
|
|
85
176
|
continue;
|
|
86
177
|
}
|
|
@@ -98,10 +189,10 @@ async function processHistorySyncNotification(deps, notification) {
|
|
|
98
189
|
lastUpdatedMs: nowMs
|
|
99
190
|
});
|
|
100
191
|
if (pendingWrites.length >= HISTORY_SYNC_MAX_PENDING_WRITES) {
|
|
101
|
-
await flushPendingWrites(pendingWrites);
|
|
192
|
+
await (0, history_blob_1.flushPendingWrites)(pendingWrites);
|
|
102
193
|
}
|
|
103
194
|
}
|
|
104
|
-
for (const c of
|
|
195
|
+
for (const c of scan.inlineContacts) {
|
|
105
196
|
const jid = c.lidJid ?? c.pnJid;
|
|
106
197
|
if (!jid) {
|
|
107
198
|
continue;
|
|
@@ -117,16 +208,55 @@ async function processHistorySyncNotification(deps, notification) {
|
|
|
117
208
|
lastUpdatedMs: nowMs
|
|
118
209
|
});
|
|
119
210
|
if (pendingWrites.length >= HISTORY_SYNC_MAX_PENDING_WRITES) {
|
|
120
|
-
await flushPendingWrites(pendingWrites);
|
|
211
|
+
await (0, history_blob_1.flushPendingWrites)(pendingWrites);
|
|
121
212
|
}
|
|
122
213
|
}
|
|
123
214
|
let messagesCount = 0;
|
|
124
|
-
|
|
215
|
+
const tokenConversations = [];
|
|
216
|
+
for (const range of scan.conversationRanges) {
|
|
217
|
+
let conversation;
|
|
218
|
+
try {
|
|
219
|
+
conversation = _proto_1.proto.Conversation.decode(decompressed.subarray(range.start, range.end));
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
await Promise.allSettled(pendingWrites);
|
|
223
|
+
throw (0, primitives_1.toError)(error);
|
|
224
|
+
}
|
|
125
225
|
const threadJid = conversation.id;
|
|
126
226
|
if (!threadJid) {
|
|
127
227
|
deps.logger.debug('skipping history sync conversation without thread jid');
|
|
128
228
|
continue;
|
|
129
229
|
}
|
|
230
|
+
if (deps.onPrivacyTokens &&
|
|
231
|
+
(conversation.tcToken ||
|
|
232
|
+
conversation.tcTokenTimestamp ||
|
|
233
|
+
conversation.tcTokenSenderTimestamp)) {
|
|
234
|
+
tokenConversations[tokenConversations.length] = {
|
|
235
|
+
jid: threadJid,
|
|
236
|
+
tcToken: conversation.tcToken ? new Uint8Array(conversation.tcToken) : undefined,
|
|
237
|
+
tcTokenTimestamp: (0, primitives_1.longToNumber)(conversation.tcTokenTimestamp) || undefined,
|
|
238
|
+
tcTokenSenderTimestamp: (0, primitives_1.longToNumber)(conversation.tcTokenSenderTimestamp) || undefined
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
const ephemeralExpiration = conversation.ephemeralExpiration ?? undefined;
|
|
242
|
+
const ephemeralSettingTimestamp = (0, message_1.normalizeEphemeralSettingSeconds)((0, primitives_1.longToNumber)(conversation.ephemeralSettingTimestamp)) || undefined;
|
|
243
|
+
if (deps.chatMetadataStore && ephemeralExpiration !== undefined) {
|
|
244
|
+
pendingWrites[pendingWrites.length] = deps.chatMetadataStore
|
|
245
|
+
.upsertChatMetadata({
|
|
246
|
+
chatJid: threadJid,
|
|
247
|
+
ephemeralExpiration,
|
|
248
|
+
...(ephemeralSettingTimestamp !== undefined
|
|
249
|
+
? { ephemeralSettingTimestamp }
|
|
250
|
+
: {}),
|
|
251
|
+
updatedAtMs: nowMs
|
|
252
|
+
})
|
|
253
|
+
.catch((error) => {
|
|
254
|
+
deps.logger.debug('failed to cache history sync chat metadata', {
|
|
255
|
+
jid: threadJid,
|
|
256
|
+
message: (0, primitives_1.toError)(error).message
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
}
|
|
130
260
|
pendingWrites[pendingWrites.length] = deps.writeBehind.persistThreadAsync({
|
|
131
261
|
jid: threadJid,
|
|
132
262
|
name: conversation.name ?? undefined,
|
|
@@ -135,10 +265,11 @@ async function processHistorySyncNotification(deps, notification) {
|
|
|
135
265
|
pinned: conversation.pinned ?? undefined,
|
|
136
266
|
muteEndMs: (0, primitives_1.longToNumber)(conversation.muteEndTime) || undefined,
|
|
137
267
|
markedAsUnread: conversation.markedAsUnread ?? undefined,
|
|
138
|
-
ephemeralExpiration
|
|
268
|
+
ephemeralExpiration,
|
|
269
|
+
ephemeralSettingTimestamp
|
|
139
270
|
});
|
|
140
271
|
if (pendingWrites.length >= HISTORY_SYNC_MAX_PENDING_WRITES) {
|
|
141
|
-
await flushPendingWrites(pendingWrites);
|
|
272
|
+
await (0, history_blob_1.flushPendingWrites)(pendingWrites);
|
|
142
273
|
}
|
|
143
274
|
if ((0, jid_1.isUserJid)(threadJid) || (conversation.lidJid ?? conversation.accountLid)) {
|
|
144
275
|
const contactDisplay = conversation.displayName || conversation.username || undefined;
|
|
@@ -153,7 +284,7 @@ async function processHistorySyncNotification(deps, notification) {
|
|
|
153
284
|
lastUpdatedMs: nowMs
|
|
154
285
|
});
|
|
155
286
|
if (pendingWrites.length >= HISTORY_SYNC_MAX_PENDING_WRITES) {
|
|
156
|
-
await flushPendingWrites(pendingWrites);
|
|
287
|
+
await (0, history_blob_1.flushPendingWrites)(pendingWrites);
|
|
157
288
|
}
|
|
158
289
|
}
|
|
159
290
|
}
|
|
@@ -176,7 +307,7 @@ async function processHistorySyncNotification(deps, notification) {
|
|
|
176
307
|
messageBytes: _proto_1.proto.Message.encode(webMsg.message).finish()
|
|
177
308
|
});
|
|
178
309
|
if (pendingWrites.length >= HISTORY_SYNC_MAX_PENDING_WRITES) {
|
|
179
|
-
await flushPendingWrites(pendingWrites);
|
|
310
|
+
await (0, history_blob_1.flushPendingWrites)(pendingWrites);
|
|
180
311
|
}
|
|
181
312
|
messagesCount += 1;
|
|
182
313
|
}
|
|
@@ -191,70 +322,33 @@ async function processHistorySyncNotification(deps, notification) {
|
|
|
191
322
|
lastUpdatedMs: nowMs
|
|
192
323
|
});
|
|
193
324
|
if (pendingWrites.length >= HISTORY_SYNC_MAX_PENDING_WRITES) {
|
|
194
|
-
await flushPendingWrites(pendingWrites);
|
|
325
|
+
await (0, history_blob_1.flushPendingWrites)(pendingWrites);
|
|
195
326
|
}
|
|
196
327
|
}
|
|
197
|
-
if (deps.onPrivacyTokens) {
|
|
198
|
-
|
|
199
|
-
for (const conversation of historySync.conversations) {
|
|
200
|
-
if (!conversation.id)
|
|
201
|
-
continue;
|
|
202
|
-
if (conversation.tcToken ||
|
|
203
|
-
conversation.tcTokenTimestamp ||
|
|
204
|
-
conversation.tcTokenSenderTimestamp) {
|
|
205
|
-
tokenConversations[tokenConversations.length] = {
|
|
206
|
-
jid: conversation.id,
|
|
207
|
-
tcToken: conversation.tcToken,
|
|
208
|
-
tcTokenTimestamp: (0, primitives_1.longToNumber)(conversation.tcTokenTimestamp) || undefined,
|
|
209
|
-
tcTokenSenderTimestamp: (0, primitives_1.longToNumber)(conversation.tcTokenSenderTimestamp) || undefined
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
if (tokenConversations.length > 0) {
|
|
214
|
-
pendingWrites[pendingWrites.length] = deps.onPrivacyTokens(tokenConversations);
|
|
215
|
-
}
|
|
328
|
+
if (deps.onPrivacyTokens && tokenConversations.length > 0) {
|
|
329
|
+
pendingWrites[pendingWrites.length] = deps.onPrivacyTokens(tokenConversations);
|
|
216
330
|
}
|
|
217
|
-
if (deps.onNctSalt &&
|
|
218
|
-
pendingWrites[pendingWrites.length] = deps.onNctSalt(
|
|
331
|
+
if (deps.onNctSalt && scan.nctSalt) {
|
|
332
|
+
pendingWrites[pendingWrites.length] = deps.onNctSalt(scan.nctSalt);
|
|
219
333
|
}
|
|
220
334
|
const event = {
|
|
221
335
|
syncType,
|
|
222
336
|
messagesCount,
|
|
223
|
-
conversationsCount:
|
|
224
|
-
pushnamesCount:
|
|
225
|
-
inlineContactsCount:
|
|
226
|
-
chunkOrder:
|
|
227
|
-
progress:
|
|
337
|
+
conversationsCount: scan.conversationRanges.length,
|
|
338
|
+
pushnamesCount: scan.pushnames.length,
|
|
339
|
+
inlineContactsCount: scan.inlineContacts.length,
|
|
340
|
+
chunkOrder: scan.chunkOrder ?? undefined,
|
|
341
|
+
progress: scan.progress ?? undefined
|
|
228
342
|
};
|
|
229
|
-
await flushPendingWrites(pendingWrites);
|
|
343
|
+
await (0, history_blob_1.flushPendingWrites)(pendingWrites);
|
|
230
344
|
deps.emitEvent('history_sync_chunk', event);
|
|
231
345
|
if (deps.onProcessed) {
|
|
232
346
|
await deps.onProcessed(syncType);
|
|
233
347
|
}
|
|
234
348
|
}
|
|
235
|
-
async function flushPendingWrites(pendingWrites) {
|
|
236
|
-
if (pendingWrites.length === 0) {
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
const settled = Promise.all(pendingWrites);
|
|
240
|
-
pendingWrites.length = 0;
|
|
241
|
-
await settled;
|
|
242
|
-
}
|
|
243
349
|
async function downloadHistorySyncBlob(deps, notification) {
|
|
244
350
|
if (notification.initialHistBootstrapInlinePayload) {
|
|
245
351
|
return (0, bytes_1.decodeProtoBytes)(notification.initialHistBootstrapInlinePayload, 'initialHistBootstrapInlinePayload');
|
|
246
352
|
}
|
|
247
|
-
|
|
248
|
-
throw new Error('history sync notification missing directPath');
|
|
249
|
-
}
|
|
250
|
-
const mediaKey = (0, bytes_1.decodeProtoBytes)(notification.mediaKey, 'history sync mediaKey');
|
|
251
|
-
const fileSha256 = (0, bytes_1.decodeProtoBytes)(notification.fileSha256, 'history sync fileSha256');
|
|
252
|
-
const fileEncSha256 = (0, bytes_1.decodeProtoBytes)(notification.fileEncSha256, 'history sync fileEncSha256');
|
|
253
|
-
return deps.mediaTransfer.downloadAndDecrypt({
|
|
254
|
-
directPath: notification.directPath,
|
|
255
|
-
mediaType: 'history',
|
|
256
|
-
mediaKey,
|
|
257
|
-
fileSha256,
|
|
258
|
-
fileEncSha256
|
|
259
|
-
});
|
|
353
|
+
return (0, history_blob_1.downloadHistoryBlob)(deps.mediaTransfer, notification, 'history', 'history sync');
|
|
260
354
|
}
|
|
@@ -63,10 +63,18 @@ type ExposedOf<P> = P extends {
|
|
|
63
63
|
* `{ readonly voip: WaVoipCoordinator }`.
|
|
64
64
|
*/
|
|
65
65
|
export type WaClientExposedFromPlugins<P extends readonly unknown[]> = UnionToIntersection<ExposedOf<P[number]>>;
|
|
66
|
-
/**
|
|
66
|
+
/**
|
|
67
|
+
* Event map a plugin contributes, carried as a phantom marker on its definition.
|
|
68
|
+
*
|
|
69
|
+
* The marker is optional (it never exists at runtime), so under
|
|
70
|
+
* `exactOptionalPropertyTypes` the inferred `E` keeps the `| undefined` the
|
|
71
|
+
* declaration emits. `Exclude` drops it before the union reaches
|
|
72
|
+
* {@link UnionToIntersection}, which would otherwise collapse
|
|
73
|
+
* `Events | undefined` to `never` and type every client listener as `never`.
|
|
74
|
+
*/
|
|
67
75
|
type EventsOf<P> = P extends {
|
|
68
76
|
readonly __pluginEvents?: infer E;
|
|
69
|
-
} ? unknown extends E ? {} : E : {};
|
|
77
|
+
} ? unknown extends E ? {} : Exclude<E, undefined> : {};
|
|
70
78
|
/**
|
|
71
79
|
* Client events contributed by a tuple of plugin definitions, derived from the
|
|
72
80
|
* plugin values (no global augmentation). Threaded into the client's
|
package/dist/client/types.d.ts
CHANGED
|
@@ -2,8 +2,10 @@ import type { AppStateCollectionName } from '../appstate/types';
|
|
|
2
2
|
import type { DataForKey, WaAppstateActionKey, WaAppstateIndexArgs } from '../appstate-spec';
|
|
3
3
|
import type { WaShortcakeAssertionSigner } from '../auth/pairing/WaShortcakeFlow';
|
|
4
4
|
import type { WaAuthClientOptions, WaAuthCredentials, WaAuthDangerousOptions, WaAuthSocketOptions } from '../auth/types';
|
|
5
|
+
import type { WaPrivacyAccountSyncResult } from './coordinators/WaPrivacyCoordinator';
|
|
5
6
|
import type { WaCallGroupParticipant, WaCallType } from './events/call';
|
|
6
7
|
import type { IncomingPresenceType, PresenceLastSeen } from './events/presence';
|
|
8
|
+
import type { WaBlocklistResult } from './events/privacy';
|
|
7
9
|
import type { CompanionHostPersistence } from './persistence/companion-host';
|
|
8
10
|
import type { WaClientPluginDefinition } from './plugins/types';
|
|
9
11
|
import type { WaMediaProcessor } from '../media/processor';
|
|
@@ -148,7 +150,9 @@ export interface WaClientOptions extends WaAuthClientOptions, WaAuthSocketOption
|
|
|
148
150
|
* on-demand backfill triggered by `message.requestHistorySync`) are
|
|
149
151
|
* downloaded and emitted as `history_sync_chunk` events. Set
|
|
150
152
|
* `enabled: false` to drop them; `requireFullSync: true` asks the
|
|
151
|
-
* primary device for a full history download instead of just recent
|
|
153
|
+
* primary device for a full history download instead of just recent;
|
|
154
|
+
* `groupBundles: true` opts into the group-history bundle a member may
|
|
155
|
+
* share after somebody joins a group.
|
|
152
156
|
*/
|
|
153
157
|
readonly history?: WaHistorySyncOptions;
|
|
154
158
|
/**
|
|
@@ -315,6 +319,14 @@ export interface WaHistorySyncOptions {
|
|
|
315
319
|
*/
|
|
316
320
|
readonly enabled?: boolean;
|
|
317
321
|
readonly requireFullSync?: boolean;
|
|
322
|
+
/**
|
|
323
|
+
* Whether to download and process the group-history bundle a member may
|
|
324
|
+
* share after somebody joins a group, emitting `group_history_bundle`.
|
|
325
|
+
* **Off by default** - a bundle is media a third party pushes at this
|
|
326
|
+
* account unprompted, so fetching it is opt-in. Bundles addressed to
|
|
327
|
+
* other members are dropped either way.
|
|
328
|
+
*/
|
|
329
|
+
readonly groupBundles?: boolean;
|
|
318
330
|
}
|
|
319
331
|
export interface WaSignalMessagePublishInput {
|
|
320
332
|
readonly to: string;
|
|
@@ -375,9 +387,23 @@ export interface WaSendMessageOptions extends WaMessagePublishOptions {
|
|
|
375
387
|
*/
|
|
376
388
|
readonly expirationSeconds?: number;
|
|
377
389
|
/**
|
|
378
|
-
*
|
|
379
|
-
*
|
|
380
|
-
*
|
|
390
|
+
* Unix seconds when disappearing-mode was enabled, sent as
|
|
391
|
+
* `contextInfo.ephemeralSettingTimestamp`. 1:1 only – groups never carry it.
|
|
392
|
+
* Overrides the value the auto-inject resolves from the thread store; omit
|
|
393
|
+
* it unless you have a reason, since a missing timestamp makes the peer warn
|
|
394
|
+
* that the message will not disappear.
|
|
395
|
+
*/
|
|
396
|
+
readonly ephemeralSettingTimestamp?: number;
|
|
397
|
+
/**
|
|
398
|
+
* Overrides `contextInfo.disappearingMode.trigger`. The 1:1 auto-inject
|
|
399
|
+
* already sets `CHAT_SETTING`.
|
|
400
|
+
*/
|
|
401
|
+
readonly disappearingModeTrigger?: Proto.DisappearingMode.Trigger;
|
|
402
|
+
/**
|
|
403
|
+
* Skip the automatic disappearing-message injection on **group** sends, which
|
|
404
|
+
* would otherwise stamp `contextInfo.expiration` and `disappearingMode` from
|
|
405
|
+
* the group metadata cache. Has no effect on 1:1 – see
|
|
406
|
+
* {@link disableDirectEphemeralAutoInject}. Off by default.
|
|
381
407
|
*
|
|
382
408
|
* Relationship with {@link expirationSeconds}: a non-undefined
|
|
383
409
|
* `expirationSeconds` already short-circuits the auto-inject, so this flag is
|
|
@@ -385,6 +411,17 @@ export interface WaSendMessageOptions extends WaMessagePublishOptions {
|
|
|
385
411
|
* auto-inject AND not set any expiration yourself.
|
|
386
412
|
*/
|
|
387
413
|
readonly disableGroupEphemeralAutoInject?: boolean;
|
|
414
|
+
/**
|
|
415
|
+
* Skip the automatic disappearing-message injection on **1:1** sends, which
|
|
416
|
+
* would otherwise stamp `contextInfo.expiration`,
|
|
417
|
+
* `ephemeralSettingTimestamp` and `disappearingMode` from the chat metadata
|
|
418
|
+
* cache. Also skips the cache lookup itself. Has no effect on groups – see
|
|
419
|
+
* {@link disableGroupEphemeralAutoInject}. Off by default.
|
|
420
|
+
*
|
|
421
|
+
* Same relationship with {@link expirationSeconds} as the group flag: a
|
|
422
|
+
* non-undefined `expirationSeconds` already short-circuits the auto-inject.
|
|
423
|
+
*/
|
|
424
|
+
readonly disableDirectEphemeralAutoInject?: boolean;
|
|
388
425
|
/** Raw child nodes appended to the `<message>` stanza. Escape hatch for protocol features the typed API doesn't cover. */
|
|
389
426
|
readonly customNodes?: readonly BinaryNode[];
|
|
390
427
|
/** Wrap the outgoing message as view-once. Only valid for image/video/audio content. */
|
|
@@ -788,19 +825,26 @@ export interface WaIncomingUnhandledStanzaEvent extends WaIncomingBaseEvent {
|
|
|
788
825
|
readonly reason: string;
|
|
789
826
|
}
|
|
790
827
|
/**
|
|
791
|
-
* Why an incoming message arrived as a content-less placeholder. `view_once`:
|
|
792
|
-
*
|
|
793
|
-
* could not be fanned out. `
|
|
794
|
-
*
|
|
828
|
+
* Why an incoming message arrived as a content-less placeholder. `view_once`: a
|
|
829
|
+
* view-once already consumed elsewhere. `hosted`: a hosted account whose message
|
|
830
|
+
* could not be fanned out. `bot`: a bot message whose fanout never ran. `other`:
|
|
831
|
+
* a plain fanout placeholder – the only kind the primary device resends.
|
|
795
832
|
*/
|
|
796
|
-
export type WaUnavailableMessageKind = 'view_once' | 'hosted' | 'other';
|
|
833
|
+
export type WaUnavailableMessageKind = 'view_once' | 'hosted' | 'bot' | 'other';
|
|
797
834
|
export interface WaIncomingUnavailableMessageEvent extends Omit<WaIncomingBaseEvent, 'chatJid' | 'stanzaId'> {
|
|
798
835
|
/** Which flavour of content the server signalled as unavailable. */
|
|
799
836
|
readonly kind: WaUnavailableMessageKind;
|
|
837
|
+
/**
|
|
838
|
+
* `true` when a resend was queued for the primary device; the payload then
|
|
839
|
+
* arrives as a `message` event with the same key. Best-effort, like wa-web:
|
|
840
|
+
* the request is not persisted, so a failed peer message is not retried.
|
|
841
|
+
* `false` for the unrecoverable flavours, messages past the server age
|
|
842
|
+
* window, and mobile-primary sessions.
|
|
843
|
+
*/
|
|
844
|
+
readonly resendRequested: boolean;
|
|
800
845
|
/**
|
|
801
846
|
* The message key (chat, stanza id, author, addressing metadata) – same
|
|
802
|
-
* shape the `message` event carries, so it can be stored or correlated.
|
|
803
|
-
* is no decrypted `message`: the payload is unavailable and cannot be fetched.
|
|
847
|
+
* shape the `message` event carries, so it can be stored or correlated.
|
|
804
848
|
*/
|
|
805
849
|
readonly key: WaIncomingMessageKey;
|
|
806
850
|
/** Stanza `t` attr (seconds since epoch). */
|
|
@@ -1032,6 +1076,32 @@ export interface WaHistorySyncChunkEvent {
|
|
|
1032
1076
|
/** Server-reported progress, 0–100. */
|
|
1033
1077
|
readonly progress?: number;
|
|
1034
1078
|
}
|
|
1079
|
+
/**
|
|
1080
|
+
* A group-history bundle shared with this account after it joined a group,
|
|
1081
|
+
* already downloaded, filtered and persisted. Emitted once per bundle, only
|
|
1082
|
+
* when `history.groupBundles` is enabled.
|
|
1083
|
+
*/
|
|
1084
|
+
export interface WaGroupHistoryBundleEvent {
|
|
1085
|
+
readonly groupJid: string;
|
|
1086
|
+
/** Member who shared the history. */
|
|
1087
|
+
readonly senderJid?: string;
|
|
1088
|
+
/** Stanza id of the message that carried the bundle. */
|
|
1089
|
+
readonly bundleMessageId?: string;
|
|
1090
|
+
/** Messages persisted from this bundle, after filtering. */
|
|
1091
|
+
readonly messagesCount: number;
|
|
1092
|
+
/** Pinned messages older than the shared window, exempt from the age cutoff. */
|
|
1093
|
+
readonly outOfWindowPinsCount: number;
|
|
1094
|
+
/** Entries skipped as stubs, foreign-chat, ephemeral-expired or too old. */
|
|
1095
|
+
readonly droppedCount: number;
|
|
1096
|
+
/** Oldest persisted message timestamp, in ms. */
|
|
1097
|
+
readonly oldestTimestampMs?: number;
|
|
1098
|
+
/**
|
|
1099
|
+
* Members the sender addressed the bundle to (PN or LID form). Copied out
|
|
1100
|
+
* of the decoded payload, so mutating it cannot corrupt the message proto
|
|
1101
|
+
* the `message` event handed to the same listener.
|
|
1102
|
+
*/
|
|
1103
|
+
readonly historyReceivers: readonly string[];
|
|
1104
|
+
}
|
|
1035
1105
|
export type WaAppStateMutationSource = 'snapshot' | 'patch' | 'local';
|
|
1036
1106
|
type MutationEventBase = {
|
|
1037
1107
|
readonly source: WaAppStateMutationSource;
|
|
@@ -1168,11 +1238,11 @@ export interface WaClientEventMap {
|
|
|
1168
1238
|
*/
|
|
1169
1239
|
readonly message_protocol: (event: WaIncomingProtocolMessageEvent) => void;
|
|
1170
1240
|
/**
|
|
1171
|
-
* A message the server delivered as a content-less placeholder
|
|
1172
|
-
*
|
|
1173
|
-
*
|
|
1174
|
-
*
|
|
1175
|
-
*
|
|
1241
|
+
* A message the server delivered as a content-less placeholder. The lib acks
|
|
1242
|
+
* it and emits this instead of a `message` event for the same stanza. A plain
|
|
1243
|
+
* fanout placeholder is asked back from the primary device and arrives later
|
|
1244
|
+
* as a `message` event (see `event.resendRequested`); a consumed view-once or
|
|
1245
|
+
* a hosted/bot message that could not be fanned out is never resent.
|
|
1176
1246
|
*/
|
|
1177
1247
|
readonly message_unavailable: (event: WaIncomingUnavailableMessageEvent) => void;
|
|
1178
1248
|
/**
|
|
@@ -1205,6 +1275,28 @@ export interface WaClientEventMap {
|
|
|
1205
1275
|
readonly business: (event: WaBusinessEvent) => void;
|
|
1206
1276
|
/** Profile/group/community picture change notification – the new picture must still be fetched explicitly. */
|
|
1207
1277
|
readonly picture: (event: WaPictureEvent) => void;
|
|
1278
|
+
/**
|
|
1279
|
+
* The account's privacy, refetched after the primary or another companion
|
|
1280
|
+
* changed it: the full category set plus any disallowed list the server
|
|
1281
|
+
* reported. The two halves are read by separate queries, so a change
|
|
1282
|
+
* landing mid-refresh can leave them describing slightly different server
|
|
1283
|
+
* states - the payload is exactly what
|
|
1284
|
+
* {@link WaPrivacyCoordinator.refreshFromAccountSync} returns.
|
|
1285
|
+
*
|
|
1286
|
+
* Two paths trigger it: the live `account_sync` notification (debounced,
|
|
1287
|
+
* so a burst of changes on the phone collapses into one refresh) and the
|
|
1288
|
+
* `account_sync` dirty bit that catches a session up after being offline.
|
|
1289
|
+
* Neither is trusted for its payload - the values always come from a
|
|
1290
|
+
* fresh read. Categories the library does not model are dropped.
|
|
1291
|
+
*/
|
|
1292
|
+
readonly privacy: (event: WaPrivacyAccountSyncResult) => void;
|
|
1293
|
+
/**
|
|
1294
|
+
* The account blocklist after a block/unblock made on another device -
|
|
1295
|
+
* same refetch path as `privacy`, from its own account-sync protocol. The
|
|
1296
|
+
* payload is the full list ({@link WaPrivacyCoordinator.getBlocklist}'s
|
|
1297
|
+
* shape), never a delta.
|
|
1298
|
+
*/
|
|
1299
|
+
readonly blocklist: (event: WaBlocklistResult) => void;
|
|
1208
1300
|
/**
|
|
1209
1301
|
* A parsed app-state mutation arriving from a sync – chat mute/star/read/
|
|
1210
1302
|
* pin/archive/contact/label/etc. changed on another device. Inbound only;
|
|
@@ -1228,12 +1320,24 @@ export interface WaClientEventMap {
|
|
|
1228
1320
|
* Skipped only when `history.enabled` is explicitly `false`.
|
|
1229
1321
|
*/
|
|
1230
1322
|
readonly history_sync_chunk: (event: WaHistorySyncChunkEvent) => void;
|
|
1323
|
+
/**
|
|
1324
|
+
* A group-history bundle another member shared with this account after it
|
|
1325
|
+
* joined a group, already downloaded and persisted. Requires
|
|
1326
|
+
* `history.groupBundles: true` - the download is opt-in because a third
|
|
1327
|
+
* party triggers it.
|
|
1328
|
+
*/
|
|
1329
|
+
readonly group_history_bundle: (event: WaGroupHistoryBundleEvent) => void;
|
|
1231
1330
|
/**
|
|
1232
1331
|
* Offline-message queue progress after a reconnect (`'resuming'` ticks
|
|
1233
1332
|
* with `remainingStanzas`, then `'complete'`). Useful to defer UI updates
|
|
1234
1333
|
* until the catch-up finishes.
|
|
1235
1334
|
*/
|
|
1236
1335
|
readonly offline_resume: (event: WaOfflineResumeEvent) => void;
|
|
1336
|
+
/**
|
|
1337
|
+
* Preview manifest of the offline queue, sent just before the flush. Not
|
|
1338
|
+
* guaranteed to arrive - use `offline_resume` for progress, never this.
|
|
1339
|
+
*/
|
|
1340
|
+
readonly offline_thread_metadata: (event: WaOfflineThreadMetadataEvent) => void;
|
|
1237
1341
|
/**
|
|
1238
1342
|
* Fatal stream-level error from the server (e.g. logged out from another
|
|
1239
1343
|
* device, stream conflict). The connection will close right after.
|
|
@@ -1314,6 +1418,36 @@ export interface WaOfflineResumeEvent {
|
|
|
1314
1418
|
/** `true` when triggered by an explicit catch-up request rather than auto-resume on reconnect. */
|
|
1315
1419
|
readonly forced: boolean;
|
|
1316
1420
|
}
|
|
1421
|
+
export interface WaOfflineThreadPreview {
|
|
1422
|
+
/** User (`@lid`/`@s.whatsapp.net`) or group (`@g.us`) jid. */
|
|
1423
|
+
readonly jid: string;
|
|
1424
|
+
/** Unix seconds of the most recent queued stanza for this thread. */
|
|
1425
|
+
readonly timestampSeconds: number;
|
|
1426
|
+
}
|
|
1427
|
+
export interface WaOfflineThreadReadWatermark {
|
|
1428
|
+
readonly jid: string;
|
|
1429
|
+
/** Unix seconds up to which the peer has already read this thread. */
|
|
1430
|
+
readonly readTimestampSeconds: number;
|
|
1431
|
+
}
|
|
1432
|
+
/**
|
|
1433
|
+
* Which threads have queued traffic, announced right before the offline flush.
|
|
1434
|
+
* Informational only - every listed thread still delivers its stanzas
|
|
1435
|
+
* normally. All fields but `threads` depend on server gating and are commonly
|
|
1436
|
+
* absent.
|
|
1437
|
+
*/
|
|
1438
|
+
export interface WaOfflineThreadMetadataEvent {
|
|
1439
|
+
readonly threads: readonly WaOfflineThreadPreview[];
|
|
1440
|
+
readonly readWatermarks?: readonly WaOfflineThreadReadWatermark[];
|
|
1441
|
+
/** Status-update backlog still queued behind this flush. */
|
|
1442
|
+
readonly pendingStatusMessages?: {
|
|
1443
|
+
readonly count: number;
|
|
1444
|
+
readonly jids: readonly string[];
|
|
1445
|
+
};
|
|
1446
|
+
/** Notification backlog still queued behind this flush. */
|
|
1447
|
+
readonly pendingNotifications?: {
|
|
1448
|
+
readonly count: number;
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1317
1451
|
export interface WaPrivacyTokenUpdateEvent {
|
|
1318
1452
|
/** Peer whose trusted-contact-token (TC token) changed. */
|
|
1319
1453
|
readonly jid: string;
|
|
@@ -7,5 +7,5 @@ export { hkdf, hkdfSplit } from '../core/hkdf';
|
|
|
7
7
|
export { toSerializedPubKey, toRawPubKey, prependVersion, readVersionedContent } from '../core/keys';
|
|
8
8
|
export { writeNonceCounter } from '../core/nonce';
|
|
9
9
|
export { randomBytesAsync, randomFillAsync, randomIntAsync } from '../core/random';
|
|
10
|
-
export { sha1, sha256, sha512, md5Bytes, aesGcmEncrypt, aesGcmDecrypt, aesCbcEncrypt, aesCbcDecrypt, aesCtrEncrypt, aesCtrDecrypt, hmacSha256Sign, hmacSha512Sign, pbkdf2Sha256 } from '../core/primitives';
|
|
10
|
+
export { sha1, sha256, sha512, md5Bytes, aesGcmEncrypt, aesGcmDecrypt, aesCbcEncrypt, aesCbcEncryptWithTrailer, aesCbcDecrypt, aesCtrEncrypt, aesCtrDecrypt, hmacSha256Sign, hmacSha512Sign, pbkdf2Sha256 } from '../core/primitives';
|
|
11
11
|
export { xeddsaSign, xeddsaVerify } from '../core/xeddsa';
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Cryptographic utilities
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.xeddsaVerify = exports.xeddsaSign = exports.pbkdf2Sha256 = exports.hmacSha512Sign = exports.hmacSha256Sign = exports.aesCtrDecrypt = exports.aesCtrEncrypt = exports.aesCbcDecrypt = exports.aesCbcEncrypt = exports.aesGcmDecrypt = exports.aesGcmEncrypt = exports.md5Bytes = exports.sha512 = exports.sha256 = exports.sha1 = exports.randomIntAsync = exports.randomFillAsync = exports.randomBytesAsync = exports.writeNonceCounter = exports.readVersionedContent = exports.prependVersion = exports.toRawPubKey = exports.toSerializedPubKey = exports.hkdfSplit = exports.hkdf = exports.X25519 = exports.Ed25519 = void 0;
|
|
6
|
+
exports.xeddsaVerify = exports.xeddsaSign = exports.pbkdf2Sha256 = exports.hmacSha512Sign = exports.hmacSha256Sign = exports.aesCtrDecrypt = exports.aesCtrEncrypt = exports.aesCbcDecrypt = exports.aesCbcEncryptWithTrailer = exports.aesCbcEncrypt = exports.aesGcmDecrypt = exports.aesGcmEncrypt = exports.md5Bytes = exports.sha512 = exports.sha256 = exports.sha1 = exports.randomIntAsync = exports.randomFillAsync = exports.randomBytesAsync = exports.writeNonceCounter = exports.readVersionedContent = exports.prependVersion = exports.toRawPubKey = exports.toSerializedPubKey = exports.hkdfSplit = exports.hkdf = exports.X25519 = exports.Ed25519 = void 0;
|
|
7
7
|
var Ed25519_1 = require("../curves/Ed25519");
|
|
8
8
|
Object.defineProperty(exports, "Ed25519", { enumerable: true, get: function () { return Ed25519_1.Ed25519; } });
|
|
9
9
|
var X25519_1 = require("../curves/X25519");
|
|
@@ -30,6 +30,7 @@ Object.defineProperty(exports, "md5Bytes", { enumerable: true, get: function ()
|
|
|
30
30
|
Object.defineProperty(exports, "aesGcmEncrypt", { enumerable: true, get: function () { return primitives_1.aesGcmEncrypt; } });
|
|
31
31
|
Object.defineProperty(exports, "aesGcmDecrypt", { enumerable: true, get: function () { return primitives_1.aesGcmDecrypt; } });
|
|
32
32
|
Object.defineProperty(exports, "aesCbcEncrypt", { enumerable: true, get: function () { return primitives_1.aesCbcEncrypt; } });
|
|
33
|
+
Object.defineProperty(exports, "aesCbcEncryptWithTrailer", { enumerable: true, get: function () { return primitives_1.aesCbcEncryptWithTrailer; } });
|
|
33
34
|
Object.defineProperty(exports, "aesCbcDecrypt", { enumerable: true, get: function () { return primitives_1.aesCbcDecrypt; } });
|
|
34
35
|
Object.defineProperty(exports, "aesCtrEncrypt", { enumerable: true, get: function () { return primitives_1.aesCtrEncrypt; } });
|
|
35
36
|
Object.defineProperty(exports, "aesCtrDecrypt", { enumerable: true, get: function () { return primitives_1.aesCtrDecrypt; } });
|