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