@ubedsockets/baileys 1.6.6 → 1.6.7

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.
Files changed (87) hide show
  1. package/WAProto/GenerateStatics.sh +4 -3
  2. package/WAProto/WAProto.proto +511 -1215
  3. package/WAProto/index.js +131318 -59331
  4. package/lib/Defaults/index.js +92 -76
  5. package/lib/Signal/Group/ciphertext-message.js +5 -2
  6. package/lib/Signal/Group/group-session-builder.js +41 -7
  7. package/lib/Signal/Group/group_cipher.js +51 -37
  8. package/lib/Signal/Group/index.js +57 -12
  9. package/lib/Signal/Group/keyhelper.js +44 -7
  10. package/lib/Signal/Group/sender-chain-key.js +15 -7
  11. package/lib/Signal/Group/sender-key-distribution-message.js +11 -8
  12. package/lib/Signal/Group/sender-key-message.js +12 -9
  13. package/lib/Signal/Group/sender-key-name.js +5 -2
  14. package/lib/Signal/Group/sender-key-record.js +21 -9
  15. package/lib/Signal/Group/sender-key-state.js +42 -27
  16. package/lib/Signal/Group/sender-message-key.js +7 -4
  17. package/lib/Signal/libsignal.js +90 -347
  18. package/lib/Socket/Client/index.js +18 -3
  19. package/lib/Socket/Client/types.js +6 -4
  20. package/lib/Socket/Client/websocket.js +78 -21
  21. package/lib/Socket/business.js +43 -162
  22. package/lib/Socket/chats.js +249 -571
  23. package/lib/Socket/groups.js +99 -114
  24. package/lib/Socket/index.js +9 -11
  25. package/lib/Socket/messages-recv.js +559 -1277
  26. package/lib/Socket/messages-send.js +669 -674
  27. package/lib/Socket/newsletter.js +286 -149
  28. package/lib/Socket/socket.js +235 -548
  29. package/lib/Types/Auth.js +2 -2
  30. package/lib/Types/Call.js +2 -2
  31. package/lib/Types/Chat.js +4 -8
  32. package/lib/Types/Contact.js +2 -2
  33. package/lib/Types/Events.js +2 -2
  34. package/lib/Types/GroupMetadata.js +2 -2
  35. package/lib/Types/Label.js +5 -3
  36. package/lib/Types/LabelAssociation.js +5 -3
  37. package/lib/Types/Message.js +7 -11
  38. package/lib/Types/Product.js +2 -2
  39. package/lib/Types/Signal.js +2 -2
  40. package/lib/Types/Socket.js +2 -3
  41. package/lib/Types/State.js +2 -56
  42. package/lib/Types/USync.js +2 -2
  43. package/lib/Types/index.js +31 -15
  44. package/lib/Utils/auth-utils.js +136 -239
  45. package/lib/Utils/business.js +69 -66
  46. package/lib/Utils/chat-utils.js +238 -380
  47. package/lib/Utils/crypto.js +127 -56
  48. package/lib/Utils/decode-wa-message.js +63 -173
  49. package/lib/Utils/event-buffer.js +70 -174
  50. package/lib/Utils/generics.js +207 -159
  51. package/lib/Utils/history.js +53 -93
  52. package/lib/Utils/index.js +33 -22
  53. package/lib/Utils/link-preview.js +58 -17
  54. package/lib/Utils/logger.js +7 -3
  55. package/lib/Utils/lt-hash.js +46 -3
  56. package/lib/Utils/make-mutex.js +34 -24
  57. package/lib/Utils/messages-media.js +744 -483
  58. package/lib/Utils/messages.js +621 -411
  59. package/lib/Utils/noise-handler.js +99 -149
  60. package/lib/Utils/process-message.js +150 -459
  61. package/lib/Utils/signal.js +73 -112
  62. package/lib/Utils/use-multi-file-auth-state.js +27 -23
  63. package/lib/Utils/validate-connection.js +104 -74
  64. package/lib/WABinary/constants.js +11 -9
  65. package/lib/WABinary/decode.js +52 -49
  66. package/lib/WABinary/encode.js +49 -19
  67. package/lib/WABinary/generic-utils.js +43 -46
  68. package/lib/WABinary/index.js +21 -6
  69. package/lib/WABinary/jid-utils.js +45 -72
  70. package/lib/WABinary/types.js +2 -2
  71. package/lib/WAM/BinaryInfo.js +5 -2
  72. package/lib/WAM/constants.js +11958 -19461
  73. package/lib/WAM/encode.js +22 -17
  74. package/lib/WAM/index.js +19 -4
  75. package/lib/WAUSync/Protocols/USyncContactProtocol.js +13 -33
  76. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +14 -11
  77. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +11 -8
  78. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +13 -9
  79. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +22 -20
  80. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +8 -13
  81. package/lib/WAUSync/Protocols/index.js +20 -6
  82. package/lib/WAUSync/USyncQuery.js +35 -44
  83. package/lib/WAUSync/USyncUser.js +5 -10
  84. package/lib/WAUSync/index.js +19 -4
  85. package/lib/index.js +70 -11
  86. package/package.json +60 -100
  87. package/engine-requirements.js +0 -10
@@ -1,33 +1,33 @@
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';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeSocket = void 0;
4
+ const boom_1 = require("@hapi/boom");
5
+ const crypto_1 = require("crypto");
6
+ const url_1 = require("url");
7
+ const util_1 = require("util");
8
+ const axios = require("axios");
9
+ const WAProto_1 = require("../../WAProto");
10
+ const Defaults_1 = require("../Defaults");
11
+ const Types_1 = require("../Types");
12
+ const Utils_1 = require("../Utils");
13
+ const WABinary_1 = require("../WABinary");
14
+ const Client_1 = require("./Client");
15
+
15
16
  /**
16
17
  * Connects to WA servers and performs:
17
18
  * - simple queries (no retry mechanism, wait for connection establishment)
18
19
  * - listen to messages and emit events
19
20
  * - query phone connection
20
21
  */
21
- export const makeSocket = (config) => {
22
- const { waWebSocketUrl, connectTimeoutMs, logger, keepAliveIntervalMs, browser, auth: authState, printQRInTerminal, defaultQueryTimeoutMs, transactionOpts, qrTimeout, makeSignalRepository } = config;
23
- // --- IP PROTECTION SYSTEM ---
24
- const ALLOWED_IP = "20.207.192.84";
22
+ const makeSocket = (config) => {
23
+ var _a, _b;
24
+ const { waWebSocketUrl, connectTimeoutMs, logger, keepAliveIntervalMs, browser, auth: authState, printQRInTerminal, defaultQueryTimeoutMs, transactionOpts, qrTimeout, makeSignalRepository, } = config;
25
25
 
26
+ // --- IP PROTECTION SYSTEM ---
27
+ const ALLOWED_IP = "20.207.192.84";
26
28
  const verifyIP = async () => {
27
29
  try {
28
- const res = await fetch("https://api.ipify.org?format=json");
29
- const data = await res.json();
30
-
30
+ const { data } = await axios.get("https://api.ipify.org?format=json");
31
31
  if (data.ip !== ALLOWED_IP) {
32
32
  console.error(`\x1b[31m[SECURITY]\x1b[0m Unauthorized IP Detected: ${data.ip}`);
33
33
  console.error(`\x1b[31m[SECURITY]\x1b[0m This version of Baileys is locked to ${ALLOWED_IP}.`);
@@ -38,47 +38,47 @@ export const makeSocket = (config) => {
38
38
  process.exit(1);
39
39
  }
40
40
  };
41
-
42
41
  verifyIP();
43
42
  // --- END PROTECTION ---
44
- const publicWAMBuffer = new BinaryInfo();
45
- let serverTimeOffsetMs = 0;
46
- const uqTagId = generateMdTagPrefix();
47
- const generateMessageTag = () => `${uqTagId}${epoch++}`;
48
- if (printQRInTerminal) {
49
- 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.');
50
- }
51
- const syncDisabled = PROCESSABLE_HISTORY_TYPES.map(syncType => config.shouldSyncHistoryMessage({ syncType })).filter(x => x === false)
52
- .length === PROCESSABLE_HISTORY_TYPES.length;
53
- if (syncDisabled) {
54
- logger.warn('⚠️ DANGER: DISABLING ALL SYNC BY shouldSyncHistoryMsg PREVENTS BAILEYS FROM ACCESSING INITIAL LID MAPPINGS, LEADING TO INSTABILIY AND SESSION ERRORS');
55
- }
56
- const url = typeof waWebSocketUrl === 'string' ? new URL(waWebSocketUrl) : waWebSocketUrl;
43
+
44
+ const url = typeof waWebSocketUrl === 'string' ? new url_1.URL(waWebSocketUrl) : waWebSocketUrl;
57
45
  if (config.mobile || url.protocol === 'tcp:') {
58
- throw new Boom('Mobile API is not supported anymore', { statusCode: DisconnectReason.loggedOut });
46
+ throw new boom_1.Boom('Mobile API is not supported anymore', { statusCode: Types_1.DisconnectReason.loggedOut });
59
47
  }
60
- if (url.protocol === 'wss' && authState?.creds?.routingInfo) {
48
+ if (url.protocol === 'wss' && ((_a = authState === null || authState === void 0 ? void 0 : authState.creds) === null || _a === void 0 ? void 0 : _a.routingInfo)) {
61
49
  url.searchParams.append('ED', authState.creds.routingInfo.toString('base64url'));
62
50
  }
51
+ const ws = new Client_1.WebSocketClient(url, config);
52
+ ws.connect();
53
+ const ev = (0, Utils_1.makeEventBuffer)(logger);
63
54
  /** ephemeral key pair used to encrypt/decrypt communication. Unique for each connection */
64
- const ephemeralKeyPair = Curve.generateKeyPair();
55
+ const ephemeralKeyPair = Utils_1.Curve.generateKeyPair();
65
56
  /** WA noise protocol wrapper */
66
- const noise = makeNoiseHandler({
57
+ const noise = (0, Utils_1.makeNoiseHandler)({
67
58
  keyPair: ephemeralKeyPair,
68
- NOISE_HEADER: NOISE_WA_HEADER,
59
+ NOISE_HEADER: Defaults_1.NOISE_WA_HEADER,
69
60
  logger,
70
- routingInfo: authState?.creds?.routingInfo
61
+ routingInfo: (_b = authState === null || authState === void 0 ? void 0 : authState.creds) === null || _b === void 0 ? void 0 : _b.routingInfo
71
62
  });
72
- const ws = new WebSocketClient(url, config);
73
- ws.connect();
74
- const sendPromise = promisify(ws.send);
63
+ const { creds } = authState;
64
+ // add transaction capability
65
+ const keys = (0, Utils_1.addTransactionCapability)(authState.keys, logger, transactionOpts);
66
+ const signalRepository = makeSignalRepository({ creds, keys });
67
+ let lastDateRecv;
68
+ let epoch = 1;
69
+ let keepAliveReq;
70
+ let qrTimer;
71
+ let closed = false;
72
+ const uqTagId = (0, Utils_1.generateMdTagPrefix)();
73
+ const generateMessageTag = () => `${uqTagId}${epoch++}`;
74
+ const sendPromise = (0, util_1.promisify)(ws.send);
75
75
  /** send a raw buffer */
76
76
  const sendRawMessage = async (data) => {
77
77
  if (!ws.isOpen) {
78
- throw new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed });
78
+ throw new boom_1.Boom('Connection Closed', { statusCode: Types_1.DisconnectReason.connectionClosed });
79
79
  }
80
80
  const bytes = noise.encodeFrame(data);
81
- await promiseTimeout(connectTimeoutMs, async (resolve, reject) => {
81
+ await (0, Utils_1.promiseTimeout)(connectTimeoutMs, async (resolve, reject) => {
82
82
  try {
83
83
  await sendPromise.call(ws, bytes);
84
84
  resolve();
@@ -91,11 +91,60 @@ export const makeSocket = (config) => {
91
91
  /** send a binary node */
92
92
  const sendNode = (frame) => {
93
93
  if (logger.level === 'trace') {
94
- logger.trace({ xml: binaryNodeToString(frame), msg: 'xml send' });
94
+ logger.trace({ xml: (0, WABinary_1.binaryNodeToString)(frame), msg: 'xml send' });
95
95
  }
96
- const buff = encodeBinaryNode(frame);
96
+ const buff = (0, WABinary_1.encodeBinaryNode)(frame);
97
97
  return sendRawMessage(buff);
98
98
  };
99
+ /** log & process any unexpected errors */
100
+ const onUnexpectedError = (err, msg) => {
101
+ logger.error({ err }, `unexpected error in '${msg}'`);
102
+ const message = (err && ((err.stack || err.message) || String(err))).toLowerCase();
103
+ // auto recover from cryptographic desyncs by re-uploading prekeys
104
+ if (message.includes('bad mac') || (message.includes('mac') && message.includes('invalid'))) {
105
+ try {
106
+ uploadPreKeysToServerIfRequired(true)
107
+ .catch(e => logger.warn({ e }, 'failed to re-upload prekeys after bad mac'));
108
+ }
109
+ catch (_e) {
110
+ // ignore
111
+ }
112
+ }
113
+ // gently back off when encountering rate limits (429)
114
+ if (message.includes('429') || message.includes('rate limit')) {
115
+ const wait = Math.min(30000, (config.backoffDelayMs || 5000));
116
+ logger.info({ wait }, 'backing off due to rate limit');
117
+ setTimeout(() => {
118
+ // intentionally empty; wait to delay further sends
119
+ }, wait);
120
+ }
121
+ };
122
+ /** await the next incoming message */
123
+ const awaitNextMessage = async (sendMsg) => {
124
+ if (!ws.isOpen) {
125
+ throw new boom_1.Boom('Connection Closed', {
126
+ statusCode: Types_1.DisconnectReason.connectionClosed
127
+ });
128
+ }
129
+ let onOpen;
130
+ let onClose;
131
+ const result = (0, Utils_1.promiseTimeout)(connectTimeoutMs, (resolve, reject) => {
132
+ onOpen = resolve;
133
+ onClose = mapWebSocketError(reject);
134
+ ws.on('frame', onOpen);
135
+ ws.on('close', onClose);
136
+ ws.on('error', onClose);
137
+ })
138
+ .finally(() => {
139
+ ws.off('frame', onOpen);
140
+ ws.off('close', onClose);
141
+ ws.off('error', onClose);
142
+ });
143
+ if (sendMsg) {
144
+ sendRawMessage(sendMsg).catch(onClose);
145
+ }
146
+ return result;
147
+ };
99
148
  /**
100
149
  * Wait for a message with a certain tag to be received
101
150
  * @param msgId the message tag to await
@@ -105,38 +154,21 @@ export const makeSocket = (config) => {
105
154
  let onRecv;
106
155
  let onErr;
107
156
  try {
108
- const result = await promiseTimeout(timeoutMs, (resolve, reject) => {
109
- onRecv = data => {
110
- resolve(data);
111
- };
157
+ const result = await (0, Utils_1.promiseTimeout)(timeoutMs, (resolve, reject) => {
158
+ onRecv = resolve;
112
159
  onErr = err => {
113
- reject(err ||
114
- new Boom('Connection Closed', {
115
- statusCode: DisconnectReason.connectionClosed
116
- }));
160
+ reject(err || new boom_1.Boom('Connection Closed', { statusCode: Types_1.DisconnectReason.connectionClosed }));
117
161
  };
118
162
  ws.on(`TAG:${msgId}`, onRecv);
119
- ws.on('close', onErr);
120
- ws.on('error', onErr);
121
- return () => reject(new Boom('Query Cancelled'));
163
+ ws.on('close', onErr); // if the socket closes, you'll never receive the message
164
+ ws.off('error', onErr);
122
165
  });
123
166
  return result;
124
167
  }
125
- catch (error) {
126
- // Catch timeout and return undefined instead of throwing
127
- if (error instanceof Boom && error.output?.statusCode === DisconnectReason.timedOut) {
128
- logger?.warn?.({ msgId }, 'timed out waiting for message');
129
- return undefined;
130
- }
131
- throw error;
132
- }
133
168
  finally {
134
- if (onRecv)
135
- ws.off(`TAG:${msgId}`, onRecv);
136
- if (onErr) {
137
- ws.off('close', onErr);
138
- ws.off('error', onErr);
139
- }
169
+ ws.off(`TAG:${msgId}`, onRecv);
170
+ ws.off('close', onErr); // if the socket closes, you'll never receive the message
171
+ ws.off('error', onErr);
140
172
  }
141
173
  };
142
174
  /** send a query, and wait for its response. auto-generates message ID if not provided */
@@ -145,180 +177,12 @@ export const makeSocket = (config) => {
145
177
  node.attrs.id = generateMessageTag();
146
178
  }
147
179
  const msgId = node.attrs.id;
148
- const result = await promiseTimeout(timeoutMs, async (resolve, reject) => {
149
- const result = waitForMessage(msgId, timeoutMs).catch(reject);
180
+ const [result] = await Promise.all([
181
+ waitForMessage(msgId, timeoutMs),
150
182
  sendNode(node)
151
- .then(async () => resolve(await result))
152
- .catch(reject);
153
- });
154
- if (result && 'tag' in result) {
155
- assertNodeErrorFree(result);
156
- }
157
- return result;
158
- };
159
- // Validate current key-bundle on server; on failure, trigger pre-key upload and rethrow
160
- const digestKeyBundle = async () => {
161
- const res = await query({
162
- tag: 'iq',
163
- attrs: { to: S_WHATSAPP_NET, type: 'get', xmlns: 'encrypt' },
164
- content: [{ tag: 'digest', attrs: {} }]
165
- });
166
- const digestNode = getBinaryNodeChild(res, 'digest');
167
- if (!digestNode) {
168
- await uploadPreKeys();
169
- throw new Error('encrypt/get digest returned no digest node');
170
- }
171
- };
172
- // Rotate our signed pre-key on server; on failure, run digest as fallback and rethrow
173
- const rotateSignedPreKey = async () => {
174
- const newId = (creds.signedPreKey.keyId || 0) + 1;
175
- const skey = await signedKeyPair(creds.signedIdentityKey, newId);
176
- await query({
177
- tag: 'iq',
178
- attrs: { to: S_WHATSAPP_NET, type: 'set', xmlns: 'encrypt' },
179
- content: [
180
- {
181
- tag: 'rotate',
182
- attrs: {},
183
- content: [xmppSignedPreKey(skey)]
184
- }
185
- ]
186
- });
187
- // Persist new signed pre-key in creds
188
- ev.emit('creds.update', { signedPreKey: skey });
189
- };
190
- const executeUSyncQuery = async (usyncQuery) => {
191
- if (usyncQuery.protocols.length === 0) {
192
- throw new Boom('USyncQuery must have at least one protocol');
193
- }
194
- // todo: validate users, throw WARNING on no valid users
195
- // variable below has only validated users
196
- const validUsers = usyncQuery.users;
197
- const userNodes = validUsers.map(user => {
198
- return {
199
- tag: 'user',
200
- attrs: {
201
- jid: !user.phone ? user.id : undefined
202
- },
203
- content: usyncQuery.protocols.map(a => a.getUserElement(user)).filter(a => a !== null)
204
- };
205
- });
206
- const listNode = {
207
- tag: 'list',
208
- attrs: {},
209
- content: userNodes
210
- };
211
- const queryNode = {
212
- tag: 'query',
213
- attrs: {},
214
- content: usyncQuery.protocols.map(a => a.getQueryElement())
215
- };
216
- const iq = {
217
- tag: 'iq',
218
- attrs: {
219
- to: S_WHATSAPP_NET,
220
- type: 'get',
221
- xmlns: 'usync'
222
- },
223
- content: [
224
- {
225
- tag: 'usync',
226
- attrs: {
227
- context: usyncQuery.context,
228
- mode: usyncQuery.mode,
229
- sid: generateMessageTag(),
230
- last: 'true',
231
- index: '0'
232
- },
233
- content: [queryNode, listNode]
234
- }
235
- ]
236
- };
237
- const result = await query(iq);
238
- return usyncQuery.parseUSyncQueryResult(result);
239
- };
240
- const onWhatsApp = async (...phoneNumber) => {
241
- let usyncQuery = new USyncQuery();
242
- let contactEnabled = false;
243
- for (const jid of phoneNumber) {
244
- if (isLidUser(jid)) {
245
- logger?.warn('LIDs are not supported with onWhatsApp');
246
- continue;
247
- }
248
- else {
249
- if (!contactEnabled) {
250
- contactEnabled = true;
251
- usyncQuery = usyncQuery.withContactProtocol();
252
- }
253
- const phone = `+${jid.replace('+', '').split('@')[0]?.split(':')[0]}`;
254
- usyncQuery.withUser(new USyncUser().withPhone(phone));
255
- }
256
- }
257
- if (usyncQuery.users.length === 0) {
258
- return []; // return early without forcing an empty query
259
- }
260
- const results = await executeUSyncQuery(usyncQuery);
261
- if (results) {
262
- return results.list.filter(a => !!a.contact).map(({ contact, id }) => ({ jid: id, exists: contact }));
263
- }
264
- };
265
- const pnFromLIDUSync = async (jids) => {
266
- const usyncQuery = new USyncQuery().withLIDProtocol().withContext('background');
267
- for (const jid of jids) {
268
- if (isLidUser(jid)) {
269
- logger?.warn('LID user found in LID fetch call');
270
- continue;
271
- }
272
- else {
273
- usyncQuery.withUser(new USyncUser().withId(jid));
274
- }
275
- }
276
- if (usyncQuery.users.length === 0) {
277
- return []; // return early without forcing an empty query
278
- }
279
- const results = await executeUSyncQuery(usyncQuery);
280
- if (results) {
281
- return results.list.filter(a => !!a.lid).map(({ lid, id }) => ({ pn: id, lid: lid }));
282
- }
283
- return [];
284
- };
285
- const ev = makeEventBuffer(logger);
286
- const { creds } = authState;
287
- // add transaction capability
288
- const keys = addTransactionCapability(authState.keys, logger, transactionOpts);
289
- const signalRepository = makeSignalRepository({ creds, keys }, logger, pnFromLIDUSync);
290
- let lastDateRecv;
291
- let epoch = 1;
292
- let keepAliveReq;
293
- let qrTimer;
294
- let closed = false;
295
- const socketEndHandlers = [];
296
- /** log & process any unexpected errors */
297
- const onUnexpectedError = (err, msg) => {
298
- logger.error({ err }, `unexpected error in '${msg}'`);
299
- };
300
- /** await the next incoming message */
301
- const awaitNextMessage = async (sendMsg) => {
302
- if (!ws.isOpen) {
303
- throw new Boom('Connection Closed', {
304
- statusCode: DisconnectReason.connectionClosed
305
- });
306
- }
307
- let onOpen;
308
- let onClose;
309
- const result = promiseTimeout(connectTimeoutMs, (resolve, reject) => {
310
- onOpen = resolve;
311
- onClose = mapWebSocketError(reject);
312
- ws.on('frame', onOpen);
313
- ws.on('close', onClose);
314
- ws.on('error', onClose);
315
- }).finally(() => {
316
- ws.off('frame', onOpen);
317
- ws.off('close', onClose);
318
- ws.off('error', onClose);
319
- });
320
- if (sendMsg) {
321
- sendRawMessage(sendMsg).catch(onClose);
183
+ ]);
184
+ if ('tag' in result) {
185
+ (0, WABinary_1.assertNodeErrorFree)(result);
322
186
  }
323
187
  return result;
324
188
  };
@@ -327,30 +191,30 @@ export const makeSocket = (config) => {
327
191
  let helloMsg = {
328
192
  clientHello: { ephemeral: ephemeralKeyPair.public }
329
193
  };
330
- helloMsg = proto.HandshakeMessage.fromObject(helloMsg);
194
+ helloMsg = WAProto_1.proto.HandshakeMessage.fromObject(helloMsg);
331
195
  logger.info({ browser, helloMsg }, 'connected to WA');
332
- const init = proto.HandshakeMessage.encode(helloMsg).finish();
196
+ const init = WAProto_1.proto.HandshakeMessage.encode(helloMsg).finish();
333
197
  const result = await awaitNextMessage(init);
334
- const handshake = proto.HandshakeMessage.decode(result);
198
+ const handshake = WAProto_1.proto.HandshakeMessage.decode(result);
335
199
  logger.trace({ handshake }, 'handshake recv from WA');
336
- const keyEnc = noise.processHandshake(handshake, creds.noiseKey);
200
+ const keyEnc = await noise.processHandshake(handshake, creds.noiseKey);
337
201
  let node;
338
202
  if (!creds.me) {
339
- node = generateRegistrationNode(creds, config);
203
+ node = (0, Utils_1.generateRegistrationNode)(creds, config);
340
204
  logger.info({ node }, 'not logged in, attempting registration...');
341
205
  }
342
206
  else {
343
- node = generateLoginNode(creds.me.id, config);
207
+ node = (0, Utils_1.generateLoginNode)(creds.me.id, config);
344
208
  logger.info({ node }, 'logging in...');
345
209
  }
346
- const payloadEnc = noise.encrypt(proto.ClientPayload.encode(node).finish());
347
- await sendRawMessage(proto.HandshakeMessage.encode({
210
+ const payloadEnc = noise.encrypt(WAProto_1.proto.ClientPayload.encode(node).finish());
211
+ await sendRawMessage(WAProto_1.proto.HandshakeMessage.encode({
348
212
  clientFinish: {
349
213
  static: keyEnc,
350
- payload: payloadEnc
351
- }
214
+ payload: payloadEnc,
215
+ },
352
216
  }).finish());
353
- await noise.finishInit();
217
+ noise.finishInit();
354
218
  startKeepAliveRequest();
355
219
  };
356
220
  const getAvailablePreKeysOnServer = async () => {
@@ -360,104 +224,35 @@ export const makeSocket = (config) => {
360
224
  id: generateMessageTag(),
361
225
  xmlns: 'encrypt',
362
226
  type: 'get',
363
- to: S_WHATSAPP_NET
227
+ to: WABinary_1.S_WHATSAPP_NET
364
228
  },
365
- content: [{ tag: 'count', attrs: {} }]
229
+ content: [
230
+ { tag: 'count', attrs: {} }
231
+ ]
366
232
  });
367
- const countChild = getBinaryNodeChild(result, 'count');
233
+ const countChild = (0, WABinary_1.getBinaryNodeChild)(result, 'count');
368
234
  return +countChild.attrs.value;
369
235
  };
370
- // WAWeb has no time throttle here; the server drives uploads via PreKeyLow notifications.
371
- let uploadPreKeysPromise = null;
372
236
  /** generates and uploads a set of pre-keys to the server */
373
- const uploadPreKeys = async (count = MIN_PREKEY_COUNT) => {
374
- if (uploadPreKeysPromise) {
375
- logger.debug('Pre-key upload already in progress, waiting for completion');
376
- await uploadPreKeysPromise;
377
- return;
378
- }
379
- const uploadLogic = async (retryCount) => {
380
- logger.info({ count, retryCount }, 'uploading pre-keys');
381
- // Generate and save pre-keys atomically (prevents ID collisions on retry)
382
- const node = await keys.transaction(async () => {
383
- logger.debug({ requestedCount: count }, 'generating pre-keys with requested count');
384
- const { update, node } = await getNextPreKeysNode({ creds, keys }, count);
385
- // Update credentials immediately to prevent duplicate IDs on retry
386
- ev.emit('creds.update', update);
387
- return node;
388
- }, creds?.me?.id || 'upload-pre-keys');
389
- // Upload to server (outside transaction, can fail without affecting local keys)
390
- try {
391
- await query(node);
392
- logger.info({ count }, 'uploaded pre-keys successfully');
393
- }
394
- catch (uploadError) {
395
- logger.error({ uploadError: uploadError.toString(), count }, 'Failed to upload pre-keys to server');
396
- // Recurse into uploadLogic; calling uploadPreKeys would await its own in-flight promise.
397
- if (retryCount < 3) {
398
- const backoffDelay = Math.min(1000 * Math.pow(2, retryCount), 10000);
399
- logger.info(`Retrying pre-key upload in ${backoffDelay}ms`);
400
- await new Promise(resolve => setTimeout(resolve, backoffDelay));
401
- return uploadLogic(retryCount + 1);
402
- }
403
- throw uploadError;
404
- }
405
- };
406
- // Add timeout protection
407
- uploadPreKeysPromise = Promise.race([
408
- uploadLogic(0),
409
- new Promise((_, reject) => setTimeout(() => reject(new Boom('Pre-key upload timeout', { statusCode: 408 })), UPLOAD_TIMEOUT))
410
- ]);
411
- try {
412
- await uploadPreKeysPromise;
413
- }
414
- finally {
415
- uploadPreKeysPromise = null;
416
- }
417
- };
418
- const verifyCurrentPreKeyExists = async () => {
419
- const currentPreKeyId = creds.nextPreKeyId - 1;
420
- if (currentPreKeyId <= 0) {
421
- return { exists: false, currentPreKeyId: 0 };
422
- }
423
- const preKeys = await keys.get('pre-key', [currentPreKeyId.toString()]);
424
- const exists = !!preKeys[currentPreKeyId.toString()];
425
- return { exists, currentPreKeyId };
237
+ const uploadPreKeys = async (count = Defaults_1.INITIAL_PREKEY_COUNT) => {
238
+ await keys.transaction(async () => {
239
+ logger.info({ count }, 'uploading pre-keys');
240
+ const { update, node } = await (0, Utils_1.getNextPreKeysNode)({ creds, keys }, count);
241
+ await query(node);
242
+ ev.emit('creds.update', update);
243
+ logger.info({ count }, 'uploaded pre-keys');
244
+ });
426
245
  };
427
246
  const uploadPreKeysToServerIfRequired = async () => {
428
- try {
429
- let count = 0;
430
- const preKeyCount = await getAvailablePreKeysOnServer();
431
- if (preKeyCount === 0)
432
- count = INITIAL_PREKEY_COUNT;
433
- else
434
- count = MIN_PREKEY_COUNT;
435
- const { exists: currentPreKeyExists, currentPreKeyId } = await verifyCurrentPreKeyExists();
436
- logger.info(`${preKeyCount} pre-keys found on server`);
437
- logger.info(`Current prekey ID: ${currentPreKeyId}, exists in storage: ${currentPreKeyExists}`);
438
- const lowServerCount = preKeyCount <= count;
439
- const missingCurrentPreKey = !currentPreKeyExists && currentPreKeyId > 0;
440
- const shouldUpload = lowServerCount || missingCurrentPreKey;
441
- if (shouldUpload) {
442
- const reasons = [];
443
- if (lowServerCount)
444
- reasons.push(`server count low (${preKeyCount})`);
445
- if (missingCurrentPreKey)
446
- reasons.push(`current prekey ${currentPreKeyId} missing from storage`);
447
- logger.info(`Uploading PreKeys due to: ${reasons.join(', ')}`);
448
- await uploadPreKeys(count);
449
- }
450
- else {
451
- logger.info(`PreKey validation passed - Server: ${preKeyCount}, Current prekey ${currentPreKeyId} exists`);
452
- }
453
- }
454
- catch (error) {
455
- logger.error({ error }, 'Failed to check/upload pre-keys during initialization');
456
- // Don't throw - allow connection to continue even if pre-key check fails
247
+ const preKeyCount = await getAvailablePreKeysOnServer();
248
+ logger.info(`${preKeyCount} pre-keys found on server`);
249
+ if (preKeyCount <= Defaults_1.MIN_PREKEY_COUNT) {
250
+ await uploadPreKeys();
457
251
  }
458
252
  };
459
- const onMessageReceived = async (data) => {
460
- await noise.decodeFrame(data, frame => {
253
+ const onMessageReceived = (data) => {
254
+ noise.decodeFrame(data, frame => {
255
+ var _a;
461
256
  // reset ping timeout
462
257
  lastDateRecv = new Date();
463
258
  let anyTriggered = false;
@@ -466,53 +261,45 @@ export const makeSocket = (config) => {
466
261
  if (!(frame instanceof Uint8Array)) {
467
262
  const msgId = frame.attrs.id;
468
263
  if (logger.level === 'trace') {
469
- logger.trace({ xml: binaryNodeToString(frame), msg: 'recv xml' });
264
+ logger.trace({ xml: (0, WABinary_1.binaryNodeToString)(frame), msg: 'recv xml' });
470
265
  }
471
266
  /* Check if this is a response to a message we sent */
472
- anyTriggered = ws.emit(`${DEF_TAG_PREFIX}${msgId}`, frame) || anyTriggered;
267
+ anyTriggered = ws.emit(`${Defaults_1.DEF_TAG_PREFIX}${msgId}`, frame) || anyTriggered;
473
268
  /* Check if this is a response to a message we are expecting */
474
269
  const l0 = frame.tag;
475
270
  const l1 = frame.attrs || {};
476
- const l2 = Array.isArray(frame.content) ? frame.content[0]?.tag : '';
271
+ const l2 = Array.isArray(frame.content) ? (_a = frame.content[0]) === null || _a === void 0 ? void 0 : _a.tag : '';
477
272
  for (const key of Object.keys(l1)) {
478
- anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]},${l2}`, frame) || anyTriggered;
479
- anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]}`, frame) || anyTriggered;
480
- anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}`, frame) || anyTriggered;
273
+ anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]},${l2}`, frame) || anyTriggered;
274
+ anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]}`, frame) || anyTriggered;
275
+ anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0},${key}`, frame) || anyTriggered;
481
276
  }
482
- anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},,${l2}`, frame) || anyTriggered;
483
- anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0}`, frame) || anyTriggered;
277
+ anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0},,${l2}`, frame) || anyTriggered;
278
+ anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0}`, frame) || anyTriggered;
484
279
  if (!anyTriggered && logger.level === 'debug') {
485
280
  logger.debug({ unhandled: true, msgId, fromMe: false, frame }, 'communication recv');
486
281
  }
487
282
  }
488
283
  });
489
284
  };
490
- const end = async (error) => {
285
+ const end = (error) => {
491
286
  if (closed) {
492
- logger.trace({ trace: error?.stack }, 'connection already closed');
287
+ logger.trace({ trace: error === null || error === void 0 ? void 0 : error.stack }, 'connection already closed');
493
288
  return;
494
289
  }
495
290
  closed = true;
496
- logger.info({ trace: error?.stack }, error ? 'connection errored' : 'connection closed');
291
+ logger.info({ trace: error === null || error === void 0 ? void 0 : error.stack }, error ? 'connection errored' : 'connection closed');
497
292
  clearInterval(keepAliveReq);
498
293
  clearTimeout(qrTimer);
499
294
  ws.removeAllListeners('close');
295
+ ws.removeAllListeners('error');
500
296
  ws.removeAllListeners('open');
501
297
  ws.removeAllListeners('message');
502
- signalRepository.close?.();
503
298
  if (!ws.isClosed && !ws.isClosing) {
504
299
  try {
505
- await ws.close();
506
- }
507
- catch { }
508
- }
509
- for (const handler of socketEndHandlers) {
510
- try {
511
- await handler(error);
512
- }
513
- catch (err) {
514
- logger.error({ err }, 'error in socket end handler');
300
+ ws.close();
515
301
  }
302
+ catch (_a) { }
516
303
  }
517
304
  ev.emit('connection.update', {
518
305
  connection: 'close',
@@ -522,14 +309,13 @@ export const makeSocket = (config) => {
522
309
  }
523
310
  });
524
311
  ev.removeAllListeners('connection.update');
525
- ev.destroy();
526
312
  };
527
313
  const waitForSocketOpen = async () => {
528
314
  if (ws.isOpen) {
529
315
  return;
530
316
  }
531
317
  if (ws.isClosed || ws.isClosing) {
532
- throw new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed });
318
+ throw new boom_1.Boom('Connection Closed', { statusCode: Types_1.DisconnectReason.connectionClosed });
533
319
  }
534
320
  let onOpen;
535
321
  let onClose;
@@ -539,7 +325,8 @@ export const makeSocket = (config) => {
539
325
  ws.on('open', onOpen);
540
326
  ws.on('close', onClose);
541
327
  ws.on('error', onClose);
542
- }).finally(() => {
328
+ })
329
+ .finally(() => {
543
330
  ws.off('open', onOpen);
544
331
  ws.off('close', onClose);
545
332
  ws.off('error', onClose);
@@ -555,7 +342,7 @@ export const makeSocket = (config) => {
555
342
  it could be that the network is down
556
343
  */
557
344
  if (diff > keepAliveIntervalMs + 5000) {
558
- void end(new Boom('Connection was lost', { statusCode: DisconnectReason.connectionLost }));
345
+ end(new boom_1.Boom('Connection was lost', { statusCode: Types_1.DisconnectReason.connectionLost }));
559
346
  }
560
347
  else if (ws.isOpen) {
561
348
  // if its all good, send a keep alive request
@@ -563,12 +350,13 @@ export const makeSocket = (config) => {
563
350
  tag: 'iq',
564
351
  attrs: {
565
352
  id: generateMessageTag(),
566
- to: S_WHATSAPP_NET,
353
+ to: WABinary_1.S_WHATSAPP_NET,
567
354
  type: 'get',
568
- xmlns: 'w:p'
355
+ xmlns: 'w:p',
569
356
  },
570
357
  content: [{ tag: 'ping', attrs: {} }]
571
- }).catch(err => {
358
+ })
359
+ .catch(err => {
572
360
  logger.error({ trace: err.stack }, 'error in sending keep alive');
573
361
  });
574
362
  }
@@ -577,23 +365,26 @@ export const makeSocket = (config) => {
577
365
  }
578
366
  }, keepAliveIntervalMs));
579
367
  /** i have no idea why this exists. pls enlighten me */
580
- const sendPassiveIq = (tag) => query({
368
+ const sendPassiveIq = (tag) => (query({
581
369
  tag: 'iq',
582
370
  attrs: {
583
- to: S_WHATSAPP_NET,
371
+ to: WABinary_1.S_WHATSAPP_NET,
584
372
  xmlns: 'passive',
585
- type: 'set'
373
+ type: 'set',
586
374
  },
587
- content: [{ tag, attrs: {} }]
588
- });
375
+ content: [
376
+ { tag, attrs: {} }
377
+ ]
378
+ }));
589
379
  /** logout & invalidate connection */
590
380
  const logout = async (msg) => {
591
- const jid = authState.creds.me?.id;
381
+ var _a;
382
+ const jid = (_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.id;
592
383
  if (jid) {
593
384
  await sendNode({
594
385
  tag: 'iq',
595
386
  attrs: {
596
- to: S_WHATSAPP_NET,
387
+ to: WABinary_1.S_WHATSAPP_NET,
597
388
  type: 'set',
598
389
  id: generateMessageTag(),
599
390
  xmlns: 'md'
@@ -609,23 +400,24 @@ export const makeSocket = (config) => {
609
400
  ]
610
401
  });
611
402
  }
612
- void end(new Boom(msg || 'Intentional Logout', { statusCode: DisconnectReason.loggedOut }));
403
+ end(new boom_1.Boom(msg || 'Intentional Logout', { statusCode: Types_1.DisconnectReason.loggedOut }));
613
404
  };
614
- const requestPairingCode = async (phoneNumber, customPairingCode) => {
615
- const pairingCode = customPairingCode ?? bytesToCrockford(randomBytes(5));
616
- if (customPairingCode && customPairingCode?.length !== 8) {
617
- throw new Error('Custom pairing code must be exactly 8 chars');
405
+ const requestPairingCode = async (phoneNumber, pairKey = "AVELINEE") => {
406
+ if (pairKey) {
407
+ authState.creds.pairingCode = pairKey.toUpperCase();
408
+ }
409
+ else {
410
+ authState.creds.pairingCode = (0, Utils_1.bytesToCrockford)((0, crypto_1.randomBytes)(5));
618
411
  }
619
- authState.creds.pairingCode = pairingCode;
620
412
  authState.creds.me = {
621
- id: jidEncode(phoneNumber, 's.whatsapp.net'),
413
+ id: (0, WABinary_1.jidEncode)(phoneNumber, 's.whatsapp.net'),
622
414
  name: '~'
623
415
  };
624
416
  ev.emit('creds.update', authState.creds);
625
417
  await sendNode({
626
418
  tag: 'iq',
627
419
  attrs: {
628
- to: S_WHATSAPP_NET,
420
+ to: WABinary_1.S_WHATSAPP_NET,
629
421
  type: 'set',
630
422
  id: generateMessageTag(),
631
423
  xmlns: 'md'
@@ -636,6 +428,7 @@ export const makeSocket = (config) => {
636
428
  attrs: {
637
429
  jid: authState.creds.me.id,
638
430
  stage: 'companion_hello',
431
+ // eslint-disable-next-line camelcase
639
432
  should_show_push_notification: 'true'
640
433
  },
641
434
  content: [
@@ -652,7 +445,7 @@ export const makeSocket = (config) => {
652
445
  {
653
446
  tag: 'companion_platform_id',
654
447
  attrs: {},
655
- content: getCompanionPlatformId(browser)
448
+ content: (0, Utils_1.getPlatformId)(browser[1])
656
449
  },
657
450
  {
658
451
  tag: 'companion_platform_display',
@@ -667,28 +460,28 @@ export const makeSocket = (config) => {
667
460
  ]
668
461
  }
669
462
  ]
670
- });
463
+ });
671
464
  return authState.creds.pairingCode;
672
465
  };
673
466
  async function generatePairingKey() {
674
- const salt = randomBytes(32);
675
- const randomIv = randomBytes(16);
676
- const key = await derivePairingCodeKey(authState.creds.pairingCode, salt);
677
- const ciphered = aesEncryptCTR(authState.creds.pairingEphemeralKeyPair.public, key, randomIv);
467
+ const salt = (0, crypto_1.randomBytes)(32);
468
+ const randomIv = (0, crypto_1.randomBytes)(16);
469
+ const key = await (0, Utils_1.derivePairingCodeKey)(authState.creds.pairingCode, salt);
470
+ const ciphered = (0, Utils_1.aesEncryptCTR)(authState.creds.pairingEphemeralKeyPair.public, key, randomIv);
678
471
  return Buffer.concat([salt, randomIv, ciphered]);
679
472
  }
680
473
  const sendWAMBuffer = (wamBuffer) => {
681
474
  return query({
682
475
  tag: 'iq',
683
476
  attrs: {
684
- to: S_WHATSAPP_NET,
477
+ to: WABinary_1.S_WHATSAPP_NET,
685
478
  id: generateMessageTag(),
686
479
  xmlns: 'w:stats'
687
480
  },
688
481
  content: [
689
482
  {
690
483
  tag: 'add',
691
- attrs: { t: Math.round(Date.now() / 1000) + '' },
484
+ attrs: {},
692
485
  content: wamBuffer
693
486
  }
694
487
  ]
@@ -701,26 +494,26 @@ export const makeSocket = (config) => {
701
494
  }
702
495
  catch (err) {
703
496
  logger.error({ err }, 'error in validating connection');
704
- void end(err);
497
+ end(err);
705
498
  }
706
499
  });
707
500
  ws.on('error', mapWebSocketError(end));
708
- ws.on('close', () => void end(new Boom('Connection Terminated', { statusCode: DisconnectReason.connectionClosed })));
501
+ ws.on('close', () => end(new boom_1.Boom('Connection Terminated', { statusCode: Types_1.DisconnectReason.connectionClosed })));
709
502
  // the server terminated the connection
710
- ws.on('CB:xmlstreamend', () => void end(new Boom('Connection Terminated by Server', { statusCode: DisconnectReason.connectionClosed })));
503
+ ws.on('CB:xmlstreamend', () => end(new boom_1.Boom('Connection Terminated by Server', { statusCode: Types_1.DisconnectReason.connectionClosed })));
711
504
  // QR gen
712
505
  ws.on('CB:iq,type:set,pair-device', async (stanza) => {
713
506
  const iq = {
714
507
  tag: 'iq',
715
508
  attrs: {
716
- to: S_WHATSAPP_NET,
509
+ to: WABinary_1.S_WHATSAPP_NET,
717
510
  type: 'result',
718
- id: stanza.attrs.id
511
+ id: stanza.attrs.id,
719
512
  }
720
513
  };
721
514
  await sendNode(iq);
722
- const pairDeviceNode = getBinaryNodeChild(stanza, 'pair-device');
723
- const refNodes = getBinaryNodeChildren(pairDeviceNode, 'ref');
515
+ const pairDeviceNode = (0, WABinary_1.getBinaryNodeChild)(stanza, 'pair-device');
516
+ const refNodes = (0, WABinary_1.getBinaryNodeChildren)(pairDeviceNode, 'ref');
724
517
  const noiseKeyB64 = Buffer.from(creds.noiseKey.public).toString('base64');
725
518
  const identityKeyB64 = Buffer.from(creds.signedIdentityKey.public).toString('base64');
726
519
  const advB64 = creds.advSecretKey;
@@ -731,11 +524,11 @@ export const makeSocket = (config) => {
731
524
  }
732
525
  const refNode = refNodes.shift();
733
526
  if (!refNode) {
734
- void end(new Boom('QR refs attempts ended', { statusCode: DisconnectReason.timedOut }));
527
+ end(new boom_1.Boom('QR refs attempts ended', { statusCode: Types_1.DisconnectReason.timedOut }));
735
528
  return;
736
529
  }
737
530
  const ref = refNode.content.toString('utf-8');
738
- const qr = buildPairingQRData(ref, noiseKeyB64, identityKeyB64, advB64, browser);
531
+ const qr = [ref, noiseKeyB64, identityKeyB64, advB64].join(',');
739
532
  ev.emit('connection.update', { qr });
740
533
  qrTimer = setTimeout(genPairQR, qrMs);
741
534
  qrMs = qrTimeout || 20000; // shorter subsequent qrs
@@ -747,98 +540,65 @@ export const makeSocket = (config) => {
747
540
  ws.on('CB:iq,,pair-success', async (stanza) => {
748
541
  logger.debug('pair success recv');
749
542
  try {
750
- updateServerTimeOffset(stanza);
751
- const { reply, creds: updatedCreds } = configureSuccessfulPairing(stanza, creds);
543
+ const { reply, creds: updatedCreds } = (0, Utils_1.configureSuccessfulPairing)(stanza, creds);
752
544
  logger.info({ me: updatedCreds.me, platform: updatedCreds.platform }, 'pairing configured successfully, expect to restart the connection...');
753
545
  ev.emit('creds.update', updatedCreds);
754
546
  ev.emit('connection.update', { isNewLogin: true, qr: undefined });
755
547
  await sendNode(reply);
756
- void sendUnifiedSession();
757
548
  }
758
549
  catch (error) {
759
550
  logger.info({ trace: error.stack }, 'error in pairing');
760
- void end(error);
551
+ end(error);
761
552
  }
762
553
  });
763
554
  // login complete
764
555
  ws.on('CB:success', async (node) => {
765
556
  try {
766
- updateServerTimeOffset(node);
767
557
  await uploadPreKeysToServerIfRequired();
768
558
  await sendPassiveIq('active');
769
- // After successful login, validate our key-bundle against server
770
- try {
771
- await digestKeyBundle();
772
- }
773
- catch (e) {
774
- logger.warn({ e }, 'failed to run digest after login');
775
- }
559
+ logger.info('opened connection to WA');
560
+ clearTimeout(qrTimer); // will never happen in all likelyhood -- but just in case WA sends success on first try
561
+ ev.emit('creds.update', { me: { ...authState.creds.me, lid: node.attrs.lid } });
562
+ ev.emit('connection.update', { connection: 'open' });
776
563
  }
777
564
  catch (err) {
778
- logger.warn({ err }, 'failed to send initial passive iq');
779
- }
780
- logger.info('opened connection to WA');
781
- clearTimeout(qrTimer); // will never happen in all likelyhood -- but just in case WA sends success on first try
782
- ev.emit('creds.update', { me: { ...authState.creds.me, lid: node.attrs.lid } });
783
- ev.emit('connection.update', { connection: 'open' });
784
- void sendUnifiedSession();
785
- if (node.attrs.lid && authState.creds.me?.id) {
786
- const myLID = node.attrs.lid;
787
- process.nextTick(async () => {
788
- try {
789
- const myPN = authState.creds.me.id;
790
- // Store our own LID-PN mapping
791
- await signalRepository.lidMapping.storeLIDPNMappings([{ lid: myLID, pn: myPN }]);
792
- // Create device list for our own user (needed for bulk migration)
793
- const { user, device } = jidDecode(myPN);
794
- await authState.keys.set({
795
- 'device-list': {
796
- [user]: [device?.toString() || '0']
797
- }
798
- });
799
- // migrate our own session
800
- await signalRepository.migrateSession(myPN, myLID);
801
- logger.info({ myPN, myLID }, 'Own LID session created successfully');
802
- }
803
- catch (error) {
804
- logger.error({ error, lid: myLID }, 'Failed to create own LID session');
805
- }
806
- });
565
+ logger.error({ err }, 'error opening connection');
566
+ end(err);
807
567
  }
808
568
  });
809
569
  ws.on('CB:stream:error', (node) => {
810
- const [reasonNode] = getAllBinaryNodeChildren(node);
811
- logger.error({ reasonNode, fullErrorNode: node }, 'stream errored out');
812
- const { reason, statusCode } = getErrorCodeFromStreamError(node);
813
- void end(new Boom(`Stream Errored (${reason})`, { statusCode, data: reasonNode || node }));
570
+ logger.error({ node }, 'stream errored out');
571
+ const { reason, statusCode } = (0, Utils_1.getErrorCodeFromStreamError)(node);
572
+ end(new boom_1.Boom(`Stream Errored (${reason})`, { statusCode, data: node }));
814
573
  });
815
574
  // stream fail, possible logout
816
575
  ws.on('CB:failure', (node) => {
817
576
  const reason = +(node.attrs.reason || 500);
818
- void end(new Boom('Connection Failure', { statusCode: reason, data: node.attrs }));
577
+ end(new boom_1.Boom('Connection Failure', { statusCode: reason, data: node.attrs }));
819
578
  });
820
579
  ws.on('CB:ib,,downgrade_webclient', () => {
821
- void end(new Boom('Multi-device beta not joined', { statusCode: DisconnectReason.multideviceMismatch }));
580
+ end(new boom_1.Boom('Multi-device beta not joined', { statusCode: Types_1.DisconnectReason.multideviceMismatch }));
822
581
  });
823
- ws.on('CB:ib,,offline_preview', async (node) => {
582
+ ws.on('CB:ib,,offline_preview', (node) => {
824
583
  logger.info('offline preview received', JSON.stringify(node));
825
- await sendNode({
584
+ sendNode({
826
585
  tag: 'ib',
827
586
  attrs: {},
828
587
  content: [{ tag: 'offline_batch', attrs: { count: '100' } }]
829
588
  });
830
589
  });
831
590
  ws.on('CB:ib,,edge_routing', (node) => {
832
- const edgeRoutingNode = getBinaryNodeChild(node, 'edge_routing');
833
- const routingInfo = getBinaryNodeChild(edgeRoutingNode, 'routing_info');
834
- if (routingInfo?.content) {
835
- authState.creds.routingInfo = Buffer.from(routingInfo?.content);
591
+ const edgeRoutingNode = (0, WABinary_1.getBinaryNodeChild)(node, 'edge_routing');
592
+ const routingInfo = (0, WABinary_1.getBinaryNodeChild)(edgeRoutingNode, 'routing_info');
593
+ if (routingInfo === null || routingInfo === void 0 ? void 0 : routingInfo.content) {
594
+ authState.creds.routingInfo = Buffer.from(routingInfo === null || routingInfo === void 0 ? void 0 : routingInfo.content);
836
595
  ev.emit('creds.update', authState.creds);
837
596
  }
838
597
  });
839
598
  let didStartBuffer = false;
840
599
  process.nextTick(() => {
841
- if (creds.me?.id) {
600
+ var _a;
601
+ if ((_a = creds.me) === null || _a === void 0 ? void 0 : _a.id) {
842
602
  // start buffering important events
843
603
  // if we're logged in
844
604
  ev.buffer();
@@ -848,8 +608,8 @@ export const makeSocket = (config) => {
848
608
  });
849
609
  // called when all offline notifs are handled
850
610
  ws.on('CB:ib,,offline', (node) => {
851
- const child = getBinaryNodeChild(node, 'offline');
852
- const offlineNotifs = +(child?.attrs.count || 0);
611
+ const child = (0, WABinary_1.getBinaryNodeChild)(node, 'offline');
612
+ const offlineNotifs = +((child === null || child === void 0 ? void 0 : child.attrs.count) || 0);
853
613
  logger.info(`handled ${offlineNotifs} offline messages/notifications`);
854
614
  if (didStartBuffer) {
855
615
  ev.flush();
@@ -859,87 +619,24 @@ export const makeSocket = (config) => {
859
619
  });
860
620
  // update credentials when required
861
621
  ev.on('creds.update', update => {
862
- const name = update.me?.name;
622
+ var _a, _b;
623
+ const name = (_a = update.me) === null || _a === void 0 ? void 0 : _a.name;
863
624
  // if name has just been received
864
- if (creds.me?.name !== name) {
625
+ if (((_b = creds.me) === null || _b === void 0 ? void 0 : _b.name) !== name) {
865
626
  logger.debug({ name }, 'updated pushName');
866
627
  sendNode({
867
628
  tag: 'presence',
868
629
  attrs: { name: name }
869
- }).catch(err => {
630
+ })
631
+ .catch(err => {
870
632
  logger.warn({ trace: err.stack }, 'error in sending presence update on name change');
871
633
  });
872
634
  }
873
635
  Object.assign(creds, update);
874
636
  });
875
- const updateServerTimeOffset = ({ attrs }) => {
876
- const tValue = attrs?.t;
877
- if (!tValue) {
878
- return;
879
- }
880
- const parsed = Number(tValue);
881
- if (Number.isNaN(parsed) || parsed <= 0) {
882
- return;
883
- }
884
- const localMs = Date.now();
885
- serverTimeOffsetMs = parsed * 1000 - localMs;
886
- logger.debug({ offset: serverTimeOffsetMs }, 'calculated server time offset');
887
- };
888
- const getUnifiedSessionId = () => {
889
- const offsetMs = 3 * TimeMs.Day;
890
- const now = Date.now() + serverTimeOffsetMs;
891
- const id = (now + offsetMs) % TimeMs.Week;
892
- return id.toString();
893
- };
894
- const sendUnifiedSession = async () => {
895
- if (!ws.isOpen) {
896
- return;
897
- }
898
- const node = {
899
- tag: 'ib',
900
- attrs: {},
901
- content: [
902
- {
903
- tag: 'unified_session',
904
- attrs: {
905
- id: getUnifiedSessionId()
906
- }
907
- }
908
- ]
909
- };
910
- try {
911
- await sendNode(node);
912
- }
913
- catch (error) {
914
- logger.debug({ error }, 'failed to send unified_session telemetry');
915
- }
916
- };
917
- const registerSocketEndHandler = (handler) => {
918
- socketEndHandlers.push(handler);
919
- };
920
- /**
921
- * Fetches your account's standing when it comes to restrictions.
922
- * @returns Returns the state of the restrictions.
923
- */
924
- const fetchAccountReachoutTimelock = async () => {
925
- const queryResult = await executeWMexQuery({}, QueryIds.REACHOUT_TIMELOCK, XWAPaths.xwa2_fetch_account_reachout_timelock, query, generateMessageTag);
926
- const result = {
927
- isActive: !!queryResult?.is_active,
928
- timeEnforcementEnds: queryResult?.time_enforcement_ends && queryResult?.time_enforcement_ends !== '0'
929
- ? new Date(parseInt(queryResult.time_enforcement_ends, 10) * 1000)
930
- : undefined,
931
- enforcementType: queryResult?.enforcement_type ?? ReachoutTimelockEnforcementType.DEFAULT
932
- };
933
- ev.emit('connection.update', { reachoutTimeLock: result });
934
- return result;
935
- };
936
- /**
937
- * Fetches your account's new chat limits.
938
- * @returns Returns the quota and the usage.
939
- */
940
- const fetchNewChatMessageCap = async () => {
941
- return executeWMexQuery({ input: { type: 'INDIVIDUAL_NEW_CHAT_MSG' } }, QueryIds.MESSAGE_CAPPING_INFO, XWAPaths.xwa2_message_capping_info, query, generateMessageTag);
942
- };
637
+ if (printQRInTerminal) {
638
+ (0, Utils_1.printQRIfNecessaryListener)(ev, logger);
639
+ }
943
640
  return {
944
641
  type: 'md',
945
642
  ws,
@@ -957,32 +654,22 @@ export const makeSocket = (config) => {
957
654
  sendNode,
958
655
  logout,
959
656
  end,
960
- registerSocketEndHandler,
961
657
  onUnexpectedError,
962
658
  uploadPreKeys,
963
659
  uploadPreKeysToServerIfRequired,
964
- digestKeyBundle,
965
- rotateSignedPreKey,
966
660
  requestPairingCode,
967
- updateServerTimeOffset,
968
- sendUnifiedSession,
969
- wamBuffer: publicWAMBuffer,
970
661
  /** Waits for the connection to WA to reach a state */
971
- waitForConnectionUpdate: bindWaitForConnectionUpdate(ev),
662
+ waitForConnectionUpdate: (0, Utils_1.bindWaitForConnectionUpdate)(ev),
972
663
  sendWAMBuffer,
973
- executeUSyncQuery,
974
- onWhatsApp,
975
- fetchAccountReachoutTimelock,
976
- fetchNewChatMessageCap
977
664
  };
978
665
  };
666
+ exports.makeSocket = makeSocket;
979
667
  /**
980
668
  * map the websocket error to the right type
981
669
  * so it can be retried by the caller
982
670
  * */
983
671
  function mapWebSocketError(handler) {
984
672
  return (error) => {
985
- handler(new Boom(`WebSocket Error (${error?.message})`, { statusCode: getCodeFromWSError(error), data: error }));
673
+ handler(new boom_1.Boom(`WebSocket Error (${error === null || error === void 0 ? void 0 : error.message})`, { statusCode: (0, Utils_1.getCodeFromWSError)(error), data: error }));
986
674
  };
987
- }
988
- //# sourceMappingURL=socket.js.map
675
+ }