@d0v3riz/baileys 6.3.0 → 6.4.0
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/README.md +6 -5
- package/WAProto/WAProto.proto +58 -24
- package/WAProto/index.d.ts +649 -410
- package/WAProto/index.js +1632 -985
- package/WASignalGroup/group_cipher.js +38 -24
- package/WASignalGroup/queue_job.js +69 -0
- package/WASignalGroup/sender_key_record.js +4 -2
- package/lib/Defaults/baileys-version.json +1 -1
- package/lib/Defaults/index.js +1 -1
- package/lib/Socket/Client/abstract-socket-client.d.ts +1 -0
- package/lib/Socket/business.d.ts +5 -3
- package/lib/Socket/chats.d.ts +6 -5
- package/lib/Socket/groups.d.ts +4 -2
- package/lib/Socket/groups.js +1 -1
- package/lib/Socket/index.d.ts +9 -7
- package/lib/Socket/messages-recv.d.ts +6 -3
- package/lib/Socket/messages-recv.js +79 -3
- package/lib/Socket/messages-send.d.ts +4 -2
- package/lib/Socket/messages-send.js +17 -8
- package/lib/Socket/registration.d.ts +6 -4
- package/lib/Socket/socket.d.ts +4 -3
- package/lib/Socket/socket.js +69 -9
- package/lib/Store/make-in-memory-store.d.ts +2 -2
- package/lib/Types/Auth.d.ts +19 -17
- package/lib/Types/Call.d.ts +2 -2
- package/lib/Types/Chat.d.ts +13 -13
- package/lib/Types/Events.d.ts +3 -3
- package/lib/Types/GroupMetadata.d.ts +4 -2
- package/lib/Types/LabelAssociation.d.ts +2 -2
- package/lib/Types/Message.d.ts +57 -45
- package/lib/Types/Product.d.ts +14 -14
- package/lib/Types/Signal.d.ts +10 -10
- package/lib/Types/Socket.d.ts +5 -4
- package/lib/Types/State.d.ts +2 -2
- package/lib/Types/index.d.ts +5 -5
- package/lib/Utils/auth-utils.js +3 -1
- package/lib/Utils/chat-utils.d.ts +4 -4
- package/lib/Utils/crypto.d.ts +3 -0
- package/lib/Utils/crypto.js +15 -1
- package/lib/Utils/event-buffer.d.ts +2 -2
- package/lib/Utils/event-buffer.js +3 -3
- package/lib/Utils/generics.d.ts +7 -6
- package/lib/Utils/generics.js +25 -27
- package/lib/Utils/link-preview.d.ts +1 -1
- package/lib/Utils/link-preview.js +1 -24
- package/lib/Utils/make-mutex.d.ts +1 -1
- package/lib/Utils/messages-media.d.ts +9 -3
- package/lib/Utils/messages-media.js +54 -6
- package/lib/Utils/messages.d.ts +6 -5
- package/lib/Utils/messages.js +37 -7
- package/lib/Utils/process-message.d.ts +2 -2
- package/lib/Utils/validate-connection.js +1 -2
- package/lib/WABinary/jid-utils.d.ts +4 -4
- package/lib/WABinary/types.d.ts +4 -4
- package/lib/index.d.ts +2 -1
- package/lib/index.js +2 -0
- package/package.json +6 -5
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const queue_job = require('./queue_job');
|
|
1
2
|
const SenderKeyMessage = require('./sender_key_message');
|
|
2
3
|
const crypto = require('libsignal/src/crypto');
|
|
3
4
|
|
|
@@ -7,11 +8,22 @@ class GroupCipher {
|
|
|
7
8
|
this.senderKeyName = senderKeyName;
|
|
8
9
|
}
|
|
9
10
|
|
|
11
|
+
queueJob(awaitable) {
|
|
12
|
+
return queue_job(this.senderKeyName.toString(), awaitable)
|
|
13
|
+
}
|
|
14
|
+
|
|
10
15
|
async encrypt(paddedPlaintext) {
|
|
11
|
-
|
|
16
|
+
return await this.queueJob(async () => {
|
|
12
17
|
const record = await this.senderKeyStore.loadSenderKey(this.senderKeyName);
|
|
18
|
+
if (!record) {
|
|
19
|
+
throw new Error("No SenderKeyRecord found for encryption")
|
|
20
|
+
}
|
|
13
21
|
const senderKeyState = record.getSenderKeyState();
|
|
14
|
-
|
|
22
|
+
if (!senderKeyState) {
|
|
23
|
+
throw new Error("No session to encrypt message");
|
|
24
|
+
}
|
|
25
|
+
const iteration = senderKeyState.getSenderChainKey().getIteration()
|
|
26
|
+
const senderKey = this.getSenderKey(senderKeyState, iteration === 0 ? 0 : iteration + 1)
|
|
15
27
|
|
|
16
28
|
const ciphertext = await this.getCipherText(
|
|
17
29
|
senderKey.getIv(),
|
|
@@ -25,35 +37,37 @@ class GroupCipher {
|
|
|
25
37
|
ciphertext,
|
|
26
38
|
senderKeyState.getSigningKeyPrivate()
|
|
27
39
|
);
|
|
28
|
-
senderKeyState.setSenderChainKey(senderKeyState.getSenderChainKey().getNext());
|
|
29
40
|
await this.senderKeyStore.storeSenderKey(this.senderKeyName, record);
|
|
30
|
-
return senderKeyMessage.serialize()
|
|
31
|
-
}
|
|
32
|
-
//console.log(e.stack);
|
|
33
|
-
throw new Error('NoSessionException');
|
|
34
|
-
}
|
|
41
|
+
return senderKeyMessage.serialize()
|
|
42
|
+
})
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
async decrypt(senderKeyMessageBytes) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
return await this.queueJob(async () => {
|
|
47
|
+
const record = await this.senderKeyStore.loadSenderKey(this.senderKeyName);
|
|
48
|
+
if (!record) {
|
|
49
|
+
throw new Error("No SenderKeyRecord found for decryption")
|
|
50
|
+
}
|
|
51
|
+
const senderKeyMessage = new SenderKeyMessage(null, null, null, null, senderKeyMessageBytes);
|
|
52
|
+
const senderKeyState = record.getSenderKeyState(senderKeyMessage.getKeyId());
|
|
53
|
+
if (!senderKeyState) {
|
|
54
|
+
throw new Error("No session found to decrypt message")
|
|
55
|
+
}
|
|
42
56
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// senderKeyState.senderKeyStateStructure.senderSigningKey.private =
|
|
57
|
+
senderKeyMessage.verifySignature(senderKeyState.getSigningKeyPublic());
|
|
58
|
+
const senderKey = this.getSenderKey(senderKeyState, senderKeyMessage.getIteration());
|
|
59
|
+
// senderKeyState.senderKeyStateStructure.senderSigningKey.private =
|
|
47
60
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
61
|
+
const plaintext = await this.getPlainText(
|
|
62
|
+
senderKey.getIv(),
|
|
63
|
+
senderKey.getCipherKey(),
|
|
64
|
+
senderKeyMessage.getCipherText()
|
|
65
|
+
);
|
|
53
66
|
|
|
54
|
-
|
|
67
|
+
await this.senderKeyStore.storeSenderKey(this.senderKeyName, record);
|
|
55
68
|
|
|
56
|
-
|
|
69
|
+
return plaintext;
|
|
70
|
+
})
|
|
57
71
|
}
|
|
58
72
|
|
|
59
73
|
getSenderKey(senderKeyState, iteration) {
|
|
@@ -67,7 +81,7 @@ class GroupCipher {
|
|
|
67
81
|
);
|
|
68
82
|
}
|
|
69
83
|
|
|
70
|
-
if (senderChainKey.getIteration()
|
|
84
|
+
if (iteration - senderChainKey.getIteration() > 2000) {
|
|
71
85
|
throw new Error('Over 2000 messages into the future!');
|
|
72
86
|
}
|
|
73
87
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// vim: ts=4:sw=4:expandtab
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* jobQueue manages multiple queues indexed by device to serialize
|
|
5
|
+
* session io ops on the database.
|
|
6
|
+
*/
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const _queueAsyncBuckets = new Map();
|
|
11
|
+
const _gcLimit = 10000;
|
|
12
|
+
|
|
13
|
+
async function _asyncQueueExecutor(queue, cleanup) {
|
|
14
|
+
let offt = 0;
|
|
15
|
+
while (true) {
|
|
16
|
+
let limit = Math.min(queue.length, _gcLimit); // Break up thundering hurds for GC duty.
|
|
17
|
+
for (let i = offt; i < limit; i++) {
|
|
18
|
+
const job = queue[i];
|
|
19
|
+
try {
|
|
20
|
+
job.resolve(await job.awaitable());
|
|
21
|
+
} catch (e) {
|
|
22
|
+
job.reject(e);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (limit < queue.length) {
|
|
26
|
+
/* Perform lazy GC of queue for faster iteration. */
|
|
27
|
+
if (limit >= _gcLimit) {
|
|
28
|
+
queue.splice(0, limit);
|
|
29
|
+
offt = 0;
|
|
30
|
+
} else {
|
|
31
|
+
offt = limit;
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
cleanup();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = function (bucket, awaitable) {
|
|
41
|
+
/* Run the async awaitable only when all other async calls registered
|
|
42
|
+
* here have completed (or thrown). The bucket argument is a hashable
|
|
43
|
+
* key representing the task queue to use. */
|
|
44
|
+
if (!awaitable.name) {
|
|
45
|
+
// Make debuging easier by adding a name to this function.
|
|
46
|
+
Object.defineProperty(awaitable, 'name', { writable: true });
|
|
47
|
+
if (typeof bucket === 'string') {
|
|
48
|
+
awaitable.name = bucket;
|
|
49
|
+
} else {
|
|
50
|
+
console.warn("Unhandled bucket type (for naming):", typeof bucket, bucket);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
let inactive;
|
|
54
|
+
if (!_queueAsyncBuckets.has(bucket)) {
|
|
55
|
+
_queueAsyncBuckets.set(bucket, []);
|
|
56
|
+
inactive = true;
|
|
57
|
+
}
|
|
58
|
+
const queue = _queueAsyncBuckets.get(bucket);
|
|
59
|
+
const job = new Promise((resolve, reject) => queue.push({
|
|
60
|
+
awaitable,
|
|
61
|
+
resolve,
|
|
62
|
+
reject
|
|
63
|
+
}));
|
|
64
|
+
if (inactive) {
|
|
65
|
+
/* An executor is not currently active; Start one now. */
|
|
66
|
+
_asyncQueueExecutor(queue, () => _queueAsyncBuckets.delete(bucket));
|
|
67
|
+
}
|
|
68
|
+
return job;
|
|
69
|
+
};
|
|
@@ -22,18 +22,20 @@ class SenderKeyRecord {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
getSenderKeyState(keyId) {
|
|
25
|
-
if (!keyId && this.senderKeyStates.length) return this.senderKeyStates[
|
|
25
|
+
if (!keyId && this.senderKeyStates.length) return this.senderKeyStates[this.senderKeyStates.length - 1];
|
|
26
26
|
for (let i = 0; i < this.senderKeyStates.length; i++) {
|
|
27
27
|
const state = this.senderKeyStates[i];
|
|
28
28
|
if (state.getKeyId() === keyId) {
|
|
29
29
|
return state;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
|
-
throw new Error(`No keys for: ${keyId}`);
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
addSenderKeyState(id, iteration, chainKey, signatureKey) {
|
|
36
35
|
this.senderKeyStates.push(new SenderKeyState(id, iteration, chainKey, null, signatureKey));
|
|
36
|
+
if (this.senderKeyStates.length > 5) {
|
|
37
|
+
this.senderKeyStates.shift()
|
|
38
|
+
}
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
setSenderKeyState(id, iteration, chainKey, keyPair) {
|
package/lib/Defaults/index.js
CHANGED
|
@@ -49,7 +49,7 @@ exports.DEFAULT_CONNECTION_CONFIG = {
|
|
|
49
49
|
browser: Utils_1.Browsers.baileys('Chrome'),
|
|
50
50
|
waWebSocketUrl: 'wss://web.whatsapp.com/ws/chat',
|
|
51
51
|
connectTimeoutMs: 20000,
|
|
52
|
-
keepAliveIntervalMs:
|
|
52
|
+
keepAliveIntervalMs: 30000,
|
|
53
53
|
logger: logger_1.default.child({ class: 'baileys' }),
|
|
54
54
|
printQRInTerminal: false,
|
|
55
55
|
emitOwnEvents: true,
|
package/lib/Socket/business.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export declare const makeBusinessSocket: (config: SocketConfig) => {
|
|
|
7
7
|
products: import("../Types").Product[];
|
|
8
8
|
nextPageCursor: string | undefined;
|
|
9
9
|
}>;
|
|
10
|
-
getCollections: (jid?: string
|
|
10
|
+
getCollections: (jid?: string, limit?: number) => Promise<{
|
|
11
11
|
collections: import("../Types").CatalogCollection[];
|
|
12
12
|
}>;
|
|
13
13
|
productCreate: (create: ProductCreate) => Promise<import("../Types").Product>;
|
|
@@ -20,7 +20,7 @@ export declare const makeBusinessSocket: (config: SocketConfig) => {
|
|
|
20
20
|
rejectCall: (callId: string, callFrom: string) => Promise<void>;
|
|
21
21
|
getPrivacyTokens: (jids: string[]) => Promise<BinaryNode>;
|
|
22
22
|
assertSessions: (jids: string[], force: boolean) => Promise<boolean>;
|
|
23
|
-
relayMessage: (jid: string, message: import("../Types").WAProto.IMessage, { messageId: msgId, participant, additionalAttributes, useUserDevicesCache, cachedGroupMetadata }: import("../Types").MessageRelayOptions) => Promise<string>;
|
|
23
|
+
relayMessage: (jid: string, message: import("../Types").WAProto.IMessage, { messageId: msgId, participant, additionalAttributes, useUserDevicesCache, cachedGroupMetadata, statusJidList }: import("../Types").MessageRelayOptions) => Promise<string>;
|
|
24
24
|
sendReceipt: (jid: string, participant: string | undefined, messageIds: string[], type: import("../Types").MessageReceiptType) => Promise<void>;
|
|
25
25
|
sendReceipts: (keys: import("../Types").WAProto.IMessageKey[], type: import("../Types").MessageReceiptType) => Promise<void>;
|
|
26
26
|
readMessages: (keys: import("../Types").WAProto.IMessageKey[]) => Promise<void>;
|
|
@@ -45,6 +45,7 @@ export declare const makeBusinessSocket: (config: SocketConfig) => {
|
|
|
45
45
|
groupParticipantsUpdate: (jid: string, participants: string[], action: import("../Types").ParticipantAction) => Promise<{
|
|
46
46
|
status: string;
|
|
47
47
|
jid: string;
|
|
48
|
+
content: BinaryNode;
|
|
48
49
|
}[]>;
|
|
49
50
|
groupUpdateDescription: (jid: string, description?: string | undefined) => Promise<void>;
|
|
50
51
|
groupInviteCode: (jid: string) => Promise<string | undefined>;
|
|
@@ -95,7 +96,7 @@ export declare const makeBusinessSocket: (config: SocketConfig) => {
|
|
|
95
96
|
addMessageLabel: (jid: string, messageId: string, labelId: string) => Promise<void>;
|
|
96
97
|
removeMessageLabel: (jid: string, messageId: string, labelId: string) => Promise<void>;
|
|
97
98
|
type: "md";
|
|
98
|
-
ws: import("./Client").MobileSocketClient | import("./Client").WebSocketClient;
|
|
99
|
+
ws: import("./Client/mobile-socket-client").MobileSocketClient | import("./Client/web-socket-client").WebSocketClient;
|
|
99
100
|
ev: import("../Types").BaileysEventEmitter & {
|
|
100
101
|
process(handler: (events: Partial<import("../Types").BaileysEventMap>) => void | Promise<void>): () => void;
|
|
101
102
|
buffer(): void;
|
|
@@ -120,5 +121,6 @@ export declare const makeBusinessSocket: (config: SocketConfig) => {
|
|
|
120
121
|
onUnexpectedError: (err: Error | import("@hapi/boom").Boom<any>, msg: string) => void;
|
|
121
122
|
uploadPreKeys: (count?: number) => Promise<void>;
|
|
122
123
|
uploadPreKeysToServerIfRequired: () => Promise<void>;
|
|
124
|
+
requestPairingCode: (phoneNumber: string) => Promise<string>;
|
|
123
125
|
waitForConnectionUpdate: (check: (u: Partial<import("../Types").ConnectionState>) => boolean | undefined, timeoutMs?: number | undefined) => Promise<void>;
|
|
124
126
|
};
|
package/lib/Socket/chats.d.ts
CHANGED
|
@@ -12,9 +12,9 @@ export declare const makeChatsSocket: (config: SocketConfig) => {
|
|
|
12
12
|
}>;
|
|
13
13
|
upsertMessage: (msg: proto.IWebMessageInfo, type: MessageUpsertType) => Promise<void>;
|
|
14
14
|
appPatch: (patchCreate: WAPatchCreate) => Promise<void>;
|
|
15
|
-
sendPresenceUpdate: (type: WAPresence, toJid?: string
|
|
16
|
-
presenceSubscribe: (toJid: string, tcToken?: Buffer
|
|
17
|
-
profilePictureUrl: (jid: string, type?: 'preview' | 'image', timeoutMs?: number
|
|
15
|
+
sendPresenceUpdate: (type: WAPresence, toJid?: string) => Promise<void>;
|
|
16
|
+
presenceSubscribe: (toJid: string, tcToken?: Buffer) => Promise<void>;
|
|
17
|
+
profilePictureUrl: (jid: string, type?: 'preview' | 'image', timeoutMs?: number) => Promise<string | undefined>;
|
|
18
18
|
onWhatsApp: (...jids: string[]) => Promise<{
|
|
19
19
|
exists: boolean;
|
|
20
20
|
jid: string;
|
|
@@ -39,13 +39,13 @@ export declare const makeChatsSocket: (config: SocketConfig) => {
|
|
|
39
39
|
getBusinessProfile: (jid: string) => Promise<WABusinessProfile | void>;
|
|
40
40
|
resyncAppState: (collections: readonly ("critical_block" | "critical_unblock_low" | "regular_high" | "regular_low" | "regular")[], isInitialSync: boolean) => Promise<void>;
|
|
41
41
|
chatModify: (mod: ChatModification, jid: string) => Promise<void>;
|
|
42
|
-
cleanDirtyBits: (type: 'account_sync' | 'groups', fromTimestamp?:
|
|
42
|
+
cleanDirtyBits: (type: 'account_sync' | 'groups', fromTimestamp?: number | string) => Promise<void>;
|
|
43
43
|
addChatLabel: (jid: string, labelId: string) => Promise<void>;
|
|
44
44
|
removeChatLabel: (jid: string, labelId: string) => Promise<void>;
|
|
45
45
|
addMessageLabel: (jid: string, messageId: string, labelId: string) => Promise<void>;
|
|
46
46
|
removeMessageLabel: (jid: string, messageId: string, labelId: string) => Promise<void>;
|
|
47
47
|
type: "md";
|
|
48
|
-
ws: import("./Client").MobileSocketClient | import("./Client").WebSocketClient;
|
|
48
|
+
ws: import("./Client/mobile-socket-client").MobileSocketClient | import("./Client/web-socket-client").WebSocketClient;
|
|
49
49
|
ev: import("../Types").BaileysEventEmitter & {
|
|
50
50
|
process(handler: (events: Partial<import("../Types").BaileysEventMap>) => void | Promise<void>): () => void;
|
|
51
51
|
buffer(): void;
|
|
@@ -70,5 +70,6 @@ export declare const makeChatsSocket: (config: SocketConfig) => {
|
|
|
70
70
|
onUnexpectedError: (err: Error | Boom<any>, msg: string) => void;
|
|
71
71
|
uploadPreKeys: (count?: number) => Promise<void>;
|
|
72
72
|
uploadPreKeysToServerIfRequired: () => Promise<void>;
|
|
73
|
+
requestPairingCode: (phoneNumber: string) => Promise<string>;
|
|
73
74
|
waitForConnectionUpdate: (check: (u: Partial<import("../Types").ConnectionState>) => boolean | undefined, timeoutMs?: number | undefined) => Promise<void>;
|
|
74
75
|
};
|
package/lib/Socket/groups.d.ts
CHANGED
|
@@ -17,8 +17,9 @@ export declare const makeGroupsSocket: (config: SocketConfig) => {
|
|
|
17
17
|
groupParticipantsUpdate: (jid: string, participants: string[], action: ParticipantAction) => Promise<{
|
|
18
18
|
status: string;
|
|
19
19
|
jid: string;
|
|
20
|
+
content: BinaryNode;
|
|
20
21
|
}[]>;
|
|
21
|
-
groupUpdateDescription: (jid: string, description?: string
|
|
22
|
+
groupUpdateDescription: (jid: string, description?: string) => Promise<void>;
|
|
22
23
|
groupInviteCode: (jid: string) => Promise<string | undefined>;
|
|
23
24
|
groupRevokeInvite: (jid: string) => Promise<string | undefined>;
|
|
24
25
|
groupAcceptInvite: (code: string) => Promise<string | undefined>;
|
|
@@ -75,7 +76,7 @@ export declare const makeGroupsSocket: (config: SocketConfig) => {
|
|
|
75
76
|
addMessageLabel: (jid: string, messageId: string, labelId: string) => Promise<void>;
|
|
76
77
|
removeMessageLabel: (jid: string, messageId: string, labelId: string) => Promise<void>;
|
|
77
78
|
type: "md";
|
|
78
|
-
ws: import("./Client").MobileSocketClient | import("./Client").WebSocketClient;
|
|
79
|
+
ws: import("./Client/mobile-socket-client").MobileSocketClient | import("./Client/web-socket-client").WebSocketClient;
|
|
79
80
|
ev: import("../Types").BaileysEventEmitter & {
|
|
80
81
|
process(handler: (events: Partial<import("../Types").BaileysEventMap>) => void | Promise<void>): () => void;
|
|
81
82
|
buffer(): void;
|
|
@@ -100,6 +101,7 @@ export declare const makeGroupsSocket: (config: SocketConfig) => {
|
|
|
100
101
|
onUnexpectedError: (err: Error | import("@hapi/boom").Boom<any>, msg: string) => void;
|
|
101
102
|
uploadPreKeys: (count?: number) => Promise<void>;
|
|
102
103
|
uploadPreKeysToServerIfRequired: () => Promise<void>;
|
|
104
|
+
requestPairingCode: (phoneNumber: string) => Promise<string>;
|
|
103
105
|
waitForConnectionUpdate: (check: (u: Partial<import("../Types").ConnectionState>) => boolean | undefined, timeoutMs?: number | undefined) => Promise<void>;
|
|
104
106
|
};
|
|
105
107
|
export declare const extractGroupMetadata: (result: BinaryNode) => GroupMetadata;
|
package/lib/Socket/groups.js
CHANGED
|
@@ -152,7 +152,7 @@ const makeGroupsSocket = (config) => {
|
|
|
152
152
|
const node = (0, WABinary_1.getBinaryNodeChild)(result, action);
|
|
153
153
|
const participantsAffected = (0, WABinary_1.getBinaryNodeChildren)(node, 'participant');
|
|
154
154
|
return participantsAffected.map(p => {
|
|
155
|
-
return { status: p.attrs.error || '200', jid: p.attrs.jid };
|
|
155
|
+
return { status: p.attrs.error || '200', jid: p.attrs.jid, content: p };
|
|
156
156
|
});
|
|
157
157
|
},
|
|
158
158
|
groupUpdateDescription: async (jid, description) => {
|
package/lib/Socket/index.d.ts
CHANGED
|
@@ -16,12 +16,12 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
|
|
|
16
16
|
deleted: number;
|
|
17
17
|
}>;
|
|
18
18
|
productUpdate: (productId: string, update: import("../Types").ProductUpdate) => Promise<import("../Types").Product>;
|
|
19
|
-
sendMessageAck: ({ tag, attrs }: import("
|
|
20
|
-
sendRetryRequest: (node: import("
|
|
19
|
+
sendMessageAck: ({ tag, attrs }: import("../index").BinaryNode) => Promise<void>;
|
|
20
|
+
sendRetryRequest: (node: import("../index").BinaryNode, forceIncludeKeys?: boolean) => Promise<void>;
|
|
21
21
|
rejectCall: (callId: string, callFrom: string) => Promise<void>;
|
|
22
|
-
getPrivacyTokens: (jids: string[]) => Promise<import("
|
|
22
|
+
getPrivacyTokens: (jids: string[]) => Promise<import("../index").BinaryNode>;
|
|
23
23
|
assertSessions: (jids: string[], force: boolean) => Promise<boolean>;
|
|
24
|
-
relayMessage: (jid: string, message: import("../Types").WAProto.IMessage, { messageId: msgId, participant, additionalAttributes, useUserDevicesCache, cachedGroupMetadata }: import("../Types").MessageRelayOptions) => Promise<string>;
|
|
24
|
+
relayMessage: (jid: string, message: import("../Types").WAProto.IMessage, { messageId: msgId, participant, additionalAttributes, useUserDevicesCache, cachedGroupMetadata, statusJidList }: import("../Types").MessageRelayOptions) => Promise<string>;
|
|
25
25
|
sendReceipt: (jid: string, participant: string | undefined, messageIds: string[], type: import("../Types").MessageReceiptType) => Promise<void>;
|
|
26
26
|
sendReceipts: (keys: import("../Types").WAProto.IMessageKey[], type: import("../Types").MessageReceiptType) => Promise<void>;
|
|
27
27
|
readMessages: (keys: import("../Types").WAProto.IMessageKey[]) => Promise<void>;
|
|
@@ -46,6 +46,7 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
|
|
|
46
46
|
groupParticipantsUpdate: (jid: string, participants: string[], action: import("../Types").ParticipantAction) => Promise<{
|
|
47
47
|
status: string;
|
|
48
48
|
jid: string;
|
|
49
|
+
content: import("../index").BinaryNode;
|
|
49
50
|
}[]>;
|
|
50
51
|
groupUpdateDescription: (jid: string, description?: string | undefined) => Promise<void>;
|
|
51
52
|
groupInviteCode: (jid: string) => Promise<string | undefined>;
|
|
@@ -96,7 +97,7 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
|
|
|
96
97
|
addMessageLabel: (jid: string, messageId: string, labelId: string) => Promise<void>;
|
|
97
98
|
removeMessageLabel: (jid: string, messageId: string, labelId: string) => Promise<void>;
|
|
98
99
|
type: "md";
|
|
99
|
-
ws: import("./Client").MobileSocketClient | import("./Client").WebSocketClient;
|
|
100
|
+
ws: import("./Client/mobile-socket-client").MobileSocketClient | import("./Client/web-socket-client").WebSocketClient;
|
|
100
101
|
ev: import("../Types").BaileysEventEmitter & {
|
|
101
102
|
process(handler: (events: Partial<import("../Types").BaileysEventMap>) => void | Promise<void>): () => void;
|
|
102
103
|
buffer(): void;
|
|
@@ -111,16 +112,17 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
|
|
|
111
112
|
signalRepository: import("../Types").SignalRepository;
|
|
112
113
|
user: import("../Types").Contact | undefined;
|
|
113
114
|
generateMessageTag: () => string;
|
|
114
|
-
query: (node: import("
|
|
115
|
+
query: (node: import("../index").BinaryNode, timeoutMs?: number | undefined) => Promise<import("../index").BinaryNode>;
|
|
115
116
|
waitForMessage: <T_2>(msgId: string, timeoutMs?: number | undefined) => Promise<T_2>;
|
|
116
117
|
waitForSocketOpen: () => Promise<void>;
|
|
117
118
|
sendRawMessage: (data: Uint8Array | Buffer) => Promise<void>;
|
|
118
|
-
sendNode: (frame: import("
|
|
119
|
+
sendNode: (frame: import("../index").BinaryNode) => Promise<void>;
|
|
119
120
|
logout: (msg?: string | undefined) => Promise<void>;
|
|
120
121
|
end: (error: Error | undefined) => void;
|
|
121
122
|
onUnexpectedError: (err: Error | import("@hapi/boom").Boom<any>, msg: string) => void;
|
|
122
123
|
uploadPreKeys: (count?: number) => Promise<void>;
|
|
123
124
|
uploadPreKeysToServerIfRequired: () => Promise<void>;
|
|
125
|
+
requestPairingCode: (phoneNumber: string) => Promise<string>;
|
|
124
126
|
waitForConnectionUpdate: (check: (u: Partial<import("../Types").ConnectionState>) => boolean | undefined, timeoutMs?: number | undefined) => Promise<void>;
|
|
125
127
|
};
|
|
126
128
|
export default makeWASocket;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
import { Boom } from '@hapi/boom';
|
|
2
3
|
import { proto } from '../../WAProto';
|
|
3
4
|
import { MessageReceiptType, MessageRelayOptions, SocketConfig } from '../Types';
|
|
4
5
|
import { BinaryNode } from '../WABinary';
|
|
@@ -8,7 +9,7 @@ export declare const makeMessagesRecvSocket: (config: SocketConfig) => {
|
|
|
8
9
|
rejectCall: (callId: string, callFrom: string) => Promise<void>;
|
|
9
10
|
getPrivacyTokens: (jids: string[]) => Promise<BinaryNode>;
|
|
10
11
|
assertSessions: (jids: string[], force: boolean) => Promise<boolean>;
|
|
11
|
-
relayMessage: (jid: string, message: proto.IMessage, { messageId: msgId, participant, additionalAttributes, useUserDevicesCache, cachedGroupMetadata }: MessageRelayOptions) => Promise<string>;
|
|
12
|
+
relayMessage: (jid: string, message: proto.IMessage, { messageId: msgId, participant, additionalAttributes, useUserDevicesCache, cachedGroupMetadata, statusJidList }: MessageRelayOptions) => Promise<string>;
|
|
12
13
|
sendReceipt: (jid: string, participant: string | undefined, messageIds: string[], type: MessageReceiptType) => Promise<void>;
|
|
13
14
|
sendReceipts: (keys: proto.IMessageKey[], type: MessageReceiptType) => Promise<void>;
|
|
14
15
|
readMessages: (keys: proto.IMessageKey[]) => Promise<void>;
|
|
@@ -33,6 +34,7 @@ export declare const makeMessagesRecvSocket: (config: SocketConfig) => {
|
|
|
33
34
|
groupParticipantsUpdate: (jid: string, participants: string[], action: import("../Types").ParticipantAction) => Promise<{
|
|
34
35
|
status: string;
|
|
35
36
|
jid: string;
|
|
37
|
+
content: BinaryNode;
|
|
36
38
|
}[]>;
|
|
37
39
|
groupUpdateDescription: (jid: string, description?: string | undefined) => Promise<void>;
|
|
38
40
|
groupInviteCode: (jid: string) => Promise<string | undefined>;
|
|
@@ -83,7 +85,7 @@ export declare const makeMessagesRecvSocket: (config: SocketConfig) => {
|
|
|
83
85
|
addMessageLabel: (jid: string, messageId: string, labelId: string) => Promise<void>;
|
|
84
86
|
removeMessageLabel: (jid: string, messageId: string, labelId: string) => Promise<void>;
|
|
85
87
|
type: "md";
|
|
86
|
-
ws: import("./Client").MobileSocketClient | import("./Client").WebSocketClient;
|
|
88
|
+
ws: import("./Client/mobile-socket-client").MobileSocketClient | import("./Client/web-socket-client").WebSocketClient;
|
|
87
89
|
ev: import("../Types").BaileysEventEmitter & {
|
|
88
90
|
process(handler: (events: Partial<import("../Types").BaileysEventMap>) => void | Promise<void>): () => void;
|
|
89
91
|
buffer(): void;
|
|
@@ -105,8 +107,9 @@ export declare const makeMessagesRecvSocket: (config: SocketConfig) => {
|
|
|
105
107
|
sendNode: (frame: BinaryNode) => Promise<void>;
|
|
106
108
|
logout: (msg?: string | undefined) => Promise<void>;
|
|
107
109
|
end: (error: Error | undefined) => void;
|
|
108
|
-
onUnexpectedError: (err: Error |
|
|
110
|
+
onUnexpectedError: (err: Error | Boom<any>, msg: string) => void;
|
|
109
111
|
uploadPreKeys: (count?: number) => Promise<void>;
|
|
110
112
|
uploadPreKeysToServerIfRequired: () => Promise<void>;
|
|
113
|
+
requestPairingCode: (phoneNumber: string) => Promise<string>;
|
|
111
114
|
waitForConnectionUpdate: (check: (u: Partial<import("../Types").ConnectionState>) => boolean | undefined, timeoutMs?: number | undefined) => Promise<void>;
|
|
112
115
|
};
|
|
@@ -4,13 +4,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.makeMessagesRecvSocket = void 0;
|
|
7
|
+
const boom_1 = require("@hapi/boom");
|
|
8
|
+
const crypto_1 = require("crypto");
|
|
7
9
|
const node_cache_1 = __importDefault(require("node-cache"));
|
|
8
10
|
const WAProto_1 = require("../../WAProto");
|
|
9
11
|
const Defaults_1 = require("../Defaults");
|
|
10
12
|
const Types_1 = require("../Types");
|
|
11
13
|
const Utils_1 = require("../Utils");
|
|
14
|
+
const Utils_2 = require("../Utils");
|
|
12
15
|
const make_mutex_1 = require("../Utils/make-mutex");
|
|
13
|
-
const process_message_1 = require("../Utils/process-message");
|
|
14
16
|
const WABinary_1 = require("../WABinary");
|
|
15
17
|
const groups_1 = require("./groups");
|
|
16
18
|
const messages_send_1 = require("./messages-send");
|
|
@@ -169,7 +171,10 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
169
171
|
name: metadata.subject,
|
|
170
172
|
conversationTimestamp: metadata.creation,
|
|
171
173
|
}]);
|
|
172
|
-
ev.emit('groups.upsert', [
|
|
174
|
+
ev.emit('groups.upsert', [{
|
|
175
|
+
...metadata,
|
|
176
|
+
author: participant
|
|
177
|
+
}]);
|
|
173
178
|
break;
|
|
174
179
|
case 'ephemeral':
|
|
175
180
|
case 'not_ephemeral':
|
|
@@ -296,11 +301,82 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
296
301
|
});
|
|
297
302
|
}
|
|
298
303
|
break;
|
|
304
|
+
case 'link_code_companion_reg':
|
|
305
|
+
const linkCodeCompanionReg = (0, WABinary_1.getBinaryNodeChild)(node, 'link_code_companion_reg');
|
|
306
|
+
const ref = toRequiredBuffer((0, WABinary_1.getBinaryNodeChildBuffer)(linkCodeCompanionReg, 'link_code_pairing_ref'));
|
|
307
|
+
const primaryIdentityPublicKey = toRequiredBuffer((0, WABinary_1.getBinaryNodeChildBuffer)(linkCodeCompanionReg, 'primary_identity_pub'));
|
|
308
|
+
const primaryEphemeralPublicKeyWrapped = toRequiredBuffer((0, WABinary_1.getBinaryNodeChildBuffer)(linkCodeCompanionReg, 'link_code_pairing_wrapped_primary_ephemeral_pub'));
|
|
309
|
+
const codePairingPublicKey = decipherLinkPublicKey(primaryEphemeralPublicKeyWrapped);
|
|
310
|
+
const companionSharedKey = Utils_1.Curve.sharedKey(authState.creds.pairingEphemeralKeyPair.private, codePairingPublicKey);
|
|
311
|
+
const random = (0, crypto_1.randomBytes)(32);
|
|
312
|
+
const linkCodeSalt = (0, crypto_1.randomBytes)(32);
|
|
313
|
+
const linkCodePairingExpanded = (0, Utils_1.hkdf)(companionSharedKey, 32, {
|
|
314
|
+
salt: linkCodeSalt,
|
|
315
|
+
info: 'link_code_pairing_key_bundle_encryption_key'
|
|
316
|
+
});
|
|
317
|
+
const encryptPayload = Buffer.concat([Buffer.from(authState.creds.signedIdentityKey.public), primaryIdentityPublicKey, random]);
|
|
318
|
+
const encryptIv = (0, crypto_1.randomBytes)(12);
|
|
319
|
+
const encrypted = (0, Utils_1.aesEncryptGCM)(encryptPayload, linkCodePairingExpanded, encryptIv, Buffer.alloc(0));
|
|
320
|
+
const encryptedPayload = Buffer.concat([linkCodeSalt, encryptIv, encrypted]);
|
|
321
|
+
const identitySharedKey = Utils_1.Curve.sharedKey(authState.creds.signedIdentityKey.private, primaryIdentityPublicKey);
|
|
322
|
+
const identityPayload = Buffer.concat([companionSharedKey, identitySharedKey, random]);
|
|
323
|
+
authState.creds.advSecretKey = (0, Utils_1.hkdf)(identityPayload, 32, { info: 'adv_secret' }).toString('base64');
|
|
324
|
+
await query({
|
|
325
|
+
tag: 'iq',
|
|
326
|
+
attrs: {
|
|
327
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
328
|
+
type: 'set',
|
|
329
|
+
id: sock.generateMessageTag(),
|
|
330
|
+
xmlns: 'md'
|
|
331
|
+
},
|
|
332
|
+
content: [
|
|
333
|
+
{
|
|
334
|
+
tag: 'link_code_companion_reg',
|
|
335
|
+
attrs: {
|
|
336
|
+
jid: authState.creds.me.id,
|
|
337
|
+
stage: 'companion_finish',
|
|
338
|
+
},
|
|
339
|
+
content: [
|
|
340
|
+
{
|
|
341
|
+
tag: 'link_code_pairing_wrapped_key_bundle',
|
|
342
|
+
attrs: {},
|
|
343
|
+
content: encryptedPayload
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
tag: 'companion_identity_public',
|
|
347
|
+
attrs: {},
|
|
348
|
+
content: authState.creds.signedIdentityKey.public
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
tag: 'link_code_pairing_ref',
|
|
352
|
+
attrs: {},
|
|
353
|
+
content: ref
|
|
354
|
+
}
|
|
355
|
+
]
|
|
356
|
+
}
|
|
357
|
+
]
|
|
358
|
+
});
|
|
359
|
+
authState.creds.registered = true;
|
|
360
|
+
ev.emit('creds.update', authState.creds);
|
|
299
361
|
}
|
|
300
362
|
if (Object.keys(result).length) {
|
|
301
363
|
return result;
|
|
302
364
|
}
|
|
303
365
|
};
|
|
366
|
+
function decipherLinkPublicKey(data) {
|
|
367
|
+
const buffer = toRequiredBuffer(data);
|
|
368
|
+
const salt = buffer.slice(0, 32);
|
|
369
|
+
const secretKey = (0, Utils_1.derivePairingCodeKey)(authState.creds.pairingCode, salt);
|
|
370
|
+
const iv = buffer.slice(32, 48);
|
|
371
|
+
const payload = buffer.slice(48, 80);
|
|
372
|
+
return (0, Utils_1.aesDecryptCTR)(payload, secretKey, iv);
|
|
373
|
+
}
|
|
374
|
+
function toRequiredBuffer(data) {
|
|
375
|
+
if (data === undefined) {
|
|
376
|
+
throw new boom_1.Boom('Invalid buffer', { statusCode: 400 });
|
|
377
|
+
}
|
|
378
|
+
return data instanceof Buffer ? data : Buffer.from(data);
|
|
379
|
+
}
|
|
304
380
|
const willSendMessageAgain = (id, participant) => {
|
|
305
381
|
const key = `${id}:${participant}`;
|
|
306
382
|
const retryCount = msgRetryCache.get(key) || 0;
|
|
@@ -501,7 +577,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
501
577
|
await sendReceipt(jid, undefined, [msg.key.id], 'hist_sync');
|
|
502
578
|
}
|
|
503
579
|
}
|
|
504
|
-
(0,
|
|
580
|
+
(0, Utils_2.cleanMessage)(msg, authState.creds.me.id);
|
|
505
581
|
await upsertMessage(msg, node.attrs.offline ? 'append' : 'notify');
|
|
506
582
|
}),
|
|
507
583
|
sendMessageAck(node)
|
|
@@ -6,7 +6,7 @@ import { BinaryNode } from '../WABinary';
|
|
|
6
6
|
export declare const makeMessagesSocket: (config: SocketConfig) => {
|
|
7
7
|
getPrivacyTokens: (jids: string[]) => Promise<BinaryNode>;
|
|
8
8
|
assertSessions: (jids: string[], force: boolean) => Promise<boolean>;
|
|
9
|
-
relayMessage: (jid: string, message: proto.IMessage, { messageId: msgId, participant, additionalAttributes, useUserDevicesCache, cachedGroupMetadata }: MessageRelayOptions) => Promise<string>;
|
|
9
|
+
relayMessage: (jid: string, message: proto.IMessage, { messageId: msgId, participant, additionalAttributes, useUserDevicesCache, cachedGroupMetadata, statusJidList }: MessageRelayOptions) => Promise<string>;
|
|
10
10
|
sendReceipt: (jid: string, participant: string | undefined, messageIds: string[], type: MessageReceiptType) => Promise<void>;
|
|
11
11
|
sendReceipts: (keys: WAMessageKey[], type: MessageReceiptType) => Promise<void>;
|
|
12
12
|
readMessages: (keys: WAMessageKey[]) => Promise<void>;
|
|
@@ -31,6 +31,7 @@ export declare const makeMessagesSocket: (config: SocketConfig) => {
|
|
|
31
31
|
groupParticipantsUpdate: (jid: string, participants: string[], action: import("../Types").ParticipantAction) => Promise<{
|
|
32
32
|
status: string;
|
|
33
33
|
jid: string;
|
|
34
|
+
content: BinaryNode;
|
|
34
35
|
}[]>;
|
|
35
36
|
groupUpdateDescription: (jid: string, description?: string | undefined) => Promise<void>;
|
|
36
37
|
groupInviteCode: (jid: string) => Promise<string | undefined>;
|
|
@@ -81,7 +82,7 @@ export declare const makeMessagesSocket: (config: SocketConfig) => {
|
|
|
81
82
|
addMessageLabel: (jid: string, messageId: string, labelId: string) => Promise<void>;
|
|
82
83
|
removeMessageLabel: (jid: string, messageId: string, labelId: string) => Promise<void>;
|
|
83
84
|
type: "md";
|
|
84
|
-
ws: import("./Client").MobileSocketClient | import("./Client").WebSocketClient;
|
|
85
|
+
ws: import("./Client/mobile-socket-client").MobileSocketClient | import("./Client/web-socket-client").WebSocketClient;
|
|
85
86
|
ev: import("../Types").BaileysEventEmitter & {
|
|
86
87
|
process(handler: (events: Partial<import("../Types").BaileysEventMap>) => void | Promise<void>): () => void;
|
|
87
88
|
buffer(): void;
|
|
@@ -106,5 +107,6 @@ export declare const makeMessagesSocket: (config: SocketConfig) => {
|
|
|
106
107
|
onUnexpectedError: (err: Error | Boom<any>, msg: string) => void;
|
|
107
108
|
uploadPreKeys: (count?: number) => Promise<void>;
|
|
108
109
|
uploadPreKeysToServerIfRequired: () => Promise<void>;
|
|
110
|
+
requestPairingCode: (phoneNumber: string) => Promise<string>;
|
|
109
111
|
waitForConnectionUpdate: (check: (u: Partial<import("../Types").ConnectionState>) => boolean | undefined, timeoutMs?: number | undefined) => Promise<void>;
|
|
110
112
|
};
|