@badzz88/baileys 8.5.6 → 8.5.8
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 +337 -1055
- package/WAProto/WAProto.proto +28 -1189
- package/WAProto/fix-imports.js +79 -69
- package/WAProto/index.d.ts +71491 -15254
- package/WAProto/index.js +126436 -19814
- package/engine-requirements.js +8 -15
- package/lib/Defaults/index.js +130 -0
- package/{src → lib}/Signal/Group/ciphertext-message.js +2 -5
- package/lib/Signal/Group/group-session-builder.js +30 -0
- package/{src → lib}/Signal/Group/group_cipher.js +11 -11
- package/lib/Signal/Group/index.js +12 -0
- package/lib/Signal/Group/keyhelper.js +18 -0
- package/{src → lib}/Signal/Group/sender-chain-key.js +6 -9
- package/{src → lib}/Signal/Group/sender-key-distribution-message.js +6 -9
- package/{src → lib}/Signal/Group/sender-key-message.js +9 -12
- package/{src → lib}/Signal/Group/sender-key-name.js +2 -5
- package/{src → lib}/Signal/Group/sender-key-record.js +8 -11
- package/{src → lib}/Signal/Group/sender-key-state.js +6 -9
- package/lib/Signal/Group/sender-message-key.js +26 -0
- package/{src → lib}/Signal/libsignal.js +131 -155
- package/{src → lib}/Signal/lid-mapping.js +27 -23
- package/lib/Socket/Client/index.js +3 -0
- package/lib/Socket/Client/types.js +11 -0
- package/{src → lib}/Socket/Client/websocket.js +11 -18
- package/{src → lib}/Socket/business.js +35 -67
- package/{src → lib}/Socket/chats.js +294 -550
- package/{src → lib}/Socket/communities.js +82 -114
- package/lib/Socket/graphql.js +716 -0
- package/lib/Socket/groups.js +374 -0
- package/lib/Socket/index.js +18 -0
- package/lib/Socket/interop.js +463 -0
- package/{src → lib}/Socket/luxu.js +120 -82
- package/lib/Socket/messages-recv.js +1916 -0
- package/lib/Socket/messages-send.js +1436 -0
- package/lib/Socket/mex.js +54 -0
- package/lib/Socket/newsletter.js +757 -0
- package/lib/Socket/privacy.js +318 -0
- package/{src → lib}/Socket/socket.js +356 -244
- package/lib/Socket/username.js +236 -0
- package/lib/Store/index.js +10 -0
- package/{src → lib}/Store/keyed-db.js +11 -21
- package/lib/Store/make-cache-manager-store.js +85 -0
- package/lib/Store/make-in-memory-store.js +244 -0
- package/{src → lib}/Store/make-ordered-dictionary.js +19 -25
- package/{src → lib}/Store/object-repository.js +11 -5
- package/lib/Types/Auth.js +2 -0
- package/lib/Types/Bussines.js +2 -0
- package/lib/Types/Call.js +2 -0
- package/lib/Types/Chat.js +8 -0
- package/lib/Types/Contact.js +2 -0
- package/lib/Types/Events.js +2 -0
- package/lib/Types/GroupMetadata.js +2 -0
- package/lib/Types/Label.js +25 -0
- package/lib/Types/LabelAssociation.js +7 -0
- package/lib/Types/Message.js +11 -0
- package/lib/Types/Mex.js +111 -0
- package/lib/Types/Product.js +2 -0
- package/lib/Types/Signal.js +2 -0
- package/lib/Types/Socket.js +3 -0
- package/lib/Types/State.js +56 -0
- package/lib/Types/USync.js +2 -0
- package/lib/Types/index.js +26 -0
- package/{src → lib}/Utils/auth-utils.js +91 -43
- package/lib/Utils/browser-utils.js +48 -0
- package/lib/Utils/business.js +231 -0
- package/lib/Utils/chat-utils.js +872 -0
- package/lib/Utils/companion-reg-client-utils.js +35 -0
- package/lib/Utils/crypto.js +118 -0
- package/lib/Utils/decode-wa-message.js +350 -0
- package/{src → lib}/Utils/event-buffer.js +81 -39
- package/lib/Utils/generics.js +403 -0
- package/lib/Utils/history.js +134 -0
- package/{src → lib}/Utils/identity-change-handler.js +9 -11
- package/lib/Utils/index.js +23 -0
- package/lib/Utils/link-preview.js +85 -0
- package/lib/Utils/logger.js +3 -0
- package/lib/Utils/lt-hash.js +8 -0
- package/{src → lib}/Utils/make-mutex.js +7 -10
- package/lib/Utils/message-composer.js +273 -0
- package/{src → lib}/Utils/message-retry-manager.js +76 -28
- package/lib/Utils/messages-media.js +870 -0
- package/lib/Utils/messages.js +1337 -0
- package/lib/Utils/noise-handler.js +201 -0
- package/{src → lib}/Utils/offline-node-processor.js +10 -4
- package/{src → lib}/Utils/pre-key-manager.js +27 -11
- package/lib/Utils/process-message.js +630 -0
- package/{src → lib}/Utils/reporting-utils.js +12 -15
- package/lib/Utils/signal.js +201 -0
- package/{src → lib}/Utils/stanza-ack.js +12 -4
- package/lib/Utils/sticker.js +110 -0
- package/{src → lib}/Utils/sync-action-utils.js +14 -10
- package/{src → lib}/Utils/tc-token-utils.js +48 -43
- package/{src → lib}/Utils/use-multi-file-auth-state.js +35 -25
- package/lib/Utils/validate-connection.js +203 -0
- package/{src → lib}/WABinary/constants.js +9 -12
- package/{src → lib}/WABinary/decode.js +38 -118
- package/{src → lib}/WABinary/encode.js +6 -11
- package/lib/WABinary/generic-utils.js +204 -0
- package/lib/WABinary/index.js +6 -0
- package/lib/WABinary/jid-utils.js +98 -0
- package/lib/WABinary/types.js +2 -0
- package/{src → lib}/WAM/BinaryInfo.js +2 -5
- package/{src → lib}/WAM/constants.js +4 -16635
- package/{src → lib}/WAM/encode.js +18 -17
- package/lib/WAM/index.js +4 -0
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +53 -0
- package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +43 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +54 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +57 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
- package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +58 -0
- package/lib/WAUSync/Protocols/USyncLIDProtocol.js +30 -0
- package/lib/WAUSync/Protocols/USyncPictureProtocol.js +32 -0
- package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +28 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +39 -0
- package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +38 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +27 -0
- package/lib/WAUSync/Protocols/index.js +12 -0
- package/lib/WAUSync/USyncQuery.js +151 -0
- package/lib/WAUSync/USyncUser.js +56 -0
- package/lib/WAUSync/index.js +3 -0
- package/{src → lib}/index.js +16 -51
- package/package.json +129 -99
- package/LICENSE +0 -21
- package/src/Defaults/index.js +0 -186
- package/src/Defaults/phonenumber-mcc.json +0 -223
- package/src/Signal/Group/group-session-builder.js +0 -86
- package/src/Signal/Group/index.js +0 -140
- package/src/Signal/Group/keyhelper.js +0 -77
- package/src/Signal/Group/sender-message-key.js +0 -29
- package/src/Socket/Client/index.js +0 -31
- package/src/Socket/Client/types.js +0 -13
- package/src/Socket/aigroups.js +0 -221
- package/src/Socket/graphql.js +0 -523
- package/src/Socket/groups.js +0 -516
- package/src/Socket/index.js +0 -31
- package/src/Socket/interactive-handler.js +0 -527
- package/src/Socket/interop.js +0 -339
- package/src/Socket/managed-account.js +0 -98
- package/src/Socket/messages-recv.js +0 -2685
- package/src/Socket/messages-send.js +0 -2047
- package/src/Socket/mex.js +0 -57
- package/src/Socket/newsletter.js +0 -455
- package/src/Socket/privacy.js +0 -125
- package/src/Socket/registration.js +0 -236
- package/src/Socket/text-router.js +0 -65
- package/src/Socket/username.js +0 -130
- package/src/Store/index.js +0 -33
- package/src/Store/make-cache-manager-store.js +0 -84
- package/src/Store/make-in-memory-store.js +0 -551
- package/src/Types/Auth.js +0 -31
- package/src/Types/Bussines.js +0 -2
- package/src/Types/Call.js +0 -2
- package/src/Types/Chat.js +0 -4
- package/src/Types/Contact.js +0 -2
- package/src/Types/Events.js +0 -2
- package/src/Types/GroupMetadata.js +0 -2
- package/src/Types/Label.js +0 -26
- package/src/Types/LabelAssociation.js +0 -8
- package/src/Types/Message.js +0 -93
- package/src/Types/Mex.js +0 -112
- package/src/Types/Newsletter.js +0 -109
- package/src/Types/Product.js +0 -2
- package/src/Types/Signal.js +0 -2
- package/src/Types/Socket.js +0 -2
- package/src/Types/State.js +0 -62
- package/src/Types/USync.js +0 -2
- package/src/Types/index.js +0 -56
- package/src/Utils/browser-utils.js +0 -112
- package/src/Utils/business.js +0 -240
- package/src/Utils/chat-utils.js +0 -1230
- package/src/Utils/command-loader.d.ts +0 -27
- package/src/Utils/command-loader.js +0 -89
- package/src/Utils/companion-reg-client-utils.js +0 -40
- package/src/Utils/consumer-application.js +0 -105
- package/src/Utils/crypto.js +0 -118
- package/src/Utils/curve25519-js.js +0 -242
- package/src/Utils/decode-wa-message.js +0 -529
- package/src/Utils/generics.js +0 -483
- package/src/Utils/group-history.js +0 -44
- package/src/Utils/history.js +0 -232
- package/src/Utils/index.js +0 -58
- package/src/Utils/jid-display-normalization.js +0 -195
- package/src/Utils/link-preview.js +0 -135
- package/src/Utils/logger.js +0 -8
- package/src/Utils/lt-hash.js +0 -25
- package/src/Utils/message-composer.js +0 -471
- package/src/Utils/messages-media.js +0 -843
- package/src/Utils/messages.js +0 -2817
- package/src/Utils/meta-ai-msmsg.js +0 -222
- package/src/Utils/native-bridge.js +0 -68
- package/src/Utils/noise-handler.js +0 -169
- package/src/Utils/process-message.js +0 -950
- package/src/Utils/session-pool.d.ts +0 -14
- package/src/Utils/session-pool.js +0 -70
- package/src/Utils/signal.js +0 -217
- package/src/Utils/sticker.d.ts +0 -13
- package/src/Utils/sticker.js +0 -123
- package/src/Utils/validate-connection.js +0 -209
- package/src/Utils/view-once-cache.d.ts +0 -12
- package/src/Utils/view-once-cache.js +0 -63
- package/src/Utils/voip-rekey.js +0 -22
- package/src/WABinary/generic-utils.js +0 -238
- package/src/WABinary/index.js +0 -34
- package/src/WABinary/jid-utils.js +0 -351
- package/src/WABinary/types.js +0 -2
- package/src/WAM/index.js +0 -32
- package/src/WAUSync/Protocols/USyncBotProfileProtocol.js +0 -53
- package/src/WAUSync/Protocols/USyncBusinessProtocol.js +0 -44
- package/src/WAUSync/Protocols/USyncContactProtocol.js +0 -55
- package/src/WAUSync/Protocols/USyncDeviceProtocol.js +0 -55
- package/src/WAUSync/Protocols/USyncDisappearingModeProtocol.js +0 -31
- package/src/WAUSync/Protocols/USyncFeatureProtocol.js +0 -54
- package/src/WAUSync/Protocols/USyncLIDProtocol.js +0 -32
- package/src/WAUSync/Protocols/USyncNewsletterProtocol.js +0 -473
- package/src/WAUSync/Protocols/USyncPictureProtocol.js +0 -34
- package/src/WAUSync/Protocols/USyncSidelistProtocol.js +0 -29
- package/src/WAUSync/Protocols/USyncStatusProtocol.js +0 -42
- package/src/WAUSync/Protocols/USyncTextStatusProtocol.js +0 -38
- package/src/WAUSync/Protocols/USyncUsernameProtocol.js +0 -28
- package/src/WAUSync/Protocols/index.js +0 -40
- package/src/WAUSync/USyncQuery.js +0 -126
- package/src/WAUSync/USyncUser.js +0 -50
- package/src/WAUSync/index.js +0 -32
- package/src/antiban.js +0 -4152
|
@@ -1,56 +1,66 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { Boom } from '@hapi/boom';
|
|
2
|
+
import { randomBytes } from 'crypto';
|
|
3
|
+
import { URL } from 'url';
|
|
4
|
+
import { promisify } from 'util';
|
|
5
|
+
import { proto } from '../../WAProto/index.js';
|
|
6
|
+
import { DEF_CALLBACK_PREFIX, DEF_TAG_PREFIX, INITIAL_PREKEY_COUNT, MIN_PREKEY_COUNT, NOISE_WA_HEADER, PROCESSABLE_HISTORY_TYPES, TimeMs, UPLOAD_TIMEOUT } from '../Defaults/index.js';
|
|
7
|
+
import { QueryIds, ReachoutTimelockEnforcementType } from '../Types/index.js';
|
|
8
|
+
import { DisconnectReason, XWAPaths } from '../Types/index.js';
|
|
9
|
+
import { addTransactionCapability, aesEncryptCTR, bindWaitForConnectionUpdate, buildPairingQRData, bytesToCrockford, configureSuccessfulPairing, Curve, derivePairingCodeKey, generateLoginNode, generateMdTagPrefix, generateRegistrationNode, getCodeFromWSError, getCompanionPlatformId, getErrorCodeFromStreamError, getNextPreKeysNode, makeEventBuffer, makeNoiseHandler, promiseTimeout, signedKeyPair, xmppSignedPreKey } from '../Utils/index.js';
|
|
10
|
+
import { assertNodeErrorFree, binaryNodeToString, encodeBinaryNode, getAllBinaryNodeChildren, getBinaryNodeChild, getBinaryNodeChildren, isLidUser, jidDecode, jidEncode, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
11
|
+
import { BinaryInfo } from '../WAM/BinaryInfo.js';
|
|
12
|
+
import { USyncQuery, USyncUser } from '../WAUSync/index.js';
|
|
13
|
+
import { WebSocketClient } from './Client/index.js';
|
|
14
|
+
import { executeWMexQuery } from './mex.js';
|
|
15
|
+
/**
|
|
16
|
+
* Connects to WA servers and performs:
|
|
17
|
+
* - simple queries (no retry mechanism, wait for connection establishment)
|
|
18
|
+
* - listen to messages and emit events
|
|
19
|
+
* - query phone connection
|
|
20
|
+
*/
|
|
21
|
+
export const makeSocket = (config) => {
|
|
19
22
|
const { waWebSocketUrl, connectTimeoutMs, logger, keepAliveIntervalMs, browser, auth: authState, printQRInTerminal, defaultQueryTimeoutMs, transactionOpts, qrTimeout, makeSignalRepository } = config;
|
|
20
|
-
const publicWAMBuffer = new
|
|
23
|
+
const publicWAMBuffer = new BinaryInfo();
|
|
21
24
|
let serverTimeOffsetMs = 0;
|
|
22
|
-
const uqTagId =
|
|
23
|
-
const generateMessageTag = () =>
|
|
25
|
+
const uqTagId = generateMdTagPrefix();
|
|
26
|
+
const generateMessageTag = () => `VINNXSYNC-${epoch++}`;
|
|
27
|
+
if (browser[1].toLocaleLowerCase().includes('android')) {
|
|
28
|
+
logger.warn('⚠️ Using the Android browser is experimental and may lead to unexpected behavior. Use at your own risk.');
|
|
29
|
+
}
|
|
24
30
|
if (printQRInTerminal) {
|
|
25
31
|
logger.warn({}, '⚠️ The printQRInTerminal option has been deprecated. You will no longer receive QR codes in the terminal automatically. Please listen to the connection.update event yourself and handle the QR your way. You can remove this message by removing this opttion. This message will be removed in a future version.');
|
|
26
32
|
}
|
|
27
|
-
const syncDisabled =
|
|
33
|
+
const syncDisabled = PROCESSABLE_HISTORY_TYPES.map(syncType => config.shouldSyncHistoryMessage({ syncType })).filter(x => x === false)
|
|
34
|
+
.length === PROCESSABLE_HISTORY_TYPES.length;
|
|
28
35
|
if (syncDisabled) {
|
|
29
36
|
logger.warn('⚠️ DANGER: DISABLING ALL SYNC BY shouldSyncHistoryMsg PREVENTS BAILEYS FROM ACCESSING INITIAL LID MAPPINGS, LEADING TO INSTABILIY AND SESSION ERRORS');
|
|
30
37
|
}
|
|
31
|
-
const url = typeof waWebSocketUrl === 'string' ? new
|
|
38
|
+
const url = typeof waWebSocketUrl === 'string' ? new URL(waWebSocketUrl) : waWebSocketUrl;
|
|
32
39
|
if (config.mobile || url.protocol === 'tcp:') {
|
|
33
|
-
throw new
|
|
40
|
+
throw new Boom('Mobile API is not supported anymore', { statusCode: DisconnectReason.loggedOut });
|
|
34
41
|
}
|
|
35
42
|
if (url.protocol === 'wss' && authState?.creds?.routingInfo) {
|
|
36
43
|
url.searchParams.append('ED', authState.creds.routingInfo.toString('base64url'));
|
|
37
44
|
}
|
|
38
|
-
|
|
39
|
-
const
|
|
45
|
+
/** ephemeral key pair used to encrypt/decrypt communication. Unique for each connection */
|
|
46
|
+
const ephemeralKeyPair = Curve.generateKeyPair();
|
|
47
|
+
/** WA noise protocol wrapper */
|
|
48
|
+
const noise = makeNoiseHandler({
|
|
40
49
|
keyPair: ephemeralKeyPair,
|
|
41
|
-
NOISE_HEADER:
|
|
50
|
+
NOISE_HEADER: NOISE_WA_HEADER,
|
|
42
51
|
logger,
|
|
43
52
|
routingInfo: authState?.creds?.routingInfo
|
|
44
53
|
});
|
|
45
|
-
const ws = new
|
|
54
|
+
const ws = new WebSocketClient(url, config);
|
|
46
55
|
ws.connect();
|
|
47
|
-
const sendPromise =
|
|
56
|
+
const sendPromise = promisify(ws.send);
|
|
57
|
+
/** send a raw buffer */
|
|
48
58
|
const sendRawMessage = async (data) => {
|
|
49
59
|
if (!ws.isOpen) {
|
|
50
|
-
throw new
|
|
60
|
+
throw new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed });
|
|
51
61
|
}
|
|
52
62
|
const bytes = noise.encodeFrame(data);
|
|
53
|
-
await
|
|
63
|
+
await promiseTimeout(connectTimeoutMs, async (resolve, reject) => {
|
|
54
64
|
try {
|
|
55
65
|
await sendPromise.call(ws, bytes);
|
|
56
66
|
resolve();
|
|
@@ -60,36 +70,43 @@ const makeSocket = config => {
|
|
|
60
70
|
}
|
|
61
71
|
});
|
|
62
72
|
};
|
|
63
|
-
|
|
73
|
+
/** send a binary node */
|
|
74
|
+
const sendNode = (frame) => {
|
|
64
75
|
if (logger.level === 'trace') {
|
|
65
|
-
logger.trace({ xml:
|
|
76
|
+
logger.trace({ xml: binaryNodeToString(frame), msg: 'xml send' });
|
|
66
77
|
}
|
|
67
|
-
const buff =
|
|
78
|
+
const buff = encodeBinaryNode(frame);
|
|
68
79
|
return sendRawMessage(buff);
|
|
69
80
|
};
|
|
81
|
+
/**
|
|
82
|
+
* Wait for a message with a certain tag to be received
|
|
83
|
+
* @param msgId the message tag to await
|
|
84
|
+
* @param timeoutMs timeout after which the promise will reject
|
|
85
|
+
*/
|
|
70
86
|
const waitForMessage = async (msgId, timeoutMs = defaultQueryTimeoutMs) => {
|
|
71
87
|
let onRecv;
|
|
72
88
|
let onErr;
|
|
73
89
|
try {
|
|
74
|
-
const result = await
|
|
90
|
+
const result = await promiseTimeout(timeoutMs, (resolve, reject) => {
|
|
75
91
|
onRecv = data => {
|
|
76
92
|
resolve(data);
|
|
77
93
|
};
|
|
78
94
|
onErr = err => {
|
|
79
95
|
reject(err ||
|
|
80
|
-
new
|
|
81
|
-
statusCode:
|
|
96
|
+
new Boom('Connection Closed', {
|
|
97
|
+
statusCode: DisconnectReason.connectionClosed
|
|
82
98
|
}));
|
|
83
99
|
};
|
|
84
100
|
ws.on(`TAG:${msgId}`, onRecv);
|
|
85
101
|
ws.on('close', onErr);
|
|
86
102
|
ws.on('error', onErr);
|
|
87
|
-
return () => reject(new
|
|
103
|
+
return () => reject(new Boom('Query Cancelled'));
|
|
88
104
|
});
|
|
89
105
|
return result;
|
|
90
106
|
}
|
|
91
107
|
catch (error) {
|
|
92
|
-
|
|
108
|
+
// Catch timeout and return undefined instead of throwing
|
|
109
|
+
if (error instanceof Boom && error.output?.statusCode === DisconnectReason.timedOut) {
|
|
93
110
|
logger?.warn?.({ msgId }, 'timed out waiting for message');
|
|
94
111
|
return undefined;
|
|
95
112
|
}
|
|
@@ -104,55 +121,60 @@ const makeSocket = config => {
|
|
|
104
121
|
}
|
|
105
122
|
}
|
|
106
123
|
};
|
|
124
|
+
/** send a query, and wait for its response. auto-generates message ID if not provided */
|
|
107
125
|
const query = async (node, timeoutMs) => {
|
|
108
126
|
if (!node.attrs.id) {
|
|
109
127
|
node.attrs.id = generateMessageTag();
|
|
110
128
|
}
|
|
111
129
|
const msgId = node.attrs.id;
|
|
112
|
-
const result = await
|
|
130
|
+
const result = await promiseTimeout(timeoutMs, async (resolve, reject) => {
|
|
113
131
|
const result = waitForMessage(msgId, timeoutMs).catch(reject);
|
|
114
132
|
sendNode(node)
|
|
115
133
|
.then(async () => resolve(await result))
|
|
116
134
|
.catch(reject);
|
|
117
135
|
});
|
|
118
136
|
if (result && 'tag' in result) {
|
|
119
|
-
;
|
|
120
|
-
(0, WABinary_1.assertNodeErrorFree)(result);
|
|
137
|
+
assertNodeErrorFree(result);
|
|
121
138
|
}
|
|
122
139
|
return result;
|
|
123
140
|
};
|
|
141
|
+
// Validate current key-bundle on server; on failure, trigger pre-key upload and rethrow
|
|
124
142
|
const digestKeyBundle = async () => {
|
|
125
143
|
const res = await query({
|
|
126
144
|
tag: 'iq',
|
|
127
|
-
attrs: { to:
|
|
145
|
+
attrs: { to: S_WHATSAPP_NET, type: 'get', xmlns: 'encrypt' },
|
|
128
146
|
content: [{ tag: 'digest', attrs: {} }]
|
|
129
147
|
});
|
|
130
|
-
const digestNode =
|
|
148
|
+
const digestNode = getBinaryNodeChild(res, 'digest');
|
|
131
149
|
if (!digestNode) {
|
|
132
150
|
await uploadPreKeys();
|
|
133
151
|
throw new Error('encrypt/get digest returned no digest node');
|
|
134
152
|
}
|
|
135
153
|
};
|
|
154
|
+
// Rotate our signed pre-key on server; on failure, run digest as fallback and rethrow
|
|
136
155
|
const rotateSignedPreKey = async () => {
|
|
137
156
|
const newId = (creds.signedPreKey.keyId || 0) + 1;
|
|
138
|
-
const skey = await
|
|
157
|
+
const skey = await signedKeyPair(creds.signedIdentityKey, newId);
|
|
139
158
|
await query({
|
|
140
159
|
tag: 'iq',
|
|
141
|
-
attrs: { to:
|
|
160
|
+
attrs: { to: S_WHATSAPP_NET, type: 'set', xmlns: 'encrypt' },
|
|
142
161
|
content: [
|
|
143
162
|
{
|
|
144
163
|
tag: 'rotate',
|
|
145
164
|
attrs: {},
|
|
146
|
-
content: [
|
|
165
|
+
content: [xmppSignedPreKey(skey)]
|
|
147
166
|
}
|
|
148
167
|
]
|
|
149
168
|
});
|
|
169
|
+
// Persist new signed pre-key in creds
|
|
150
170
|
ev.emit('creds.update', { signedPreKey: skey });
|
|
151
171
|
};
|
|
152
172
|
const executeUSyncQuery = async (usyncQuery) => {
|
|
153
173
|
if (usyncQuery.protocols.length === 0) {
|
|
154
|
-
throw new
|
|
174
|
+
throw new Boom('USyncQuery must have at least one protocol');
|
|
155
175
|
}
|
|
176
|
+
// todo: validate users, throw WARNING on no valid users
|
|
177
|
+
// variable below has only validated users
|
|
156
178
|
const validUsers = usyncQuery.users;
|
|
157
179
|
const userNodes = validUsers.map(user => {
|
|
158
180
|
return {
|
|
@@ -176,7 +198,7 @@ const makeSocket = config => {
|
|
|
176
198
|
const iq = {
|
|
177
199
|
tag: 'iq',
|
|
178
200
|
attrs: {
|
|
179
|
-
to:
|
|
201
|
+
to: S_WHATSAPP_NET,
|
|
180
202
|
type: 'get',
|
|
181
203
|
xmlns: 'usync'
|
|
182
204
|
},
|
|
@@ -197,44 +219,75 @@ const makeSocket = config => {
|
|
|
197
219
|
const result = await query(iq);
|
|
198
220
|
return usyncQuery.parseUSyncQueryResult(result);
|
|
199
221
|
};
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
222
|
+
const buildAllProtocolsQuery = () => new USyncQuery()
|
|
223
|
+
.withContactProtocol()
|
|
224
|
+
.withLIDProtocol()
|
|
225
|
+
.withDeviceProtocol()
|
|
226
|
+
.withStatusProtocol()
|
|
227
|
+
.withDisappearingModeProtocol()
|
|
228
|
+
.withBotProfileProtocol()
|
|
229
|
+
.withUsernameProtocol()
|
|
230
|
+
.withBusinessProtocol()
|
|
231
|
+
.withPictureProtocol()
|
|
232
|
+
.withTextStatusProtocol()
|
|
233
|
+
.withSidelistProtocol()
|
|
234
|
+
.withFeatureProtocol();
|
|
235
|
+
const onWhatsApp = async (...pn) => {
|
|
236
|
+
const usyncQuery = buildAllProtocolsQuery();
|
|
237
|
+
for (const jid of pn) {
|
|
238
|
+
if (isLidUser(jid)) {
|
|
205
239
|
logger?.warn('LIDs are not supported with onWhatsApp');
|
|
206
240
|
continue;
|
|
207
241
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
contactEnabled = true;
|
|
211
|
-
usyncQuery = usyncQuery.withContactProtocol();
|
|
212
|
-
}
|
|
213
|
-
const phone = `+${jid.replace('+', '').split('@')[0]?.split(':')[0]}`;
|
|
214
|
-
usyncQuery.withUser(new WAUSync_1.USyncUser().withPhone(phone));
|
|
215
|
-
}
|
|
242
|
+
const phone = `+${jid.replace('+', '').split('@')[0]?.split(':')[0]}`;
|
|
243
|
+
usyncQuery.withUser(new USyncUser().withPhone(phone));
|
|
216
244
|
}
|
|
217
245
|
if (usyncQuery.users.length === 0) {
|
|
218
|
-
return [];
|
|
246
|
+
return []; // return early without forcing an empty query
|
|
247
|
+
}
|
|
248
|
+
let results;
|
|
249
|
+
try {
|
|
250
|
+
results = await executeUSyncQuery(usyncQuery);
|
|
251
|
+
}
|
|
252
|
+
catch (err) {
|
|
253
|
+
logger?.warn({ err }, 'onWhatsApp: full usync query failed, retrying with contact+lid protocols only');
|
|
254
|
+
const fallbackQuery = new USyncQuery().withContactProtocol().withLIDProtocol();
|
|
255
|
+
fallbackQuery.users = usyncQuery.users;
|
|
256
|
+
results = await executeUSyncQuery(fallbackQuery);
|
|
219
257
|
}
|
|
220
|
-
const results = await executeUSyncQuery(usyncQuery);
|
|
221
258
|
if (results) {
|
|
222
|
-
return results.list
|
|
259
|
+
return results.list
|
|
260
|
+
.filter(a => !!a.contact)
|
|
261
|
+
.map(({ contact, id, lid, devices, status, disappearing_mode, bot, username, business, picture, text_status, sidelist, feature }) => ({
|
|
262
|
+
jid: id,
|
|
263
|
+
exists: contact,
|
|
264
|
+
lid: lid ?? null,
|
|
265
|
+
devices: devices ?? null,
|
|
266
|
+
status: status ?? null,
|
|
267
|
+
disappearingMode: disappearing_mode ?? null,
|
|
268
|
+
bot: bot ?? null,
|
|
269
|
+
username: username ?? null,
|
|
270
|
+
business: business ?? null,
|
|
271
|
+
picture: picture ?? null,
|
|
272
|
+
textStatus: text_status ?? null,
|
|
273
|
+
sidelist: sidelist ?? null,
|
|
274
|
+
feature: feature ?? null
|
|
275
|
+
}));
|
|
223
276
|
}
|
|
224
277
|
};
|
|
225
278
|
const pnFromLIDUSync = async (jids) => {
|
|
226
|
-
const usyncQuery = new
|
|
279
|
+
const usyncQuery = new USyncQuery().withLIDProtocol().withContext('background');
|
|
227
280
|
for (const jid of jids) {
|
|
228
|
-
if (
|
|
281
|
+
if (isLidUser(jid)) {
|
|
229
282
|
logger?.warn('LID user found in LID fetch call');
|
|
230
283
|
continue;
|
|
231
284
|
}
|
|
232
285
|
else {
|
|
233
|
-
usyncQuery.withUser(new
|
|
286
|
+
usyncQuery.withUser(new USyncUser().withId(jid));
|
|
234
287
|
}
|
|
235
288
|
}
|
|
236
289
|
if (usyncQuery.users.length === 0) {
|
|
237
|
-
return [];
|
|
290
|
+
return []; // return early without forcing an empty query
|
|
238
291
|
}
|
|
239
292
|
const results = await executeUSyncQuery(usyncQuery);
|
|
240
293
|
if (results) {
|
|
@@ -242,76 +295,99 @@ const makeSocket = config => {
|
|
|
242
295
|
}
|
|
243
296
|
return [];
|
|
244
297
|
};
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
298
|
+
/**
|
|
299
|
+
* @param {string | string[]} lid - @lid JID or array of @lid JID
|
|
300
|
+
* @returns {Promise<{ lid: string, pn: string | null }[]>}
|
|
301
|
+
*/
|
|
302
|
+
const toPn = async lid => {
|
|
303
|
+
const lids = Array.isArray(lid) ? lid : [lid]
|
|
304
|
+
const usyncQuery = new USyncQuery()
|
|
305
|
+
.withContactProtocol()
|
|
306
|
+
.withLIDProtocol()
|
|
307
|
+
for (const l of lids) {
|
|
308
|
+
const decoded = jidDecode(l)
|
|
309
|
+
if (!decoded) continue
|
|
310
|
+
usyncQuery.withUser(
|
|
311
|
+
new USyncUser()
|
|
312
|
+
.withId(jidEncode(decoded.user, 's.whatsapp.net'))
|
|
313
|
+
.withLid(l)
|
|
314
|
+
)
|
|
315
|
+
}
|
|
316
|
+
const result = await executeUSyncQuery(usyncQuery)
|
|
317
|
+
return lids.map(l => {
|
|
318
|
+
const decoded = jidDecode(l)
|
|
319
|
+
if (!decoded) return { lid: l, pn: null }
|
|
320
|
+
|
|
321
|
+
const match = result?.list?.find(entry => {
|
|
322
|
+
const entryDecoded = jidDecode(entry.id)
|
|
323
|
+
return entryDecoded?.user === decoded.user
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
if (!match?.contact) return { lid: l, pn: null }
|
|
327
|
+
|
|
328
|
+
const pn = jidEncode(jidDecode(match.id)?.user, 's.whatsapp.net')
|
|
329
|
+
return { lid: l, pn: pn ?? null }
|
|
330
|
+
})
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* @param {string | string[]} s.whatsapp.net - @s.whatsapp.net JID or array of @s.whatsapp.net JID
|
|
334
|
+
* @returns {Promise<{ pn: string, lid: string | null }[]>}
|
|
335
|
+
*/
|
|
336
|
+
const toLID = async pn => {
|
|
337
|
+
const pns = Array.isArray(pn) ? pn : [pn]
|
|
338
|
+
const usyncQuery = new USyncQuery()
|
|
339
|
+
.withContactProtocol()
|
|
340
|
+
.withLIDProtocol()
|
|
341
|
+
for (const p of pns) {
|
|
342
|
+
const decoded = jidDecode(p)
|
|
343
|
+
if (!decoded) continue
|
|
344
|
+
usyncQuery.withUser(
|
|
345
|
+
new USyncUser().withId(jidEncode(decoded.user, 's.whatsapp.net'))
|
|
346
|
+
)
|
|
347
|
+
}
|
|
348
|
+
const result = await executeUSyncQuery(usyncQuery)
|
|
349
|
+
return pns.map(p => {
|
|
350
|
+
const decoded = jidDecode(p)
|
|
351
|
+
if (!decoded) return { pn: p, lid: null }
|
|
352
|
+
|
|
353
|
+
const match = result?.list?.find(entry => {
|
|
354
|
+
return jidDecode(entry.id)?.user === decoded.user
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
if (!match?.contact) return { pn: p, lid: null }
|
|
358
|
+
|
|
359
|
+
const lidVal = match?.lid ?? null
|
|
360
|
+
const lid = lidVal ? jidEncode(jidDecode(lidVal)?.user ?? lidVal, 'lid') : null
|
|
361
|
+
return { pn: p, lid }
|
|
362
|
+
})
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* @param {string, pin} username - username to fetch, pin - pin of username if da user enable it
|
|
366
|
+
* @returns {Promise<{ username: string, pn: string | null, lid: string | null }[]>}
|
|
367
|
+
*/
|
|
368
|
+
const fetchUsername = async (username, pin) => {
|
|
369
|
+
const usernames = Array.isArray(username) ? username : [username]
|
|
370
|
+
const usyncQuery = new USyncQuery()
|
|
371
|
+
.withContactProtocol()
|
|
372
|
+
.withLIDProtocol()
|
|
373
|
+
for (const u of usernames) {
|
|
374
|
+
const user = new USyncUser().withUsername(u)
|
|
375
|
+
if (pin) user.withUsernameKey(pin)
|
|
376
|
+
usyncQuery.withUser(user)
|
|
377
|
+
}
|
|
378
|
+
const result = await executeUSyncQuery(usyncQuery)
|
|
379
|
+
return usernames.map(u => {
|
|
380
|
+
const match = result?.list?.find(entry => entry?.username === u)
|
|
381
|
+
if (!match?.contact) return { username: u, pn: null, lid: null }
|
|
382
|
+
const lid = match.lid;
|
|
383
|
+
const pn = jidEncode(jidDecode(match.id)?.user, 's.whatsapp.net')
|
|
384
|
+
return { username: u, pn: pn ?? null, lid: lid ?? null }
|
|
385
|
+
})
|
|
386
|
+
}
|
|
387
|
+
const ev = makeEventBuffer(logger);
|
|
313
388
|
const { creds } = authState;
|
|
314
|
-
|
|
389
|
+
// add transaction capability
|
|
390
|
+
const keys = addTransactionCapability(authState.keys, logger, transactionOpts);
|
|
315
391
|
const signalRepository = makeSignalRepository({ creds, keys }, logger, pnFromLIDUSync);
|
|
316
392
|
let lastDateRecv;
|
|
317
393
|
let epoch = 1;
|
|
@@ -319,18 +395,20 @@ const makeSocket = config => {
|
|
|
319
395
|
let qrTimer;
|
|
320
396
|
let closed = false;
|
|
321
397
|
const socketEndHandlers = [];
|
|
398
|
+
/** log & process any unexpected errors */
|
|
322
399
|
const onUnexpectedError = (err, msg) => {
|
|
323
400
|
logger.error({ err }, `unexpected error in '${msg}'`);
|
|
324
401
|
};
|
|
402
|
+
/** await the next incoming message */
|
|
325
403
|
const awaitNextMessage = async (sendMsg) => {
|
|
326
404
|
if (!ws.isOpen) {
|
|
327
|
-
throw new
|
|
328
|
-
statusCode:
|
|
405
|
+
throw new Boom('Connection Closed', {
|
|
406
|
+
statusCode: DisconnectReason.connectionClosed
|
|
329
407
|
});
|
|
330
408
|
}
|
|
331
409
|
let onOpen;
|
|
332
410
|
let onClose;
|
|
333
|
-
const result =
|
|
411
|
+
const result = promiseTimeout(connectTimeoutMs, (resolve, reject) => {
|
|
334
412
|
onOpen = resolve;
|
|
335
413
|
onClose = mapWebSocketError(reject);
|
|
336
414
|
ws.on('frame', onOpen);
|
|
@@ -346,28 +424,29 @@ const makeSocket = config => {
|
|
|
346
424
|
}
|
|
347
425
|
return result;
|
|
348
426
|
};
|
|
427
|
+
/** connection handshake */
|
|
349
428
|
const validateConnection = async () => {
|
|
350
429
|
let helloMsg = {
|
|
351
430
|
clientHello: { ephemeral: ephemeralKeyPair.public }
|
|
352
431
|
};
|
|
353
|
-
helloMsg =
|
|
432
|
+
helloMsg = proto.HandshakeMessage.fromObject(helloMsg);
|
|
354
433
|
logger.info({ browser, helloMsg }, 'connected to WA');
|
|
355
|
-
const init =
|
|
434
|
+
const init = proto.HandshakeMessage.encode(helloMsg).finish();
|
|
356
435
|
const result = await awaitNextMessage(init);
|
|
357
|
-
const handshake =
|
|
436
|
+
const handshake = proto.HandshakeMessage.decode(result);
|
|
358
437
|
logger.trace({ handshake }, 'handshake recv from WA');
|
|
359
438
|
const keyEnc = noise.processHandshake(handshake, creds.noiseKey);
|
|
360
439
|
let node;
|
|
361
440
|
if (!creds.me) {
|
|
362
|
-
node =
|
|
441
|
+
node = generateRegistrationNode(creds, config);
|
|
363
442
|
logger.info({ node }, 'not logged in, attempting registration...');
|
|
364
443
|
}
|
|
365
444
|
else {
|
|
366
|
-
node =
|
|
445
|
+
node = generateLoginNode(creds.me.id, config);
|
|
367
446
|
logger.info({ node }, 'logging in...');
|
|
368
447
|
}
|
|
369
|
-
const payloadEnc = noise.encrypt(
|
|
370
|
-
await sendRawMessage(
|
|
448
|
+
const payloadEnc = noise.encrypt(proto.ClientPayload.encode(node).finish());
|
|
449
|
+
await sendRawMessage(proto.HandshakeMessage.encode({
|
|
371
450
|
clientFinish: {
|
|
372
451
|
static: keyEnc,
|
|
373
452
|
payload: payloadEnc
|
|
@@ -383,54 +462,53 @@ const makeSocket = config => {
|
|
|
383
462
|
id: generateMessageTag(),
|
|
384
463
|
xmlns: 'encrypt',
|
|
385
464
|
type: 'get',
|
|
386
|
-
to:
|
|
465
|
+
to: S_WHATSAPP_NET
|
|
387
466
|
},
|
|
388
467
|
content: [{ tag: 'count', attrs: {} }]
|
|
389
468
|
});
|
|
390
|
-
const countChild =
|
|
469
|
+
const countChild = getBinaryNodeChild(result, 'count');
|
|
391
470
|
return +countChild.attrs.value;
|
|
392
471
|
};
|
|
472
|
+
// WAWeb has no time throttle here; the server drives uploads via PreKeyLow notifications.
|
|
393
473
|
let uploadPreKeysPromise = null;
|
|
394
|
-
|
|
395
|
-
const uploadPreKeys = async (count =
|
|
396
|
-
if (retryCount === 0) {
|
|
397
|
-
const timeSinceLastUpload = Date.now() - lastUploadTime;
|
|
398
|
-
if (timeSinceLastUpload < Defaults_1.MIN_UPLOAD_INTERVAL) {
|
|
399
|
-
logger.debug(`Skipping upload, only ${timeSinceLastUpload}ms since last upload`);
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
474
|
+
/** generates and uploads a set of pre-keys to the server */
|
|
475
|
+
const uploadPreKeys = async (count = MIN_PREKEY_COUNT) => {
|
|
403
476
|
if (uploadPreKeysPromise) {
|
|
404
477
|
logger.debug('Pre-key upload already in progress, waiting for completion');
|
|
405
478
|
await uploadPreKeysPromise;
|
|
479
|
+
return;
|
|
406
480
|
}
|
|
407
|
-
const uploadLogic = async () => {
|
|
481
|
+
const uploadLogic = async (retryCount) => {
|
|
408
482
|
logger.info({ count, retryCount }, 'uploading pre-keys');
|
|
483
|
+
// Generate and save pre-keys atomically (prevents ID collisions on retry)
|
|
409
484
|
const node = await keys.transaction(async () => {
|
|
410
485
|
logger.debug({ requestedCount: count }, 'generating pre-keys with requested count');
|
|
411
|
-
const { update, node } = await
|
|
486
|
+
const { update, node } = await getNextPreKeysNode({ creds, keys }, count);
|
|
487
|
+
// Update credentials immediately to prevent duplicate IDs on retry
|
|
412
488
|
ev.emit('creds.update', update);
|
|
413
489
|
return node;
|
|
414
490
|
}, creds?.me?.id || 'upload-pre-keys');
|
|
491
|
+
// Upload to server (outside transaction, can fail without affecting local keys)
|
|
415
492
|
try {
|
|
416
493
|
await query(node);
|
|
417
494
|
logger.info({ count }, 'uploaded pre-keys successfully');
|
|
418
|
-
lastUploadTime = Date.now();
|
|
419
495
|
}
|
|
420
496
|
catch (uploadError) {
|
|
421
497
|
logger.error({ uploadError: uploadError.toString(), count }, 'Failed to upload pre-keys to server');
|
|
498
|
+
// Recurse into uploadLogic; calling uploadPreKeys would await its own in-flight promise.
|
|
422
499
|
if (retryCount < 3) {
|
|
423
500
|
const backoffDelay = Math.min(1000 * Math.pow(2, retryCount), 10000);
|
|
424
501
|
logger.info(`Retrying pre-key upload in ${backoffDelay}ms`);
|
|
425
502
|
await new Promise(resolve => setTimeout(resolve, backoffDelay));
|
|
426
|
-
return
|
|
503
|
+
return uploadLogic(retryCount + 1);
|
|
427
504
|
}
|
|
428
505
|
throw uploadError;
|
|
429
506
|
}
|
|
430
507
|
};
|
|
508
|
+
// Add timeout protection
|
|
431
509
|
uploadPreKeysPromise = Promise.race([
|
|
432
|
-
uploadLogic(),
|
|
433
|
-
new Promise((_, reject) => setTimeout(() => reject(new
|
|
510
|
+
uploadLogic(0),
|
|
511
|
+
new Promise((_, reject) => setTimeout(() => reject(new Boom('Pre-key upload timeout', { statusCode: 408 })), UPLOAD_TIMEOUT))
|
|
434
512
|
]);
|
|
435
513
|
try {
|
|
436
514
|
await uploadPreKeysPromise;
|
|
@@ -453,9 +531,9 @@ const makeSocket = config => {
|
|
|
453
531
|
let count = 0;
|
|
454
532
|
const preKeyCount = await getAvailablePreKeysOnServer();
|
|
455
533
|
if (preKeyCount === 0)
|
|
456
|
-
count =
|
|
534
|
+
count = INITIAL_PREKEY_COUNT;
|
|
457
535
|
else
|
|
458
|
-
count =
|
|
536
|
+
count = MIN_PREKEY_COUNT;
|
|
459
537
|
const { exists: currentPreKeyExists, currentPreKeyId } = await verifyCurrentPreKeyExists();
|
|
460
538
|
logger.info(`${preKeyCount} pre-keys found on server`);
|
|
461
539
|
logger.info(`Current prekey ID: ${currentPreKeyId}, exists in storage: ${currentPreKeyExists}`);
|
|
@@ -477,30 +555,34 @@ const makeSocket = config => {
|
|
|
477
555
|
}
|
|
478
556
|
catch (error) {
|
|
479
557
|
logger.error({ error }, 'Failed to check/upload pre-keys during initialization');
|
|
558
|
+
// Don't throw - allow connection to continue even if pre-key check fails
|
|
480
559
|
}
|
|
481
560
|
};
|
|
482
561
|
const onMessageReceived = async (data) => {
|
|
483
562
|
await noise.decodeFrame(data, frame => {
|
|
563
|
+
// reset ping timeout
|
|
484
564
|
lastDateRecv = new Date();
|
|
485
565
|
let anyTriggered = false;
|
|
486
566
|
anyTriggered = ws.emit('frame', frame);
|
|
567
|
+
// if it's a binary node
|
|
487
568
|
if (!(frame instanceof Uint8Array)) {
|
|
488
569
|
const msgId = frame.attrs.id;
|
|
489
570
|
if (logger.level === 'trace') {
|
|
490
|
-
logger.trace({ xml:
|
|
571
|
+
logger.trace({ xml: binaryNodeToString(frame), msg: 'recv xml' });
|
|
491
572
|
}
|
|
492
|
-
|
|
573
|
+
/* Check if this is a response to a message we sent */
|
|
574
|
+
anyTriggered = ws.emit(`${DEF_TAG_PREFIX}${msgId}`, frame) || anyTriggered;
|
|
575
|
+
/* Check if this is a response to a message we are expecting */
|
|
493
576
|
const l0 = frame.tag;
|
|
494
577
|
const l1 = frame.attrs || {};
|
|
495
578
|
const l2 = Array.isArray(frame.content) ? frame.content[0]?.tag : '';
|
|
496
579
|
for (const key of Object.keys(l1)) {
|
|
497
|
-
anyTriggered =
|
|
498
|
-
|
|
499
|
-
anyTriggered = ws.emit(`${
|
|
500
|
-
anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0},${key}`, frame) || anyTriggered;
|
|
580
|
+
anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]},${l2}`, frame) || anyTriggered;
|
|
581
|
+
anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]}`, frame) || anyTriggered;
|
|
582
|
+
anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}`, frame) || anyTriggered;
|
|
501
583
|
}
|
|
502
|
-
anyTriggered = ws.emit(`${
|
|
503
|
-
anyTriggered = ws.emit(`${
|
|
584
|
+
anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},,${l2}`, frame) || anyTriggered;
|
|
585
|
+
anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0}`, frame) || anyTriggered;
|
|
504
586
|
if (!anyTriggered && logger.level === 'debug') {
|
|
505
587
|
logger.debug({ unhandled: true, msgId, fromMe: false, frame }, 'communication recv');
|
|
506
588
|
}
|
|
@@ -519,6 +601,7 @@ const makeSocket = config => {
|
|
|
519
601
|
ws.removeAllListeners('close');
|
|
520
602
|
ws.removeAllListeners('open');
|
|
521
603
|
ws.removeAllListeners('message');
|
|
604
|
+
signalRepository.close?.();
|
|
522
605
|
if (!ws.isClosed && !ws.isClosing) {
|
|
523
606
|
try {
|
|
524
607
|
await ws.close();
|
|
@@ -541,13 +624,14 @@ const makeSocket = config => {
|
|
|
541
624
|
}
|
|
542
625
|
});
|
|
543
626
|
ev.removeAllListeners('connection.update');
|
|
627
|
+
ev.destroy();
|
|
544
628
|
};
|
|
545
629
|
const waitForSocketOpen = async () => {
|
|
546
630
|
if (ws.isOpen) {
|
|
547
631
|
return;
|
|
548
632
|
}
|
|
549
633
|
if (ws.isClosed || ws.isClosing) {
|
|
550
|
-
throw new
|
|
634
|
+
throw new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed });
|
|
551
635
|
}
|
|
552
636
|
let onOpen;
|
|
553
637
|
let onClose;
|
|
@@ -568,15 +652,20 @@ const makeSocket = config => {
|
|
|
568
652
|
lastDateRecv = new Date();
|
|
569
653
|
}
|
|
570
654
|
const diff = Date.now() - lastDateRecv.getTime();
|
|
655
|
+
/*
|
|
656
|
+
check if it's been a suspicious amount of time since the server responded with our last seen
|
|
657
|
+
it could be that the network is down
|
|
658
|
+
*/
|
|
571
659
|
if (diff > keepAliveIntervalMs + 5000) {
|
|
572
|
-
void end(new
|
|
660
|
+
void end(new Boom('Connection was lost', { statusCode: DisconnectReason.connectionLost }));
|
|
573
661
|
}
|
|
574
662
|
else if (ws.isOpen) {
|
|
663
|
+
// if its all good, send a keep alive request
|
|
575
664
|
query({
|
|
576
665
|
tag: 'iq',
|
|
577
666
|
attrs: {
|
|
578
667
|
id: generateMessageTag(),
|
|
579
|
-
to:
|
|
668
|
+
to: S_WHATSAPP_NET,
|
|
580
669
|
type: 'get',
|
|
581
670
|
xmlns: 'w:p'
|
|
582
671
|
},
|
|
@@ -589,22 +678,24 @@ const makeSocket = config => {
|
|
|
589
678
|
logger.warn('keep alive called when WS not open');
|
|
590
679
|
}
|
|
591
680
|
}, keepAliveIntervalMs));
|
|
592
|
-
|
|
681
|
+
/** i have no idea why this exists. pls enlighten me */
|
|
682
|
+
const sendPassiveIq = (tag) => query({
|
|
593
683
|
tag: 'iq',
|
|
594
684
|
attrs: {
|
|
595
|
-
to:
|
|
685
|
+
to: S_WHATSAPP_NET,
|
|
596
686
|
xmlns: 'passive',
|
|
597
687
|
type: 'set'
|
|
598
688
|
},
|
|
599
689
|
content: [{ tag, attrs: {} }]
|
|
600
690
|
});
|
|
691
|
+
/** logout & invalidate connection */
|
|
601
692
|
const logout = async (msg) => {
|
|
602
693
|
const jid = authState.creds.me?.id;
|
|
603
694
|
if (jid) {
|
|
604
695
|
await sendNode({
|
|
605
696
|
tag: 'iq',
|
|
606
697
|
attrs: {
|
|
607
|
-
to:
|
|
698
|
+
to: S_WHATSAPP_NET,
|
|
608
699
|
type: 'set',
|
|
609
700
|
id: generateMessageTag(),
|
|
610
701
|
xmlns: 'md'
|
|
@@ -620,23 +711,25 @@ const makeSocket = config => {
|
|
|
620
711
|
]
|
|
621
712
|
});
|
|
622
713
|
}
|
|
623
|
-
void end(new
|
|
714
|
+
void end(new Boom(msg || 'Intentional Logout', { statusCode: DisconnectReason.loggedOut }));
|
|
624
715
|
};
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
716
|
+
|
|
717
|
+
const requestPairingCode = async (phoneNumber, customPairingCode = 'VINXSYNC') => {
|
|
718
|
+
const pairingCode = customPairingCode;
|
|
719
|
+
if (pairingCode && pairingCode.length !== 8) {
|
|
628
720
|
throw new Error('Custom pairing code must be exactly 8 chars');
|
|
629
721
|
}
|
|
722
|
+
|
|
630
723
|
authState.creds.pairingCode = pairingCode;
|
|
631
724
|
authState.creds.me = {
|
|
632
|
-
id:
|
|
725
|
+
id: jidEncode(phoneNumber, 's.whatsapp.net'),
|
|
633
726
|
name: '~'
|
|
634
727
|
};
|
|
635
728
|
ev.emit('creds.update', authState.creds);
|
|
636
729
|
await sendNode({
|
|
637
730
|
tag: 'iq',
|
|
638
731
|
attrs: {
|
|
639
|
-
to:
|
|
732
|
+
to: S_WHATSAPP_NET,
|
|
640
733
|
type: 'set',
|
|
641
734
|
id: generateMessageTag(),
|
|
642
735
|
xmlns: 'md'
|
|
@@ -663,7 +756,7 @@ const makeSocket = config => {
|
|
|
663
756
|
{
|
|
664
757
|
tag: 'companion_platform_id',
|
|
665
758
|
attrs: {},
|
|
666
|
-
content: (
|
|
759
|
+
content: getCompanionPlatformId(browser)
|
|
667
760
|
},
|
|
668
761
|
{
|
|
669
762
|
tag: 'companion_platform_display',
|
|
@@ -682,17 +775,17 @@ const makeSocket = config => {
|
|
|
682
775
|
return authState.creds.pairingCode;
|
|
683
776
|
};
|
|
684
777
|
async function generatePairingKey() {
|
|
685
|
-
const salt =
|
|
686
|
-
const randomIv =
|
|
687
|
-
const key = await
|
|
688
|
-
const ciphered =
|
|
778
|
+
const salt = randomBytes(32);
|
|
779
|
+
const randomIv = randomBytes(16);
|
|
780
|
+
const key = await derivePairingCodeKey(authState.creds.pairingCode, salt);
|
|
781
|
+
const ciphered = aesEncryptCTR(authState.creds.pairingEphemeralKeyPair.public, key, randomIv);
|
|
689
782
|
return Buffer.concat([salt, randomIv, ciphered]);
|
|
690
783
|
}
|
|
691
|
-
const sendWAMBuffer = wamBuffer => {
|
|
784
|
+
const sendWAMBuffer = (wamBuffer) => {
|
|
692
785
|
return query({
|
|
693
786
|
tag: 'iq',
|
|
694
787
|
attrs: {
|
|
695
|
-
to:
|
|
788
|
+
to: S_WHATSAPP_NET,
|
|
696
789
|
id: generateMessageTag(),
|
|
697
790
|
xmlns: 'w:stats'
|
|
698
791
|
},
|
|
@@ -716,46 +809,50 @@ const makeSocket = config => {
|
|
|
716
809
|
}
|
|
717
810
|
});
|
|
718
811
|
ws.on('error', mapWebSocketError(end));
|
|
719
|
-
ws.on('close', () => void end(new
|
|
720
|
-
|
|
812
|
+
ws.on('close', () => void end(new Boom('Connection Terminated', { statusCode: DisconnectReason.connectionClosed })));
|
|
813
|
+
// the server terminated the connection
|
|
814
|
+
ws.on('CB:xmlstreamend', () => void end(new Boom('Connection Terminated by Server', { statusCode: DisconnectReason.connectionClosed })));
|
|
815
|
+
// QR gen
|
|
721
816
|
ws.on('CB:iq,type:set,pair-device', async (stanza) => {
|
|
722
817
|
const iq = {
|
|
723
818
|
tag: 'iq',
|
|
724
819
|
attrs: {
|
|
725
|
-
to:
|
|
820
|
+
to: S_WHATSAPP_NET,
|
|
726
821
|
type: 'result',
|
|
727
822
|
id: stanza.attrs.id
|
|
728
823
|
}
|
|
729
824
|
};
|
|
730
825
|
await sendNode(iq);
|
|
731
|
-
const pairDeviceNode =
|
|
732
|
-
const refNodes =
|
|
826
|
+
const pairDeviceNode = getBinaryNodeChild(stanza, 'pair-device');
|
|
827
|
+
const refNodes = getBinaryNodeChildren(pairDeviceNode, 'ref');
|
|
733
828
|
const noiseKeyB64 = Buffer.from(creds.noiseKey.public).toString('base64');
|
|
734
829
|
const identityKeyB64 = Buffer.from(creds.signedIdentityKey.public).toString('base64');
|
|
735
830
|
const advB64 = creds.advSecretKey;
|
|
736
|
-
let qrMs = qrTimeout || 60000;
|
|
831
|
+
let qrMs = qrTimeout || 60000; // time to let a QR live
|
|
737
832
|
const genPairQR = () => {
|
|
738
833
|
if (!ws.isOpen) {
|
|
739
834
|
return;
|
|
740
835
|
}
|
|
741
836
|
const refNode = refNodes.shift();
|
|
742
837
|
if (!refNode) {
|
|
743
|
-
void end(new
|
|
838
|
+
void end(new Boom('QR refs attempts ended', { statusCode: DisconnectReason.timedOut }));
|
|
744
839
|
return;
|
|
745
840
|
}
|
|
746
841
|
const ref = refNode.content.toString('utf-8');
|
|
747
|
-
const qr =
|
|
842
|
+
const qr = buildPairingQRData(ref, noiseKeyB64, identityKeyB64, advB64, browser);
|
|
748
843
|
ev.emit('connection.update', { qr });
|
|
749
844
|
qrTimer = setTimeout(genPairQR, qrMs);
|
|
750
|
-
qrMs = qrTimeout || 20000;
|
|
845
|
+
qrMs = qrTimeout || 20000; // shorter subsequent qrs
|
|
751
846
|
};
|
|
752
847
|
genPairQR();
|
|
753
848
|
});
|
|
849
|
+
// device paired for the first time
|
|
850
|
+
// if device pairs successfully, the server asks to restart the connection
|
|
754
851
|
ws.on('CB:iq,,pair-success', async (stanza) => {
|
|
755
852
|
logger.debug('pair success recv');
|
|
756
853
|
try {
|
|
757
854
|
updateServerTimeOffset(stanza);
|
|
758
|
-
const { reply, creds: updatedCreds } =
|
|
855
|
+
const { reply, creds: updatedCreds } = configureSuccessfulPairing(stanza, creds);
|
|
759
856
|
logger.info({ me: updatedCreds.me, platform: updatedCreds.platform }, 'pairing configured successfully, expect to restart the connection...');
|
|
760
857
|
ev.emit('creds.update', updatedCreds);
|
|
761
858
|
ev.emit('connection.update', { isNewLogin: true, qr: undefined });
|
|
@@ -767,13 +864,13 @@ const makeSocket = config => {
|
|
|
767
864
|
void end(error);
|
|
768
865
|
}
|
|
769
866
|
});
|
|
867
|
+
// login complete
|
|
770
868
|
ws.on('CB:success', async (node) => {
|
|
771
869
|
try {
|
|
772
870
|
updateServerTimeOffset(node);
|
|
773
871
|
await uploadPreKeysToServerIfRequired();
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
}
|
|
872
|
+
await sendPassiveIq('active');
|
|
873
|
+
// After successful login, validate our key-bundle against server
|
|
777
874
|
try {
|
|
778
875
|
await digestKeyBundle();
|
|
779
876
|
}
|
|
@@ -785,12 +882,8 @@ const makeSocket = config => {
|
|
|
785
882
|
logger.warn({ err }, 'failed to send initial passive iq');
|
|
786
883
|
}
|
|
787
884
|
logger.info('opened connection to WA');
|
|
788
|
-
clearTimeout(qrTimer);
|
|
885
|
+
clearTimeout(qrTimer); // will never happen in all likelyhood -- but just in case WA sends success on first try
|
|
789
886
|
ev.emit('creds.update', { me: { ...authState.creds.me, lid: node.attrs.lid } });
|
|
790
|
-
if (config.syncFullHistory && authState.creds.initialFullSyncDone !== true) {
|
|
791
|
-
logger.debug('initial full history sync completed, persisting one-time flag');
|
|
792
|
-
ev.emit('creds.update', { initialFullSyncDone: true });
|
|
793
|
-
}
|
|
794
887
|
ev.emit('connection.update', { connection: 'open' });
|
|
795
888
|
void sendUnifiedSession();
|
|
796
889
|
if (node.attrs.lid && authState.creds.me?.id) {
|
|
@@ -798,13 +891,16 @@ const makeSocket = config => {
|
|
|
798
891
|
process.nextTick(async () => {
|
|
799
892
|
try {
|
|
800
893
|
const myPN = authState.creds.me.id;
|
|
894
|
+
// Store our own LID-PN mapping
|
|
801
895
|
await signalRepository.lidMapping.storeLIDPNMappings([{ lid: myLID, pn: myPN }]);
|
|
802
|
-
|
|
896
|
+
// Create device list for our own user (needed for bulk migration)
|
|
897
|
+
const { user, device } = jidDecode(myPN);
|
|
803
898
|
await authState.keys.set({
|
|
804
899
|
'device-list': {
|
|
805
900
|
[user]: [device?.toString() || '0']
|
|
806
901
|
}
|
|
807
902
|
});
|
|
903
|
+
// migrate our own session
|
|
808
904
|
await signalRepository.migrateSession(myPN, myLID);
|
|
809
905
|
logger.info({ myPN, myLID }, 'Own LID session created successfully');
|
|
810
906
|
}
|
|
@@ -814,18 +910,19 @@ const makeSocket = config => {
|
|
|
814
910
|
});
|
|
815
911
|
}
|
|
816
912
|
});
|
|
817
|
-
ws.on('CB:stream:error', node => {
|
|
818
|
-
const [reasonNode] =
|
|
913
|
+
ws.on('CB:stream:error', (node) => {
|
|
914
|
+
const [reasonNode] = getAllBinaryNodeChildren(node);
|
|
819
915
|
logger.error({ reasonNode, fullErrorNode: node }, 'stream errored out');
|
|
820
|
-
const { reason, statusCode } =
|
|
821
|
-
void end(new
|
|
916
|
+
const { reason, statusCode } = getErrorCodeFromStreamError(node);
|
|
917
|
+
void end(new Boom(`Stream Errored (${reason})`, { statusCode, data: reasonNode || node }));
|
|
822
918
|
});
|
|
823
|
-
|
|
919
|
+
// stream fail, possible logout
|
|
920
|
+
ws.on('CB:failure', (node) => {
|
|
824
921
|
const reason = +(node.attrs.reason || 500);
|
|
825
|
-
void end(new
|
|
922
|
+
void end(new Boom('Connection Failure', { statusCode: reason, data: node.attrs }));
|
|
826
923
|
});
|
|
827
924
|
ws.on('CB:ib,,downgrade_webclient', () => {
|
|
828
|
-
void end(new
|
|
925
|
+
void end(new Boom('Multi-device beta not joined', { statusCode: DisconnectReason.multideviceMismatch }));
|
|
829
926
|
});
|
|
830
927
|
ws.on('CB:ib,,offline_preview', async (node) => {
|
|
831
928
|
logger.info('offline preview received', JSON.stringify(node));
|
|
@@ -835,9 +932,9 @@ const makeSocket = config => {
|
|
|
835
932
|
content: [{ tag: 'offline_batch', attrs: { count: '100' } }]
|
|
836
933
|
});
|
|
837
934
|
});
|
|
838
|
-
ws.on('CB:ib,,edge_routing', node => {
|
|
839
|
-
const edgeRoutingNode =
|
|
840
|
-
const routingInfo =
|
|
935
|
+
ws.on('CB:ib,,edge_routing', (node) => {
|
|
936
|
+
const edgeRoutingNode = getBinaryNodeChild(node, 'edge_routing');
|
|
937
|
+
const routingInfo = getBinaryNodeChild(edgeRoutingNode, 'routing_info');
|
|
841
938
|
if (routingInfo?.content) {
|
|
842
939
|
authState.creds.routingInfo = Buffer.from(routingInfo?.content);
|
|
843
940
|
ev.emit('creds.update', authState.creds);
|
|
@@ -846,13 +943,16 @@ const makeSocket = config => {
|
|
|
846
943
|
let didStartBuffer = false;
|
|
847
944
|
process.nextTick(() => {
|
|
848
945
|
if (creds.me?.id) {
|
|
946
|
+
// start buffering important events
|
|
947
|
+
// if we're logged in
|
|
849
948
|
ev.buffer();
|
|
850
949
|
didStartBuffer = true;
|
|
851
950
|
}
|
|
852
951
|
ev.emit('connection.update', { connection: 'connecting', receivedPendingNotifications: false, qr: undefined });
|
|
853
952
|
});
|
|
854
|
-
|
|
855
|
-
|
|
953
|
+
// called when all offline notifs are handled
|
|
954
|
+
ws.on('CB:ib,,offline', (node) => {
|
|
955
|
+
const child = getBinaryNodeChild(node, 'offline');
|
|
856
956
|
const offlineNotifs = +(child?.attrs.count || 0);
|
|
857
957
|
logger.info(`handled ${offlineNotifs} offline messages/notifications`);
|
|
858
958
|
if (didStartBuffer) {
|
|
@@ -861,8 +961,10 @@ const makeSocket = config => {
|
|
|
861
961
|
}
|
|
862
962
|
ev.emit('connection.update', { receivedPendingNotifications: true });
|
|
863
963
|
});
|
|
964
|
+
// update credentials when required
|
|
864
965
|
ev.on('creds.update', update => {
|
|
865
966
|
const name = update.me?.name;
|
|
967
|
+
// if name has just been received
|
|
866
968
|
if (creds.me?.name !== name) {
|
|
867
969
|
logger.debug({ name }, 'updated pushName');
|
|
868
970
|
sendNode({
|
|
@@ -888,9 +990,9 @@ const makeSocket = config => {
|
|
|
888
990
|
logger.debug({ offset: serverTimeOffsetMs }, 'calculated server time offset');
|
|
889
991
|
};
|
|
890
992
|
const getUnifiedSessionId = () => {
|
|
891
|
-
const offsetMs = 3 *
|
|
993
|
+
const offsetMs = 3 * TimeMs.Day;
|
|
892
994
|
const now = Date.now() + serverTimeOffsetMs;
|
|
893
|
-
const id = (now + offsetMs) %
|
|
995
|
+
const id = (now + offsetMs) % TimeMs.Week;
|
|
894
996
|
return id.toString();
|
|
895
997
|
};
|
|
896
998
|
const sendUnifiedSession = async () => {
|
|
@@ -916,23 +1018,31 @@ const makeSocket = config => {
|
|
|
916
1018
|
logger.debug({ error }, 'failed to send unified_session telemetry');
|
|
917
1019
|
}
|
|
918
1020
|
};
|
|
1021
|
+
const registerSocketEndHandler = (handler) => {
|
|
1022
|
+
socketEndHandlers.push(handler);
|
|
1023
|
+
};
|
|
1024
|
+
/**
|
|
1025
|
+
* Fetches your account's standing when it comes to restrictions.
|
|
1026
|
+
* @returns Returns the state of the restrictions.
|
|
1027
|
+
*/
|
|
919
1028
|
const fetchAccountReachoutTimelock = async () => {
|
|
920
|
-
const queryResult = await
|
|
1029
|
+
const queryResult = await executeWMexQuery({}, QueryIds.REACHOUT_TIMELOCK, XWAPaths.xwa2_fetch_account_reachout_timelock, query, generateMessageTag);
|
|
921
1030
|
const result = {
|
|
922
1031
|
isActive: !!queryResult?.is_active,
|
|
923
1032
|
timeEnforcementEnds: queryResult?.time_enforcement_ends && queryResult?.time_enforcement_ends !== '0'
|
|
924
1033
|
? new Date(parseInt(queryResult.time_enforcement_ends, 10) * 1000)
|
|
925
1034
|
: undefined,
|
|
926
|
-
enforcementType: queryResult?.enforcement_type ??
|
|
1035
|
+
enforcementType: queryResult?.enforcement_type ?? ReachoutTimelockEnforcementType.DEFAULT
|
|
927
1036
|
};
|
|
928
1037
|
ev.emit('connection.update', { reachoutTimeLock: result });
|
|
929
1038
|
return result;
|
|
930
1039
|
};
|
|
1040
|
+
/**
|
|
1041
|
+
* Fetches your account's new chat limits.
|
|
1042
|
+
* @returns Returns the quota and the usage.
|
|
1043
|
+
*/
|
|
931
1044
|
const fetchNewChatMessageCap = async () => {
|
|
932
|
-
return
|
|
933
|
-
};
|
|
934
|
-
const registerSocketEndHandler = handler => {
|
|
935
|
-
socketEndHandlers.push(handler);
|
|
1045
|
+
return executeWMexQuery({ input: { type: 'INDIVIDUAL_NEW_CHAT_MSG' } }, QueryIds.MESSAGE_CAPPING_INFO, XWAPaths.xwa2_message_capping_info, query, generateMessageTag);
|
|
936
1046
|
};
|
|
937
1047
|
return {
|
|
938
1048
|
type: 'md',
|
|
@@ -952,9 +1062,6 @@ const makeSocket = config => {
|
|
|
952
1062
|
logout,
|
|
953
1063
|
end,
|
|
954
1064
|
registerSocketEndHandler,
|
|
955
|
-
toPn,
|
|
956
|
-
toLID,
|
|
957
|
-
fetchUsername,
|
|
958
1065
|
onUnexpectedError,
|
|
959
1066
|
uploadPreKeys,
|
|
960
1067
|
uploadPreKeysToServerIfRequired,
|
|
@@ -964,20 +1071,25 @@ const makeSocket = config => {
|
|
|
964
1071
|
updateServerTimeOffset,
|
|
965
1072
|
sendUnifiedSession,
|
|
966
1073
|
wamBuffer: publicWAMBuffer,
|
|
967
|
-
|
|
1074
|
+
/** Waits for the connection to WA to reach a state */
|
|
1075
|
+
waitForConnectionUpdate: bindWaitForConnectionUpdate(ev),
|
|
968
1076
|
sendWAMBuffer,
|
|
969
1077
|
executeUSyncQuery,
|
|
970
1078
|
onWhatsApp,
|
|
971
1079
|
fetchAccountReachoutTimelock,
|
|
972
|
-
fetchNewChatMessageCap
|
|
1080
|
+
fetchNewChatMessageCap,
|
|
1081
|
+
toPn,
|
|
1082
|
+
toLID,
|
|
1083
|
+
fetchUsername
|
|
973
1084
|
};
|
|
974
1085
|
};
|
|
975
|
-
|
|
1086
|
+
/**
|
|
1087
|
+
* map the websocket error to the right type
|
|
1088
|
+
* so it can be retried by the caller
|
|
1089
|
+
* */
|
|
976
1090
|
function mapWebSocketError(handler) {
|
|
977
|
-
return error => {
|
|
978
|
-
handler(new
|
|
979
|
-
statusCode: (0, Utils_1.getCodeFromWSError)(error),
|
|
980
|
-
data: error
|
|
981
|
-
}));
|
|
1091
|
+
return (error) => {
|
|
1092
|
+
handler(new Boom(`WebSocket Error (${error?.message})`, { statusCode: getCodeFromWSError(error), data: error }));
|
|
982
1093
|
};
|
|
983
1094
|
}
|
|
1095
|
+
//# sourceMappingURL=socket.js.map
|