@shenira/baileysx 7.0.4

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.

Potentially problematic release.


This version of @shenira/baileysx might be problematic. Click here for more details.

Files changed (193) hide show
  1. package/WAProto/index.js +169661 -0
  2. package/engine-requirements.js +10 -0
  3. package/lib/Defaults/baileys-version.json +3 -0
  4. package/lib/Defaults/index.d.ts +53 -0
  5. package/lib/Defaults/index.js +147 -0
  6. package/lib/Defaults/phonenumber-mcc.json +223 -0
  7. package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
  8. package/lib/Signal/Group/ciphertext-message.js +15 -0
  9. package/lib/Signal/Group/group-session-builder.d.ts +14 -0
  10. package/lib/Signal/Group/group-session-builder.js +64 -0
  11. package/lib/Signal/Group/group_cipher.d.ts +17 -0
  12. package/lib/Signal/Group/group_cipher.js +96 -0
  13. package/lib/Signal/Group/index.d.ts +11 -0
  14. package/lib/Signal/Group/index.js +57 -0
  15. package/lib/Signal/Group/keyhelper.d.ts +10 -0
  16. package/lib/Signal/Group/keyhelper.js +55 -0
  17. package/lib/Signal/Group/queue-job.d.ts +1 -0
  18. package/lib/Signal/Group/queue-job.js +57 -0
  19. package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
  20. package/lib/Signal/Group/sender-chain-key.js +34 -0
  21. package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
  22. package/lib/Signal/Group/sender-key-distribution-message.js +66 -0
  23. package/lib/Signal/Group/sender-key-message.d.ts +18 -0
  24. package/lib/Signal/Group/sender-key-message.js +69 -0
  25. package/lib/Signal/Group/sender-key-name.d.ts +17 -0
  26. package/lib/Signal/Group/sender-key-name.js +51 -0
  27. package/lib/Signal/Group/sender-key-record.d.ts +30 -0
  28. package/lib/Signal/Group/sender-key-record.js +53 -0
  29. package/lib/Signal/Group/sender-key-state.d.ts +38 -0
  30. package/lib/Signal/Group/sender-key-state.js +99 -0
  31. package/lib/Signal/Group/sender-message-key.d.ts +11 -0
  32. package/lib/Signal/Group/sender-message-key.js +29 -0
  33. package/lib/Signal/libsignal.d.ts +3 -0
  34. package/lib/Signal/libsignal.js +174 -0
  35. package/lib/Socket/Client/abstract-socket-client.d.ts +17 -0
  36. package/lib/Socket/Client/abstract-socket-client.js +13 -0
  37. package/lib/Socket/Client/index.d.ts +3 -0
  38. package/lib/Socket/Client/index.js +19 -0
  39. package/lib/Socket/Client/mobile-socket-client.d.ts +13 -0
  40. package/lib/Socket/Client/mobile-socket-client.js +65 -0
  41. package/lib/Socket/Client/web-socket-client.d.ts +12 -0
  42. package/lib/Socket/Client/web-socket-client.js +62 -0
  43. package/lib/Socket/business.d.ts +171 -0
  44. package/lib/Socket/business.js +260 -0
  45. package/lib/Socket/chats.d.ts +267 -0
  46. package/lib/Socket/chats.js +1018 -0
  47. package/lib/Socket/dugong.d.ts +254 -0
  48. package/lib/Socket/dugong.js +514 -0
  49. package/lib/Socket/groups.d.ts +115 -0
  50. package/lib/Socket/groups.js +317 -0
  51. package/lib/Socket/index.d.ts +173 -0
  52. package/lib/Socket/index.js +11 -0
  53. package/lib/Socket/messages-recv.d.ts +161 -0
  54. package/lib/Socket/messages-recv.js +1110 -0
  55. package/lib/Socket/messages-send.d.ts +149 -0
  56. package/lib/Socket/messages-send.js +909 -0
  57. package/lib/Socket/newsletter.d.ts +134 -0
  58. package/lib/Socket/newsletter.js +347 -0
  59. package/lib/Socket/registration.d.ts +267 -0
  60. package/lib/Socket/registration.js +166 -0
  61. package/lib/Socket/socket.d.ts +43 -0
  62. package/lib/Socket/socket.js +727 -0
  63. package/lib/Socket/usync.d.ts +36 -0
  64. package/lib/Socket/usync.js +70 -0
  65. package/lib/Store/index.d.ts +3 -0
  66. package/lib/Store/index.js +10 -0
  67. package/lib/Store/make-cache-manager-store.d.ts +13 -0
  68. package/lib/Store/make-cache-manager-store.js +83 -0
  69. package/lib/Store/make-in-memory-store.d.ts +118 -0
  70. package/lib/Store/make-in-memory-store.js +427 -0
  71. package/lib/Store/make-ordered-dictionary.d.ts +13 -0
  72. package/lib/Store/make-ordered-dictionary.js +81 -0
  73. package/lib/Store/object-repository.d.ts +10 -0
  74. package/lib/Store/object-repository.js +27 -0
  75. package/lib/Types/Auth.d.ts +110 -0
  76. package/lib/Types/Auth.js +2 -0
  77. package/lib/Types/Call.d.ts +13 -0
  78. package/lib/Types/Call.js +2 -0
  79. package/lib/Types/Chat.d.ts +102 -0
  80. package/lib/Types/Chat.js +4 -0
  81. package/lib/Types/Contact.d.ts +19 -0
  82. package/lib/Types/Contact.js +2 -0
  83. package/lib/Types/Events.d.ts +157 -0
  84. package/lib/Types/Events.js +2 -0
  85. package/lib/Types/GroupMetadata.d.ts +55 -0
  86. package/lib/Types/GroupMetadata.js +2 -0
  87. package/lib/Types/Label.d.ts +35 -0
  88. package/lib/Types/Label.js +27 -0
  89. package/lib/Types/LabelAssociation.d.ts +29 -0
  90. package/lib/Types/LabelAssociation.js +9 -0
  91. package/lib/Types/Message.d.ts +273 -0
  92. package/lib/Types/Message.js +9 -0
  93. package/lib/Types/Newsletter.d.ts +103 -0
  94. package/lib/Types/Newsletter.js +38 -0
  95. package/lib/Types/Product.d.ts +78 -0
  96. package/lib/Types/Product.js +2 -0
  97. package/lib/Types/Signal.d.ts +57 -0
  98. package/lib/Types/Signal.js +2 -0
  99. package/lib/Types/Socket.d.ts +111 -0
  100. package/lib/Types/Socket.js +2 -0
  101. package/lib/Types/State.d.ts +27 -0
  102. package/lib/Types/State.js +2 -0
  103. package/lib/Types/USync.d.ts +25 -0
  104. package/lib/Types/USync.js +2 -0
  105. package/lib/Types/index.d.ts +57 -0
  106. package/lib/Types/index.js +42 -0
  107. package/lib/Utils/auth-utils.d.ts +18 -0
  108. package/lib/Utils/auth-utils.js +206 -0
  109. package/lib/Utils/baileys-event-stream.d.ts +16 -0
  110. package/lib/Utils/baileys-event-stream.js +63 -0
  111. package/lib/Utils/business.d.ts +22 -0
  112. package/lib/Utils/business.js +234 -0
  113. package/lib/Utils/chat-utils.d.ts +71 -0
  114. package/lib/Utils/chat-utils.js +729 -0
  115. package/lib/Utils/crypto.d.ts +41 -0
  116. package/lib/Utils/crypto.js +151 -0
  117. package/lib/Utils/decode-wa-message.d.ts +19 -0
  118. package/lib/Utils/decode-wa-message.js +198 -0
  119. package/lib/Utils/event-buffer.d.ts +35 -0
  120. package/lib/Utils/event-buffer.js +514 -0
  121. package/lib/Utils/generics.d.ts +92 -0
  122. package/lib/Utils/generics.js +423 -0
  123. package/lib/Utils/history.d.ts +15 -0
  124. package/lib/Utils/history.js +96 -0
  125. package/lib/Utils/index.d.ts +17 -0
  126. package/lib/Utils/index.js +33 -0
  127. package/lib/Utils/link-preview.d.ts +21 -0
  128. package/lib/Utils/link-preview.js +93 -0
  129. package/lib/Utils/logger.d.ts +4 -0
  130. package/lib/Utils/logger.js +7 -0
  131. package/lib/Utils/lt-hash.d.ts +12 -0
  132. package/lib/Utils/lt-hash.js +51 -0
  133. package/lib/Utils/make-mutex.d.ts +7 -0
  134. package/lib/Utils/make-mutex.js +43 -0
  135. package/lib/Utils/messages-media.d.ts +116 -0
  136. package/lib/Utils/messages-media.js +819 -0
  137. package/lib/Utils/messages.d.ts +77 -0
  138. package/lib/Utils/messages.js +816 -0
  139. package/lib/Utils/noise-handler.d.ts +21 -0
  140. package/lib/Utils/noise-handler.js +155 -0
  141. package/lib/Utils/process-message.d.ts +41 -0
  142. package/lib/Utils/process-message.js +321 -0
  143. package/lib/Utils/signal.d.ts +32 -0
  144. package/lib/Utils/signal.js +153 -0
  145. package/lib/Utils/use-multi-file-auth-state.d.ts +13 -0
  146. package/lib/Utils/use-multi-file-auth-state.js +119 -0
  147. package/lib/Utils/validate-connection.d.ts +11 -0
  148. package/lib/Utils/validate-connection.js +229 -0
  149. package/lib/WABinary/constants.d.ts +30 -0
  150. package/lib/WABinary/constants.js +40 -0
  151. package/lib/WABinary/decode.d.ts +7 -0
  152. package/lib/WABinary/decode.js +252 -0
  153. package/lib/WABinary/encode.d.ts +3 -0
  154. package/lib/WABinary/encode.js +265 -0
  155. package/lib/WABinary/generic-utils.d.ts +17 -0
  156. package/lib/WABinary/generic-utils.js +198 -0
  157. package/lib/WABinary/index.d.ts +5 -0
  158. package/lib/WABinary/index.js +21 -0
  159. package/lib/WABinary/jid-utils.d.ts +31 -0
  160. package/lib/WABinary/jid-utils.js +62 -0
  161. package/lib/WABinary/types.d.ts +18 -0
  162. package/lib/WABinary/types.js +2 -0
  163. package/lib/WAM/BinaryInfo.d.ts +17 -0
  164. package/lib/WAM/BinaryInfo.js +13 -0
  165. package/lib/WAM/constants.d.ts +38 -0
  166. package/lib/WAM/constants.js +15350 -0
  167. package/lib/WAM/encode.d.ts +3 -0
  168. package/lib/WAM/encode.js +155 -0
  169. package/lib/WAM/index.d.ts +3 -0
  170. package/lib/WAM/index.js +19 -0
  171. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +9 -0
  172. package/lib/WAUSync/Protocols/USyncContactProtocol.js +32 -0
  173. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +22 -0
  174. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +57 -0
  175. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
  176. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
  177. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
  178. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +42 -0
  179. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +25 -0
  180. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +53 -0
  181. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +8 -0
  182. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
  183. package/lib/WAUSync/Protocols/index.d.ts +4 -0
  184. package/lib/WAUSync/Protocols/index.js +20 -0
  185. package/lib/WAUSync/USyncQuery.d.ts +28 -0
  186. package/lib/WAUSync/USyncQuery.js +89 -0
  187. package/lib/WAUSync/USyncUser.d.ts +12 -0
  188. package/lib/WAUSync/USyncUser.js +26 -0
  189. package/lib/WAUSync/index.d.ts +3 -0
  190. package/lib/WAUSync/index.js +19 -0
  191. package/lib/index.d.ts +12 -0
  192. package/lib/index.js +90 -0
  193. package/package.json +114 -0
@@ -0,0 +1,727 @@
1
+ "use strict";
2
+ const boom_1 = require("@hapi/boom");
3
+ const crypto_1 = require("crypto");
4
+ const url_1 = require("url");
5
+ const util_1 = require("util");
6
+ const WAProto_1 = require("../../WAProto");
7
+ const Defaults_1 = require("../Defaults");
8
+ const Types_1 = require("../Types");
9
+ const Utils_1 = require("../Utils");
10
+ const WABinary_1 = require("../WABinary");
11
+ const Client_1 = require("./Client");
12
+
13
+ const makeSocket = (config) => {
14
+ const {
15
+ waWebSocketUrl,
16
+ connectTimeoutMs,
17
+ logger,
18
+ keepAliveIntervalMs,
19
+ browser,
20
+ authState,
21
+ printQRInTerminal,
22
+ defaultQueryTimeoutMs,
23
+ transactionOpts,
24
+ qrTimeout,
25
+ makeSignalRepository
26
+ } = config;
27
+
28
+ const url = typeof waWebSocketUrl === 'string'
29
+ ? new url_1.URL(waWebSocketUrl)
30
+ : waWebSocketUrl;
31
+
32
+ // Validasi URL
33
+ if (config.rejectUnauthorized || url.protocol === 'http:') {
34
+ throw new boom_1.Boom('Invalid WebSocket URL', {
35
+ statusCode: Types_1.DisconnectReason.badSession
36
+ });
37
+ }
38
+
39
+ // Tambahkan auth state ke URL jika ada
40
+ if (url.protocol === 'ws:' && authState?.creds?.deviceSecret) {
41
+ url.searchParams.set('ED', authState.creds.deviceSecret.toString('base64'));
42
+ }
43
+
44
+ // Inisialisasi WebSocket
45
+ const ws = new Client_1.WebSocketClient(url, config);
46
+ ws.connect();
47
+
48
+ // Event emitter
49
+ const ev = Utils_1.makeEventEmitter(logger);
50
+
51
+ // Generate ephemeral key pair untuk noise handshake
52
+ const ephemeralKeyPair = Utils_1.Curve.generateKeyPair();
53
+
54
+ // Inisialisasi noise protocol
55
+ const noise = Utils_1.makeNoiseHandler({
56
+ ephemeralKeyPair,
57
+ staticKeyPairs: Defaults_1.KEY_BUNDLE_TYPE,
58
+ logger,
59
+ deviceSecret: authState?.creds?.deviceSecret
60
+ });
61
+
62
+ const { creds } = authState;
63
+ const keys = Utils_1.makeKeyStore(authState.keys, logger, transactionOpts);
64
+ const signalRepository = makeSignalRepository({ creds, keys });
65
+
66
+ let lastDateRecv;
67
+ let epoch = 1;
68
+ let keepAliveReq;
69
+ let qrTimer;
70
+ let closed = false;
71
+
72
+ // Generate unique tag ID untuk message
73
+ const uqTagId = Utils_1.generateMessageTag();
74
+ const generateMessageTag = () => {
75
+ return `${uqTagId}${epoch++}`;
76
+ };
77
+
78
+ // Promisify websocket send
79
+ const sendPromise = util_1.promisify(ws.send);
80
+
81
+ const sendRawMessage = async (data) => {
82
+ if (!ws.isOpen) {
83
+ throw new boom_1.Boom('Connection closed', {
84
+ statusCode: Types_1.DisconnectReason.connectionClosed
85
+ });
86
+ }
87
+
88
+ const bytes = noise.encodeFrame(data);
89
+
90
+ await Utils_1.promiseWithTimeout(connectTimeoutMs, async (resolve, reject) => {
91
+ try {
92
+ await sendPromise.call(ws, bytes);
93
+ resolve();
94
+ } catch (error) {
95
+ reject(error);
96
+ }
97
+ });
98
+ };
99
+
100
+ const sendNode = (frame) => {
101
+ if (logger.level === 'trace') {
102
+ logger.trace({
103
+ node: WABinary_1.getBinaryNodeString(frame),
104
+ from: 'sendNode'
105
+ });
106
+ }
107
+
108
+ const buff = WABinary_1.encodeBinaryNode(frame);
109
+ return sendRawMessage(buff);
110
+ };
111
+
112
+ const onUnexpectedError = (err, msg) => {
113
+ logger.warn({ err }, `'${msg}' errored`);
114
+
115
+ const message = (err && (err.message || err.reason || String(err))).toLowerCase();
116
+
117
+ if (message.includes('pre-key') ||
118
+ message.includes('session') && message.includes('404')) {
119
+ try {
120
+ uploadPreKeysToServerIfRequired(true).catch(e => {
121
+ return logger.warn({ e }, 'failed to upload prekeys');
122
+ });
123
+ } catch (_e) {}
124
+ }
125
+
126
+ if (message.includes('rate-overlimit') || message.includes('rate-overlimit')) {
127
+ const wait = Math.min(30000, config.retryRequestDelayMs || 5000);
128
+ logger.warn({ wait }, 'rate limiting hit, waiting...');
129
+ setTimeout(() => {}, wait);
130
+ }
131
+ };
132
+
133
+ const awaitNextMessage = async (sendMsg) => {
134
+ if (!ws.isOpen) {
135
+ throw new boom_1.Boom('Connection not open', {
136
+ statusCode: Types_1.DisconnectReason.connectionClosed
137
+ });
138
+ }
139
+
140
+ let onOpen, onClose;
141
+
142
+ const result = Utils_1.promiseWithTimeout(
143
+ connectTimeoutMs,
144
+ (resolve, reject) => {
145
+ onOpen = resolve;
146
+ onClose = mapWebSocketError(reject);
147
+ ws.on('open', onOpen);
148
+ ws.on('close', onClose);
149
+ ws.on('error', onClose);
150
+ }
151
+ ).finally(() => {
152
+ ws.off('open', onOpen);
153
+ ws.off('close', onClose);
154
+ ws.off('error', onClose);
155
+ });
156
+
157
+ if (sendMsg) {
158
+ sendRawMessage(sendMsg).catch(onClose);
159
+ }
160
+
161
+ return result;
162
+ };
163
+
164
+ const waitForMessage = async (msgId, timeoutMs = defaultQueryTimeoutMs) => {
165
+ let onRecv, onErr;
166
+
167
+ try {
168
+ const result = await Utils_1.promiseWithTimeout(
169
+ timeoutMs,
170
+ (resolve, reject) => {
171
+ onRecv = resolve;
172
+ onErr = (err) => {
173
+ reject(err || new boom_1.Boom('Timed out', {
174
+ statusCode: Types_1.DisconnectReason.timedOut
175
+ }));
176
+ };
177
+
178
+ ws.on(`response:${msgId}`, onRecv);
179
+ ws.on('close', onErr);
180
+ ws.on('error', onErr);
181
+ }
182
+ );
183
+
184
+ return result;
185
+ } finally {
186
+ ws.off(`response:${msgId}`, onRecv);
187
+ ws.off('close', onErr);
188
+ ws.off('error', onErr);
189
+ }
190
+ };
191
+
192
+ const query = async (node, timeoutMs) => {
193
+ if (!node.attrs.id) {
194
+ node.attrs.id = generateMessageTag();
195
+ }
196
+
197
+ const msgId = node.attrs.id;
198
+ const [result] = await Promise.all([
199
+ waitForMessage(msgId, timeoutMs),
200
+ sendNode(node)
201
+ ]);
202
+
203
+ if ('error' in result) {
204
+ WABinary_1.assertNodeErrorFree(result);
205
+ }
206
+
207
+ return result;
208
+ };
209
+
210
+ const validateConnection = async () => {
211
+ // Buat hello message untuk handshake
212
+ let helloMsg = {
213
+ clientHello: {
214
+ ephemeral: ephemeralKeyPair.public
215
+ }
216
+ };
217
+
218
+ helloMsg = WAProto_1.proto.HandshakeMessage.ClientHello.encode(helloMsg);
219
+ logger.trace({ browser, helloMsg }, 'sending client hello');
220
+
221
+ const init = WAProto_1.proto.HandshakeMessage.ClientHello.encode(helloMsg).finish();
222
+ const result = await awaitNextMessage(init);
223
+ const handshake = WAProto_1.proto.HandshakeMessage.decode(result);
224
+
225
+ logger.debug({ handshake }, 'received handshake');
226
+
227
+ const keyEnc = await noise.processHandshake(handshake, creds.signedKeyPair);
228
+
229
+ let node;
230
+
231
+ if (!creds.me) {
232
+ node = Utils_1.newLoginPayload(creds, config);
233
+ logger.debug({ node }, 'sending login payload');
234
+ } else {
235
+ node = Utils_1.newRegisteredPayload(creds.me.id, config);
236
+ logger.debug({ node }, 'sending registered payload');
237
+ }
238
+
239
+ const payloadEnc = noise.encrypt(
240
+ WAProto_1.proto.HandshakeMessage.ClientFinish.encode(node).finish()
241
+ );
242
+
243
+ await sendRawMessage(
244
+ WAProto_1.proto.HandshakeMessage.encode({
245
+ clientFinish: {
246
+ key: keyEnc,
247
+ payload: payloadEnc
248
+ }
249
+ }).finish()
250
+ );
251
+
252
+ noise.finishInit();
253
+ startKeepAliveRequest();
254
+ };
255
+
256
+ const getAvailablePreKeysOnServer = async () => {
257
+ const result = await query({
258
+ tag: 'iq',
259
+ attrs: {
260
+ id: generateMessageTag(),
261
+ xmlns: 'encrypt',
262
+ type: 'get',
263
+ to: WABinary_1.S_WHATSAPP_NET
264
+ },
265
+ content: [
266
+ { tag: 'key', attrs: {} }
267
+ ]
268
+ });
269
+
270
+ const countChild = WABinary_1.getBinaryNodeChild(result, 'key');
271
+ return +countChild.attrs.count;
272
+ };
273
+
274
+ const uploadPreKeys = async (count = Defaults_1.INITIAL_PREKEY_COUNT) => {
275
+ await keys.transaction(async () => {
276
+ logger.debug({ count }, 'uploading pre keys');
277
+
278
+ const { update, node } = await Utils_1.generatePreKeys({
279
+ creds,
280
+ keys
281
+ }, count);
282
+
283
+ await query(node);
284
+ ev.emit('creds.update', update);
285
+ logger.debug({ count }, 'pre keys uploaded');
286
+ });
287
+ };
288
+
289
+ const uploadPreKeysToServerIfRequired = async () => {
290
+ const preKeyCount = await getAvailablePreKeysOnServer();
291
+ logger.debug(`${preKeyCount} pre keys available on server`);
292
+
293
+ if (preKeyCount <= Defaults_1.MIN_PREKEY_COUNT) {
294
+ await uploadPreKeys();
295
+ }
296
+ };
297
+
298
+ const onMessageReceived = (data) => {
299
+ noise.processIncomingData(data, (frame) => {
300
+ let anyTriggered = false;
301
+ anyTriggered = ws.emit('frame', frame);
302
+
303
+ if (!(frame instanceof Uint8Array)) {
304
+ const msgId = frame.attrs?.id;
305
+
306
+ if (logger.level === 'silly') {
307
+ logger.silly({
308
+ node: WABinary_1.getBinaryNodeString(frame),
309
+ from: 'onMessageReceived'
310
+ });
311
+ }
312
+
313
+ anyTriggered = ws.emit(`response:${Defaults_1.DEFAULT_ORIGIN}${msgId}`, frame) || anyTriggered;
314
+
315
+ const l0 = frame.tag;
316
+ const l1 = frame.attrs || {};
317
+ const l2 = Array.isArray(frame.content) ? frame.content[0]?.tag : '';
318
+
319
+ for (const key of Object.keys(l1)) {
320
+ anyTriggered = ws.emit(`${Defaults_1.DEFAULT_ORIGIN}${l0},${key}:${l1[key]},${l2}`, frame) || anyTriggered;
321
+ anyTriggered = ws.emit(`${Defaults_1.DEFAULT_ORIGIN}${l0},${key}:${l1[key]}`, frame) || anyTriggered;
322
+ anyTriggered = ws.emit(`${Defaults_1.DEFAULT_ORIGIN}${l0},${key}`, frame) || anyTriggered;
323
+ }
324
+
325
+ anyTriggered = ws.emit(`${Defaults_1.DEFAULT_ORIGIN}${l0},,${l2}`, frame) || anyTriggered;
326
+ anyTriggered = ws.emit(`${Defaults_1.DEFAULT_ORIGIN}${l0}`, frame) || anyTriggered;
327
+
328
+ if (!anyTriggered && logger.level === 'silly') {
329
+ logger.silly({
330
+ unhandled: true,
331
+ msgId,
332
+ triggered: false,
333
+ frame
334
+ }, 'unhandled message');
335
+ }
336
+ }
337
+ });
338
+ };
339
+
340
+ const end = (error) => {
341
+ if (closed) {
342
+ logger.warn({ error: error?.message }, 'end already closed');
343
+ return;
344
+ }
345
+
346
+ closed = true;
347
+ logger.debug({ error: error?.message }, error ? 'socket errored' : 'socket ended');
348
+
349
+ clearInterval(keepAliveReq);
350
+ clearTimeout(qrTimer);
351
+ ws.removeAllListeners('open');
352
+ ws.removeAllListeners('close');
353
+ ws.removeAllListeners('error');
354
+ ws.removeAllListeners('frame');
355
+
356
+ if (!ws.isClosed && !ws.isClosing) {
357
+ try {
358
+ ws.terminate();
359
+ } catch (_a) {}
360
+ }
361
+
362
+ ev.emit('connection.update', {
363
+ connection: 'close',
364
+ lastDisconnect: { error, date: new Date }
365
+ });
366
+ ev.removeAllListeners('connection.update');
367
+ };
368
+
369
+ const waitForSocketOpen = async () => {
370
+ if (ws.isOpen) {
371
+ return;
372
+ }
373
+
374
+ if (ws.isClosing || ws.isClosed) {
375
+ throw new boom_1.Boom('Connection closed', {
376
+ statusCode: Types_1.DisconnectReason.connectionClosed
377
+ });
378
+ }
379
+
380
+ let onOpen, onClose;
381
+
382
+ await new Promise((resolve, reject) => {
383
+ onOpen = () => { return resolve(true); };
384
+ onClose = mapWebSocketError(reject);
385
+
386
+ ws.on('open', onOpen);
387
+ ws.on('close', onClose);
388
+ ws.on('error', onClose);
389
+ }).finally(() => {
390
+ ws.off('open', onOpen);
391
+ ws.off('close', onClose);
392
+ ws.off('error', onClose);
393
+ });
394
+ };
395
+
396
+ const startKeepAliveRequest = () => {
397
+ return keepAliveReq = setInterval(() => {
398
+ if (!lastDateRecv) {
399
+ lastDateRecv = new Date();
400
+ }
401
+
402
+ const diff = Date.now() - lastDateRecv.getTime();
403
+
404
+ if (diff > keepAliveIntervalMs + 5000) {
405
+ end(new boom_1.Boom('Keep alive timeout', {
406
+ statusCode: Types_1.DisconnectReason.connectionLost
407
+ }));
408
+ } else {
409
+ if (ws.isOpen) {
410
+ query({
411
+ tag: 'iq',
412
+ attrs: {
413
+ id: generateMessageTag(),
414
+ to: WABinary_1.S_WHATSAPP_NET,
415
+ type: 'get',
416
+ xmlns: 'w:keepalive'
417
+ },
418
+ content: [
419
+ { tag: 'pong', attrs: {} }
420
+ ]
421
+ }).catch(err => {
422
+ logger.warn({ error: err.message }, 'keep alive failed');
423
+ });
424
+ } else {
425
+ logger.debug('keep alive skipped, socket closed');
426
+ }
427
+ }
428
+ }, keepAliveIntervalMs);
429
+ };
430
+
431
+ const sendPassiveIq = (tag) => {
432
+ return query({
433
+ tag: 'iq',
434
+ attrs: {
435
+ to: WABinary_1.S_WHATSAPP_NET,
436
+ type: 'get',
437
+ xmlns: 'passive',
438
+ xml: 'passive'
439
+ },
440
+ content: [
441
+ { tag: tag, attrs: {} }
442
+ ]
443
+ });
444
+ };
445
+
446
+ const logout = async (msg) => {
447
+ const jid = authState.creds?.me?.id;
448
+
449
+ if (jid) {
450
+ await sendNode({
451
+ tag: 'iq',
452
+ attrs: {
453
+ to: WABinary_1.S_WHATSAPP_NET,
454
+ type: 'set',
455
+ id: generateMessageTag(),
456
+ xmlns: 'md'
457
+ },
458
+ content: [{
459
+ tag: 'remove-companion-device',
460
+ attrs: {
461
+ jid: jid,
462
+ reason: 'user_initiated'
463
+ }
464
+ }]
465
+ });
466
+ }
467
+
468
+ end(new boom_1.Boom(msg || 'logout', {
469
+ statusCode: Types_1.DisconnectReason.loggedOut
470
+ }));
471
+ };
472
+
473
+ const requestPairingCode = async (phoneNumber, pairKey) => {
474
+ if (pairKey) {
475
+ authState.creds.pairingKey = pairKey.publicKey();
476
+ } else {
477
+ authState.creds.pairingEphemeralKey = Utils_1.Curve.generateKeyPair(
478
+ crypto_1.randomBytes(32)
479
+ );
480
+ }
481
+
482
+ authState.creds.me = {
483
+ id: WABinary_1.jidNormalizedUser(phoneNumber, 's.whatsapp.net'),
484
+ lid: '~'
485
+ };
486
+
487
+ ev.emit('creds.update', authState.creds);
488
+
489
+ await sendNode({
490
+ tag: 'iq',
491
+ attrs: {
492
+ to: WABinary_1.S_WHATSAPP_NET,
493
+ type: 'set',
494
+ id: generateMessageTag(),
495
+ xmlns: 'md'
496
+ },
497
+ content: [{
498
+ tag: 'pair-device',
499
+ attrs: {
500
+ jid: authState.creds.me.id,
501
+ ref: 'link_code',
502
+ action: 'request'
503
+ },
504
+ content: [
505
+ { tag: 'link_code', attrs: {}, content: await generatePairingKey() },
506
+ { tag: 'ephemeral_key', attrs: {}, content: authState.creds.pairingEphemeralKey.public },
507
+ { tag: 'companion_props', attrs: {}, content: Utils_1.encodeCompanionProps(browser[1]) },
508
+ { tag: 'companion_os', attrs: {}, content: `${browser[1]} (${browser[0]})` },
509
+ { tag: 'companion_version', attrs: {}, content: '0' }
510
+ ]
511
+ }]
512
+ });
513
+
514
+ return authState.creds.pairingCode;
515
+ };
516
+
517
+ async function generatePairingKey() {
518
+ const salt = crypto_1.randomBytes(32);
519
+ const randomIv = crypto_1.randomBytes(16);
520
+ const key = await Utils_1.hkdf(
521
+ authState.creds.pairingEphemeralKey.sharedSecret,
522
+ salt
523
+ );
524
+ const ciphered = Utils_1.aes256GcmEncrypt(
525
+ authState.creds.pairingEphemeralKey.publicKey,
526
+ key,
527
+ randomIv
528
+ );
529
+
530
+ return Buffer.concat([salt, randomIv, ciphered]);
531
+ }
532
+
533
+ const sendWAMBuffer = (wamBuffer) => {
534
+ return query({
535
+ tag: 'iq',
536
+ attrs: {
537
+ to: WABinary_1.S_WHATSAPP_NET,
538
+ id: generateMessageTag(),
539
+ type: 'set',
540
+ xmlns: 'w:stats:wam'
541
+ },
542
+ content: [
543
+ { tag: 'wam', attrs: {}, content: wamBuffer }
544
+ ]
545
+ });
546
+ };
547
+
548
+ // Register event handlers
549
+ ws.on('message', onMessageReceived);
550
+ ws.on('open', async () => {
551
+ try {
552
+ await validateConnection();
553
+ } catch (err) {
554
+ logger.error({ err }, 'connection validation failed');
555
+ end(err);
556
+ }
557
+ });
558
+
559
+ ws.on('error', mapWebSocketError(end));
560
+ ws.on('upgradeError', () => {
561
+ return end(new boom_1.Boom('Upgrade error', {
562
+ statusCode: Types_1.DisconnectReason.upgradeError
563
+ }));
564
+ });
565
+
566
+ ws.on('close', () => {
567
+ return end(new boom_1.Boom('Connection closed', {
568
+ statusCode: Types_1.DisconnectReason.connectionClosed
569
+ }));
570
+ });
571
+
572
+ ws.on('stream', async (stanza) => {
573
+ try {
574
+ await uploadPreKeysToServerIfRequired();
575
+ await sendPassiveIq('active');
576
+ logger.debug('stream resumed');
577
+ clearTimeout(qrTimer);
578
+
579
+ ev.emit('creds.update', {
580
+ me: {
581
+ ...authState.creds.me,
582
+ lid: stanza.attrs.lid
583
+ }
584
+ });
585
+
586
+ ev.emit('connection.update', {
587
+ connection: 'open'
588
+ });
589
+ } catch (err) {
590
+ logger.error({ err }, 'stream error');
591
+ end(err);
592
+ }
593
+ });
594
+
595
+ ws.on('failure', (node) => {
596
+ logger.error({ node }, 'failure received');
597
+ const { reason, statusCode } = Utils_1.extractFailureReason(node);
598
+ end(new boom_1.Boom(`Failure: ${reason}`, {
599
+ statusCode: statusCode,
600
+ data: node
601
+ }));
602
+ });
603
+
604
+ ws.on('streamError', (node) => {
605
+ const reason = +(node.attrs.code || 500);
606
+ end(new boom_1.Boom('Stream error', {
607
+ data: reason,
608
+ node: node.content
609
+ }));
610
+ });
611
+
612
+ ws.on('timeout', () => {
613
+ end(new boom_1.Boom('WebSocket timeout', {
614
+ statusCode: Types_1.DisconnectReason.connectionTimeout
615
+ }));
616
+ });
617
+
618
+ ws.on('ping', (node) => {
619
+ logger.debug('ping received', JSON.stringify(node));
620
+ sendNode({
621
+ tag: 'ib',
622
+ attrs: {},
623
+ content: [
624
+ { tag: 'd', attrs: { ping: 'pong' } }
625
+ ]
626
+ });
627
+ });
628
+
629
+ ws.on('edge_routing', (node) => {
630
+ const edgeRoutingNode = WABinary_1.getBinaryNodeChild(node, 'edge_routing');
631
+ const routingInfo = WABinary_1.getBinaryNodeChild(edgeRoutingNode, 'routing_info');
632
+
633
+ if (routingInfo?.content) {
634
+ authState.creds.routingInfo = Buffer.from(routingInfo.content);
635
+ ev.emit('creds.update', authState.creds);
636
+ }
637
+ });
638
+
639
+ let didStartBuffer = false;
640
+
641
+ process.nextTick(() => {
642
+ if (creds?.me?.id) {
643
+ ev.flush();
644
+ didStartBuffer = true;
645
+ }
646
+
647
+ ev.emit('connection.update', {
648
+ connection: 'connecting',
649
+ receivedPendingNotifications: false,
650
+ qr: null
651
+ });
652
+ });
653
+
654
+ ws.on('stream:resumed', (node) => {
655
+ const child = WABinary_1.getBinaryNodeChild(node, 'stream');
656
+ const offlineNotifs = +((child?.attrs?.count) || 0);
657
+
658
+ logger.debug(`stream resumed, pending notifs: ${offlineNotifs}`);
659
+
660
+ if (didStartBuffer) {
661
+ ev.flush();
662
+ logger.debug('flushed buffer');
663
+ }
664
+
665
+ ev.emit('connection.update', { receivedPendingNotifications: true });
666
+ });
667
+
668
+ ev.on('creds.update', (update) => {
669
+ const name = update.me?.name;
670
+
671
+ if (creds.me?.name !== name) {
672
+ logger.debug({ name }, 'sending pushname update');
673
+ sendNode({
674
+ tag: 'presence',
675
+ attrs: { name: name }
676
+ }).catch(err => {
677
+ logger.warn({ error: err.message }, 'failed to send pushname update');
678
+ });
679
+ }
680
+
681
+ Object.assign(creds, update);
682
+ });
683
+
684
+ // Print QR di terminal jika diminta
685
+ if (printQRInTerminal) {
686
+ Utils_1.printQRIfNecessaryListener(ev, logger);
687
+ }
688
+
689
+ return {
690
+ type: 'md',
691
+ ws,
692
+ ev,
693
+ authState: { creds, keys },
694
+ signalRepository,
695
+ get user() {
696
+ return authState.creds.me;
697
+ },
698
+ generateMessageTag,
699
+ query,
700
+ waitForMessage,
701
+ waitForSocketOpen,
702
+ sendRawMessage,
703
+ sendNode,
704
+ logout,
705
+ end,
706
+ onUnexpectedError,
707
+ uploadPreKeys,
708
+ uploadPreKeysToServerIfRequired,
709
+ requestPairingCode,
710
+ createBufferedFunction: Utils_1.createBufferedFunction(ev),
711
+ sendWAMBuffer
712
+ };
713
+ };
714
+
715
+ exports.makeSocket = makeSocket;
716
+
717
+ function mapWebSocketError(handler) {
718
+ return (error) => {
719
+ handler(new boom_1.Boom(
720
+ `WebSocket error: ${error?.message}`,
721
+ {
722
+ statusCode: Utils_1.getErrorCode(error),
723
+ data: error
724
+ }
725
+ ));
726
+ };
727
+ }