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