@pontalabs/baileys 1.0.11 → 1.1.1

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 (119) hide show
  1. package/README.md +96 -85
  2. package/lib/Defaults/connection.js +39 -0
  3. package/lib/Defaults/constants.js +50 -0
  4. package/lib/Defaults/history.js +13 -0
  5. package/lib/Defaults/index.js +36 -151
  6. package/lib/Defaults/media.js +43 -0
  7. package/lib/Defaults/phonenumber-mcc.json +221 -221
  8. package/lib/Defaults/prefix.js +12 -0
  9. package/lib/Defaults/vialeys-version.json +7 -0
  10. package/lib/Signal/Group/ciphertext-message.js +10 -15
  11. package/lib/Signal/Group/group-session-builder.js +34 -60
  12. package/lib/Signal/Group/group_cipher.js +69 -76
  13. package/lib/Signal/Group/index.js +41 -60
  14. package/lib/Signal/Group/keyhelper.js +12 -57
  15. package/lib/Signal/Group/sender-chain-key.js +20 -33
  16. package/lib/Signal/Group/sender-key-distribution-message.js +43 -48
  17. package/lib/Signal/Group/sender-key-message.js +58 -53
  18. package/lib/Signal/Group/sender-key-name.js +21 -31
  19. package/lib/Signal/Group/sender-key-record.js +21 -34
  20. package/lib/Signal/Group/sender-key-state.js +59 -106
  21. package/lib/Signal/Group/sender-message-key.js +16 -21
  22. package/lib/Signal/libsignal.js +282 -203
  23. package/lib/Signal/lid-mapping.js +164 -184
  24. package/lib/Socket/Client/index.js +31 -22
  25. package/lib/Socket/Client/types.js +9 -15
  26. package/lib/Socket/Client/websocket.js +42 -37
  27. package/lib/Socket/business.js +212 -336
  28. package/lib/Socket/chats.js +696 -940
  29. package/lib/Socket/community.js +454 -369
  30. package/lib/Socket/groups.js +278 -280
  31. package/lib/Socket/index.js +9 -21
  32. package/lib/Socket/messages-recv.js +1027 -1570
  33. package/lib/Socket/messages-send.js +1180 -1136
  34. package/lib/Socket/mex.js +59 -0
  35. package/lib/Socket/newsletter.js +193 -251
  36. package/lib/Socket/socket.js +758 -898
  37. package/lib/Store/index.js +35 -24
  38. package/lib/Store/make-cache-manager-store.js +53 -66
  39. package/lib/Store/make-in-memory-store.js +319 -325
  40. package/lib/Store/make-ordered-dictionary.js +49 -57
  41. package/lib/Store/object-repository.js +10 -15
  42. package/lib/Types/Auth.js +2 -3
  43. package/lib/Types/Bussines.js +2 -3
  44. package/lib/Types/Call.js +2 -3
  45. package/lib/Types/Chat.js +10 -9
  46. package/lib/Types/Contact.js +2 -3
  47. package/lib/Types/Events.js +2 -3
  48. package/lib/Types/GroupMetadata.js +2 -3
  49. package/lib/Types/Label.js +6 -12
  50. package/lib/Types/LabelAssociation.js +4 -13
  51. package/lib/Types/Message.js +10 -18
  52. package/lib/Types/MexUpdates.js +15 -18
  53. package/lib/Types/Newsletter.js +26 -34
  54. package/lib/Types/Product.js +2 -3
  55. package/lib/Types/Signal.js +2 -3
  56. package/lib/Types/Socket.js +2 -3
  57. package/lib/Types/State.js +8 -13
  58. package/lib/Types/USync.js +2 -3
  59. package/lib/Types/index.js +49 -40
  60. package/lib/Utils/auth-utils.js +190 -495
  61. package/lib/Utils/browser-utils.js +29 -0
  62. package/lib/Utils/business.js +177 -199
  63. package/lib/Utils/chat-utils.js +711 -624
  64. package/lib/Utils/crypto.js +116 -161
  65. package/lib/Utils/decode-wa-message.js +225 -321
  66. package/lib/Utils/event-buffer.js +363 -405
  67. package/lib/Utils/generics.js +318 -472
  68. package/lib/Utils/history.js +72 -76
  69. package/lib/Utils/index.js +49 -41
  70. package/lib/Utils/link-preview.js +59 -103
  71. package/lib/Utils/logger.js +4 -7
  72. package/lib/Utils/lt-hash.js +29 -42
  73. package/lib/Utils/make-mutex.js +26 -42
  74. package/lib/Utils/message-retry-manager.js +134 -160
  75. package/lib/Utils/messages-media.js +665 -731
  76. package/lib/Utils/messages.js +518 -1
  77. package/lib/Utils/noise-handler.js +127 -125
  78. package/lib/Utils/pre-key-manager.js +86 -0
  79. package/lib/Utils/process-message.js +739 -351
  80. package/lib/Utils/signal.js +146 -129
  81. package/lib/Utils/use-multi-file-auth-state.js +68 -135
  82. package/lib/Utils/validate-connection.js +183 -142
  83. package/lib/Utils/vialeys-event-stream.js +41 -0
  84. package/lib/WABinary/constants.js +1281 -1289
  85. package/lib/WABinary/decode.js +145 -200
  86. package/lib/WABinary/encode.js +149 -202
  87. package/lib/WABinary/generic-utils.js +79 -97
  88. package/lib/WABinary/index.js +36 -25
  89. package/lib/WABinary/jid-utils.js +91 -123
  90. package/lib/WABinary/types.js +2 -3
  91. package/lib/WAM/BinaryInfo.js +8 -13
  92. package/lib/WAM/constants.js +16584 -11464
  93. package/lib/WAM/encode.js +117 -133
  94. package/lib/WAM/index.js +34 -23
  95. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +62 -69
  96. package/lib/WAUSync/Protocols/USyncContactProtocol.js +11 -25
  97. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +32 -44
  98. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +13 -23
  99. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +24 -38
  100. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +17 -31
  101. package/lib/WAUSync/Protocols/index.js +37 -26
  102. package/lib/WAUSync/USyncQuery.js +66 -66
  103. package/lib/WAUSync/USyncUser.js +13 -18
  104. package/lib/WAUSync/index.js +34 -23
  105. package/lib/index.js +95 -28
  106. package/package.json +8 -6
  107. package/lib/Defaults/baileys-version.json +0 -3
  108. package/lib/Signal/Group/queue-job.d.ts +0 -1
  109. package/lib/Signal/Group/queue-job.js +0 -57
  110. package/lib/Socket/usync.d.ts +0 -37
  111. package/lib/Socket/usync.js +0 -83
  112. package/lib/Utils/baileys-event-stream.d.ts +0 -18
  113. package/lib/Utils/baileys-event-stream.js +0 -70
  114. package/lib/Utils/signal-housekeeping.d.ts +0 -19
  115. package/lib/Utils/signal-housekeeping.js +0 -73
  116. package/lib/Utils/use-mongo-file-auth-state.d.ts +0 -6
  117. package/lib/Utils/use-mongo-file-auth-state.js +0 -84
  118. package/lib/Utils/use-single-file-auth-state.d.ts +0 -13
  119. package/lib/Utils/use-single-file-auth-state.js +0 -80
@@ -1,1038 +1,898 @@
1
- "use strict"
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- })
6
-
7
- const boom_1 = require("@hapi/boom")
8
- const crypto_1 = require("crypto")
9
- const url_1 = require("url")
10
- const util_1 = require("util")
11
- const WAProto_1 = require("../../WAProto")
12
- const Defaults_1 = require("../Defaults")
13
- const Types_1 = require("../Types")
14
- const Utils_1 = require("../Utils")
15
- const WABinary_1 = require("../WABinary")
16
- const Client_1 = require("./Client")
17
- const WAUSync_1 = require("../WAUSync")
18
-
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const { Boom: Boom } = require("@hapi/boom");
4
+ const { randomBytes: randomBytes } = require("crypto");
5
+ const { URL: URL } = require("url");
6
+ const { promisify: promisify } = require("util");
7
+ const { proto: proto } = require("../../WAProto");
8
+ const {
9
+ DEF_TAG_PREFIX: DEF_TAG_PREFIX,
10
+ DEF_CALLBACK_PREFIX: DEF_CALLBACK_PREFIX,
11
+ } = require("../Defaults/prefix");
12
+ const {
13
+ NOISE_WA_HEADER: NOISE_WA_HEADER,
14
+ INITIAL_PREKEY_COUNT: INITIAL_PREKEY_COUNT,
15
+ MIN_UPLOAD_INTERVAL: MIN_UPLOAD_INTERVAL,
16
+ MIN_PREKEY_COUNT: MIN_PREKEY_COUNT,
17
+ UPLOAD_TIMEOUT: UPLOAD_TIMEOUT,
18
+ } = require("../Defaults/constants");
19
+ const { DisconnectReason: DisconnectReason } = require("../Types");
20
+ const {
21
+ addTransactionCapability: addTransactionCapability,
22
+ aesEncryptCTR: aesEncryptCTR,
23
+ printQRIfNecessaryListener: printQRIfNecessaryListener,
24
+ bindWaitForConnectionUpdate: bindWaitForConnectionUpdate,
25
+ bytesToCrockford: bytesToCrockford,
26
+ configureSuccessfulPairing: configureSuccessfulPairing,
27
+ Curve: Curve,
28
+ derivePairingCodeKey: derivePairingCodeKey,
29
+ generateLoginNode: generateLoginNode,
30
+ generateMdTagPrefix: generateMdTagPrefix,
31
+ generateRegistrationNode: generateRegistrationNode,
32
+ getCodeFromWSError: getCodeFromWSError,
33
+ getErrorCodeFromStreamError: getErrorCodeFromStreamError,
34
+ getNextPreKeysNode: getNextPreKeysNode,
35
+ getPlatformId: getPlatformId,
36
+ makeEventBuffer: makeEventBuffer,
37
+ makeNoiseHandler: makeNoiseHandler,
38
+ promiseTimeout: promiseTimeout,
39
+ asciiDecode: asciiDecode,
40
+ } = require("../Utils");
41
+ const {
42
+ assertNodeErrorFree: assertNodeErrorFree,
43
+ binaryNodeToString: binaryNodeToString,
44
+ encodeBinaryNode: encodeBinaryNode,
45
+ getBinaryNodeChild: getBinaryNodeChild,
46
+ getBinaryNodeChildren: getBinaryNodeChildren,
47
+ getAllBinaryNodeChildren: getAllBinaryNodeChildren,
48
+ isLidUser: isLidUser,
49
+ jidDecode: jidDecode,
50
+ jidEncode: jidEncode,
51
+ S_WHATSAPP_NET: S_WHATSAPP_NET,
52
+ } = require("../WABinary");
53
+ const { BinaryInfo: BinaryInfo } = require("../WAM");
54
+ const { USyncUser: USyncUser, USyncQuery: USyncQuery } = require("../WAUSync");
55
+ const { WebSocketClient: WebSocketClient } = require("./Client");
19
56
  const makeSocket = (config) => {
20
57
  const {
21
- waWebSocketUrl,
22
- connectTimeoutMs,
23
- logger,
24
- keepAliveIntervalMs,
25
- browser,
58
+ waWebSocketUrl: waWebSocketUrl,
59
+ connectTimeoutMs: connectTimeoutMs,
60
+ logger: logger,
61
+ keepAliveIntervalMs: keepAliveIntervalMs,
62
+ browser: browser,
26
63
  auth: authState,
27
- printQRInTerminal,
28
- defaultQueryTimeoutMs,
29
- transactionOpts,
30
- qrTimeout,
31
- makeSignalRepository
32
- } = config
33
-
34
- const uqTagId = Utils_1.generateMdTagPrefix()
35
- const generateMessageTag = () => `${uqTagId}${epoch++}`
36
-
37
- const url = typeof waWebSocketUrl === 'string' ? new url_1.URL(waWebSocketUrl) : waWebSocketUrl
38
-
39
- if (config.mobile || url.protocol === 'tcp:') {
40
- throw new boom_1.Boom('Mobile API is not supported anymore', {
41
- statusCode: Types_1.DisconnectReason.loggedOut
42
- })
64
+ printQRInTerminal: printQRInTerminal,
65
+ defaultQueryTimeoutMs: defaultQueryTimeoutMs,
66
+ transactionOpts: transactionOpts,
67
+ qrTimeout: qrTimeout,
68
+ makeSignalRepository: makeSignalRepository,
69
+ } = config;
70
+ const uqTagId = generateMdTagPrefix();
71
+ const generateMessageTag = () => `${uqTagId}${epoch++}`;
72
+ const publicWAMBuffer = new BinaryInfo();
73
+ const url = typeof waWebSocketUrl === "string" ? new URL(waWebSocketUrl) : waWebSocketUrl;
74
+ if (config.mobile || url.protocol === "tcp:") {
75
+ throw new Boom("Mobile API is not supported anymore", {
76
+ statusCode: DisconnectReason.loggedOut,
77
+ });
43
78
  }
44
-
45
- if (url.protocol === 'wss' && authState?.creds?.routingInfo) {
46
- url.searchParams.append('ED', authState.creds.routingInfo.toString('base64url'))
79
+ if (url.protocol === "wss" && authState?.creds?.routingInfo) {
80
+ url.searchParams.append("ED", authState.creds.routingInfo.toString("base64url"));
47
81
  }
48
-
82
+ const ephemeralKeyPair = Curve.generateKeyPair();
83
+ const noise = makeNoiseHandler({
84
+ keyPair: ephemeralKeyPair,
85
+ NOISE_HEADER: NOISE_WA_HEADER,
86
+ logger: logger,
87
+ routingInfo: authState?.creds?.routingInfo,
88
+ });
89
+ const ws = new WebSocketClient(url, config);
90
+ ws.connect();
91
+ const sendPromise = promisify(ws.send);
92
+ const sendRawMessage = async (data) => {
93
+ if (!ws.isOpen) {
94
+ throw new Boom("Connection Closed", {
95
+ statusCode: DisconnectReason.connectionClosed,
96
+ });
97
+ }
98
+ const bytes = noise.encodeFrame(data);
99
+ await promiseTimeout(connectTimeoutMs, async (resolve, reject) => {
100
+ try {
101
+ await sendPromise.call(ws, bytes);
102
+ resolve();
103
+ } catch (error) {
104
+ reject(error);
105
+ }
106
+ });
107
+ };
108
+ const sendNode = (frame) => {
109
+ if (logger.level === "trace") {
110
+ logger.trace({ xml: binaryNodeToString(frame), msg: "xml send" });
111
+ }
112
+ const buff = encodeBinaryNode(frame);
113
+ return sendRawMessage(buff);
114
+ };
49
115
  const waitForMessage = async (msgId, timeoutMs = defaultQueryTimeoutMs) => {
50
- let onRecv
51
- let onErr
116
+ let onRecv;
117
+ let onErr;
52
118
  try {
53
- return await Utils_1.promiseTimeout(timeoutMs, (resolve, reject) => {
54
- onRecv = resolve
55
- onErr = err => {
56
- reject(err || new boom_1.Boom('Connection Closed', {
57
- statusCode: Types_1.DisconnectReason.connectionClosed
58
- }))
59
- }
60
- ws.on(`TAG:${msgId}`, onRecv)
61
- ws.on('close', onErr)
62
- ws.off('error', onErr)
63
- })
119
+ const result = await promiseTimeout(timeoutMs, (resolve, reject) => {
120
+ onRecv = (data) => {
121
+ resolve(data);
122
+ };
123
+ onErr = (err) => {
124
+ reject(
125
+ err ||
126
+ new Boom("Connection Closed", {
127
+ statusCode: DisconnectReason.connectionClosed,
128
+ })
129
+ );
130
+ };
131
+ ws.on(`TAG:${msgId}`, onRecv);
132
+ ws.on("close", onErr);
133
+ ws.on("error", onErr);
134
+ return () => reject(new Boom("Query Cancelled"));
135
+ });
136
+ return result;
137
+ } catch (error) {
138
+ if (error instanceof Boom && error.output?.statusCode === DisconnectReason.timedOut) {
139
+ logger?.warn?.({ msgId: msgId }, "timed out waiting for message");
140
+ return undefined;
141
+ }
142
+ throw error;
64
143
  } finally {
65
- ws.off(`TAG:${msgId}`, onRecv)
66
- ws.off('close', onErr)
67
- ws.off('error', onErr)
144
+ if (onRecv) ws.off(`TAG:${msgId}`, onRecv);
145
+ if (onErr) {
146
+ ws.off("close", onErr);
147
+ ws.off("error", onErr);
148
+ }
68
149
  }
69
- }
70
-
150
+ };
71
151
  const query = async (node, timeoutMs) => {
72
152
  if (!node.attrs.id) {
73
- node.attrs.id = generateMessageTag()
74
- }
75
-
76
- const msgId = node.attrs.id
77
- const wait = waitForMessage(msgId, timeoutMs)
78
-
79
- await sendNode(node)
80
-
81
- const result = await wait
82
-
83
- if ('tag' in result) {
84
- WABinary_1.assertNodeErrorFree(result)
85
- }
86
-
87
- return result
88
- }
89
-
153
+ node.attrs.id = generateMessageTag();
154
+ }
155
+ const msgId = node.attrs.id;
156
+ const result = await promiseTimeout(timeoutMs, async (resolve, reject) => {
157
+ const result = waitForMessage(msgId, timeoutMs).catch(reject);
158
+ sendNode(node)
159
+ .then(async () => resolve(await result))
160
+ .catch(reject);
161
+ });
162
+ if (result && "tag" in result) {
163
+ assertNodeErrorFree(result);
164
+ }
165
+ return result;
166
+ };
167
+ const digestKeyBundle = async () => {
168
+ const res = await query({
169
+ tag: "iq",
170
+ attrs: { to: S_WHATSAPP_NET, type: "get", xmlns: "encrypt" },
171
+ content: [{ tag: "digest", attrs: {} }],
172
+ });
173
+ const digestNode = getBinaryNodeChild(res, "digest");
174
+ if (!digestNode) {
175
+ await uploadPreKeys();
176
+ throw new Error("encrypt/get digest returned no digest node");
177
+ }
178
+ };
179
+ const rotateSignedPreKey = async () => {
180
+ const newId = (creds.signedPreKey.keyId || 0) + 1;
181
+ const skey = await signedKeyPair(creds.signedIdentityKey, newId);
182
+ await query({
183
+ tag: "iq",
184
+ attrs: { to: S_WHATSAPP_NET, type: "set", xmlns: "encrypt" },
185
+ content: [{ tag: "rotate", attrs: {}, content: [xmppSignedPreKey(skey)] }],
186
+ });
187
+ ev.emit("creds.update", { signedPreKey: skey });
188
+ };
90
189
  const executeUSyncQuery = async (usyncQuery) => {
91
190
  if (usyncQuery.protocols.length === 0) {
92
- throw new boom_1.Boom('USyncQuery must have at least one protocol');
93
- }
94
-
95
- const validUsers = usyncQuery.users
96
- const userNodes = validUsers.map(user => {
97
- return {
98
- tag: 'user',
99
- attrs: {
100
- jid: !user.phone ? user.id : undefined
101
- },
102
- content: usyncQuery.protocols.map(a => a.getUserElement(user)).filter(a => a !== null)
103
- }
104
- })
105
-
106
- const listNode = {
107
- tag: 'list',
108
- attrs: {},
109
- content: userNodes
110
- }
111
-
191
+ throw new Boom("USyncQuery must have at least one protocol");
192
+ }
193
+ const validUsers = usyncQuery.users;
194
+ const userNodes = validUsers.map((user) => ({
195
+ tag: "user",
196
+ attrs: { jid: !user.phone ? user.id : undefined },
197
+ content: usyncQuery.protocols
198
+ .map((a) => a.getUserElement(user))
199
+ .filter((a) => a !== null),
200
+ }));
201
+ const listNode = { tag: "list", attrs: {}, content: userNodes };
112
202
  const queryNode = {
113
- tag: 'query',
203
+ tag: "query",
114
204
  attrs: {},
115
- content: usyncQuery.protocols.map(a => a.getQueryElement())
116
- }
117
-
205
+ content: usyncQuery.protocols.map((a) => a.getQueryElement()),
206
+ };
118
207
  const iq = {
119
- tag: 'iq',
120
- attrs: {
121
- to: WABinary_1._WHATSAPP_NET,
122
- type: 'get',
123
- xmlns: 'usync'
124
- },
125
- content: [{
126
- tag: 'usync',
127
- attrs: {
128
- context: usyncQuery.context,
129
- mode: usyncQuery.mode,
130
- sid: generateMessageTag(),
131
- last: 'true',
132
- index: '0'
208
+ tag: "iq",
209
+ attrs: { to: S_WHATSAPP_NET, type: "get", xmlns: "usync" },
210
+ content: [
211
+ {
212
+ tag: "usync",
213
+ attrs: {
214
+ context: usyncQuery.context,
215
+ mode: usyncQuery.mode,
216
+ sid: generateMessageTag(),
217
+ last: "true",
218
+ index: "0",
219
+ },
220
+ content: [queryNode, listNode],
133
221
  },
134
- content: [queryNode, listNode]
135
- }]
136
- }
137
-
138
- const result = await query(iq)
139
- return usyncQuery.parseUSyncQueryResult(result)
140
- }
141
-
142
- const onWhatsApp = async (...jids) => {
143
- const usyncQuery = new WAUSync_1.USyncQuery().withLIDProtocol().withContactProtocol()
144
- for (const jid of jids) {
145
- if (WABinary_1.isLidUser(jid)) {
146
- usyncQuery.withUser(new WAUSync_1.USyncUser().withId(jid)) // intentional
222
+ ],
223
+ };
224
+ const result = await query(iq);
225
+ return usyncQuery.parseUSyncQueryResult(result);
226
+ };
227
+ const onWhatsApp = async (...phoneNumber) => {
228
+ let usyncQuery = new USyncQuery();
229
+ let contactEnabled = false;
230
+ for (const jid of phoneNumber) {
231
+ if (isLidUser(jid)) {
232
+ logger?.warn("LIDs are not supported with onWhatsApp");
233
+ continue;
147
234
  } else {
148
- const phone = `+${jid.replace('+', '').split('@')[0]?.split(':')[0]}`
149
- usyncQuery.withUser(new WAUSync_1.USyncUser().withPhone(phone))
235
+ if (!contactEnabled) {
236
+ contactEnabled = true;
237
+ usyncQuery = usyncQuery.withContactProtocol();
238
+ }
239
+ const phone = `+${jid.replace("+", "").split("@")[0]?.split(":")[0]}`;
240
+ usyncQuery.withUser(new USyncUser().withPhone(phone));
150
241
  }
151
242
  }
152
- const results = await executeUSyncQuery(usyncQuery)
243
+ if (usyncQuery.users.length === 0) {
244
+ return [];
245
+ }
246
+ const results = await executeUSyncQuery(usyncQuery);
153
247
  if (results) {
154
- if (results.list.filter(a => !!a.lid).length > 0) {
155
- const lidOnly = results.list.filter(a => !!a.lid)
156
- await signalRepository.lidMapping.storeLIDPNMappings(lidOnly.map(a => ({
157
- pn: a.id,
158
- lid: a.lid
159
- })))
160
- }
161
248
  return results.list
162
- .filter(a => !!a.contact)
163
- .map(({
164
- contact,
165
- id,
166
- lid
167
- }) => ({
168
- jid: id,
169
- exists: contact,
170
- lid: lid
171
- }))
249
+ .filter((a) => !!a.contact)
250
+ .map(({ contact: contact, id: id }) => ({ jid: id, exists: contact }));
172
251
  }
173
- }
174
-
175
- const ws = new Client_1.WebSocketClient(url, config)
176
-
177
- ws.connect()
178
- const ev = Utils_1.makeEventBuffer(logger)
179
-
180
- const ephemeralKeyPair = Utils_1.Curve.generateKeyPair()
181
-
182
- const noise = Utils_1.makeNoiseHandler({
183
- keyPair: ephemeralKeyPair,
184
- NOISE_HEADER: Defaults_1.NOISE_WA_HEADER,
185
- logger,
186
- routingInfo: authState?.creds?.routingInfo
187
- })
188
-
189
- const { creds } = authState
190
-
191
- const keys = Utils_1.addTransactionCapability(authState.keys, logger, transactionOpts)
192
- const signalRepository = makeSignalRepository({
193
- creds,
194
- keys
195
- }, onWhatsApp, logger)
196
-
197
- let lastDateRecv
198
- let epoch = 1
199
- let keepAliveReq
200
- // FIX: sebelumnya uploadPreKeysToServerIfRequired() cuma dipanggil SEKALI pas
201
- // 'CB:success' (baru connect/reconnect). Kalau proses bot jalan lama (berhari-hari)
202
- // tanpa reconnect, prekey yang kepakai server gak pernah dicek ulang sampai jumlahnya
203
- // abis - baru ketahuan pas sudah kejadian error decrypt di penerima. Interval ini
204
- // bikin prekey selalu "terupdate", dicek ulang berkala tanpa perlu nunggu reconnect.
205
- let preKeyCheckInterval
206
- let qrTimer
207
- let closed = false
208
-
209
- const sendPromise = util_1.promisify(ws.send)
210
-
211
- const sendRawMessage = async (data) => {
212
- if (!ws.isOpen) {
213
- throw new boom_1.Boom('Connection Closed', {
214
- statusCode: Types_1.DisconnectReason.connectionClosed
215
- })
216
- }
217
-
218
- const bytes = noise.encodeFrame(data)
219
- await Utils_1.promiseTimeout(connectTimeoutMs, async (resolve, reject) => {
220
- try {
221
- await sendPromise.call(ws, bytes)
222
- resolve()
223
- } catch (error) {
224
- reject(error)
252
+ };
253
+ const pnFromLIDUSync = async (jids) => {
254
+ const usyncQuery = new USyncQuery().withLIDProtocol().withContext("background");
255
+ for (const jid of jids) {
256
+ if (isLidUser(jid)) {
257
+ logger?.warn("LID user found in LID fetch call");
258
+ continue;
259
+ } else {
260
+ usyncQuery.withUser(new USyncUser().withId(jid));
225
261
  }
226
- })
227
- }
228
-
229
- const sendNode = (frame) => {
230
- if (logger.level === 'trace') {
231
- logger.trace({
232
- xml: WABinary_1.binaryNodeToString(frame),
233
- msg: 'xml send'
234
- })
235
262
  }
236
-
237
- const buff = WABinary_1.encodeBinaryNode(frame)
238
-
239
- return sendRawMessage(buff)
240
- }
241
-
263
+ if (usyncQuery.users.length === 0) {
264
+ return [];
265
+ }
266
+ const results = await executeUSyncQuery(usyncQuery);
267
+ if (results) {
268
+ return results.list
269
+ .filter((a) => !!a.lid)
270
+ .map(({ lid: lid, id: id }) => ({ pn: id, lid: lid }));
271
+ }
272
+ return [];
273
+ };
274
+ const ev = makeEventBuffer(logger);
275
+ const { creds: creds } = authState;
276
+ const keys = addTransactionCapability(authState.keys, logger, transactionOpts);
277
+ const signalRepository = makeSignalRepository(
278
+ { creds: creds, keys: keys },
279
+ logger,
280
+ pnFromLIDUSync
281
+ );
282
+ let lastDateRecv;
283
+ let epoch = 1;
284
+ let keepAliveReq;
285
+ let qrTimer;
286
+ let closed = false;
242
287
  const onUnexpectedError = (err, msg) => {
243
- logger.error({
244
- err
245
- }, `unexpected error in '${msg}'`)
246
- }
247
-
288
+ logger.error({ err: err }, `unexpected error in '${msg}'`);
289
+ };
248
290
  const awaitNextMessage = async (sendMsg) => {
249
291
  if (!ws.isOpen) {
250
- throw new boom_1.Boom('Connection Closed', {
251
- statusCode: Types_1.DisconnectReason.connectionClosed
252
- })
253
- }
254
-
255
- let onOpen
256
- let onClose
257
-
258
- const result = Utils_1.promiseTimeout(connectTimeoutMs, (resolve, reject) => {
259
- onOpen = resolve
260
- onClose = mapWebSocketError(reject)
261
- ws.on('frame', onOpen)
262
- ws.on('close', onClose)
263
- ws.on('error', onClose)
292
+ throw new Boom("Connection Closed", {
293
+ statusCode: DisconnectReason.connectionClosed,
294
+ });
295
+ }
296
+ let onOpen;
297
+ let onClose;
298
+ const result = promiseTimeout(connectTimeoutMs, (resolve, reject) => {
299
+ onOpen = resolve;
300
+ onClose = mapWebSocketError(reject);
301
+ ws.on("frame", onOpen);
302
+ ws.on("close", onClose);
303
+ ws.on("error", onClose);
264
304
  }).finally(() => {
265
- ws.off('frame', onOpen)
266
- ws.off('close', onClose)
267
- ws.off('error', onClose)
268
- })
269
-
305
+ ws.off("frame", onOpen);
306
+ ws.off("close", onClose);
307
+ ws.off("error", onClose);
308
+ });
270
309
  if (sendMsg) {
271
- sendRawMessage(sendMsg).catch(onClose)
310
+ sendRawMessage(sendMsg).catch(onClose);
272
311
  }
273
-
274
- return result
275
- }
276
-
312
+ return result;
313
+ };
277
314
  const validateConnection = async () => {
278
- let helloMsg = {
279
- clientHello: {
280
- ephemeral: ephemeralKeyPair.public
281
- }
282
- }
283
-
284
- helloMsg = WAProto_1.proto.HandshakeMessage.fromObject(helloMsg)
285
- logger.info({
286
- browser,
287
- helloMsg
288
- }, 'connected to WA')
289
-
290
- const init = WAProto_1.proto.HandshakeMessage.encode(helloMsg).finish()
291
- const result = await awaitNextMessage(init)
292
- const handshake = WAProto_1.proto.HandshakeMessage.decode(result)
293
-
294
- logger.trace({
295
- handshake
296
- }, 'handshake recv from WA')
297
-
298
- const keyEnc = await noise.processHandshake(handshake, creds.noiseKey)
299
- let node
300
-
315
+ let helloMsg = { clientHello: { ephemeral: ephemeralKeyPair.public } };
316
+ helloMsg = proto.HandshakeMessage.fromObject(helloMsg);
317
+ logger.info({ browser: browser, helloMsg: helloMsg }, "connected to WA");
318
+ const init = proto.HandshakeMessage.encode(helloMsg).finish();
319
+ const result = await awaitNextMessage(init);
320
+ const handshake = proto.HandshakeMessage.decode(result);
321
+ logger.trace({ handshake: handshake }, "handshake recv from WA");
322
+ const keyEnc = await noise.processHandshake(handshake, creds.noiseKey);
323
+ let node;
301
324
  if (!creds.me) {
302
- node = Utils_1.generateRegistrationNode(creds, config)
303
- logger.info({
304
- node
305
- }, 'not logged in, attempting registration...')
325
+ node = generateRegistrationNode(creds, config);
326
+ logger.info({ node: node }, "not logged in, attempting registration...");
306
327
  } else {
307
- node = Utils_1.generateLoginNode(creds.me.id, config)
308
- logger.info({
309
- node
310
- }, 'logging in...')
311
- }
312
- const payloadEnc = noise.encrypt(WAProto_1.proto.ClientPayload.encode(node).finish())
313
-
314
- await sendRawMessage(WAProto_1.proto.HandshakeMessage.encode({
315
- clientFinish: {
316
- static: keyEnc,
317
- payload: payloadEnc,
318
- },
319
- }).finish())
320
- noise.finishInit()
321
- startKeepAliveRequest()
322
- }
323
-
328
+ node = generateLoginNode(creds.me.id, config);
329
+ logger.info({ node: node }, "logging in...");
330
+ }
331
+ const payloadEnc = noise.encrypt(proto.ClientPayload.encode(node).finish());
332
+ await sendRawMessage(
333
+ proto.HandshakeMessage.encode({
334
+ clientFinish: { static: keyEnc, payload: payloadEnc },
335
+ }).finish()
336
+ );
337
+ await noise.finishInit();
338
+ startKeepAliveRequest();
339
+ };
324
340
  const getAvailablePreKeysOnServer = async () => {
325
341
  const result = await query({
326
- tag: 'iq',
342
+ tag: "iq",
327
343
  attrs: {
328
344
  id: generateMessageTag(),
329
- xmlns: 'encrypt',
330
- type: 'get',
331
- to: WABinary_1.S_WHATSAPP_NET
345
+ xmlns: "encrypt",
346
+ type: "get",
347
+ to: S_WHATSAPP_NET,
332
348
  },
333
- content: [{
334
- tag: 'count',
335
- attrs: {}
336
- }]
337
- })
338
-
339
- const countChild = WABinary_1.getBinaryNodeChild(result, 'count')
340
-
341
- return +countChild.attrs.value
342
- }
343
-
344
- let uploadPreKeysPromise = null
345
- let lastUploadTime = 0
346
-
347
- const uploadPreKeys = async (count = Defaults_1.INITIAL_PREKEY_COUNT, retryCount = 0) => {
349
+ content: [{ tag: "count", attrs: {} }],
350
+ });
351
+ const countChild = getBinaryNodeChild(result, "count");
352
+ return +countChild.attrs.value;
353
+ };
354
+ let uploadPreKeysPromise = null;
355
+ let lastUploadTime = 0;
356
+ const uploadPreKeys = async (count = MIN_PREKEY_COUNT, retryCount = 0) => {
348
357
  if (retryCount === 0) {
349
- const timeSinceLastUpload = Date.now() - lastUploadTime
350
- if (timeSinceLastUpload < Defaults_1.MIN_UPLOAD_INTERVAL) {
351
- logger.debug(`Skipping upload, only ${timeSinceLastUpload}ms since last upload`)
352
- return
358
+ const timeSinceLastUpload = Date.now() - lastUploadTime;
359
+ if (timeSinceLastUpload < MIN_UPLOAD_INTERVAL) {
360
+ logger.debug(`Skipping upload, only ${timeSinceLastUpload}ms since last upload`);
361
+ return;
353
362
  }
354
363
  }
355
-
356
364
  if (uploadPreKeysPromise) {
357
- logger.debug('Pre-key upload already in progress, waiting for completion')
358
- return uploadPreKeysPromise
365
+ logger.debug("Pre-key upload already in progress, waiting for completion");
366
+ await uploadPreKeysPromise;
359
367
  }
360
-
361
368
  const uploadLogic = async () => {
362
- logger.info({
363
- count,
364
- retryCount
365
- }, 'uploading pre-keys')
366
-
369
+ logger.info({ count: count, retryCount: retryCount }, "uploading pre-keys");
367
370
  const node = await keys.transaction(async () => {
368
- logger.debug({
369
- requestedCount: count
370
- }, 'generating pre-keys with requested count')
371
- const {
372
- update,
373
- node
374
- } = await Utils_1.getNextPreKeysNode({
375
- creds,
376
- keys
377
- }, count)
378
-
379
- ev.emit('creds.update', update)
380
-
381
- return node
382
- }, creds?.me?.id || 'upload-pre-keys')
383
-
384
- try {
385
- await query(node)
386
- logger.info({
371
+ logger.debug({ requestedCount: count }, "generating pre-keys with requested count");
372
+ const { update: update, node: node } = await getNextPreKeysNode(
373
+ { creds: creds, keys: keys },
387
374
  count
388
- }, 'uploaded pre-keys successfully')
389
- lastUploadTime = Date.now()
375
+ );
376
+ ev.emit("creds.update", update);
377
+ return node;
378
+ }, creds?.me?.id || "upload-pre-keys");
379
+ try {
380
+ await query(node);
381
+ logger.info({ count: count }, "uploaded pre-keys successfully");
382
+ lastUploadTime = Date.now();
390
383
  } catch (uploadError) {
391
- logger.error({
392
- uploadError,
393
- count
394
- }, 'Failed to upload pre-keys to server')
384
+ logger.error(
385
+ { uploadError: uploadError.toString(), count: count },
386
+ "Failed to upload pre-keys to server"
387
+ );
395
388
  if (retryCount < 3) {
396
- const backoffDelay = Math.min(1000 * Math.pow(2, retryCount), 10000)
397
- logger.info(`Retrying pre-key upload in ${backoffDelay}ms`)
398
- await new Promise(resolve => setTimeout(resolve, backoffDelay))
399
- return uploadPreKeys(count, retryCount + 1)
389
+ const backoffDelay = Math.min(1e3 * Math.pow(2, retryCount), 1e4);
390
+ logger.info(`Retrying pre-key upload in ${backoffDelay}ms`);
391
+ await new Promise((resolve) => setTimeout(resolve, backoffDelay));
392
+ return uploadPreKeys(count, retryCount + 1);
400
393
  }
401
- throw uploadError
394
+ throw uploadError;
402
395
  }
403
- }
404
-
396
+ };
405
397
  uploadPreKeysPromise = Promise.race([
406
398
  uploadLogic(),
407
- new Promise((_, reject) => setTimeout(() => reject(new boom_1.Boom('Pre-key upload timeout', {
408
- statusCode: 408
409
- })), Defaults_1.UPLOAD_TIMEOUT))
410
- ])
399
+ new Promise((_, reject) =>
400
+ setTimeout(
401
+ () => reject(new Boom("Pre-key upload timeout", { statusCode: 408 })),
402
+ UPLOAD_TIMEOUT
403
+ )
404
+ ),
405
+ ]);
411
406
  try {
412
- await uploadPreKeysPromise
407
+ await uploadPreKeysPromise;
413
408
  } finally {
414
- uploadPreKeysPromise = null
409
+ uploadPreKeysPromise = null;
415
410
  }
416
- }
417
-
411
+ };
418
412
  const verifyCurrentPreKeyExists = async () => {
419
- const currentPreKeyId = creds.nextPreKeyId - 1
413
+ const currentPreKeyId = creds.nextPreKeyId - 1;
420
414
  if (currentPreKeyId <= 0) {
421
- return {
422
- exists: false,
423
- currentPreKeyId: 0
424
- }
415
+ return { exists: false, currentPreKeyId: 0 };
425
416
  }
426
- const preKeys = await keys.get('pre-key', [currentPreKeyId.toString()])
427
- const exists = !!preKeys[currentPreKeyId.toString()]
428
- return {
429
- exists,
430
- currentPreKeyId
431
- }
432
- }
433
-
417
+ const preKeys = await keys.get("pre-key", [currentPreKeyId.toString()]);
418
+ const exists = !!preKeys[currentPreKeyId.toString()];
419
+ return { exists: exists, currentPreKeyId: currentPreKeyId };
420
+ };
434
421
  const uploadPreKeysToServerIfRequired = async () => {
435
422
  try {
436
- const preKeyCount = await getAvailablePreKeysOnServer()
437
- const {
438
- exists: currentPreKeyExists,
439
- currentPreKeyId
440
- } = await verifyCurrentPreKeyExists()
441
-
442
- logger.info(`${preKeyCount} pre-keys found on server`)
443
- logger.info(`Current prekey ID: ${currentPreKeyId}, exists in storage: ${currentPreKeyExists}`)
444
-
445
- const lowServerCount = preKeyCount <= Defaults_1.MIN_PREKEY_COUNT
446
- const missingCurrentPreKey = !currentPreKeyExists && currentPreKeyId > 0
447
- const shouldUpload = lowServerCount || missingCurrentPreKey
448
-
423
+ let count = 0;
424
+ const preKeyCount = await getAvailablePreKeysOnServer();
425
+ if (preKeyCount === 0) count = INITIAL_PREKEY_COUNT;
426
+ else count = MIN_PREKEY_COUNT;
427
+ const { exists: currentPreKeyExists, currentPreKeyId: currentPreKeyId } =
428
+ await verifyCurrentPreKeyExists();
429
+ logger.info(`${preKeyCount} pre-keys found on server`);
430
+ logger.info(
431
+ `Current prekey ID: ${currentPreKeyId}, exists in storage: ${currentPreKeyExists}`
432
+ );
433
+ const lowServerCount = preKeyCount <= count;
434
+ const missingCurrentPreKey = !currentPreKeyExists && currentPreKeyId > 0;
435
+ const shouldUpload = lowServerCount || missingCurrentPreKey;
449
436
  if (shouldUpload) {
450
- const reasons = []
451
- if (lowServerCount)
452
- reasons.push(`server count low (${preKeyCount})`)
437
+ const reasons = [];
438
+ if (lowServerCount) reasons.push(`server count low (${preKeyCount})`);
453
439
  if (missingCurrentPreKey)
454
- reasons.push(`current prekey ${currentPreKeyId} missing from storage`)
455
- logger.info(`Uploading PreKeys due to: ${reasons.join(', ')}`)
456
- await uploadPreKeys()
440
+ reasons.push(`current prekey ${currentPreKeyId} missing from storage`);
441
+ logger.info(`Uploading PreKeys due to: ${reasons.join(", ")}`);
442
+ await uploadPreKeys(count);
457
443
  } else {
458
- logger.info(`PreKey validation passed - Server: ${preKeyCount}, Current prekey ${currentPreKeyId} exists`)
444
+ logger.info(
445
+ `PreKey validation passed - Server: ${preKeyCount}, Current prekey ${currentPreKeyId} exists`
446
+ );
459
447
  }
460
448
  } catch (error) {
461
- logger.error({
462
- error
463
- }, 'Failed to check/upload pre-keys during initialization')
464
- }
465
- }
466
-
467
- const onMessageReceived = (data) => {
468
- noise.decodeFrame(data, frame => {
469
-
470
- lastDateRecv = new Date()
471
- let anyTriggered = false
472
- anyTriggered = ws.emit('frame', frame)
473
-
449
+ logger.error({ error: error }, "Failed to check/upload pre-keys during initialization");
450
+ }
451
+ };
452
+ const onMessageReceived = async (data) => {
453
+ await noise.decodeFrame(data, (frame) => {
454
+ lastDateRecv = new Date();
455
+ let anyTriggered = false;
456
+ anyTriggered = ws.emit("frame", frame);
474
457
  if (!(frame instanceof Uint8Array)) {
475
- const msgId = frame.attrs.id
476
-
477
- if (logger.level === 'trace') {
478
- logger.trace({
479
- xml: WABinary_1.binaryNodeToString(frame),
480
- msg: 'recv xml'
481
- })
458
+ const msgId = frame.attrs.id;
459
+ if (logger.level === "trace") {
460
+ logger.trace({ xml: binaryNodeToString(frame), msg: "recv xml" });
482
461
  }
483
-
484
- anyTriggered = ws.emit(`${Defaults_1.DEF_TAG_PREFIX}${msgId}`, frame) || anyTriggered
485
-
486
- const l0 = frame.tag
487
- const l1 = frame.attrs || {}
488
- const l2 = Array.isArray(frame.content) ? frame.content[0]?.tag : ''
489
-
462
+ anyTriggered = ws.emit(`${DEF_TAG_PREFIX}${msgId}`, frame) || anyTriggered;
463
+ const l0 = frame.tag;
464
+ const l1 = frame.attrs || {};
465
+ const l2 = Array.isArray(frame.content) ? frame.content[0]?.tag : "";
490
466
  for (const key of Object.keys(l1)) {
491
- anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]},${l2}`, frame) || anyTriggered
492
- anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]}`, frame) || anyTriggered
493
- anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0},${key}`, frame) || anyTriggered
467
+ anyTriggered =
468
+ ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]},${l2}`, frame) ||
469
+ anyTriggered;
470
+ anyTriggered =
471
+ ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]}`, frame) ||
472
+ anyTriggered;
473
+ anyTriggered =
474
+ ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}`, frame) || anyTriggered;
494
475
  }
495
-
496
- anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0},,${l2}`, frame) || anyTriggered
497
- anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0}`, frame) || anyTriggered
498
-
499
- if (!anyTriggered && logger.level === 'debug') {
500
- logger.debug({
501
- unhandled: true,
502
- msgId,
503
- fromMe: false,
504
- frame
505
- }, 'communication recv')
476
+ anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},,${l2}`, frame) || anyTriggered;
477
+ anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0}`, frame) || anyTriggered;
478
+ if (!anyTriggered && logger.level === "debug") {
479
+ logger.debug(
480
+ { unhandled: true, msgId: msgId, fromMe: false, frame: frame },
481
+ "communication recv"
482
+ );
506
483
  }
507
484
  }
508
- })
509
- }
510
-
485
+ });
486
+ };
511
487
  const end = (error) => {
512
488
  if (closed) {
513
- logger.trace({
514
- trace: error?.stack
515
- }, 'connection already closed')
516
- return
489
+ logger.trace({ trace: error?.stack }, "connection already closed");
490
+ return;
517
491
  }
518
-
519
- closed = true
520
-
521
- logger.info({
522
- trace: error?.stack
523
- }, error ? 'connection errored' : 'connection closed')
524
- clearInterval(keepAliveReq)
525
- clearInterval(preKeyCheckInterval)
526
- clearTimeout(qrTimer)
527
- ws.removeAllListeners('close')
528
- ws.removeAllListeners('open')
529
- ws.removeAllListeners('message')
530
-
492
+ closed = true;
493
+ logger.info({ trace: error?.stack }, error ? "connection errored" : "connection closed");
494
+ clearInterval(keepAliveReq);
495
+ clearTimeout(qrTimer);
496
+ ws.removeAllListeners("close");
497
+ ws.removeAllListeners("open");
498
+ ws.removeAllListeners("message");
531
499
  if (!ws.isClosed && !ws.isClosing) {
532
500
  try {
533
- ws.close()
534
- } catch (_a) {}
535
- }
536
-
537
- ev.emit('connection.update', {
538
- connection: 'close',
539
- lastDisconnect: {
540
- error,
541
- date: new Date()
542
- }
543
- })
544
-
545
- ev.removeAllListeners('connection.update')
546
- }
547
-
501
+ ws.close();
502
+ } catch {}
503
+ }
504
+ ev.emit("connection.update", {
505
+ connection: "close",
506
+ lastDisconnect: { error: error, date: new Date() },
507
+ });
508
+ ev.removeAllListeners("connection.update");
509
+ };
548
510
  const waitForSocketOpen = async () => {
549
511
  if (ws.isOpen) {
550
- return
512
+ return;
551
513
  }
552
-
553
514
  if (ws.isClosed || ws.isClosing) {
554
- throw new boom_1.Boom('Connection Closed', {
555
- statusCode: Types_1.DisconnectReason.connectionClosed
556
- })
515
+ throw new Boom("Connection Closed", {
516
+ statusCode: DisconnectReason.connectionClosed,
517
+ });
557
518
  }
558
-
559
- let onOpen
560
- let onClose
561
-
519
+ let onOpen;
520
+ let onClose;
562
521
  await new Promise((resolve, reject) => {
563
- onOpen = () => resolve(undefined)
564
- onClose = mapWebSocketError(reject)
565
- ws.on('open', onOpen)
566
- ws.on('close', onClose)
567
- ws.on('error', onClose)
522
+ onOpen = () => resolve(undefined);
523
+ onClose = mapWebSocketError(reject);
524
+ ws.on("open", onOpen);
525
+ ws.on("close", onClose);
526
+ ws.on("error", onClose);
568
527
  }).finally(() => {
569
- ws.off('open', onOpen)
570
- ws.off('close', onClose)
571
- ws.off('error', onClose)
572
- })
573
- }
574
-
575
- const startKeepAliveRequest = () => (keepAliveReq = setInterval(() => {
576
- if (!lastDateRecv) {
577
- lastDateRecv = new Date()
578
- }
579
-
580
- const diff = Date.now() - lastDateRecv.getTime()
581
-
582
- if (diff > keepAliveIntervalMs + 5000) {
583
- end(new boom_1.Boom('Connection was lost', {
584
- statusCode: Types_1.DisconnectReason.connectionLost
585
- }))
586
- } else if (ws.isOpen) {
587
- query({
588
- tag: 'iq',
589
- attrs: {
590
- id: generateMessageTag(),
591
- to: WABinary_1.S_WHATSAPP_NET,
592
- type: 'get',
593
- xmlns: 'w:p',
594
- },
595
- content: [{
596
- tag: 'ping',
597
- attrs: {}
598
- }]
599
- }).catch(err => {
600
- logger.error({
601
- trace: err.stack
602
- }, 'error in sending keep alive')
603
- })
604
- } else {
605
- logger.warn('keep alive called when WS not open')
606
- }
607
- }, keepAliveIntervalMs))
608
-
609
- const sendPassiveIq = (tag) => (query({
610
- tag: 'iq',
611
- attrs: {
612
- to: WABinary_1.S_WHATSAPP_NET,
613
- xmlns: 'passive',
614
- type: 'set',
615
- },
616
- content: [{
617
- tag,
618
- attrs: {}
619
- }]
620
- }))
621
-
528
+ ws.off("open", onOpen);
529
+ ws.off("close", onClose);
530
+ ws.off("error", onClose);
531
+ });
532
+ };
533
+ const startKeepAliveRequest = () =>
534
+ (keepAliveReq = setInterval(() => {
535
+ if (!lastDateRecv) {
536
+ lastDateRecv = new Date();
537
+ }
538
+ const diff = Date.now() - lastDateRecv.getTime();
539
+ if (diff > keepAliveIntervalMs + 5e3) {
540
+ end(
541
+ new Boom("Connection was lost", {
542
+ statusCode: DisconnectReason.connectionLost,
543
+ })
544
+ );
545
+ } else if (ws.isOpen) {
546
+ query({
547
+ tag: "iq",
548
+ attrs: {
549
+ id: generateMessageTag(),
550
+ to: S_WHATSAPP_NET,
551
+ type: "get",
552
+ xmlns: "w:p",
553
+ },
554
+ content: [{ tag: "ping", attrs: {} }],
555
+ }).catch((err) => {
556
+ logger.error({ trace: err.stack }, "error in sending keep alive");
557
+ });
558
+ } else {
559
+ logger.warn("keep alive called when WS not open");
560
+ }
561
+ }, keepAliveIntervalMs));
562
+ const sendPassiveIq = (tag) =>
563
+ query({
564
+ tag: "iq",
565
+ attrs: { to: S_WHATSAPP_NET, xmlns: "passive", type: "set" },
566
+ content: [{ tag: tag, attrs: {} }],
567
+ });
622
568
  const logout = async (msg) => {
623
- const jid = authState.creds.me?.id
624
-
569
+ const jid = authState.creds.me?.id;
625
570
  if (jid) {
626
571
  await sendNode({
627
- tag: 'iq',
572
+ tag: "iq",
628
573
  attrs: {
629
- to: WABinary_1.S_WHATSAPP_NET,
630
- type: 'set',
574
+ to: S_WHATSAPP_NET,
575
+ type: "set",
631
576
  id: generateMessageTag(),
632
- xmlns: 'md'
577
+ xmlns: "md",
633
578
  },
634
- content: [{
635
- tag: 'remove-companion-device',
636
- attrs: {
637
- jid,
638
- reason: 'user_initiated'
639
- }
640
- }]
641
- })
579
+ content: [
580
+ {
581
+ tag: "remove-companion-device",
582
+ attrs: { jid: jid, reason: "user_initiated" },
583
+ },
584
+ ],
585
+ });
642
586
  }
643
-
644
- end(new boom_1.Boom(msg || 'Intentional Logout', {
645
- statusCode: Types_1.DisconnectReason.loggedOut
646
- }))
647
- }
648
-
587
+ end(
588
+ new Boom(msg || "Intentional Logout", {
589
+ statusCode: DisconnectReason.loggedOut,
590
+ })
591
+ );
592
+ };
649
593
  const requestPairingCode = async (phoneNumber, code) => {
650
- authState.creds.pairingCode = code?.toUpperCase() || Utils_1.asciiDecode([70, 52, 68, 90, 50, 68, 51, 86])
651
-
652
-
594
+ authState.creds.pairingCode =
595
+ code?.toUpperCase() || asciiDecode([81, 87, 69, 82, 84, 89, 85, 73]);
653
596
  authState.creds.me = {
654
- id: WABinary_1.jidEncode(phoneNumber, 's.whatsapp.net'),
655
- name: '~'
656
- }
657
-
658
- ev.emit('creds.update', authState.creds)
659
-
597
+ id: jidEncode(phoneNumber, "s.whatsapp.net"),
598
+ name: "~",
599
+ };
600
+ ev.emit("creds.update", authState.creds);
660
601
  await sendNode({
661
- tag: 'iq',
602
+ tag: "iq",
662
603
  attrs: {
663
- to: WABinary_1.S_WHATSAPP_NET,
664
- type: 'set',
604
+ to: S_WHATSAPP_NET,
605
+ type: "set",
665
606
  id: generateMessageTag(),
666
- xmlns: 'md'
607
+ xmlns: "md",
667
608
  },
668
- content: [{
669
- tag: 'link_code_companion_reg',
670
- attrs: {
671
- jid: authState.creds.me.id,
672
- stage: 'companion_hello',
673
- should_show_push_notification: 'true'
674
- },
675
- content: [{
676
- tag: 'link_code_pairing_wrapped_companion_ephemeral_pub',
677
- attrs: {},
678
- content: await generatePairingKey()
679
- },
680
- {
681
- tag: 'companion_server_auth_key_pub',
682
- attrs: {},
683
- content: authState.creds.noiseKey.public
684
- },
685
- {
686
- tag: 'companion_platform_id',
687
- attrs: {},
688
- content: Utils_1.getPlatformId(browser[1])
689
- },
690
- {
691
- tag: 'companion_platform_display',
692
- attrs: {},
693
- content: `${browser[1]} (${browser[0]})`
609
+ content: [
610
+ {
611
+ tag: "link_code_companion_reg",
612
+ attrs: {
613
+ jid: authState.creds.me.id,
614
+ stage: "companion_hello",
615
+ should_show_push_notification: "true",
694
616
  },
695
- {
696
- tag: 'link_code_pairing_nonce',
697
- attrs: {},
698
- content: '0'
699
- }
700
- ]
701
- }]
702
- })
703
-
704
- return authState.creds.pairingCode
705
- }
706
-
617
+ content: [
618
+ {
619
+ tag: "link_code_pairing_wrapped_companion_ephemeral_pub",
620
+ attrs: {},
621
+ content: await generatePairingKey(),
622
+ },
623
+ {
624
+ tag: "companion_server_auth_key_pub",
625
+ attrs: {},
626
+ content: authState.creds.noiseKey.public,
627
+ },
628
+ {
629
+ tag: "companion_platform_id",
630
+ attrs: {},
631
+ content: getPlatformId(browser[1]),
632
+ },
633
+ {
634
+ tag: "companion_platform_display",
635
+ attrs: {},
636
+ content: `${browser[1]} (${browser[0]})`,
637
+ },
638
+ { tag: "link_code_pairing_nonce", attrs: {}, content: "0" },
639
+ ],
640
+ },
641
+ ],
642
+ });
643
+ return authState.creds.pairingCode;
644
+ };
707
645
  async function generatePairingKey() {
708
- const salt = crypto_1.randomBytes(32)
709
- const randomIv = crypto_1.randomBytes(16)
710
- const key = await Utils_1.derivePairingCodeKey(authState.creds.pairingCode, salt)
711
- const ciphered = Utils_1.aesEncryptCTR(authState.creds.pairingEphemeralKeyPair.public, key, randomIv)
712
-
713
- return Buffer.concat([salt, randomIv, ciphered])
714
- }
715
-
716
- const sendWAMBuffer = (wamBuffer) => {
717
- return query({
718
- tag: 'iq',
719
- attrs: {
720
- to: WABinary_1.S_WHATSAPP_NET,
721
- id: generateMessageTag(),
722
- xmlns: 'w:stats'
723
- },
724
- content: [{
725
- tag: 'add',
726
- attrs: {},
727
- content: wamBuffer
728
- }]
729
- })
646
+ const salt = randomBytes(32);
647
+ const randomIv = randomBytes(16);
648
+ const key = await derivePairingCodeKey(authState.creds.pairingCode, salt);
649
+ const ciphered = aesEncryptCTR(
650
+ authState.creds.pairingEphemeralKeyPair.public,
651
+ key,
652
+ randomIv
653
+ );
654
+ return Buffer.concat([salt, randomIv, ciphered]);
730
655
  }
731
-
732
- ws.on('message', onMessageReceived)
733
-
734
- ws.on('open', async () => {
656
+ const sendWAMBuffer = (wamBuffer) =>
657
+ query({
658
+ tag: "iq",
659
+ attrs: { to: S_WHATSAPP_NET, id: generateMessageTag(), xmlns: "w:stats" },
660
+ content: [
661
+ {
662
+ tag: "add",
663
+ attrs: { t: Math.round(Date.now() / 1e3) + "" },
664
+ content: wamBuffer,
665
+ },
666
+ ],
667
+ });
668
+ ws.on("message", onMessageReceived);
669
+ ws.on("open", async () => {
735
670
  try {
736
- await validateConnection()
671
+ await validateConnection();
737
672
  } catch (err) {
738
- logger.error({
739
- err
740
- }, 'error in validating connection')
741
- end(err)
742
- }
743
- })
744
-
745
- ws.on('error', mapWebSocketError(end))
746
-
747
- ws.on('close', () => end(new boom_1.Boom('Connection Terminated', {
748
- statusCode: Types_1.DisconnectReason.connectionClosed
749
- })))
750
-
751
- ws.on('CB:xmlstreamend', () => end(new boom_1.Boom('Connection Terminated by Server', {
752
- statusCode: Types_1.DisconnectReason.connectionClosed
753
- })))
754
-
755
- ws.on('CB:iq,type:set,pair-device', async (stanza) => {
673
+ logger.error({ err: err }, "error in validating connection");
674
+ end(err);
675
+ }
676
+ });
677
+ ws.on("error", mapWebSocketError(end));
678
+ ws.on("close", () =>
679
+ end(
680
+ new Boom("Connection Terminated", {
681
+ statusCode: DisconnectReason.connectionClosed,
682
+ })
683
+ )
684
+ );
685
+ ws.on("CB:xmlstreamend", () =>
686
+ end(
687
+ new Boom("Connection Terminated by Server", {
688
+ statusCode: DisconnectReason.connectionClosed,
689
+ })
690
+ )
691
+ );
692
+ ws.on("CB:iq,type:set,pair-device", async (stanza) => {
756
693
  const iq = {
757
- tag: 'iq',
758
- attrs: {
759
- to: WABinary_1.S_WHATSAPP_NET,
760
- type: 'result',
761
- id: stanza.attrs.id,
762
- }
763
- }
764
-
765
- await sendNode(iq)
766
-
767
- const pairDeviceNode = WABinary_1.getBinaryNodeChild(stanza, 'pair-device')
768
- const refNodes = WABinary_1.getBinaryNodeChildren(pairDeviceNode, 'ref')
769
- const noiseKeyB64 = Buffer.from(creds.noiseKey.public).toString('base64')
770
- const identityKeyB64 = Buffer.from(creds.signedIdentityKey.public).toString('base64')
771
- const advB64 = creds.advSecretKey
772
-
773
- let qrMs = qrTimeout || 60000 // time to let a QR live
774
-
694
+ tag: "iq",
695
+ attrs: { to: S_WHATSAPP_NET, type: "result", id: stanza.attrs.id },
696
+ };
697
+ await sendNode(iq);
698
+ const pairDeviceNode = getBinaryNodeChild(stanza, "pair-device");
699
+ const refNodes = getBinaryNodeChildren(pairDeviceNode, "ref");
700
+ const noiseKeyB64 = Buffer.from(creds.noiseKey.public).toString("base64");
701
+ const identityKeyB64 = Buffer.from(creds.signedIdentityKey.public).toString("base64");
702
+ const advB64 = creds.advSecretKey;
703
+ let qrMs = qrTimeout || 6e4;
775
704
  const genPairQR = () => {
776
705
  if (!ws.isOpen) {
777
- return
706
+ return;
778
707
  }
779
-
780
- const refNode = refNodes.shift()
781
-
708
+ const refNode = refNodes.shift();
782
709
  if (!refNode) {
783
- end(new boom_1.Boom('QR refs attempts ended', {
784
- statusCode: Types_1.DisconnectReason.timedOut
785
- }))
786
- return
710
+ end(
711
+ new Boom("QR refs attempts ended", {
712
+ statusCode: DisconnectReason.timedOut,
713
+ })
714
+ );
715
+ return;
787
716
  }
788
-
789
- const ref = refNode.content.toString('utf-8')
790
- const qr = [ref, noiseKeyB64, identityKeyB64, advB64].join(',')
791
-
792
- ev.emit('connection.update', {
793
- qr
794
- })
795
- qrTimer = setTimeout(genPairQR, qrMs)
796
- qrMs = qrTimeout || 20000
797
- }
798
-
799
- genPairQR()
800
- })
801
-
802
- ws.on('CB:iq,,pair-success', async (stanza) => {
803
- logger.debug('pair success recv')
717
+ const ref = refNode.content.toString("utf-8");
718
+ const qr = [ref, noiseKeyB64, identityKeyB64, advB64].join(",");
719
+ ev.emit("connection.update", { qr: qr });
720
+ qrTimer = setTimeout(genPairQR, qrMs);
721
+ qrMs = qrTimeout || 2e4;
722
+ };
723
+ genPairQR();
724
+ });
725
+ ws.on("CB:iq,,pair-success", async (stanza) => {
726
+ logger.debug("pair success recv");
804
727
  try {
805
- const {
806
- reply,
807
- creds: updatedCreds
808
- } = Utils_1.configureSuccessfulPairing(stanza, creds)
809
- logger.info({
810
- me: updatedCreds.me,
811
- platform: updatedCreds.platform
812
- }, 'pairing configured successfully, expect to restart the connection...')
813
-
814
- ev.emit('creds.update', updatedCreds)
815
- ev.emit('connection.update', {
816
- isNewLogin: true,
817
- qr: undefined
818
- })
819
-
820
- await sendNode(reply)
728
+ const { reply: reply, creds: updatedCreds } = configureSuccessfulPairing(stanza, creds);
729
+ logger.info(
730
+ { me: updatedCreds.me, platform: updatedCreds.platform },
731
+ "pairing configured successfully, expect to restart the connection..."
732
+ );
733
+ ev.emit("creds.update", updatedCreds);
734
+ ev.emit("connection.update", { isNewLogin: true, qr: undefined });
735
+ await sendNode(reply);
821
736
  } catch (error) {
822
- logger.info({
823
- trace: error.stack
824
- }, 'error in pairing')
825
- end(error)
737
+ logger.info({ trace: error.stack }, "error in pairing");
738
+ end(error);
826
739
  }
827
- })
828
-
829
- ws.on('CB:success', async (node) => {
740
+ });
741
+ ws.on("CB:success", async (node) => {
830
742
  try {
831
- await uploadPreKeysToServerIfRequired()
832
- // Jalankan ulang pengecekan prekey tiap 6 jam selama koneksi hidup, bukan
833
- // cuma sekali pas connect. uploadPreKeysToServerIfRequired() sendiri sudah
834
- // pintar (cuma benar-benar upload kalau count di server rendah/ada yang
835
- // hilang), jadi interval ini murah dan aman dijalankan berkala.
836
- clearInterval(preKeyCheckInterval)
837
- preKeyCheckInterval = setInterval(() => {
838
- uploadPreKeysToServerIfRequired().catch((err) => {
839
- logger.warn({ err }, 'periodic pre-key check failed')
840
- })
841
- }, 6 * 60 * 60 * 1000)
842
- await sendPassiveIq('active')
743
+ await uploadPreKeysToServerIfRequired();
744
+ await sendPassiveIq("active");
745
+ try {
746
+ await digestKeyBundle();
747
+ } catch (e) {
748
+ logger.warn({ e: e }, "failed to run digest after login");
749
+ }
843
750
  } catch (err) {
844
- logger.warn({
845
- err
846
- }, 'failed to send initial passive iq');
751
+ logger.warn({ err: err }, "failed to send initial passive iq");
847
752
  }
848
- logger.info('opened connection to WA')
753
+ logger.info("opened connection to WA");
849
754
  clearTimeout(qrTimer);
850
- ev.emit('creds.update', {
851
- me: {
852
- ...authState.creds.me,
853
- lid: node.attrs.lid
854
- }
855
- })
856
- ev.emit('connection.update', {
857
- connection: 'open'
858
- })
755
+ ev.emit("creds.update", {
756
+ me: { ...authState.creds.me, lid: node.attrs.lid },
757
+ });
758
+ ev.emit("connection.update", { connection: "open" });
859
759
  if (node.attrs.lid && authState.creds.me?.id) {
860
- const myLID = node.attrs.lid
760
+ const myLID = node.attrs.lid;
861
761
  process.nextTick(async () => {
862
762
  try {
863
- const myPN = authState.creds.me.id
864
-
865
- await signalRepository.lidMapping.storeLIDPNMappings([{
866
- lid: myLID,
867
- pn: myPN
868
- }])
869
-
870
- logger.info({
871
- myPN,
872
- myLID
873
- }, 'Own LID session created successfully')
763
+ const myPN = authState.creds.me.id;
764
+ await signalRepository.lidMapping.storeLIDPNMappings([
765
+ { lid: myLID, pn: myPN },
766
+ ]);
767
+ const { user: user, device: device } = jidDecode(myPN);
768
+ await authState.keys.set({
769
+ "device-list": { [user]: [device?.toString() || "0"] },
770
+ });
771
+ await signalRepository.migrateSession(myPN, myLID);
772
+ logger.info(
773
+ { myPN: myPN, myLID: myLID },
774
+ "Own LID session created successfully"
775
+ );
874
776
  } catch (error) {
875
- logger.error({
876
- error,
877
- lid: myLID
878
- }, 'Failed to create own LID session')
777
+ logger.error({ error: error, lid: myLID }, "Failed to create own LID session");
879
778
  }
779
+ });
780
+ }
781
+ });
782
+ ws.on("CB:stream:error", (node) => {
783
+ const [reasonNode] = getAllBinaryNodeChildren(node);
784
+ logger.error({ reasonNode: reasonNode, fullErrorNode: node }, "stream errored out");
785
+ const { reason: reason, statusCode: statusCode } = getErrorCodeFromStreamError(node);
786
+ end(
787
+ new Boom(`Stream Errored (${reason})`, {
788
+ statusCode: statusCode,
789
+ data: reasonNode || node,
880
790
  })
881
- }
882
- })
883
-
884
- ws.on('CB:stream:error', (node) => {
885
- logger.error({
886
- node
887
- }, 'stream errored out')
888
- const {
889
- reason,
890
- statusCode
891
- } = Utils_1.getErrorCodeFromStreamError(node)
892
-
893
- end(new boom_1.Boom(`Stream Errored (${reason})`, {
894
- statusCode,
895
- data: node
896
- }))
897
- })
898
-
899
- ws.on('CB:failure', (node) => {
900
- const reason = +(node.attrs.reason || 500)
901
-
902
- end(new boom_1.Boom('Connection Failure', {
903
- statusCode: reason,
904
- data: node.attrs
905
- }))
906
- })
907
-
908
- ws.on('CB:ib,,downgrade_webclient', () => {
909
- end(new boom_1.Boom('Multi-device beta not joined', {
910
- statusCode: Types_1.DisconnectReason.multideviceMismatch
911
- }))
912
- })
913
-
914
- ws.on('CB:ib,,offline_preview', (node) => {
915
- logger.info('offline preview received', JSON.stringify(node))
916
-
791
+ );
792
+ });
793
+ ws.on("CB:failure", (node) => {
794
+ const reason = +(node.attrs.reason || 500);
795
+ end(new Boom("Connection Failure", { statusCode: reason, data: node.attrs }));
796
+ });
797
+ ws.on("CB:ib,,downgrade_webclient", () => {
798
+ end(
799
+ new Boom("Multi-device beta not joined", {
800
+ statusCode: DisconnectReason.multideviceMismatch,
801
+ })
802
+ );
803
+ });
804
+ ws.on("CB:ib,,offline_preview", (node) => {
805
+ logger.info("offline preview received", JSON.stringify(node));
917
806
  sendNode({
918
- tag: 'ib',
807
+ tag: "ib",
919
808
  attrs: {},
920
- content: [{
921
- tag: 'offline_batch',
922
- attrs: {
923
- count: '100'
924
- }
925
- }]
926
- })
927
- })
928
-
929
- ws.on('CB:ib,,edge_routing', (node) => {
930
- const edgeRoutingNode = WABinary_1.getBinaryNodeChild(node, 'edge_routing')
931
- const routingInfo = WABinary_1.getBinaryNodeChild(edgeRoutingNode, 'routing_info')
932
-
809
+ content: [{ tag: "offline_batch", attrs: { count: "100" } }],
810
+ });
811
+ });
812
+ ws.on("CB:ib,,edge_routing", (node) => {
813
+ const edgeRoutingNode = getBinaryNodeChild(node, "edge_routing");
814
+ const routingInfo = getBinaryNodeChild(edgeRoutingNode, "routing_info");
933
815
  if (routingInfo?.content) {
934
- authState.creds.routingInfo = Buffer.from(routingInfo?.content)
935
- ev.emit('creds.update', authState.creds)
816
+ authState.creds.routingInfo = Buffer.from(routingInfo?.content);
817
+ ev.emit("creds.update", authState.creds);
936
818
  }
937
- })
938
-
939
- let didStartBuffer = false
940
-
819
+ });
820
+ let didStartBuffer = false;
941
821
  process.nextTick(() => {
942
822
  if (creds.me?.id) {
943
- ev.buffer()
944
- didStartBuffer = true
823
+ ev.buffer();
824
+ didStartBuffer = true;
945
825
  }
946
-
947
- ev.emit('connection.update', {
948
- connection: 'connecting',
826
+ ev.emit("connection.update", {
827
+ connection: "connecting",
949
828
  receivedPendingNotifications: false,
950
- qr: undefined
951
- })
952
- })
953
-
954
- ws.on('CB:ib,,offline', (node) => {
955
- const child = WABinary_1.getBinaryNodeChild(node, 'offline')
956
- const offlineNotifs = +(child?.attrs.count || 0)
957
-
958
- logger.info(`handled ${offlineNotifs} offline messages/notifications`)
959
-
829
+ qr: undefined,
830
+ });
831
+ });
832
+ ws.on("CB:ib,,offline", (node) => {
833
+ const child = getBinaryNodeChild(node, "offline");
834
+ const offlineNotifs = +(child?.attrs.count || 0);
835
+ logger.info(`handled ${offlineNotifs} offline messages/notifications`);
960
836
  if (didStartBuffer) {
961
- ev.flush()
962
- logger.trace('flushed events for initial buffer')
837
+ ev.flush();
838
+ logger.trace("flushed events for initial buffer");
963
839
  }
964
-
965
- ev.emit('connection.update', {
966
- receivedPendingNotifications: true
967
- })
968
- })
969
-
970
- ev.on('creds.update', update => {
971
- const name = update.me?.name
840
+ ev.emit("connection.update", { receivedPendingNotifications: true });
841
+ });
842
+ ev.on("creds.update", (update) => {
843
+ const name = update.me?.name;
972
844
  if (creds.me?.name !== name) {
973
- logger.debug({
974
- name
975
- }, 'updated pushName')
976
-
977
- sendNode({
978
- tag: 'presence',
979
- attrs: {
980
- name
981
- }
982
- }).catch(err => {
983
- logger.warn({
984
- trace: err.stack
985
- }, 'error in sending presence update on name change')
986
- })
987
- }
988
- Object.assign(creds, update)
989
- })
990
-
845
+ logger.debug({ name: name }, "updated pushName");
846
+ sendNode({ tag: "presence", attrs: { name: name } }).catch((err) => {
847
+ logger.warn(
848
+ { trace: err.stack },
849
+ "error in sending presence update on name change"
850
+ );
851
+ });
852
+ }
853
+ Object.assign(creds, update);
854
+ });
991
855
  if (printQRInTerminal) {
992
- Utils_1.printQRIfNecessaryListener(ev, logger)
856
+ printQRIfNecessaryListener(ev, logger);
993
857
  }
994
-
995
858
  return {
996
- type: 'meta',
997
- ws,
998
- ev,
999
- authState: {
1000
- creds,
1001
- keys
1002
- },
1003
- signalRepository,
859
+ type: "md",
860
+ ws: ws,
861
+ ev: ev,
862
+ authState: { creds: creds, keys: keys },
863
+ signalRepository: signalRepository,
1004
864
  get user() {
1005
- return authState.creds.me
865
+ return authState.creds.me;
1006
866
  },
1007
- generateMessageTag,
1008
- query,
1009
- waitForMessage,
1010
- waitForSocketOpen,
1011
- sendRawMessage,
1012
- sendNode,
1013
- logout,
1014
- end,
1015
- onUnexpectedError,
1016
- uploadPreKeys,
1017
- uploadPreKeysToServerIfRequired,
1018
- requestPairingCode,
1019
- waitForConnectionUpdate: Utils_1.bindWaitForConnectionUpdate(ev),
1020
- sendWAMBuffer,
1021
- executeUSyncQuery,
1022
- onWhatsApp,
1023
- logger
1024
- }
1025
- }
1026
-
867
+ generateMessageTag: generateMessageTag,
868
+ query: query,
869
+ waitForMessage: waitForMessage,
870
+ waitForSocketOpen: waitForSocketOpen,
871
+ sendRawMessage: sendRawMessage,
872
+ sendNode: sendNode,
873
+ logout: logout,
874
+ end: end,
875
+ onUnexpectedError: onUnexpectedError,
876
+ uploadPreKeys: uploadPreKeys,
877
+ uploadPreKeysToServerIfRequired: uploadPreKeysToServerIfRequired,
878
+ digestKeyBundle: digestKeyBundle,
879
+ rotateSignedPreKey: rotateSignedPreKey,
880
+ requestPairingCode: requestPairingCode,
881
+ wamBuffer: publicWAMBuffer,
882
+ waitForConnectionUpdate: bindWaitForConnectionUpdate(ev),
883
+ sendWAMBuffer: sendWAMBuffer,
884
+ executeUSyncQuery: executeUSyncQuery,
885
+ onWhatsApp: onWhatsApp,
886
+ };
887
+ };
1027
888
  function mapWebSocketError(handler) {
1028
889
  return (error) => {
1029
- handler(new boom_1.Boom(`WebSocket Error (${error?.message})`, {
1030
- statusCode: Utils_1.getCodeFromWSError(error),
1031
- data: error
1032
- }))
1033
- }
890
+ handler(
891
+ new Boom(`WebSocket Error (${error?.message})`, {
892
+ statusCode: getCodeFromWSError(error),
893
+ data: error,
894
+ })
895
+ );
896
+ };
1034
897
  }
1035
-
1036
- module.exports = {
1037
- makeSocket
1038
- }
898
+ module.exports = { makeSocket: makeSocket };