@d0v3riz/baileys 7.0.0-rc.8 → 7.0.0-rc13
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 +21 -15
- package/WAProto/fix-imports.js +74 -18
- package/WAProto/index.js +201 -160
- package/lib/Defaults/index.d.ts +19 -6
- package/lib/Defaults/index.d.ts.map +1 -1
- package/lib/Defaults/index.js +24 -10
- package/lib/Defaults/index.js.map +1 -1
- package/lib/Signal/libsignal.d.ts.map +1 -1
- package/lib/Signal/libsignal.js +105 -16
- package/lib/Signal/libsignal.js.map +1 -1
- package/lib/Signal/lid-mapping.d.ts +8 -8
- package/lib/Signal/lid-mapping.d.ts.map +1 -1
- package/lib/Signal/lid-mapping.js +176 -70
- package/lib/Signal/lid-mapping.js.map +1 -1
- package/lib/Socket/Client/websocket.d.ts +1 -1
- package/lib/Socket/Client/websocket.d.ts.map +1 -1
- package/lib/Socket/Client/websocket.js +5 -1
- package/lib/Socket/Client/websocket.js.map +1 -1
- package/lib/Socket/business.d.ts +36 -8
- package/lib/Socket/business.d.ts.map +1 -1
- package/lib/Socket/business.js +11 -8
- package/lib/Socket/business.js.map +1 -1
- package/lib/Socket/chats.d.ts +29 -5
- package/lib/Socket/chats.d.ts.map +1 -1
- package/lib/Socket/chats.js +292 -63
- package/lib/Socket/chats.js.map +1 -1
- package/lib/Socket/communities.d.ts +36 -8
- package/lib/Socket/communities.d.ts.map +1 -1
- package/lib/Socket/groups.d.ts +27 -5
- package/lib/Socket/groups.d.ts.map +1 -1
- package/lib/Socket/groups.js +20 -0
- package/lib/Socket/groups.js.map +1 -1
- package/lib/Socket/index.d.ts +36 -8
- package/lib/Socket/index.d.ts.map +1 -1
- package/lib/Socket/index.js +0 -6
- package/lib/Socket/index.js.map +1 -1
- package/lib/Socket/messages-recv.d.ts +40 -11
- package/lib/Socket/messages-recv.d.ts.map +1 -1
- package/lib/Socket/messages-recv.js +841 -354
- package/lib/Socket/messages-recv.js.map +1 -1
- package/lib/Socket/messages-send.d.ts +35 -6
- package/lib/Socket/messages-send.d.ts.map +1 -1
- package/lib/Socket/messages-send.js +263 -92
- package/lib/Socket/messages-send.js.map +1 -1
- package/lib/Socket/mex.d.ts.map +1 -1
- package/lib/Socket/mex.js +2 -0
- package/lib/Socket/mex.js.map +1 -1
- package/lib/Socket/newsletter.d.ts +27 -5
- package/lib/Socket/newsletter.d.ts.map +1 -1
- package/lib/Socket/newsletter.js +35 -3
- package/lib/Socket/newsletter.js.map +1 -1
- package/lib/Socket/socket.d.ts +9 -3
- package/lib/Socket/socket.d.ts.map +1 -1
- package/lib/Socket/socket.js +124 -39
- package/lib/Socket/socket.js.map +1 -1
- package/lib/Types/Auth.d.ts +2 -0
- package/lib/Types/Auth.d.ts.map +1 -1
- package/lib/Types/Call.d.ts +2 -1
- package/lib/Types/Call.d.ts.map +1 -1
- package/lib/Types/Chat.d.ts +1 -0
- package/lib/Types/Chat.d.ts.map +1 -1
- package/lib/Types/Contact.d.ts +2 -0
- package/lib/Types/Contact.d.ts.map +1 -1
- package/lib/Types/Events.d.ts +60 -6
- package/lib/Types/Events.d.ts.map +1 -1
- package/lib/Types/GroupMetadata.d.ts +4 -0
- package/lib/Types/GroupMetadata.d.ts.map +1 -1
- package/lib/Types/Message.d.ts +20 -5
- package/lib/Types/Message.d.ts.map +1 -1
- package/lib/Types/Message.js.map +1 -1
- package/lib/Types/{Newsletter.d.ts → Mex.d.ts} +13 -5
- package/lib/Types/Mex.d.ts.map +1 -0
- package/lib/Types/{Newsletter.js → Mex.js} +11 -3
- package/lib/Types/Mex.js.map +1 -0
- package/lib/Types/Signal.d.ts +12 -1
- package/lib/Types/Signal.d.ts.map +1 -1
- package/lib/Types/Socket.d.ts +3 -0
- package/lib/Types/Socket.d.ts.map +1 -1
- package/lib/Types/State.d.ts +58 -0
- package/lib/Types/State.d.ts.map +1 -1
- package/lib/Types/State.js +43 -0
- package/lib/Types/State.js.map +1 -1
- package/lib/Types/index.d.ts +1 -1
- package/lib/Types/index.d.ts.map +1 -1
- package/lib/Types/index.js +1 -1
- package/lib/Types/index.js.map +1 -1
- package/lib/Utils/auth-utils.d.ts +5 -0
- package/lib/Utils/auth-utils.d.ts.map +1 -1
- package/lib/Utils/auth-utils.js +65 -20
- package/lib/Utils/auth-utils.js.map +1 -1
- package/lib/Utils/chat-utils.d.ts +31 -1
- package/lib/Utils/chat-utils.d.ts.map +1 -1
- package/lib/Utils/chat-utils.js +180 -71
- package/lib/Utils/chat-utils.js.map +1 -1
- package/lib/Utils/companion-reg-client-utils.d.ts +17 -0
- package/lib/Utils/companion-reg-client-utils.d.ts.map +1 -0
- package/lib/Utils/companion-reg-client-utils.js +35 -0
- package/lib/Utils/companion-reg-client-utils.js.map +1 -0
- package/lib/Utils/crypto.d.ts +4 -8
- package/lib/Utils/crypto.d.ts.map +1 -1
- package/lib/Utils/crypto.js +2 -26
- package/lib/Utils/crypto.js.map +1 -1
- package/lib/Utils/decode-wa-message.d.ts +18 -0
- package/lib/Utils/decode-wa-message.d.ts.map +1 -1
- package/lib/Utils/decode-wa-message.js +34 -0
- package/lib/Utils/decode-wa-message.js.map +1 -1
- package/lib/Utils/event-buffer.d.ts +2 -0
- package/lib/Utils/event-buffer.d.ts.map +1 -1
- package/lib/Utils/event-buffer.js +82 -8
- package/lib/Utils/event-buffer.js.map +1 -1
- package/lib/Utils/generics.d.ts +2 -0
- package/lib/Utils/generics.d.ts.map +1 -1
- package/lib/Utils/generics.js +13 -1
- package/lib/Utils/generics.js.map +1 -1
- package/lib/Utils/history.d.ts +8 -3
- package/lib/Utils/history.d.ts.map +1 -1
- package/lib/Utils/history.js +58 -14
- package/lib/Utils/history.js.map +1 -1
- package/lib/Utils/identity-change-handler.d.ts +44 -0
- package/lib/Utils/identity-change-handler.d.ts.map +1 -0
- package/lib/Utils/identity-change-handler.js +50 -0
- package/lib/Utils/identity-change-handler.js.map +1 -0
- package/lib/Utils/index.d.ts +3 -0
- package/lib/Utils/index.d.ts.map +1 -1
- package/lib/Utils/index.js +3 -0
- package/lib/Utils/index.js.map +1 -1
- package/lib/Utils/link-preview.js +2 -2
- package/lib/Utils/link-preview.js.map +1 -1
- package/lib/Utils/lt-hash.d.ts +7 -12
- package/lib/Utils/lt-hash.d.ts.map +1 -1
- package/lib/Utils/lt-hash.js +2 -42
- package/lib/Utils/lt-hash.js.map +1 -1
- package/lib/Utils/make-mutex.d.ts +1 -0
- package/lib/Utils/make-mutex.d.ts.map +1 -1
- package/lib/Utils/make-mutex.js +20 -27
- package/lib/Utils/make-mutex.js.map +1 -1
- package/lib/Utils/message-retry-manager.d.ts +35 -2
- package/lib/Utils/message-retry-manager.d.ts.map +1 -1
- package/lib/Utils/message-retry-manager.js +98 -5
- package/lib/Utils/message-retry-manager.js.map +1 -1
- package/lib/Utils/messages-media.d.ts +22 -3
- package/lib/Utils/messages-media.d.ts.map +1 -1
- package/lib/Utils/messages-media.js +169 -44
- package/lib/Utils/messages-media.js.map +1 -1
- package/lib/Utils/messages.d.ts +2 -0
- package/lib/Utils/messages.d.ts.map +1 -1
- package/lib/Utils/messages.js +70 -27
- package/lib/Utils/messages.js.map +1 -1
- package/lib/Utils/noise-handler.d.ts +4 -4
- package/lib/Utils/noise-handler.d.ts.map +1 -1
- package/lib/Utils/noise-handler.js +139 -85
- package/lib/Utils/noise-handler.js.map +1 -1
- package/lib/Utils/offline-node-processor.d.ts +17 -0
- package/lib/Utils/offline-node-processor.d.ts.map +1 -0
- package/lib/Utils/offline-node-processor.js +40 -0
- package/lib/Utils/offline-node-processor.js.map +1 -0
- package/lib/Utils/process-message.d.ts.map +1 -1
- package/lib/Utils/process-message.js +165 -15
- package/lib/Utils/process-message.js.map +1 -1
- package/lib/Utils/reporting-utils.d.ts +11 -0
- package/lib/Utils/reporting-utils.d.ts.map +1 -0
- package/lib/Utils/reporting-utils.js +258 -0
- package/lib/Utils/reporting-utils.js.map +1 -0
- package/lib/Utils/signal.d.ts +13 -0
- package/lib/Utils/signal.d.ts.map +1 -1
- package/lib/Utils/signal.js +42 -0
- package/lib/Utils/signal.js.map +1 -1
- package/lib/Utils/stanza-ack.d.ts +11 -0
- package/lib/Utils/stanza-ack.d.ts.map +1 -0
- package/lib/Utils/stanza-ack.js +38 -0
- package/lib/Utils/stanza-ack.js.map +1 -0
- package/lib/Utils/sync-action-utils.d.ts +19 -0
- package/lib/Utils/sync-action-utils.d.ts.map +1 -0
- package/lib/Utils/sync-action-utils.js +49 -0
- package/lib/Utils/sync-action-utils.js.map +1 -0
- package/lib/Utils/tc-token-utils.d.ts +37 -0
- package/lib/Utils/tc-token-utils.d.ts.map +1 -0
- package/lib/Utils/tc-token-utils.js +163 -0
- package/lib/Utils/tc-token-utils.js.map +1 -0
- package/lib/Utils/validate-connection.d.ts.map +1 -1
- package/lib/Utils/validate-connection.js +4 -1
- package/lib/Utils/validate-connection.js.map +1 -1
- package/lib/WABinary/decode.d.ts.map +1 -1
- package/lib/WABinary/decode.js +24 -0
- package/lib/WABinary/decode.js.map +1 -1
- package/lib/WABinary/encode.js +5 -1
- package/lib/WABinary/encode.js.map +1 -1
- package/lib/WABinary/generic-utils.d.ts +1 -1
- package/lib/WABinary/generic-utils.d.ts.map +1 -1
- package/lib/WABinary/generic-utils.js +19 -8
- package/lib/WABinary/generic-utils.js.map +1 -1
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +1 -1
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +26 -3
- package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +1 -1
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +10 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/index.d.ts +1 -0
- package/lib/WAUSync/Protocols/index.d.ts.map +1 -1
- package/lib/WAUSync/Protocols/index.js +1 -0
- package/lib/WAUSync/Protocols/index.js.map +1 -1
- package/lib/WAUSync/USyncQuery.d.ts +1 -0
- package/lib/WAUSync/USyncQuery.d.ts.map +1 -1
- package/lib/WAUSync/USyncQuery.js +6 -2
- package/lib/WAUSync/USyncQuery.js.map +1 -1
- package/lib/WAUSync/USyncUser.d.ts +4 -0
- package/lib/WAUSync/USyncUser.d.ts.map +1 -1
- package/lib/WAUSync/USyncUser.js +8 -0
- package/lib/WAUSync/USyncUser.js.map +1 -1
- package/package.json +39 -8
- package/lib/Types/Newsletter.d.ts.map +0 -1
- package/lib/Types/Newsletter.js.map +0 -1
package/lib/Socket/chats.js
CHANGED
|
@@ -1,34 +1,56 @@
|
|
|
1
1
|
import NodeCache from '@cacheable/node-cache';
|
|
2
2
|
import { Boom } from '@hapi/boom';
|
|
3
3
|
import { proto } from '../../WAProto/index.js';
|
|
4
|
-
import { DEFAULT_CACHE_TTLS, PROCESSABLE_HISTORY_TYPES } from '../Defaults/index.js';
|
|
4
|
+
import { DEFAULT_CACHE_TTLS, HISTORY_SYNC_PAUSED_TIMEOUT_MS, PROCESSABLE_HISTORY_TYPES } from '../Defaults/index.js';
|
|
5
5
|
import { ALL_WA_PATCH_NAMES } from '../Types/index.js';
|
|
6
6
|
import { SyncState } from '../Types/State.js';
|
|
7
|
-
import { chatModificationToAppPatch, decodePatches, decodeSyncdSnapshot, encodeSyncdPatch, extractSyncdPatches, generateProfilePicture, getHistoryMsg, newLTHashState, processSyncAction } from '../Utils/index.js';
|
|
7
|
+
import { chatModificationToAppPatch, decodePatches, decodeSyncdSnapshot, encodeSyncdPatch, ensureLTHashStateVersion, extractSyncdPatches, generateProfilePicture, getHistoryMsg, isAppStateSyncIrrecoverable, isMissingKeyError, MAX_SYNC_ATTEMPTS, newLTHashState, processSyncAction } from '../Utils/index.js';
|
|
8
8
|
import { makeMutex } from '../Utils/make-mutex.js';
|
|
9
9
|
import processMessage from '../Utils/process-message.js';
|
|
10
|
-
import {
|
|
10
|
+
import { buildTcTokenFromJid } from '../Utils/tc-token-utils.js';
|
|
11
|
+
import { getBinaryNodeChild, getBinaryNodeChildren, isHostedLidUser, isHostedPnUser, isLidUser, isPnUser, jidDecode, jidNormalizedUser, reduceBinaryNodeToDictionary, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
11
12
|
import { USyncQuery, USyncUser } from '../WAUSync/index.js';
|
|
12
13
|
import { makeSocket } from './socket.js';
|
|
13
|
-
const MAX_SYNC_ATTEMPTS = 2;
|
|
14
14
|
export const makeChatsSocket = (config) => {
|
|
15
15
|
const { logger, markOnlineOnConnect, fireInitQueries, appStateMacVerification, shouldIgnoreJid, shouldSyncHistoryMessage, getMessage } = config;
|
|
16
16
|
const sock = makeSocket(config);
|
|
17
|
-
const { ev, ws, authState, generateMessageTag, sendNode, query, signalRepository, onUnexpectedError } = sock;
|
|
17
|
+
const { ev, ws, authState, generateMessageTag, sendNode, query, signalRepository, onUnexpectedError, sendUnifiedSession, registerSocketEndHandler } = sock;
|
|
18
|
+
const getLIDForPN = signalRepository.lidMapping.getLIDForPN.bind(signalRepository.lidMapping);
|
|
18
19
|
let privacySettings;
|
|
20
|
+
/** Server-assigned AB props for protocol behavior. */
|
|
21
|
+
const serverProps = {
|
|
22
|
+
/** AB prop 10518: gate tctoken on 1:1 messages. Default true (safe: avoids 463). */
|
|
23
|
+
privacyTokenOn1to1: true,
|
|
24
|
+
/** AB prop 9666: gate tctoken on profile picture IQs. WA Web default: true. */
|
|
25
|
+
profilePicPrivacyToken: true,
|
|
26
|
+
/** AB prop 14303: issue tctokens to LID instead of PN. WA Web default: false. */
|
|
27
|
+
lidTrustedTokenIssueToLid: false
|
|
28
|
+
};
|
|
19
29
|
let syncState = SyncState.Connecting;
|
|
20
|
-
/** this mutex ensures that
|
|
21
|
-
const
|
|
30
|
+
/** this mutex ensures that messages are processed in order */
|
|
31
|
+
const messageMutex = makeMutex();
|
|
32
|
+
/** this mutex ensures that receipts are processed in order */
|
|
33
|
+
const receiptMutex = makeMutex();
|
|
34
|
+
/** this mutex ensures that app state patches are processed in order */
|
|
35
|
+
const appStatePatchMutex = makeMutex();
|
|
36
|
+
/** this mutex ensures that notifications are processed in order */
|
|
37
|
+
const notificationMutex = makeMutex();
|
|
22
38
|
// Timeout for AwaitingInitialSync state
|
|
23
39
|
let awaitingSyncTimeout;
|
|
40
|
+
// In-memory history sync completion tracking (resets on reconnection)
|
|
41
|
+
const historySyncStatus = {
|
|
42
|
+
initialBootstrapComplete: false,
|
|
43
|
+
recentSyncComplete: false
|
|
44
|
+
};
|
|
45
|
+
let historySyncPausedTimeout;
|
|
46
|
+
// Collections blocked on missing app state sync keys (mirrors WA Web's "Blocked" state).
|
|
47
|
+
// When a key arrives via APP_STATE_SYNC_KEY_SHARE, these are re-synced.
|
|
48
|
+
const blockedCollections = new Set();
|
|
24
49
|
const placeholderResendCache = config.placeholderResendCache ||
|
|
25
50
|
new NodeCache({
|
|
26
51
|
stdTTL: DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
|
|
27
52
|
useClones: false
|
|
28
53
|
});
|
|
29
|
-
if (!config.placeholderResendCache) {
|
|
30
|
-
config.placeholderResendCache = placeholderResendCache;
|
|
31
|
-
}
|
|
32
54
|
/** helper function to fetch the given app state sync key */
|
|
33
55
|
const getAppStateSyncKey = async (keyId) => {
|
|
34
56
|
const { [keyId]: key } = await authState.keys.get('app-state-sync-key', [keyId]);
|
|
@@ -251,6 +273,42 @@ export const makeChatsSocket = (config) => {
|
|
|
251
273
|
return getBinaryNodeChildren(listNode, 'item').map(n => n.attrs.jid);
|
|
252
274
|
};
|
|
253
275
|
const updateBlockStatus = async (jid, action) => {
|
|
276
|
+
const normalizedJid = jidNormalizedUser(jid);
|
|
277
|
+
let lid;
|
|
278
|
+
let pn_jid;
|
|
279
|
+
if (isLidUser(normalizedJid) || isHostedLidUser(normalizedJid)) {
|
|
280
|
+
lid = normalizedJid;
|
|
281
|
+
if (action === 'block') {
|
|
282
|
+
const pn = await signalRepository.lidMapping.getPNForLID(normalizedJid);
|
|
283
|
+
if (!pn) {
|
|
284
|
+
throw new Boom(`Unable to resolve PN JID for LID: ${jid}`, { statusCode: 400 });
|
|
285
|
+
}
|
|
286
|
+
pn_jid = jidNormalizedUser(pn);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
else if (isPnUser(normalizedJid) || isHostedPnUser(normalizedJid)) {
|
|
290
|
+
const mapped = await signalRepository.lidMapping.getLIDForPN(normalizedJid);
|
|
291
|
+
if (!mapped) {
|
|
292
|
+
throw new Boom(`Unable to resolve LID for PN JID: ${jid}`, { statusCode: 400 });
|
|
293
|
+
}
|
|
294
|
+
lid = mapped;
|
|
295
|
+
if (action === 'block') {
|
|
296
|
+
pn_jid = jidNormalizedUser(normalizedJid);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
throw new Boom(`Invalid jid: ${jid}`, { statusCode: 400 });
|
|
301
|
+
}
|
|
302
|
+
const itemAttrs = {
|
|
303
|
+
action,
|
|
304
|
+
jid: lid
|
|
305
|
+
};
|
|
306
|
+
if (action === 'block') {
|
|
307
|
+
if (!pn_jid) {
|
|
308
|
+
throw new Boom(`pn_jid required for block: ${jid}`, { statusCode: 400 });
|
|
309
|
+
}
|
|
310
|
+
itemAttrs.pn_jid = pn_jid;
|
|
311
|
+
}
|
|
254
312
|
await query({
|
|
255
313
|
tag: 'iq',
|
|
256
314
|
attrs: {
|
|
@@ -261,10 +319,7 @@ export const makeChatsSocket = (config) => {
|
|
|
261
319
|
content: [
|
|
262
320
|
{
|
|
263
321
|
tag: 'item',
|
|
264
|
-
attrs:
|
|
265
|
-
action,
|
|
266
|
-
jid
|
|
267
|
-
}
|
|
322
|
+
attrs: itemAttrs
|
|
268
323
|
}
|
|
269
324
|
]
|
|
270
325
|
});
|
|
@@ -346,6 +401,15 @@ export const makeChatsSocket = (config) => {
|
|
|
346
401
|
};
|
|
347
402
|
};
|
|
348
403
|
const resyncAppState = ev.createBufferedFunction(async (collections, isInitialSync) => {
|
|
404
|
+
const appStateSyncKeyCache = new Map();
|
|
405
|
+
const getCachedAppStateSyncKey = async (keyId) => {
|
|
406
|
+
if (appStateSyncKeyCache.has(keyId)) {
|
|
407
|
+
return appStateSyncKeyCache.get(keyId) ?? undefined;
|
|
408
|
+
}
|
|
409
|
+
const key = await getAppStateSyncKey(keyId);
|
|
410
|
+
appStateSyncKeyCache.set(keyId, key ?? null);
|
|
411
|
+
return key;
|
|
412
|
+
};
|
|
349
413
|
// we use this to determine which events to fire
|
|
350
414
|
// otherwise when we resync from scratch -- all notifications will fire
|
|
351
415
|
const initialVersionMap = {};
|
|
@@ -354,6 +418,9 @@ export const makeChatsSocket = (config) => {
|
|
|
354
418
|
const collectionsToHandle = new Set(collections);
|
|
355
419
|
// in case something goes wrong -- ensure we don't enter a loop that cannot be exited from
|
|
356
420
|
const attemptsMap = {};
|
|
421
|
+
// collections that failed and need a full snapshot on retry
|
|
422
|
+
// mirrors WA Web's ErrorFatal -> force snapshot behavior
|
|
423
|
+
const forceSnapshotCollections = new Set();
|
|
357
424
|
// keep executing till all collections are done
|
|
358
425
|
// sometimes a single patch request will not return all the patches (God knows why)
|
|
359
426
|
// so we fetch till they're all done (this is determined by the "has_more_patches" flag)
|
|
@@ -364,6 +431,7 @@ export const makeChatsSocket = (config) => {
|
|
|
364
431
|
const result = await authState.keys.get('app-state-sync-version', [name]);
|
|
365
432
|
let state = result[name];
|
|
366
433
|
if (state) {
|
|
434
|
+
state = ensureLTHashStateVersion(state);
|
|
367
435
|
if (typeof initialVersionMap[name] === 'undefined') {
|
|
368
436
|
initialVersionMap[name] = state.version;
|
|
369
437
|
}
|
|
@@ -372,14 +440,18 @@ export const makeChatsSocket = (config) => {
|
|
|
372
440
|
state = newLTHashState();
|
|
373
441
|
}
|
|
374
442
|
states[name] = state;
|
|
375
|
-
|
|
443
|
+
const shouldForceSnapshot = forceSnapshotCollections.has(name);
|
|
444
|
+
if (shouldForceSnapshot) {
|
|
445
|
+
forceSnapshotCollections.delete(name);
|
|
446
|
+
}
|
|
447
|
+
logger.info(`resyncing ${name} from v${state.version}${shouldForceSnapshot ? ' (forcing snapshot)' : ''}`);
|
|
376
448
|
nodes.push({
|
|
377
449
|
tag: 'collection',
|
|
378
450
|
attrs: {
|
|
379
451
|
name,
|
|
380
452
|
version: state.version.toString(),
|
|
381
|
-
// return snapshot if
|
|
382
|
-
return_snapshot: (!state.version).toString()
|
|
453
|
+
// return snapshot if syncing from scratch or forcing after a failed attempt
|
|
454
|
+
return_snapshot: (shouldForceSnapshot || !state.version).toString()
|
|
383
455
|
}
|
|
384
456
|
});
|
|
385
457
|
}
|
|
@@ -405,7 +477,7 @@ export const makeChatsSocket = (config) => {
|
|
|
405
477
|
const { patches, hasMorePatches, snapshot } = decoded[name];
|
|
406
478
|
try {
|
|
407
479
|
if (snapshot) {
|
|
408
|
-
const { state: newState, mutationMap } = await decodeSyncdSnapshot(name, snapshot,
|
|
480
|
+
const { state: newState, mutationMap } = await decodeSyncdSnapshot(name, snapshot, getCachedAppStateSyncKey, initialVersionMap[name], appStateMacVerification.snapshot, logger);
|
|
409
481
|
states[name] = newState;
|
|
410
482
|
Object.assign(globalMutationMap, mutationMap);
|
|
411
483
|
logger.info(`restored state of ${name} from snapshot to v${newState.version} with mutations`);
|
|
@@ -413,7 +485,7 @@ export const makeChatsSocket = (config) => {
|
|
|
413
485
|
}
|
|
414
486
|
// only process if there are syncd patches
|
|
415
487
|
if (patches.length) {
|
|
416
|
-
const { state: newState, mutationMap } = await decodePatches(name, patches, states[name],
|
|
488
|
+
const { state: newState, mutationMap } = await decodePatches(name, patches, states[name], getCachedAppStateSyncKey, config.options, initialVersionMap[name], logger, appStateMacVerification.patch);
|
|
417
489
|
await authState.keys.set({ 'app-state-sync-version': { [name]: newState } });
|
|
418
490
|
logger.info(`synced ${name} to v${newState.version}`);
|
|
419
491
|
initialVersionMap[name] = newState.version;
|
|
@@ -428,19 +500,37 @@ export const makeChatsSocket = (config) => {
|
|
|
428
500
|
}
|
|
429
501
|
}
|
|
430
502
|
catch (error) {
|
|
431
|
-
// if retry attempts overshoot
|
|
432
|
-
// or key not found
|
|
433
|
-
const isIrrecoverableError = attemptsMap[name] >= MAX_SYNC_ATTEMPTS ||
|
|
434
|
-
error.output?.statusCode === 404 ||
|
|
435
|
-
error.name === 'TypeError';
|
|
436
|
-
logger.info({ name, error: error.stack }, `failed to sync state from version${isIrrecoverableError ? '' : ', removing and trying from scratch'}`);
|
|
437
|
-
await authState.keys.set({ 'app-state-sync-version': { [name]: null } });
|
|
438
|
-
// increment number of retries
|
|
439
503
|
attemptsMap[name] = (attemptsMap[name] || 0) + 1;
|
|
440
|
-
|
|
441
|
-
|
|
504
|
+
const logData = {
|
|
505
|
+
name,
|
|
506
|
+
attempt: attemptsMap[name],
|
|
507
|
+
version: states[name].version,
|
|
508
|
+
statusCode: error.output?.statusCode,
|
|
509
|
+
errorType: error.name,
|
|
510
|
+
error: error.stack
|
|
511
|
+
};
|
|
512
|
+
if (isMissingKeyError(error) && attemptsMap[name] >= MAX_SYNC_ATTEMPTS) {
|
|
513
|
+
// WA Web treats missing keys as "Blocked" — park the collection
|
|
514
|
+
// until the key arrives via APP_STATE_SYNC_KEY_SHARE.
|
|
515
|
+
logger.warn(logData, `${name} blocked on missing key from v${states[name].version}, parking after ${attemptsMap[name]} attempts`);
|
|
516
|
+
blockedCollections.add(name);
|
|
517
|
+
collectionsToHandle.delete(name);
|
|
518
|
+
}
|
|
519
|
+
else if (isMissingKeyError(error)) {
|
|
520
|
+
// Retry with a snapshot which may use a different key.
|
|
521
|
+
logger.info(logData, `${name} blocked on missing key from v${states[name].version}, retrying with snapshot`);
|
|
522
|
+
forceSnapshotCollections.add(name);
|
|
523
|
+
}
|
|
524
|
+
else if (isAppStateSyncIrrecoverable(error, attemptsMap[name])) {
|
|
525
|
+
logger.warn(logData, `failed to sync ${name} from v${states[name].version}, giving up`);
|
|
442
526
|
collectionsToHandle.delete(name);
|
|
443
527
|
}
|
|
528
|
+
else {
|
|
529
|
+
logger.info(logData, `failed to sync ${name} from v${states[name].version}, forcing snapshot retry`);
|
|
530
|
+
// force a full snapshot on retry to recover from
|
|
531
|
+
// corrupted local state (e.g. LTHash MAC mismatch)
|
|
532
|
+
forceSnapshotCollections.add(name);
|
|
533
|
+
}
|
|
444
534
|
}
|
|
445
535
|
}
|
|
446
536
|
}
|
|
@@ -456,7 +546,23 @@ export const makeChatsSocket = (config) => {
|
|
|
456
546
|
* type = "image for the high res picture"
|
|
457
547
|
*/
|
|
458
548
|
const profilePictureUrl = async (jid, type = 'preview', timeoutMs) => {
|
|
459
|
-
|
|
549
|
+
const baseContent = [{ tag: 'picture', attrs: { type, query: 'url' } }];
|
|
550
|
+
// WA Web only includes tctoken for user JIDs (not groups/newsletters)
|
|
551
|
+
// and never for own profile pic (Chat model for self has no tcToken).
|
|
552
|
+
// Including tctoken for own JID causes the server to never respond.
|
|
553
|
+
const normalizedJid = jidNormalizedUser(jid);
|
|
554
|
+
const isUserJid = isPnUser(normalizedJid) || isLidUser(normalizedJid);
|
|
555
|
+
const me = authState.creds.me;
|
|
556
|
+
const isSelf = me && (normalizedJid === jidNormalizedUser(me.id) || (me.lid && normalizedJid === jidNormalizedUser(me.lid)));
|
|
557
|
+
let content = baseContent;
|
|
558
|
+
if (serverProps.profilePicPrivacyToken && isUserJid && !isSelf) {
|
|
559
|
+
content = await buildTcTokenFromJid({
|
|
560
|
+
authState,
|
|
561
|
+
jid: normalizedJid,
|
|
562
|
+
baseContent,
|
|
563
|
+
getLIDForPN
|
|
564
|
+
});
|
|
565
|
+
}
|
|
460
566
|
jid = jidNormalizedUser(jid);
|
|
461
567
|
const result = await query({
|
|
462
568
|
tag: 'iq',
|
|
@@ -466,7 +572,7 @@ export const makeChatsSocket = (config) => {
|
|
|
466
572
|
type: 'get',
|
|
467
573
|
xmlns: 'w:profile:picture'
|
|
468
574
|
},
|
|
469
|
-
content
|
|
575
|
+
content
|
|
470
576
|
}, timeoutMs);
|
|
471
577
|
const child = getBinaryNodeChild(result, 'picture');
|
|
472
578
|
return child?.attrs?.url;
|
|
@@ -491,16 +597,20 @@ export const makeChatsSocket = (config) => {
|
|
|
491
597
|
};
|
|
492
598
|
const sendPresenceUpdate = async (type, toJid) => {
|
|
493
599
|
const me = authState.creds.me;
|
|
494
|
-
|
|
600
|
+
const isAvailableType = type === 'available';
|
|
601
|
+
if (isAvailableType || type === 'unavailable') {
|
|
495
602
|
if (!me.name) {
|
|
496
603
|
logger.warn('no name present, ignoring presence update request...');
|
|
497
604
|
return;
|
|
498
605
|
}
|
|
499
|
-
ev.emit('connection.update', { isOnline:
|
|
606
|
+
ev.emit('connection.update', { isOnline: isAvailableType });
|
|
607
|
+
if (isAvailableType) {
|
|
608
|
+
void sendUnifiedSession();
|
|
609
|
+
}
|
|
500
610
|
await sendNode({
|
|
501
611
|
tag: 'presence',
|
|
502
612
|
attrs: {
|
|
503
|
-
name: me.
|
|
613
|
+
name: me.id.replace(/@/g, ''),
|
|
504
614
|
type
|
|
505
615
|
}
|
|
506
616
|
});
|
|
@@ -527,23 +637,23 @@ export const makeChatsSocket = (config) => {
|
|
|
527
637
|
* @param toJid the jid to subscribe to
|
|
528
638
|
* @param tcToken token for subscription, use if present
|
|
529
639
|
*/
|
|
530
|
-
const presenceSubscribe = (toJid
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
}
|
|
640
|
+
const presenceSubscribe = async (toJid) => {
|
|
641
|
+
// Only include tctoken for user JIDs — groups/newsletters don't use tctokens
|
|
642
|
+
const normalizedToJid = jidNormalizedUser(toJid);
|
|
643
|
+
const isUserJid = isPnUser(normalizedToJid) || isLidUser(normalizedToJid);
|
|
644
|
+
const tcTokenContent = isUserJid
|
|
645
|
+
? await buildTcTokenFromJid({ authState, jid: normalizedToJid, getLIDForPN })
|
|
646
|
+
: undefined;
|
|
647
|
+
return sendNode({
|
|
648
|
+
tag: 'presence',
|
|
649
|
+
attrs: {
|
|
650
|
+
to: toJid,
|
|
651
|
+
id: generateMessageTag(),
|
|
652
|
+
type: 'subscribe'
|
|
653
|
+
},
|
|
654
|
+
content: tcTokenContent
|
|
655
|
+
});
|
|
656
|
+
};
|
|
547
657
|
const handlePresenceUpdate = ({ tag, attrs, content }) => {
|
|
548
658
|
let presence;
|
|
549
659
|
const jid = attrs.from;
|
|
@@ -554,7 +664,8 @@ export const makeChatsSocket = (config) => {
|
|
|
554
664
|
if (tag === 'presence') {
|
|
555
665
|
presence = {
|
|
556
666
|
lastKnownPresence: attrs.type === 'unavailable' ? 'unavailable' : 'available',
|
|
557
|
-
lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined
|
|
667
|
+
lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined,
|
|
668
|
+
groupOnlineCount: attrs.count ? +attrs.count : undefined
|
|
558
669
|
};
|
|
559
670
|
}
|
|
560
671
|
else if (Array.isArray(content)) {
|
|
@@ -583,12 +694,12 @@ export const makeChatsSocket = (config) => {
|
|
|
583
694
|
}
|
|
584
695
|
let initial;
|
|
585
696
|
let encodeResult;
|
|
586
|
-
await
|
|
697
|
+
await appStatePatchMutex.mutex(async () => {
|
|
587
698
|
await authState.keys.transaction(async () => {
|
|
588
699
|
logger.debug({ patch: patchCreate }, 'applying app patch');
|
|
589
700
|
await resyncAppState([name], false);
|
|
590
701
|
const { [name]: currentSyncVersion } = await authState.keys.get('app-state-sync-version', [name]);
|
|
591
|
-
initial = currentSyncVersion
|
|
702
|
+
initial = currentSyncVersion ? ensureLTHashStateVersion(currentSyncVersion) : newLTHashState();
|
|
592
703
|
encodeResult = await encodeSyncdPatch(patchCreate, myAppStateKeyId, initial, getAppStateSyncKey);
|
|
593
704
|
const { patch, state } = encodeResult;
|
|
594
705
|
const node = {
|
|
@@ -634,22 +745,21 @@ export const makeChatsSocket = (config) => {
|
|
|
634
745
|
}
|
|
635
746
|
}
|
|
636
747
|
};
|
|
637
|
-
/**
|
|
748
|
+
/** fetch AB props */
|
|
638
749
|
const fetchProps = async () => {
|
|
639
|
-
//TODO: implement both protocol 1 and protocol 2 prop fetching, specially for abKey for WM
|
|
640
750
|
const resultNode = await query({
|
|
641
751
|
tag: 'iq',
|
|
642
752
|
attrs: {
|
|
643
753
|
to: S_WHATSAPP_NET,
|
|
644
|
-
xmlns: '
|
|
754
|
+
xmlns: 'abt',
|
|
645
755
|
type: 'get'
|
|
646
756
|
},
|
|
647
757
|
content: [
|
|
648
758
|
{
|
|
649
759
|
tag: 'props',
|
|
650
760
|
attrs: {
|
|
651
|
-
protocol: '
|
|
652
|
-
hash: authState
|
|
761
|
+
protocol: '1',
|
|
762
|
+
...(authState?.creds?.lastPropHash ? { hash: authState.creds.lastPropHash } : {})
|
|
653
763
|
}
|
|
654
764
|
}
|
|
655
765
|
]
|
|
@@ -664,7 +774,20 @@ export const makeChatsSocket = (config) => {
|
|
|
664
774
|
}
|
|
665
775
|
props = reduceBinaryNodeToDictionary(propsNode, 'prop');
|
|
666
776
|
}
|
|
667
|
-
|
|
777
|
+
// Extract protocol-relevant AB props (only the ones we need)
|
|
778
|
+
const privacyTokenProp = props['10518'] ?? props['privacy_token_sending_on_all_1_on_1_messages'];
|
|
779
|
+
if (privacyTokenProp !== undefined) {
|
|
780
|
+
serverProps.privacyTokenOn1to1 = privacyTokenProp === 'true' || privacyTokenProp === '1';
|
|
781
|
+
}
|
|
782
|
+
const profilePicProp = props['9666'] ?? props['profile_scraping_privacy_token_in_photo_iq'];
|
|
783
|
+
if (profilePicProp !== undefined) {
|
|
784
|
+
serverProps.profilePicPrivacyToken = profilePicProp === 'true' || profilePicProp === '1';
|
|
785
|
+
}
|
|
786
|
+
const lidIssueProp = props['14303'] ?? props['lid_trusted_token_issue_to_lid'];
|
|
787
|
+
if (lidIssueProp !== undefined) {
|
|
788
|
+
serverProps.lidTrustedTokenIssueToLid = lidIssueProp === 'true' || lidIssueProp === '1';
|
|
789
|
+
}
|
|
790
|
+
logger.debug({ serverProps }, 'fetched props');
|
|
668
791
|
return props;
|
|
669
792
|
};
|
|
670
793
|
/**
|
|
@@ -804,6 +927,47 @@ export const makeChatsSocket = (config) => {
|
|
|
804
927
|
? shouldSyncHistoryMessage(historyMsg) &&
|
|
805
928
|
PROCESSABLE_HISTORY_TYPES.includes(historyMsg.syncType)
|
|
806
929
|
: false;
|
|
930
|
+
if (historyMsg && shouldProcessHistoryMsg) {
|
|
931
|
+
const syncType = historyMsg.syncType;
|
|
932
|
+
// INITIAL_BOOTSTRAP — fire immediately, no progress check (same as WA Web K function)
|
|
933
|
+
if (syncType === proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP &&
|
|
934
|
+
!historySyncStatus.initialBootstrapComplete) {
|
|
935
|
+
historySyncStatus.initialBootstrapComplete = true;
|
|
936
|
+
ev.emit('messaging-history.status', {
|
|
937
|
+
syncType,
|
|
938
|
+
status: 'complete',
|
|
939
|
+
explicit: true
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
// RECENT with progress === 100 — explicit completion
|
|
943
|
+
if (syncType === proto.HistorySync.HistorySyncType.RECENT &&
|
|
944
|
+
historyMsg.progress === 100 &&
|
|
945
|
+
!historySyncStatus.recentSyncComplete) {
|
|
946
|
+
historySyncStatus.recentSyncComplete = true;
|
|
947
|
+
clearTimeout(historySyncPausedTimeout);
|
|
948
|
+
historySyncPausedTimeout = undefined;
|
|
949
|
+
ev.emit('messaging-history.status', {
|
|
950
|
+
syncType,
|
|
951
|
+
status: 'complete',
|
|
952
|
+
explicit: true
|
|
953
|
+
});
|
|
954
|
+
}
|
|
955
|
+
// Reset 120s paused timeout on any RECENT chunk (like WA Web's handleChunkProgress)
|
|
956
|
+
if (syncType === proto.HistorySync.HistorySyncType.RECENT && !historySyncStatus.recentSyncComplete) {
|
|
957
|
+
clearTimeout(historySyncPausedTimeout);
|
|
958
|
+
historySyncPausedTimeout = setTimeout(() => {
|
|
959
|
+
if (!historySyncStatus.recentSyncComplete) {
|
|
960
|
+
historySyncStatus.recentSyncComplete = true;
|
|
961
|
+
ev.emit('messaging-history.status', {
|
|
962
|
+
syncType: proto.HistorySync.HistorySyncType.RECENT,
|
|
963
|
+
status: 'paused',
|
|
964
|
+
explicit: false
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
historySyncPausedTimeout = undefined;
|
|
968
|
+
}, HISTORY_SYNC_PAUSED_TIMEOUT_MS);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
807
971
|
// State machine: decide on sync and flush
|
|
808
972
|
if (historyMsg && syncState === SyncState.AwaitingInitialSync) {
|
|
809
973
|
if (awaitingSyncTimeout) {
|
|
@@ -823,6 +987,8 @@ export const makeChatsSocket = (config) => {
|
|
|
823
987
|
}
|
|
824
988
|
const doAppStateSync = async () => {
|
|
825
989
|
if (syncState === SyncState.Syncing) {
|
|
990
|
+
// All collections will be synced, so clear any blocked ones
|
|
991
|
+
blockedCollections.clear();
|
|
826
992
|
logger.info('Doing app state sync');
|
|
827
993
|
await resyncAppState(ALL_WA_PATCH_NAMES, true);
|
|
828
994
|
// Sync is complete, go online and flush everything
|
|
@@ -882,6 +1048,11 @@ export const makeChatsSocket = (config) => {
|
|
|
882
1048
|
}
|
|
883
1049
|
});
|
|
884
1050
|
ev.on('connection.update', ({ connection, receivedPendingNotifications }) => {
|
|
1051
|
+
if (connection === 'close') {
|
|
1052
|
+
blockedCollections.clear();
|
|
1053
|
+
clearTimeout(historySyncPausedTimeout);
|
|
1054
|
+
historySyncPausedTimeout = undefined;
|
|
1055
|
+
}
|
|
885
1056
|
if (connection === 'open') {
|
|
886
1057
|
if (fireInitQueries) {
|
|
887
1058
|
executeInitQueries().catch(error => onUnexpectedError(error, 'init queries'));
|
|
@@ -891,6 +1062,10 @@ export const makeChatsSocket = (config) => {
|
|
|
891
1062
|
if (!receivedPendingNotifications || syncState !== SyncState.Connecting) {
|
|
892
1063
|
return;
|
|
893
1064
|
}
|
|
1065
|
+
historySyncStatus.initialBootstrapComplete = false;
|
|
1066
|
+
historySyncStatus.recentSyncComplete = false;
|
|
1067
|
+
clearTimeout(historySyncPausedTimeout);
|
|
1068
|
+
historySyncPausedTimeout = undefined;
|
|
894
1069
|
syncState = SyncState.AwaitingInitialSync;
|
|
895
1070
|
logger.info('Connection is now AwaitingInitialSync, buffering events');
|
|
896
1071
|
ev.buffer();
|
|
@@ -903,24 +1078,77 @@ export const makeChatsSocket = (config) => {
|
|
|
903
1078
|
setTimeout(() => ev.flush(), 0);
|
|
904
1079
|
return;
|
|
905
1080
|
}
|
|
906
|
-
|
|
1081
|
+
// On reconnection (accountSyncCounter > 0), the server does not push
|
|
1082
|
+
// history sync notifications — the device already has its data.
|
|
1083
|
+
// Skip the 20s wait and go online immediately.
|
|
1084
|
+
if (authState.creds.accountSyncCounter > 0) {
|
|
1085
|
+
logger.info('Reconnection with existing sync data, skipping history sync wait. Transitioning to Online.');
|
|
1086
|
+
syncState = SyncState.Online;
|
|
1087
|
+
setTimeout(() => ev.flush(), 0);
|
|
1088
|
+
return;
|
|
1089
|
+
}
|
|
1090
|
+
logger.info('First connection, awaiting history sync notification with a 20s timeout.');
|
|
907
1091
|
if (awaitingSyncTimeout) {
|
|
908
1092
|
clearTimeout(awaitingSyncTimeout);
|
|
909
1093
|
}
|
|
910
1094
|
awaitingSyncTimeout = setTimeout(() => {
|
|
911
1095
|
if (syncState === SyncState.AwaitingInitialSync) {
|
|
912
|
-
// TODO: investigate
|
|
913
1096
|
logger.warn('Timeout in AwaitingInitialSync, forcing state to Online and flushing buffer');
|
|
914
1097
|
syncState = SyncState.Online;
|
|
915
1098
|
ev.flush();
|
|
1099
|
+
// Increment so subsequent reconnections skip the 20s wait.
|
|
1100
|
+
// Late-arriving history is still processed via processMessage
|
|
1101
|
+
// regardless of the state machine phase.
|
|
1102
|
+
const accountSyncCounter = (authState.creds.accountSyncCounter || 0) + 1;
|
|
1103
|
+
ev.emit('creds.update', { accountSyncCounter });
|
|
916
1104
|
}
|
|
917
1105
|
}, 20000);
|
|
918
1106
|
});
|
|
1107
|
+
// When an app state sync key arrives (myAppStateKeyId is set) and there are
|
|
1108
|
+
// collections blocked on a missing key, trigger a re-sync for just those collections.
|
|
1109
|
+
// This mirrors WA Web's Blocked → retry-on-key-arrival behavior.
|
|
1110
|
+
ev.on('creds.update', ({ myAppStateKeyId }) => {
|
|
1111
|
+
if (!myAppStateKeyId || blockedCollections.size === 0) {
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
1114
|
+
// If we're in the middle of a full sync, doAppStateSync handles all collections
|
|
1115
|
+
if (syncState === SyncState.Syncing) {
|
|
1116
|
+
blockedCollections.clear();
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1119
|
+
const collections = [...blockedCollections];
|
|
1120
|
+
blockedCollections.clear();
|
|
1121
|
+
logger.info({ collections }, 'app state sync key arrived, re-syncing blocked collections');
|
|
1122
|
+
resyncAppState(collections, false).catch(error => onUnexpectedError(error, 'blocked collections resync'));
|
|
1123
|
+
});
|
|
1124
|
+
ev.on('lid-mapping.update', async ({ lid, pn }) => {
|
|
1125
|
+
try {
|
|
1126
|
+
await signalRepository.lidMapping.storeLIDPNMappings([{ lid, pn }]);
|
|
1127
|
+
}
|
|
1128
|
+
catch (error) {
|
|
1129
|
+
logger.warn({ lid, pn, error }, 'Failed to store LID-PN mapping');
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1132
|
+
registerSocketEndHandler(() => {
|
|
1133
|
+
if (awaitingSyncTimeout) {
|
|
1134
|
+
clearTimeout(awaitingSyncTimeout);
|
|
1135
|
+
awaitingSyncTimeout = undefined;
|
|
1136
|
+
}
|
|
1137
|
+
if (!config.placeholderResendCache && placeholderResendCache.close) {
|
|
1138
|
+
placeholderResendCache.close();
|
|
1139
|
+
}
|
|
1140
|
+
syncState = SyncState.Connecting;
|
|
1141
|
+
privacySettings = undefined;
|
|
1142
|
+
});
|
|
919
1143
|
return {
|
|
920
1144
|
...sock,
|
|
1145
|
+
serverProps,
|
|
921
1146
|
createCallLink,
|
|
922
1147
|
getBotListV2,
|
|
923
|
-
|
|
1148
|
+
messageMutex,
|
|
1149
|
+
receiptMutex,
|
|
1150
|
+
appStatePatchMutex,
|
|
1151
|
+
notificationMutex,
|
|
924
1152
|
fetchPrivacySettings,
|
|
925
1153
|
upsertMessage,
|
|
926
1154
|
appPatch,
|
|
@@ -951,6 +1179,7 @@ export const makeChatsSocket = (config) => {
|
|
|
951
1179
|
cleanDirtyBits,
|
|
952
1180
|
addOrEditContact,
|
|
953
1181
|
removeContact,
|
|
1182
|
+
placeholderResendCache,
|
|
954
1183
|
addLabel,
|
|
955
1184
|
addChatLabel,
|
|
956
1185
|
removeChatLabel,
|