@alannxd/baileys 6.0.5 → 6.0.6

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