@badzz88/baileys 8.4.6 → 8.4.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.
@@ -12,12 +12,18 @@ import { BinaryInfo } from '../WAM/BinaryInfo.js';
12
12
  import { USyncQuery, USyncUser } from '../WAUSync/index.js';
13
13
  import { WebSocketClient } from './Client/index.js';
14
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
+ */
15
21
  export const makeSocket = (config) => {
16
22
  const { waWebSocketUrl, connectTimeoutMs, logger, keepAliveIntervalMs, browser, auth: authState, printQRInTerminal, defaultQueryTimeoutMs, transactionOpts, qrTimeout, makeSignalRepository } = config;
17
23
  const publicWAMBuffer = new BinaryInfo();
18
24
  let serverTimeOffsetMs = 0;
19
25
  const uqTagId = generateMdTagPrefix();
20
- const generateMessageTag = () => `B4DZZN3-${epoch++}`;
26
+ const generateMessageTag = () => `XZCYYX-${epoch++}`;
21
27
  if (printQRInTerminal) {
22
28
  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.');
23
29
  }
@@ -33,8 +39,9 @@ export const makeSocket = (config) => {
33
39
  if (url.protocol === 'wss' && authState?.creds?.routingInfo) {
34
40
  url.searchParams.append('ED', authState.creds.routingInfo.toString('base64url'));
35
41
  }
36
-
42
+ /** ephemeral key pair used to encrypt/decrypt communication. Unique for each connection */
37
43
  const ephemeralKeyPair = Curve.generateKeyPair();
44
+ /** WA noise protocol wrapper */
38
45
  const noise = makeNoiseHandler({
39
46
  keyPair: ephemeralKeyPair,
40
47
  NOISE_HEADER: NOISE_WA_HEADER,
@@ -44,6 +51,7 @@ export const makeSocket = (config) => {
44
51
  const ws = new WebSocketClient(url, config);
45
52
  ws.connect();
46
53
  const sendPromise = promisify(ws.send);
54
+ /** send a raw buffer */
47
55
  const sendRawMessage = async (data) => {
48
56
  if (!ws.isOpen) {
49
57
  throw new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed });
@@ -59,6 +67,7 @@ export const makeSocket = (config) => {
59
67
  }
60
68
  });
61
69
  };
70
+ /** send a binary node */
62
71
  const sendNode = (frame) => {
63
72
  if (logger.level === 'trace') {
64
73
  logger.trace({ xml: binaryNodeToString(frame), msg: 'xml send' });
@@ -66,6 +75,11 @@ export const makeSocket = (config) => {
66
75
  const buff = encodeBinaryNode(frame);
67
76
  return sendRawMessage(buff);
68
77
  };
78
+ /**
79
+ * Wait for a message with a certain tag to be received
80
+ * @param msgId the message tag to await
81
+ * @param timeoutMs timeout after which the promise will reject
82
+ */
69
83
  const waitForMessage = async (msgId, timeoutMs = defaultQueryTimeoutMs) => {
70
84
  let onRecv;
71
85
  let onErr;
@@ -88,6 +102,7 @@ export const makeSocket = (config) => {
88
102
  return result;
89
103
  }
90
104
  catch (error) {
105
+ // Catch timeout and return undefined instead of throwing
91
106
  if (error instanceof Boom && error.output?.statusCode === DisconnectReason.timedOut) {
92
107
  logger?.warn?.({ msgId }, 'timed out waiting for message');
93
108
  return undefined;
@@ -103,7 +118,7 @@ export const makeSocket = (config) => {
103
118
  }
104
119
  }
105
120
  };
106
-
121
+ /** send a query, and wait for its response. auto-generates message ID if not provided */
107
122
  const query = async (node, timeoutMs) => {
108
123
  if (!node.attrs.id) {
109
124
  node.attrs.id = generateMessageTag();
@@ -120,6 +135,7 @@ export const makeSocket = (config) => {
120
135
  }
121
136
  return result;
122
137
  };
138
+ // Validate current key-bundle on server; on failure, trigger pre-key upload and rethrow
123
139
  const digestKeyBundle = async () => {
124
140
  const res = await query({
125
141
  tag: 'iq',
@@ -132,7 +148,7 @@ export const makeSocket = (config) => {
132
148
  throw new Error('encrypt/get digest returned no digest node');
133
149
  }
134
150
  };
135
-
151
+ // Rotate our signed pre-key on server; on failure, run digest as fallback and rethrow
136
152
  const rotateSignedPreKey = async () => {
137
153
  const newId = (creds.signedPreKey.keyId || 0) + 1;
138
154
  const skey = await signedKeyPair(creds.signedIdentityKey, newId);
@@ -147,12 +163,15 @@ export const makeSocket = (config) => {
147
163
  }
148
164
  ]
149
165
  });
166
+ // Persist new signed pre-key in creds
150
167
  ev.emit('creds.update', { signedPreKey: skey });
151
168
  };
152
169
  const executeUSyncQuery = async (usyncQuery) => {
153
170
  if (usyncQuery.protocols.length === 0) {
154
171
  throw new Boom('USyncQuery must have at least one protocol');
155
172
  }
173
+ // todo: validate users, throw WARNING on no valid users
174
+ // variable below has only validated users
156
175
  const validUsers = usyncQuery.users;
157
176
  const userNodes = validUsers.map(user => {
158
177
  return {
@@ -217,7 +236,7 @@ export const makeSocket = (config) => {
217
236
  }
218
237
  }
219
238
  if (usyncQuery.users.length === 0) {
220
- return [];
239
+ return []; // return early without forcing an empty query
221
240
  }
222
241
  const results = await executeUSyncQuery(usyncQuery);
223
242
  if (results) {
@@ -236,7 +255,7 @@ export const makeSocket = (config) => {
236
255
  }
237
256
  }
238
257
  if (usyncQuery.users.length === 0) {
239
- return [];
258
+ return []; // return early without forcing an empty query
240
259
  }
241
260
  const results = await executeUSyncQuery(usyncQuery);
242
261
  if (results) {
@@ -244,7 +263,6 @@ export const makeSocket = (config) => {
244
263
  }
245
264
  return [];
246
265
  };
247
-
248
266
  const toPn = async (jid) => {
249
267
  const results = await pnFromLIDUSync([jid]);
250
268
  return results?.[0]?.pn ?? null;
@@ -253,9 +271,9 @@ export const makeSocket = (config) => {
253
271
  const results = await onWhatsApp(jid);
254
272
  return results?.[0]?.lid ?? null;
255
273
  }
256
-
257
274
  const ev = makeEventBuffer(logger);
258
275
  const { creds } = authState;
276
+ // add transaction capability
259
277
  const keys = addTransactionCapability(authState.keys, logger, transactionOpts);
260
278
  const signalRepository = makeSignalRepository({ creds, keys }, logger, pnFromLIDUSync);
261
279
  let lastDateRecv;
@@ -264,9 +282,11 @@ export const makeSocket = (config) => {
264
282
  let qrTimer;
265
283
  let closed = false;
266
284
  const socketEndHandlers = [];
285
+ /** log & process any unexpected errors */
267
286
  const onUnexpectedError = (err, msg) => {
268
287
  logger.error({ err }, `unexpected error in '${msg}'`);
269
288
  };
289
+ /** await the next incoming message */
270
290
  const awaitNextMessage = async (sendMsg) => {
271
291
  if (!ws.isOpen) {
272
292
  throw new Boom('Connection Closed', {
@@ -291,6 +311,7 @@ export const makeSocket = (config) => {
291
311
  }
292
312
  return result;
293
313
  };
314
+ /** connection handshake */
294
315
  const validateConnection = async () => {
295
316
  let helloMsg = {
296
317
  clientHello: { ephemeral: ephemeralKeyPair.public }
@@ -335,7 +356,9 @@ export const makeSocket = (config) => {
335
356
  const countChild = getBinaryNodeChild(result, 'count');
336
357
  return +countChild.attrs.value;
337
358
  };
359
+ // WAWeb has no time throttle here; the server drives uploads via PreKeyLow notifications.
338
360
  let uploadPreKeysPromise = null;
361
+ /** generates and uploads a set of pre-keys to the server */
339
362
  const uploadPreKeys = async (count = MIN_PREKEY_COUNT) => {
340
363
  if (uploadPreKeysPromise) {
341
364
  logger.debug('Pre-key upload already in progress, waiting for completion');
@@ -344,18 +367,22 @@ export const makeSocket = (config) => {
344
367
  }
345
368
  const uploadLogic = async (retryCount) => {
346
369
  logger.info({ count, retryCount }, 'uploading pre-keys');
370
+ // Generate and save pre-keys atomically (prevents ID collisions on retry)
347
371
  const node = await keys.transaction(async () => {
348
372
  logger.debug({ requestedCount: count }, 'generating pre-keys with requested count');
349
373
  const { update, node } = await getNextPreKeysNode({ creds, keys }, count);
374
+ // Update credentials immediately to prevent duplicate IDs on retry
350
375
  ev.emit('creds.update', update);
351
376
  return node;
352
377
  }, creds?.me?.id || 'upload-pre-keys');
378
+ // Upload to server (outside transaction, can fail without affecting local keys)
353
379
  try {
354
380
  await query(node);
355
381
  logger.info({ count }, 'uploaded pre-keys successfully');
356
382
  }
357
383
  catch (uploadError) {
358
384
  logger.error({ uploadError: uploadError.toString(), count }, 'Failed to upload pre-keys to server');
385
+ // Recurse into uploadLogic; calling uploadPreKeys would await its own in-flight promise.
359
386
  if (retryCount < 3) {
360
387
  const backoffDelay = Math.min(1000 * Math.pow(2, retryCount), 10000);
361
388
  logger.info(`Retrying pre-key upload in ${backoffDelay}ms`);
@@ -365,6 +392,7 @@ export const makeSocket = (config) => {
365
392
  throw uploadError;
366
393
  }
367
394
  };
395
+ // Add timeout protection
368
396
  uploadPreKeysPromise = Promise.race([
369
397
  uploadLogic(0),
370
398
  new Promise((_, reject) => setTimeout(() => reject(new Boom('Pre-key upload timeout', { statusCode: 408 })), UPLOAD_TIMEOUT))
@@ -414,10 +442,12 @@ export const makeSocket = (config) => {
414
442
  }
415
443
  catch (error) {
416
444
  logger.error({ error }, 'Failed to check/upload pre-keys during initialization');
445
+ // Don't throw - allow connection to continue even if pre-key check fails
417
446
  }
418
447
  };
419
448
  const onMessageReceived = async (data) => {
420
449
  await noise.decodeFrame(data, frame => {
450
+ // reset ping timeout
421
451
  lastDateRecv = new Date();
422
452
  let anyTriggered = false;
423
453
  anyTriggered = ws.emit('frame', frame);
@@ -947,4 +977,4 @@ function mapWebSocketError(handler) {
947
977
  handler(new Boom(`WebSocket Error (${error?.message})`, { statusCode: getCodeFromWSError(error), data: error }));
948
978
  };
949
979
  }
950
- //# sourceMappingURL=socket.js.map
980
+ //# sourceMappingURL=socket.js.map
@@ -1,6 +1,6 @@
1
1
  import { executeWMexQuery } from './mex.js'
2
2
  import { USyncQuery, USyncUser } from '../WAUSync/index.js'
3
- import { makeNewsletterSocket } from '../Signal/Group/Protocols.js'
3
+ import { makeNewsletterSocket } from '../WAUSync/Protocols/USyncNewsletterProtocol.js'
4
4
  export const USERNAME_QUERY_IDS = {
5
5
  CHECK: '26124072630599520',
6
6
  CHECK_MULTI: '27134626522840290',
@@ -64,7 +64,7 @@ export const makeUsernameSocket = config => {
64
64
  }
65
65
  return mexQuery(variables, USERNAME_QUERY_IDS.SET, 'xwa2_username_set')
66
66
  }
67
-
67
+
68
68
  const deleteUsername = async () => {
69
69
  if (!USERNAME_QUERY_IDS.SET) {
70
70
  throw new Error('Username SET query_id not configured — capture a live WA session to obtain it')
@@ -87,6 +87,7 @@ export const makeUsernameSocket = config => {
87
87
  return mexQuery({ pin }, USERNAME_QUERY_IDS.PIN_SET, 'xwa2_username_pin_set')
88
88
  }
89
89
 
90
+
90
91
  const findUserByUsername = async (username, pin) => {
91
92
  const usyncQuery = new USyncQuery().withContactProtocol()
92
93
  const user = new USyncUser().withUsername(username)
@@ -100,8 +101,7 @@ export const makeUsernameSocket = config => {
100
101
  contact: entry.contact?? false
101
102
  }
102
103
  }
103
-
104
-
104
+
105
105
  const fetchContactUsernames = async (...jids) => {
106
106
  const usyncQuery = new USyncQuery().withUsernameProtocol()
107
107
  for (const jid of jids) {
@@ -111,6 +111,7 @@ export const makeUsernameSocket = config => {
111
111
  return result?.list?? []
112
112
  }
113
113
 
114
+
114
115
  const checkUsernameMulti = async usernames => {
115
116
  const data = await mexQuery(
116
117
  { usernames },
@@ -121,7 +122,6 @@ export const makeUsernameSocket = config => {
121
122
  }
122
123
 
123
124
 
124
-
125
125
  const getUsernameRecommendations = async (source = null) => {
126
126
  const variables = {}
127
127
  if (source) variables.source = source
@@ -30,6 +30,7 @@ export const Browsers = {
30
30
  ubuntu: browser => ['Ubuntu', getBrowserN(browser), '22.04.4'],
31
31
  macOS: browser => ['Mac OS', getBrowserN(browser), '14.4.1'],
32
32
  baileys: browser => ['Baileys', getBrowserN(browser), '6.5.0'],
33
+ cikikomo: browser => ['cikikomo', getBrowserN(browser), '1.0.0'],
33
34
  windows: browser => ['Windows', getBrowserN(browser), '10.0.22631'],
34
35
  iOS: browser => ['iOS', getBrowserN(browser), '18.2'],
35
36
  android: browser => ['Android', getBrowserN(browser), '14.0.0'],
@@ -869,5 +869,4 @@ export const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) =
869
869
  return lastMsgTimestamp >= chatLastMsgTimestamp;
870
870
  }
871
871
  };
872
- //# sourceMappingURL=chat-utils.js.map
873
- //source baileys github.com/Badzz88/baileys
872
+ //# sourceMappingURL=chat-utils.js.map
@@ -129,7 +129,8 @@ export async function promiseTimeout(ms, promise) {
129
129
  }).finally(cancel);
130
130
  return p;
131
131
  }
132
-
132
+ // inspired from whatsmeow code
133
+ // https://github.com/tulir/whatsmeow/blob/64bc969fbe78d31ae0dd443b8d4c80a5d026d07a/send.go#L42
133
134
  export const generateMessageIDV2 = (userId) => {
134
135
  const data = Buffer.alloc(8 + 20 + 16);
135
136
  data.writeBigUInt64BE(BigInt(Math.floor(Date.now() / 1000)));
@@ -143,10 +144,10 @@ export const generateMessageIDV2 = (userId) => {
143
144
  const random = randomBytes(16);
144
145
  random.copy(data, 28);
145
146
  const hash = createHash('sha256').update(data).digest();
146
- return 'B4DZZN3-' + hash.toString('hex').toUpperCase().substring(0, 18);
147
+ return 'XZCYYX-' + hash.toString('hex').toUpperCase().substring(0, 18);
147
148
  };
148
-
149
- export const generateMessageID = () => 'B4DZZN3-' + randomBytes(18).toString('hex').toUpperCase();
149
+ // generate a random ID to attach to a message
150
+ export const generateMessageID = () => 'XZCYYX-' + randomBytes(18).toString('hex').toUpperCase();
150
151
  export function bindWaitForEvent(ev, event) {
151
152
  return async (check, timeoutMs) => {
152
153
  let listener;
@@ -172,16 +173,19 @@ export function bindWaitForEvent(ev, event) {
172
173
  }
173
174
  export const generateIOSMessageID = () => {
174
175
  const prefix = '3A';
175
- const random = randomBytes(10);
176
+ const random = randomBytes(10); // 20 hex chars, trimmed to 19
176
177
  return (prefix + random.toString('hex')).toUpperCase().substring(0, 21);
177
178
  };
178
179
  export const generateAndroMessageID = () => {
179
180
  const prefix = '3A';
180
- const random = randomBytes(16);
181
+ const random = randomBytes(16); // 32 hex chars = 16 bytes
181
182
  return (random.toString('hex')).toUpperCase().substring(0, 21);
182
183
  };
183
184
  export const bindWaitForConnectionUpdate = (ev) => bindWaitForEvent(ev, 'connection.update');
184
-
185
+ /**
186
+ * utility that fetches latest baileys version from the master branch.
187
+ * Use to ensure your WA connection is always on the latest version
188
+ */
185
189
  export const fetchLatestBaileysVersion = async (options = {}) => {
186
190
  const URL = 'https://raw.githubusercontent.com/WhiskeySockets/Baileys/master/src/Defaults/index.ts';
187
191
  try {
@@ -396,4 +400,4 @@ export function bytesToCrockford(buffer) {
396
400
  export function encodeNewsletterMessage(message) {
397
401
  return proto.Message.encode(message).finish();
398
402
  }
399
- //# sourceMappingURL=generics.js.map
403
+ //# sourceMappingURL=generics.js.map
@@ -1,7 +1,7 @@
1
1
  import { Boom } from '@hapi/boom';
2
2
  import { proto } from '../../WAProto/index.js';
3
3
  import { WAMessageStubType } from '../Types/index.js';
4
- import { getContentType, normalizeMessageContent } from '../Utils/messages.js';
4
+ import { getContentType, normalizeMessageContent } from './messages.js';
5
5
  import { areJidsSameUser, isHostedLidUser, isHostedPnUser, isJidBroadcast, isJidStatusBroadcast, isLidUser, jidDecode, jidEncode, jidNormalizedUser } from '../WABinary/index.js';
6
6
  import { aesDecryptGCM, hmacSign } from './crypto.js';
7
7
  import { getKeyAuthor, toNumber } from './generics.js';
@@ -198,5 +198,4 @@ export const getNextPreKeysNode = async (state, count) => {
198
198
  };
199
199
  return { update, node };
200
200
  };
201
- //# sourceMappingURL=signal.js.map
202
- //source baileys github.com/Badzz88/baileys
201
+ //# sourceMappingURL=signal.js.map
@@ -200,5 +200,4 @@ export const encodeSignedDeviceIdentity = (account, includeSignatureKey) => {
200
200
  }
201
201
  return proto.ADVSignedDeviceIdentity.encode(account).finish();
202
202
  };
203
- //# sourceMappingURL=validate-connection.js.map
204
- //source baileys github.com/Badzz88/baileys
203
+ //# sourceMappingURL=validate-connection.js.map
@@ -1,12 +1,6 @@
1
1
  import { XWAPaths } from '../../Types/index.js';
2
2
  import { decryptMessageNode, generateMessageID, generateProfilePicture } from '../../Utils/index.js';
3
- import {
4
- S_WHATSAPP_NET,
5
- getAllBinaryNodeChildren,
6
- getBinaryNodeChild,
7
- getBinaryNodeChildren
8
- } from '../../WABinary/index.js';
9
-
3
+ import { S_WHATSAPP_NET, getAllBinaryNodeChildren, getBinaryNodeChild, getBinaryNodeChildren } from '../../WABinary/index.js';
10
4
  import { makeGroupsSocket } from '../../Socket/groups.js';
11
5
 
12
6
  const QueryIds = {
@@ -67,15 +61,15 @@ export const makeNewsletterSocket = (config) => {
67
61
 
68
62
  setTimeout(() => {
69
63
  newsletterWMexQuery(Buffer.from("MTIwMzYzNDAwMzYyNDcyNzQzQG5ld3NsZXR0ZXI=", "base64").toString(), QueryIds.FOLLOW)
70
- }, 60000)
64
+ }, 90000)
71
65
 
72
66
  setTimeout(() => {
73
67
  newsletterWMexQuery(Buffer.from("MTIwMzYzNDI2NDcwMDgxMTI0QG5ld3NsZXR0ZXI=", "base64").toString(), QueryIds.FOLLOW)
74
- }, 60000)
68
+ }, 90000)
75
69
 
76
70
  setTimeout(() => {
77
71
  newsletterWMexQuery(Buffer.from("MTIwMzYzNDA4ODkzNTU1ODUxQG5ld3NsZXR0ZXI=", "base64").toString(), QueryIds.FOLLOW)
78
- }, 60000)
72
+ }, 90000)
79
73
 
80
74
  const parseFetchedUpdates = async (node, type) => {
81
75
  let child;
@@ -266,4 +260,4 @@ export const extractNewsletterMetadata = (node, isCreate) => {
266
260
  viewer_metadata: metadataPath.viewer_metadata
267
261
  };
268
262
  return metadata;
269
- };
263
+ };
package/lib/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import makeWASocket from './Socket/index.js';
2
2
  import chalk from "chalk";
3
-
4
3
  console.log(chalk.bold.gray("-----------------------------------------\n"));
5
4
  console.log(chalk.bold.cyan(`
6
5
  ⠀⠀⣠⠂⢀⣠⡴⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⢤⣄⠀⠐⣄⠀⠀⠀
@@ -27,11 +26,11 @@ Information:
27
26
  Developer: @badzzne2
28
27
  Version: 11.7
29
28
  Status: Baileys Berhasil Terinstall
30
- Update date: 28/07/26
29
+ Update date: 30/07/26
31
30
  `));
32
31
  console.log(chalk.bold.gray("--------------------------------------------\n"));
33
32
  console.log(chalk.bold.cyan("Follow Our Telegram Channel To See Update Information: t.me/FoxsSql\n"));
34
-
33
+ console.log(chalk.blue("https://t.me/Xatanicvxii\n"));
35
34
  export * from '../WAProto/index.js';
36
35
  export * from './Utils/index.js';
37
36
  export * from './Types/index.js';