@baileys-md/baileys 10.1.0 → 11.0.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/LICENSE +1 -1
- package/README.md +1303 -2
- package/WAProto/GenerateStatics.sh +3 -0
- package/WAProto/WAProto.proto +4633 -0
- package/WAProto/fix-imports.js +29 -0
- package/WAProto/index.js +13516 -4182
- package/lib/Defaults/baileys-version.js +1 -0
- package/lib/Defaults/index.js +51 -72
- package/lib/Signal/Group/ciphertext-message.js +12 -0
- package/lib/Signal/Group/group-session-builder.js +30 -0
- package/lib/Signal/Group/group_cipher.js +94 -0
- package/lib/Signal/Group/index.js +12 -0
- package/lib/Signal/Group/keyhelper.js +19 -0
- package/lib/Signal/Group/queue-job.js +54 -0
- package/lib/Signal/Group/sender-chain-key.js +32 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +63 -0
- package/lib/Signal/Group/sender-key-message.js +67 -0
- package/lib/Signal/Group/sender-key-name.js +48 -0
- package/lib/Signal/Group/sender-key-record.js +50 -0
- package/lib/Signal/Group/sender-key-state.js +96 -0
- package/{WASignalGroup/sender_message_key.js → lib/Signal/Group/sender-message-key.js} +4 -16
- package/lib/Signal/libsignal.js +41 -61
- package/lib/Socket/Client/index.js +3 -19
- package/lib/Socket/Client/types.js +11 -0
- package/lib/Socket/Client/websocket.js +50 -0
- package/lib/Socket/business.js +37 -42
- package/lib/Socket/chats.js +194 -187
- package/lib/Socket/communities.js +351 -0
- package/lib/Socket/groups.js +87 -90
- package/lib/Socket/index.js +7 -8
- package/lib/Socket/messages-recv.js +360 -335
- package/lib/Socket/messages-send.js +156 -279
- package/lib/Socket/mex.js +42 -0
- package/lib/Socket/newsletter.js +144 -213
- package/lib/Socket/socket.js +128 -161
- package/lib/Socket/usync.js +19 -26
- package/lib/Types/Auth.js +2 -2
- package/lib/Types/Call.js +2 -2
- package/lib/Types/Chat.js +8 -4
- package/lib/Types/Contact.js +2 -2
- package/lib/Types/Events.js +2 -2
- package/lib/Types/GroupMetadata.js +2 -2
- package/lib/Types/Label.js +3 -5
- package/lib/Types/LabelAssociation.js +3 -5
- package/lib/Types/Message.js +7 -7
- package/lib/Types/Newsletter.js +30 -17
- package/lib/Types/Product.js +2 -2
- package/lib/Types/Signal.js +2 -2
- package/lib/Types/Socket.js +3 -2
- package/lib/Types/State.js +2 -2
- package/lib/Types/USync.js +2 -2
- package/lib/Types/index.js +15 -31
- package/lib/Utils/auth-utils.js +31 -47
- package/lib/Utils/baileys-event-stream.js +15 -22
- package/lib/Utils/business.js +66 -69
- package/lib/Utils/chat-utils.js +200 -195
- package/lib/Utils/crypto.js +70 -85
- package/lib/Utils/decode-wa-message.js +47 -51
- package/lib/Utils/event-buffer.js +36 -46
- package/lib/Utils/generics.js +116 -188
- package/lib/Utils/history.js +37 -46
- package/lib/Utils/index.js +19 -33
- package/lib/Utils/link-preview.js +14 -55
- package/lib/Utils/logger.js +3 -7
- package/lib/Utils/lt-hash.js +23 -26
- package/lib/{Store → Utils}/make-in-memory-store.js +19 -27
- package/lib/Utils/make-mutex.js +7 -10
- package/lib/{Store → Utils}/make-ordered-dictionary.js +1 -3
- package/lib/Utils/messages-media.js +236 -368
- package/lib/Utils/messages.js +278 -510
- package/lib/Utils/noise-handler.js +22 -31
- package/lib/{Store → Utils}/object-repository.js +1 -4
- package/lib/Utils/process-message.js +144 -148
- package/lib/Utils/signal.js +71 -64
- package/lib/Utils/use-multi-file-auth-state.js +112 -84
- package/lib/Utils/validate-connection.js +72 -115
- package/lib/WABinary/constants.js +1281 -20
- package/lib/WABinary/decode.js +15 -52
- package/lib/WABinary/encode.js +14 -48
- package/lib/WABinary/generic-utils.js +31 -39
- package/lib/WABinary/index.js +6 -21
- package/lib/WABinary/jid-utils.js +23 -40
- package/lib/WABinary/types.js +2 -2
- package/lib/WAM/BinaryInfo.js +2 -5
- package/lib/WAM/constants.js +2257 -2366
- package/lib/WAM/encode.js +17 -21
- package/lib/WAM/index.js +4 -19
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +8 -11
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +11 -14
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +9 -12
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +9 -13
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +20 -22
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +3 -6
- package/lib/WAUSync/Protocols/index.js +5 -20
- package/lib/WAUSync/USyncQuery.js +34 -32
- package/lib/WAUSync/USyncUser.js +2 -5
- package/lib/WAUSync/index.js +4 -19
- package/lib/index.js +11 -33
- package/package.json +25 -54
- package/WASignalGroup/GroupProtocol.js +0 -1697
- package/WASignalGroup/ciphertext_message.js +0 -16
- package/WASignalGroup/group_cipher.js +0 -120
- package/WASignalGroup/group_session_builder.js +0 -46
- package/WASignalGroup/index.js +0 -5
- package/WASignalGroup/keyhelper.js +0 -21
- package/WASignalGroup/protobufs.js +0 -3
- package/WASignalGroup/queue_job.js +0 -69
- package/WASignalGroup/sender_chain_key.js +0 -50
- package/WASignalGroup/sender_key_distribution_message.js +0 -78
- package/WASignalGroup/sender_key_message.js +0 -92
- package/WASignalGroup/sender_key_name.js +0 -70
- package/WASignalGroup/sender_key_record.js +0 -56
- package/WASignalGroup/sender_key_state.js +0 -129
- package/lib/Defaults/baileys-version.json +0 -3
- package/lib/Defaults/phonenumber-mcc.json +0 -223
- package/lib/Socket/Client/abstract-socket-client.js +0 -13
- package/lib/Socket/Client/mobile-socket-client.js +0 -65
- package/lib/Socket/Client/web-socket-client.js +0 -62
- package/lib/Socket/registration.js +0 -166
- package/lib/Store/index.js +0 -8
- package/lib/Store/make-cache-manager-store.js +0 -83
- package/lib/Store/make-mongo-store.js +0 -567
|
@@ -1,38 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
const make_mutex_1 = require("../Utils/make-mutex");
|
|
15
|
-
const WABinary_1 = require("../WABinary");
|
|
16
|
-
const groups_1 = require("./groups");
|
|
17
|
-
const messages_send_1 = require("./messages-send");
|
|
18
|
-
const makeMessagesRecvSocket = (config) => {
|
|
1
|
+
import NodeCache from '@cacheable/node-cache';
|
|
2
|
+
import { Boom } from '@hapi/boom';
|
|
3
|
+
import { randomBytes } from 'crypto';
|
|
4
|
+
import Long from 'long';
|
|
5
|
+
import { proto } from '../../WAProto/index.js';
|
|
6
|
+
import { DEFAULT_CACHE_TTLS, KEY_BUNDLE_TYPE, MIN_PREKEY_COUNT } from '../Defaults/index.js';
|
|
7
|
+
import { WAMessageStatus, WAMessageStubType } from '../Types/index.js';
|
|
8
|
+
import { aesDecryptCTR, aesEncryptGCM, cleanMessage, Curve, decodeMediaRetryNode, decodeMessageNode, decryptMessageNode, delay, derivePairingCodeKey, encodeBigEndian, encodeSignedDeviceIdentity, getCallStatusFromNode, getHistoryMsg, getNextPreKeys, getStatusFromReceiptType, hkdf, MISSING_KEYS_ERROR_TEXT, NACK_REASONS, NO_MESSAGE_FOUND_ERROR_TEXT, unixTimestampSeconds, xmppPreKey, xmppSignedPreKey } from '../Utils/index.js';
|
|
9
|
+
import { makeMutex } from '../Utils/make-mutex.js';
|
|
10
|
+
import { areJidsSameUser, getAllBinaryNodeChildren, getBinaryNodeChild, getBinaryNodeChildBuffer, getBinaryNodeChildren, getBinaryNodeChildString, isJidGroup, isJidStatusBroadcast, isJidUser, jidDecode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
11
|
+
import { extractGroupMetadata } from './groups.js';
|
|
12
|
+
import { makeMessagesSocket } from './messages-send.js';
|
|
13
|
+
export const makeMessagesRecvSocket = (config) => {
|
|
19
14
|
const { logger, retryRequestDelayMs, maxMsgRetryCount, getMessage, shouldIgnoreJid } = config;
|
|
20
|
-
const sock =
|
|
21
|
-
const { ev, authState, ws, processingMutex, signalRepository, query, upsertMessage, resyncAppState, onUnexpectedError, assertSessions, sendNode, relayMessage, sendReceipt, uploadPreKeys,
|
|
15
|
+
const sock = makeMessagesSocket(config);
|
|
16
|
+
const { ev, authState, ws, processingMutex, signalRepository, query, upsertMessage, resyncAppState, onUnexpectedError, assertSessions, sendNode, relayMessage, sendReceipt, uploadPreKeys, sendPeerDataOperationMessage } = sock;
|
|
22
17
|
/** this mutex ensures that each retryRequest will wait for the previous one to finish */
|
|
23
|
-
const retryMutex =
|
|
24
|
-
const msgRetryCache = config.msgRetryCounterCache ||
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
18
|
+
const retryMutex = makeMutex();
|
|
19
|
+
const msgRetryCache = config.msgRetryCounterCache ||
|
|
20
|
+
new NodeCache({
|
|
21
|
+
stdTTL: DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
|
|
22
|
+
useClones: false
|
|
23
|
+
});
|
|
24
|
+
const callOfferCache = config.callOfferCache ||
|
|
25
|
+
new NodeCache({
|
|
26
|
+
stdTTL: DEFAULT_CACHE_TTLS.CALL_OFFER, // 5 mins
|
|
27
|
+
useClones: false
|
|
28
|
+
});
|
|
29
|
+
const placeholderResendCache = config.placeholderResendCache ||
|
|
30
|
+
new NodeCache({
|
|
31
|
+
stdTTL: DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
|
|
32
|
+
useClones: false
|
|
33
|
+
});
|
|
36
34
|
let sendActiveReceipts = false;
|
|
37
35
|
const sendMessageAck = async ({ tag, attrs, content }, errorCode) => {
|
|
38
36
|
const stanza = {
|
|
@@ -52,97 +50,42 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
52
50
|
if (!!attrs.recipient) {
|
|
53
51
|
stanza.attrs.recipient = attrs.recipient;
|
|
54
52
|
}
|
|
55
|
-
if (!!attrs.type &&
|
|
53
|
+
if (!!attrs.type &&
|
|
54
|
+
(tag !== 'message' || getBinaryNodeChild({ tag, attrs, content }, 'unavailable') || errorCode !== 0)) {
|
|
56
55
|
stanza.attrs.type = attrs.type;
|
|
57
56
|
}
|
|
58
|
-
if (tag === 'message' &&
|
|
57
|
+
if (tag === 'message' && getBinaryNodeChild({ tag, attrs, content }, 'unavailable')) {
|
|
59
58
|
stanza.attrs.from = authState.creds.me.id;
|
|
60
59
|
}
|
|
61
60
|
logger.debug({ recv: { tag, attrs }, sent: stanza.attrs }, 'sent ack');
|
|
62
61
|
await sendNode(stanza);
|
|
63
62
|
};
|
|
64
|
-
const offerCall = async (toJid, isVideo = false) => {
|
|
65
|
-
const callId = (0, crypto_1.randomBytes)(16).toString('hex').toUpperCase().substring(0, 64);
|
|
66
|
-
const offerContent = [];
|
|
67
|
-
offerContent.push({ tag: 'audio', attrs: { enc: 'opus', rate: '16000' }, content: undefined });
|
|
68
|
-
offerContent.push({ tag: 'audio', attrs: { enc: 'opus', rate: '8000' }, content: undefined });
|
|
69
|
-
if (isVideo) {
|
|
70
|
-
offerContent.push({
|
|
71
|
-
tag: 'video',
|
|
72
|
-
attrs: {
|
|
73
|
-
orientation: '0',
|
|
74
|
-
'screen_width': '1920',
|
|
75
|
-
'screen_height': '1080',
|
|
76
|
-
'device_orientation': '0',
|
|
77
|
-
enc: 'vp8',
|
|
78
|
-
dec: 'vp8',
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
offerContent.push({ tag: 'net', attrs: { medium: '3' }, content: undefined });
|
|
83
|
-
offerContent.push({ tag: 'capability', attrs: { ver: '1' }, content: new Uint8Array([1, 4, 255, 131, 207, 4]) });
|
|
84
|
-
offerContent.push({ tag: 'encopt', attrs: { keygen: '2' }, content: undefined });
|
|
85
|
-
const encKey = (0, crypto_1.randomBytes)(32);
|
|
86
|
-
const devices = (await getUSyncDevices([toJid], true, false)).map(({ user, device }) => (0, WABinary_1.jidEncode)(user, 's.whatsapp.net', device));
|
|
87
|
-
await assertSessions(devices, true);
|
|
88
|
-
const { nodes: destinations, shouldIncludeDeviceIdentity } = await createParticipantNodes(devices, {
|
|
89
|
-
call: {
|
|
90
|
-
callKey: encKey
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
offerContent.push({ tag: 'destination', attrs: {}, content: destinations });
|
|
94
|
-
if (shouldIncludeDeviceIdentity) {
|
|
95
|
-
offerContent.push({
|
|
96
|
-
tag: 'device-identity',
|
|
97
|
-
attrs: {},
|
|
98
|
-
content: (0, Utils_1.encodeSignedDeviceIdentity)(authState.creds.account, true)
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
const stanza = ({
|
|
102
|
-
tag: 'call',
|
|
103
|
-
attrs: {
|
|
104
|
-
to: toJid,
|
|
105
|
-
},
|
|
106
|
-
content: [{
|
|
107
|
-
tag: 'offer',
|
|
108
|
-
attrs: {
|
|
109
|
-
'call-id': callId,
|
|
110
|
-
'call-creator': authState.creds.me.id,
|
|
111
|
-
},
|
|
112
|
-
content: offerContent,
|
|
113
|
-
}],
|
|
114
|
-
});
|
|
115
|
-
await query(stanza);
|
|
116
|
-
return {
|
|
117
|
-
callId,
|
|
118
|
-
toJid,
|
|
119
|
-
isVideo,
|
|
120
|
-
};
|
|
121
|
-
};
|
|
122
63
|
const rejectCall = async (callId, callFrom) => {
|
|
123
|
-
const stanza =
|
|
64
|
+
const stanza = {
|
|
124
65
|
tag: 'call',
|
|
125
66
|
attrs: {
|
|
126
67
|
from: authState.creds.me.id,
|
|
127
|
-
to: callFrom
|
|
68
|
+
to: callFrom
|
|
128
69
|
},
|
|
129
|
-
content: [
|
|
70
|
+
content: [
|
|
71
|
+
{
|
|
130
72
|
tag: 'reject',
|
|
131
73
|
attrs: {
|
|
132
74
|
'call-id': callId,
|
|
133
75
|
'call-creator': callFrom,
|
|
134
|
-
count: '0'
|
|
76
|
+
count: '0'
|
|
135
77
|
},
|
|
136
|
-
content: undefined
|
|
137
|
-
}
|
|
138
|
-
|
|
78
|
+
content: undefined
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
};
|
|
139
82
|
await query(stanza);
|
|
140
83
|
};
|
|
141
84
|
const sendRetryRequest = async (node, forceIncludeKeys = false) => {
|
|
142
|
-
const { fullMessage } =
|
|
85
|
+
const { fullMessage } = decodeMessageNode(node, authState.creds.me.id, authState.creds.me.lid || '');
|
|
143
86
|
const { key: msgKey } = fullMessage;
|
|
144
87
|
const msgId = msgKey.id;
|
|
145
|
-
const key = `${msgId}:${msgKey
|
|
88
|
+
const key = `${msgId}:${msgKey?.participant}`;
|
|
146
89
|
let retryCount = msgRetryCache.get(key) || 0;
|
|
147
90
|
if (retryCount >= maxMsgRetryCount) {
|
|
148
91
|
logger.debug({ retryCount, msgId }, 'reached retry limit, clearing');
|
|
@@ -157,7 +100,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
157
100
|
const msgId = await requestPlaceholderResend(msgKey);
|
|
158
101
|
logger.debug(`sendRetryRequest: requested placeholder resend for message ${msgId}`);
|
|
159
102
|
}
|
|
160
|
-
const deviceIdentity =
|
|
103
|
+
const deviceIdentity = encodeSignedDeviceIdentity(account, true);
|
|
161
104
|
await authState.keys.transaction(async () => {
|
|
162
105
|
const receipt = {
|
|
163
106
|
tag: 'receipt',
|
|
@@ -179,7 +122,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
179
122
|
{
|
|
180
123
|
tag: 'registration',
|
|
181
124
|
attrs: {},
|
|
182
|
-
content:
|
|
125
|
+
content: encodeBigEndian(authState.creds.registrationId)
|
|
183
126
|
}
|
|
184
127
|
]
|
|
185
128
|
};
|
|
@@ -190,7 +133,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
190
133
|
receipt.attrs.participant = node.attrs.participant;
|
|
191
134
|
}
|
|
192
135
|
if (retryCount > 1 || forceIncludeKeys) {
|
|
193
|
-
const { update, preKeys } = await
|
|
136
|
+
const { update, preKeys } = await getNextPreKeys(authState, 1);
|
|
194
137
|
const [keyId] = Object.keys(preKeys);
|
|
195
138
|
const key = preKeys[+keyId];
|
|
196
139
|
const content = receipt.content;
|
|
@@ -198,10 +141,10 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
198
141
|
tag: 'keys',
|
|
199
142
|
attrs: {},
|
|
200
143
|
content: [
|
|
201
|
-
{ tag: 'type', attrs: {}, content: Buffer.from(
|
|
144
|
+
{ tag: 'type', attrs: {}, content: Buffer.from(KEY_BUNDLE_TYPE) },
|
|
202
145
|
{ tag: 'identity', attrs: {}, content: identityKey.public },
|
|
203
|
-
|
|
204
|
-
|
|
146
|
+
xmppPreKey(key, +keyId),
|
|
147
|
+
xmppSignedPreKey(signedPreKey),
|
|
205
148
|
{ tag: 'device-identity', attrs: {}, content: deviceIdentity }
|
|
206
149
|
]
|
|
207
150
|
});
|
|
@@ -213,17 +156,17 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
213
156
|
};
|
|
214
157
|
const handleEncryptNotification = async (node) => {
|
|
215
158
|
const from = node.attrs.from;
|
|
216
|
-
if (from ===
|
|
217
|
-
const countChild =
|
|
159
|
+
if (from === S_WHATSAPP_NET) {
|
|
160
|
+
const countChild = getBinaryNodeChild(node, 'count');
|
|
218
161
|
const count = +countChild.attrs.value;
|
|
219
|
-
const shouldUploadMorePreKeys = count <
|
|
162
|
+
const shouldUploadMorePreKeys = count < MIN_PREKEY_COUNT;
|
|
220
163
|
logger.debug({ count, shouldUploadMorePreKeys }, 'recv pre-key count');
|
|
221
164
|
if (shouldUploadMorePreKeys) {
|
|
222
165
|
await uploadPreKeys();
|
|
223
166
|
}
|
|
224
167
|
}
|
|
225
168
|
else {
|
|
226
|
-
const identityNode =
|
|
169
|
+
const identityNode = getBinaryNodeChild(node, 'identity');
|
|
227
170
|
if (identityNode) {
|
|
228
171
|
logger.info({ jid: from }, 'identity changed');
|
|
229
172
|
// not handling right now
|
|
@@ -235,37 +178,40 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
235
178
|
}
|
|
236
179
|
};
|
|
237
180
|
const handleGroupNotification = (participant, child, msg) => {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
switch (child === null || child === void 0 ? void 0 : child.tag) {
|
|
181
|
+
const participantJid = getBinaryNodeChild(child, 'participant')?.attrs?.jid || participant;
|
|
182
|
+
switch (child?.tag) {
|
|
241
183
|
case 'create':
|
|
242
|
-
const metadata =
|
|
243
|
-
msg.messageStubType =
|
|
184
|
+
const metadata = extractGroupMetadata(child);
|
|
185
|
+
msg.messageStubType = WAMessageStubType.GROUP_CREATE;
|
|
244
186
|
msg.messageStubParameters = [metadata.subject];
|
|
245
187
|
msg.key = { participant: metadata.owner };
|
|
246
|
-
ev.emit('chats.upsert', [
|
|
188
|
+
ev.emit('chats.upsert', [
|
|
189
|
+
{
|
|
247
190
|
id: metadata.id,
|
|
248
191
|
name: metadata.subject,
|
|
249
|
-
conversationTimestamp: metadata.creation
|
|
250
|
-
}
|
|
251
|
-
|
|
192
|
+
conversationTimestamp: metadata.creation
|
|
193
|
+
}
|
|
194
|
+
]);
|
|
195
|
+
ev.emit('groups.upsert', [
|
|
196
|
+
{
|
|
252
197
|
...metadata,
|
|
253
198
|
author: participant
|
|
254
|
-
}
|
|
199
|
+
}
|
|
200
|
+
]);
|
|
255
201
|
break;
|
|
256
202
|
case 'ephemeral':
|
|
257
203
|
case 'not_ephemeral':
|
|
258
204
|
msg.message = {
|
|
259
205
|
protocolMessage: {
|
|
260
|
-
type:
|
|
206
|
+
type: proto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
|
|
261
207
|
ephemeralExpiration: +(child.attrs.expiration || 0)
|
|
262
208
|
}
|
|
263
209
|
};
|
|
264
210
|
break;
|
|
265
211
|
case 'modify':
|
|
266
|
-
const oldNumber =
|
|
212
|
+
const oldNumber = getBinaryNodeChildren(child, 'participant').map(p => p.attrs.jid);
|
|
267
213
|
msg.messageStubParameters = oldNumber || [];
|
|
268
|
-
msg.messageStubType =
|
|
214
|
+
msg.messageStubType = WAMessageStubType.GROUP_PARTICIPANT_CHANGE_NUMBER;
|
|
269
215
|
break;
|
|
270
216
|
case 'promote':
|
|
271
217
|
case 'demote':
|
|
@@ -273,121 +219,73 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
273
219
|
case 'add':
|
|
274
220
|
case 'leave':
|
|
275
221
|
const stubType = `GROUP_PARTICIPANT_${child.tag.toUpperCase()}`;
|
|
276
|
-
msg.messageStubType =
|
|
277
|
-
const participants =
|
|
222
|
+
msg.messageStubType = WAMessageStubType[stubType];
|
|
223
|
+
const participants = getBinaryNodeChildren(child, 'participant').map(p => p.attrs.jid);
|
|
278
224
|
if (participants.length === 1 &&
|
|
279
225
|
// if recv. "remove" message and sender removed themselves
|
|
280
226
|
// mark as left
|
|
281
|
-
|
|
227
|
+
areJidsSameUser(participants[0], participant) &&
|
|
282
228
|
child.tag === 'remove') {
|
|
283
|
-
msg.messageStubType =
|
|
229
|
+
msg.messageStubType = WAMessageStubType.GROUP_PARTICIPANT_LEAVE;
|
|
284
230
|
}
|
|
285
231
|
msg.messageStubParameters = participants;
|
|
286
232
|
break;
|
|
287
233
|
case 'subject':
|
|
288
|
-
msg.messageStubType =
|
|
234
|
+
msg.messageStubType = WAMessageStubType.GROUP_CHANGE_SUBJECT;
|
|
289
235
|
msg.messageStubParameters = [child.attrs.subject];
|
|
290
236
|
break;
|
|
291
237
|
case 'description':
|
|
292
|
-
const description =
|
|
293
|
-
msg.messageStubType =
|
|
238
|
+
const description = getBinaryNodeChild(child, 'body')?.content?.toString();
|
|
239
|
+
msg.messageStubType = WAMessageStubType.GROUP_CHANGE_DESCRIPTION;
|
|
294
240
|
msg.messageStubParameters = description ? [description] : undefined;
|
|
295
241
|
break;
|
|
296
242
|
case 'announcement':
|
|
297
243
|
case 'not_announcement':
|
|
298
|
-
msg.messageStubType =
|
|
299
|
-
msg.messageStubParameters = [
|
|
244
|
+
msg.messageStubType = WAMessageStubType.GROUP_CHANGE_ANNOUNCE;
|
|
245
|
+
msg.messageStubParameters = [child.tag === 'announcement' ? 'on' : 'off'];
|
|
300
246
|
break;
|
|
301
247
|
case 'locked':
|
|
302
248
|
case 'unlocked':
|
|
303
|
-
msg.messageStubType =
|
|
304
|
-
msg.messageStubParameters = [
|
|
249
|
+
msg.messageStubType = WAMessageStubType.GROUP_CHANGE_RESTRICT;
|
|
250
|
+
msg.messageStubParameters = [child.tag === 'locked' ? 'on' : 'off'];
|
|
305
251
|
break;
|
|
306
252
|
case 'invite':
|
|
307
|
-
msg.messageStubType =
|
|
253
|
+
msg.messageStubType = WAMessageStubType.GROUP_CHANGE_INVITE_LINK;
|
|
308
254
|
msg.messageStubParameters = [child.attrs.code];
|
|
309
255
|
break;
|
|
310
256
|
case 'member_add_mode':
|
|
311
257
|
const addMode = child.content;
|
|
312
258
|
if (addMode) {
|
|
313
|
-
msg.messageStubType =
|
|
259
|
+
msg.messageStubType = WAMessageStubType.GROUP_MEMBER_ADD_MODE;
|
|
314
260
|
msg.messageStubParameters = [addMode.toString()];
|
|
315
261
|
}
|
|
316
262
|
break;
|
|
317
263
|
case 'membership_approval_mode':
|
|
318
|
-
const approvalMode =
|
|
264
|
+
const approvalMode = getBinaryNodeChild(child, 'group_join');
|
|
319
265
|
if (approvalMode) {
|
|
320
|
-
msg.messageStubType =
|
|
266
|
+
msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_MODE;
|
|
321
267
|
msg.messageStubParameters = [approvalMode.attrs.state];
|
|
322
268
|
}
|
|
323
269
|
break;
|
|
324
270
|
case 'created_membership_requests':
|
|
325
|
-
msg.messageStubType =
|
|
271
|
+
msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
|
|
326
272
|
msg.messageStubParameters = [participantJid, 'created', child.attrs.request_method];
|
|
327
273
|
break;
|
|
328
274
|
case 'revoked_membership_requests':
|
|
329
|
-
const isDenied =
|
|
330
|
-
msg.messageStubType =
|
|
275
|
+
const isDenied = areJidsSameUser(participantJid, participant);
|
|
276
|
+
msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
|
|
331
277
|
msg.messageStubParameters = [participantJid, isDenied ? 'revoked' : 'rejected'];
|
|
332
278
|
break;
|
|
333
|
-
break;
|
|
334
|
-
default:
|
|
335
|
-
// console.log("BAILEYS-DEBUG:", JSON.stringify({ ...child, content: Buffer.isBuffer(child.content) ? child.content.toString() : child.content, participant }, null, 2))
|
|
336
|
-
}
|
|
337
|
-
};
|
|
338
|
-
const handleNewsletterNotification = (id, node) => {
|
|
339
|
-
const messages = (0, WABinary_1.getBinaryNodeChild)(node, 'messages');
|
|
340
|
-
const message = (0, WABinary_1.getBinaryNodeChild)(messages, 'message');
|
|
341
|
-
const server_id = message.attrs.server_id;
|
|
342
|
-
const reactionsList = (0, WABinary_1.getBinaryNodeChild)(message, 'reactions');
|
|
343
|
-
const viewsList = (0, WABinary_1.getBinaryNodeChildren)(message, 'views_count');
|
|
344
|
-
if (reactionsList) {
|
|
345
|
-
const reactions = (0, WABinary_1.getBinaryNodeChildren)(reactionsList, 'reaction');
|
|
346
|
-
if (reactions.length === 0) {
|
|
347
|
-
ev.emit('newsletter.reaction', { id, server_id, reaction: { removed: true } });
|
|
348
|
-
}
|
|
349
|
-
reactions.forEach(item => {
|
|
350
|
-
var _a, _b;
|
|
351
|
-
ev.emit('newsletter.reaction', { id, server_id, reaction: { code: (_a = item.attrs) === null || _a === void 0 ? void 0 : _a.code, count: +((_b = item.attrs) === null || _b === void 0 ? void 0 : _b.count) } });
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
if (viewsList.length) {
|
|
355
|
-
viewsList.forEach(item => {
|
|
356
|
-
ev.emit('newsletter.view', { id, server_id, count: +item.attrs.count });
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
};
|
|
360
|
-
const handleMexNewsletterNotification = (id, node) => {
|
|
361
|
-
var _a;
|
|
362
|
-
const operation = node === null || node === void 0 ? void 0 : node.attrs.op_name;
|
|
363
|
-
const content = JSON.parse((_a = node === null || node === void 0 ? void 0 : node.content) === null || _a === void 0 ? void 0 : _a.toString());
|
|
364
|
-
let contentPath;
|
|
365
|
-
if (operation === Types_1.MexOperations.PROMOTE || operation === Types_1.MexOperations.DEMOTE) {
|
|
366
|
-
let action;
|
|
367
|
-
if (operation === Types_1.MexOperations.PROMOTE) {
|
|
368
|
-
action = 'promote';
|
|
369
|
-
contentPath = content.data[Types_1.XWAPaths.PROMOTE];
|
|
370
|
-
}
|
|
371
|
-
if (operation === Types_1.MexOperations.DEMOTE) {
|
|
372
|
-
action = 'demote';
|
|
373
|
-
contentPath = content.data[Types_1.XWAPaths.DEMOTE];
|
|
374
|
-
}
|
|
375
|
-
ev.emit('newsletter-participants.update', { id, author: contentPath.actor.pn, user: contentPath.user.pn, new_role: contentPath.user_new_role, action });
|
|
376
|
-
}
|
|
377
|
-
if (operation === Types_1.MexOperations.UPDATE) {
|
|
378
|
-
contentPath = content.data[Types_1.XWAPaths.METADATA_UPDATE];
|
|
379
|
-
ev.emit('newsletter-settings.update', { id, update: contentPath.thread_metadata.settings });
|
|
380
279
|
}
|
|
381
280
|
};
|
|
382
281
|
const processNotification = async (node) => {
|
|
383
|
-
var _a, _b;
|
|
384
282
|
const result = {};
|
|
385
|
-
const [child] =
|
|
283
|
+
const [child] = getAllBinaryNodeChildren(node);
|
|
386
284
|
const nodeType = node.attrs.type;
|
|
387
|
-
const from =
|
|
285
|
+
const from = jidNormalizedUser(node.attrs.from);
|
|
388
286
|
switch (nodeType) {
|
|
389
287
|
case 'privacy_token':
|
|
390
|
-
const tokenList =
|
|
288
|
+
const tokenList = getBinaryNodeChildren(child, 'token');
|
|
391
289
|
for (const { attrs, content } of tokenList) {
|
|
392
290
|
const jid = attrs.jid;
|
|
393
291
|
ev.emit('chats.update', [
|
|
@@ -400,52 +298,54 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
400
298
|
}
|
|
401
299
|
break;
|
|
402
300
|
case 'newsletter':
|
|
403
|
-
handleNewsletterNotification(node
|
|
301
|
+
await handleNewsletterNotification(node);
|
|
404
302
|
break;
|
|
405
303
|
case 'mex':
|
|
406
|
-
handleMexNewsletterNotification(node
|
|
304
|
+
await handleMexNewsletterNotification(node);
|
|
407
305
|
break;
|
|
408
306
|
case 'w:gp2':
|
|
409
307
|
handleGroupNotification(node.attrs.participant, child, result);
|
|
410
308
|
break;
|
|
411
309
|
case 'mediaretry':
|
|
412
|
-
const event =
|
|
310
|
+
const event = decodeMediaRetryNode(node);
|
|
413
311
|
ev.emit('messages.media-update', [event]);
|
|
414
312
|
break;
|
|
415
313
|
case 'encrypt':
|
|
416
314
|
await handleEncryptNotification(node);
|
|
417
315
|
break;
|
|
418
316
|
case 'devices':
|
|
419
|
-
const devices =
|
|
420
|
-
if (
|
|
317
|
+
const devices = getBinaryNodeChildren(child, 'device');
|
|
318
|
+
if (areJidsSameUser(child.attrs.jid, authState.creds.me.id)) {
|
|
421
319
|
const deviceJids = devices.map(d => d.attrs.jid);
|
|
422
320
|
logger.info({ deviceJids }, 'got my own devices');
|
|
423
321
|
}
|
|
424
322
|
break;
|
|
425
323
|
case 'server_sync':
|
|
426
|
-
const update =
|
|
324
|
+
const update = getBinaryNodeChild(node, 'collection');
|
|
427
325
|
if (update) {
|
|
428
326
|
const name = update.attrs.name;
|
|
429
327
|
await resyncAppState([name], false);
|
|
430
328
|
}
|
|
431
329
|
break;
|
|
432
330
|
case 'picture':
|
|
433
|
-
const setPicture =
|
|
434
|
-
const delPicture =
|
|
435
|
-
ev.emit('contacts.update', [
|
|
436
|
-
|
|
331
|
+
const setPicture = getBinaryNodeChild(node, 'set');
|
|
332
|
+
const delPicture = getBinaryNodeChild(node, 'delete');
|
|
333
|
+
ev.emit('contacts.update', [
|
|
334
|
+
{
|
|
335
|
+
id: jidNormalizedUser(node?.attrs?.from) || (setPicture || delPicture)?.attrs?.hash || '',
|
|
437
336
|
imgUrl: setPicture ? 'changed' : 'removed'
|
|
438
|
-
}
|
|
439
|
-
|
|
337
|
+
}
|
|
338
|
+
]);
|
|
339
|
+
if (isJidGroup(from)) {
|
|
440
340
|
const node = setPicture || delPicture;
|
|
441
|
-
result.messageStubType =
|
|
341
|
+
result.messageStubType = WAMessageStubType.GROUP_CHANGE_ICON;
|
|
442
342
|
if (setPicture) {
|
|
443
343
|
result.messageStubParameters = [setPicture.attrs.id];
|
|
444
344
|
}
|
|
445
|
-
result.participant = node
|
|
345
|
+
result.participant = node?.attrs.author;
|
|
446
346
|
result.key = {
|
|
447
|
-
...result.key || {},
|
|
448
|
-
participant: setPicture
|
|
347
|
+
...(result.key || {}),
|
|
348
|
+
participant: setPicture?.attrs.author
|
|
449
349
|
};
|
|
450
350
|
}
|
|
451
351
|
break;
|
|
@@ -459,44 +359,48 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
459
359
|
...authState.creds.accountSettings,
|
|
460
360
|
defaultDisappearingMode: {
|
|
461
361
|
ephemeralExpiration: newDuration,
|
|
462
|
-
ephemeralSettingTimestamp: timestamp
|
|
463
|
-
}
|
|
362
|
+
ephemeralSettingTimestamp: timestamp
|
|
363
|
+
}
|
|
464
364
|
}
|
|
465
365
|
});
|
|
466
366
|
}
|
|
467
367
|
else if (child.tag === 'blocklist') {
|
|
468
|
-
const blocklists =
|
|
368
|
+
const blocklists = getBinaryNodeChildren(child, 'item');
|
|
469
369
|
for (const { attrs } of blocklists) {
|
|
470
370
|
const blocklist = [attrs.jid];
|
|
471
|
-
const type =
|
|
371
|
+
const type = attrs.action === 'block' ? 'add' : 'remove';
|
|
472
372
|
ev.emit('blocklist.update', { blocklist, type });
|
|
473
373
|
}
|
|
474
374
|
}
|
|
475
375
|
break;
|
|
476
376
|
case 'link_code_companion_reg':
|
|
477
|
-
const linkCodeCompanionReg =
|
|
478
|
-
const ref = toRequiredBuffer(
|
|
479
|
-
const primaryIdentityPublicKey = toRequiredBuffer(
|
|
480
|
-
const primaryEphemeralPublicKeyWrapped = toRequiredBuffer(
|
|
377
|
+
const linkCodeCompanionReg = getBinaryNodeChild(node, 'link_code_companion_reg');
|
|
378
|
+
const ref = toRequiredBuffer(getBinaryNodeChildBuffer(linkCodeCompanionReg, 'link_code_pairing_ref'));
|
|
379
|
+
const primaryIdentityPublicKey = toRequiredBuffer(getBinaryNodeChildBuffer(linkCodeCompanionReg, 'primary_identity_pub'));
|
|
380
|
+
const primaryEphemeralPublicKeyWrapped = toRequiredBuffer(getBinaryNodeChildBuffer(linkCodeCompanionReg, 'link_code_pairing_wrapped_primary_ephemeral_pub'));
|
|
481
381
|
const codePairingPublicKey = await decipherLinkPublicKey(primaryEphemeralPublicKeyWrapped);
|
|
482
|
-
const companionSharedKey =
|
|
483
|
-
const random =
|
|
484
|
-
const linkCodeSalt =
|
|
485
|
-
const linkCodePairingExpanded = await
|
|
382
|
+
const companionSharedKey = Curve.sharedKey(authState.creds.pairingEphemeralKeyPair.private, codePairingPublicKey);
|
|
383
|
+
const random = randomBytes(32);
|
|
384
|
+
const linkCodeSalt = randomBytes(32);
|
|
385
|
+
const linkCodePairingExpanded = await hkdf(companionSharedKey, 32, {
|
|
486
386
|
salt: linkCodeSalt,
|
|
487
387
|
info: 'link_code_pairing_key_bundle_encryption_key'
|
|
488
388
|
});
|
|
489
|
-
const encryptPayload = Buffer.concat([
|
|
490
|
-
|
|
491
|
-
|
|
389
|
+
const encryptPayload = Buffer.concat([
|
|
390
|
+
Buffer.from(authState.creds.signedIdentityKey.public),
|
|
391
|
+
primaryIdentityPublicKey,
|
|
392
|
+
random
|
|
393
|
+
]);
|
|
394
|
+
const encryptIv = randomBytes(12);
|
|
395
|
+
const encrypted = aesEncryptGCM(encryptPayload, linkCodePairingExpanded, encryptIv, Buffer.alloc(0));
|
|
492
396
|
const encryptedPayload = Buffer.concat([linkCodeSalt, encryptIv, encrypted]);
|
|
493
|
-
const identitySharedKey =
|
|
397
|
+
const identitySharedKey = Curve.sharedKey(authState.creds.signedIdentityKey.private, primaryIdentityPublicKey);
|
|
494
398
|
const identityPayload = Buffer.concat([companionSharedKey, identitySharedKey, random]);
|
|
495
|
-
authState.creds.advSecretKey = (await
|
|
399
|
+
authState.creds.advSecretKey = (await hkdf(identityPayload, 32, { info: 'adv_secret' })).toString('base64');
|
|
496
400
|
await query({
|
|
497
401
|
tag: 'iq',
|
|
498
402
|
attrs: {
|
|
499
|
-
to:
|
|
403
|
+
to: S_WHATSAPP_NET,
|
|
500
404
|
type: 'set',
|
|
501
405
|
id: sock.generateMessageTag(),
|
|
502
406
|
xmlns: 'md'
|
|
@@ -506,7 +410,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
506
410
|
tag: 'link_code_companion_reg',
|
|
507
411
|
attrs: {
|
|
508
412
|
jid: authState.creds.me.id,
|
|
509
|
-
stage: 'companion_finish'
|
|
413
|
+
stage: 'companion_finish'
|
|
510
414
|
},
|
|
511
415
|
content: [
|
|
512
416
|
{
|
|
@@ -538,14 +442,14 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
538
442
|
async function decipherLinkPublicKey(data) {
|
|
539
443
|
const buffer = toRequiredBuffer(data);
|
|
540
444
|
const salt = buffer.slice(0, 32);
|
|
541
|
-
const secretKey = await
|
|
445
|
+
const secretKey = await derivePairingCodeKey(authState.creds.pairingCode, salt);
|
|
542
446
|
const iv = buffer.slice(32, 48);
|
|
543
447
|
const payload = buffer.slice(48, 80);
|
|
544
|
-
return
|
|
448
|
+
return aesDecryptCTR(payload, secretKey, iv);
|
|
545
449
|
}
|
|
546
450
|
function toRequiredBuffer(data) {
|
|
547
451
|
if (data === undefined) {
|
|
548
|
-
throw new
|
|
452
|
+
throw new Boom('Invalid buffer', { statusCode: 400 });
|
|
549
453
|
}
|
|
550
454
|
return data instanceof Buffer ? data : Buffer.from(data);
|
|
551
455
|
}
|
|
@@ -560,7 +464,6 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
560
464
|
msgRetryCache.set(key, newValue);
|
|
561
465
|
};
|
|
562
466
|
const sendMessagesAgain = async (key, ids, retryNode) => {
|
|
563
|
-
var _a;
|
|
564
467
|
// todo: implement a cache to store the last 256 sent messages (copy whatsmeow)
|
|
565
468
|
const msgs = await Promise.all(ids.map(id => getMessage({ ...key, id })));
|
|
566
469
|
const remoteJid = key.remoteJid;
|
|
@@ -568,14 +471,13 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
568
471
|
// if it's the primary jid sending the request
|
|
569
472
|
// just re-send the message to everyone
|
|
570
473
|
// prevents the first message decryption failure
|
|
571
|
-
const sendToAll = !
|
|
474
|
+
const sendToAll = !jidDecode(participant)?.device;
|
|
572
475
|
await assertSessions([participant], true);
|
|
573
|
-
if (
|
|
476
|
+
if (isJidGroup(remoteJid)) {
|
|
574
477
|
await authState.keys.set({ 'sender-key-memory': { [remoteJid]: null } });
|
|
575
478
|
}
|
|
576
479
|
logger.debug({ participant, sendToAll }, 'forced new session for retry recp');
|
|
577
|
-
for (
|
|
578
|
-
const msg = msgs[i];
|
|
480
|
+
for (const [i, msg] of msgs.entries()) {
|
|
579
481
|
if (msg) {
|
|
580
482
|
updateSendMessageAgainCount(ids[i], participant);
|
|
581
483
|
const msgRelayOpts = { messageId: ids[i] };
|
|
@@ -596,12 +498,11 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
596
498
|
}
|
|
597
499
|
};
|
|
598
500
|
const handleReceipt = async (node) => {
|
|
599
|
-
var _a, _b;
|
|
600
501
|
const { attrs, content } = node;
|
|
601
502
|
const isLid = attrs.from.includes('lid');
|
|
602
|
-
const isNodeFromMe =
|
|
603
|
-
const remoteJid = !isNodeFromMe ||
|
|
604
|
-
const fromMe = !attrs.recipient || (attrs.type === 'retry' && isNodeFromMe);
|
|
503
|
+
const isNodeFromMe = areJidsSameUser(attrs.participant || attrs.from, isLid ? authState.creds.me?.lid : authState.creds.me?.id);
|
|
504
|
+
const remoteJid = !isNodeFromMe || isJidGroup(attrs.from) ? attrs.from : attrs.recipient;
|
|
505
|
+
const fromMe = !attrs.recipient || ((attrs.type === 'retry' || attrs.type === 'sender') && isNodeFromMe);
|
|
605
506
|
const key = {
|
|
606
507
|
remoteJid,
|
|
607
508
|
id: '',
|
|
@@ -615,26 +516,24 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
615
516
|
}
|
|
616
517
|
const ids = [attrs.id];
|
|
617
518
|
if (Array.isArray(content)) {
|
|
618
|
-
const items =
|
|
519
|
+
const items = getBinaryNodeChildren(content[0], 'item');
|
|
619
520
|
ids.push(...items.map(i => i.attrs.id));
|
|
620
521
|
}
|
|
621
522
|
try {
|
|
622
523
|
await Promise.all([
|
|
623
524
|
processingMutex.mutex(async () => {
|
|
624
|
-
const status =
|
|
525
|
+
const status = getStatusFromReceiptType(attrs.type);
|
|
625
526
|
if (typeof status !== 'undefined' &&
|
|
626
|
-
(
|
|
627
527
|
// basically, we only want to know when a message from us has been delivered to/read by the other person
|
|
628
528
|
// or another device of ours has read some messages
|
|
629
|
-
status >=
|
|
630
|
-
|
|
631
|
-
if ((0, WABinary_1.isJidGroup)(remoteJid) || (0, WABinary_1.isJidStatusBroadcast)(remoteJid)) {
|
|
529
|
+
(status >= proto.WebMessageInfo.Status.SERVER_ACK || !isNodeFromMe)) {
|
|
530
|
+
if (isJidGroup(remoteJid) || isJidStatusBroadcast(remoteJid)) {
|
|
632
531
|
if (attrs.participant) {
|
|
633
|
-
const updateKey = status ===
|
|
532
|
+
const updateKey = status === proto.WebMessageInfo.Status.DELIVERY_ACK ? 'receiptTimestamp' : 'readTimestamp';
|
|
634
533
|
ev.emit('message-receipt.update', ids.map(id => ({
|
|
635
534
|
key: { ...key, id },
|
|
636
535
|
receipt: {
|
|
637
|
-
userJid:
|
|
536
|
+
userJid: jidNormalizedUser(attrs.participant),
|
|
638
537
|
[updateKey]: +attrs.t
|
|
639
538
|
}
|
|
640
539
|
})));
|
|
@@ -650,7 +549,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
650
549
|
if (attrs.type === 'retry') {
|
|
651
550
|
// correctly set who is asking for the retry
|
|
652
551
|
key.participant = key.participant || attrs.from;
|
|
653
|
-
const retryNode =
|
|
552
|
+
const retryNode = getBinaryNodeChild(node, 'retry');
|
|
654
553
|
if (willSendMessageAgain(ids[0], key.participant)) {
|
|
655
554
|
if (key.fromMe) {
|
|
656
555
|
try {
|
|
@@ -686,10 +585,9 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
686
585
|
try {
|
|
687
586
|
await Promise.all([
|
|
688
587
|
processingMutex.mutex(async () => {
|
|
689
|
-
var _a;
|
|
690
588
|
const msg = await processNotification(node);
|
|
691
589
|
if (msg) {
|
|
692
|
-
const fromMe =
|
|
590
|
+
const fromMe = areJidsSameUser(node.attrs.participant || remoteJid, authState.creds.me.id);
|
|
693
591
|
msg.key = {
|
|
694
592
|
remoteJid,
|
|
695
593
|
fromMe,
|
|
@@ -697,9 +595,9 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
697
595
|
id: node.attrs.id,
|
|
698
596
|
...(msg.key || {})
|
|
699
597
|
};
|
|
700
|
-
|
|
598
|
+
msg.participant ?? (msg.participant = node.attrs.participant);
|
|
701
599
|
msg.messageTimestamp = +node.attrs.t;
|
|
702
|
-
const fullMsg =
|
|
600
|
+
const fullMsg = proto.WebMessageInfo.fromObject(msg);
|
|
703
601
|
await upsertMessage(fullMsg, 'append');
|
|
704
602
|
}
|
|
705
603
|
})
|
|
@@ -710,13 +608,12 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
710
608
|
}
|
|
711
609
|
};
|
|
712
610
|
const handleMessage = async (node) => {
|
|
713
|
-
var _a, _b, _c;
|
|
714
611
|
if (shouldIgnoreJid(node.attrs.from) && node.attrs.from !== '@s.whatsapp.net') {
|
|
715
612
|
logger.debug({ key: node.attrs.key }, 'ignored message');
|
|
716
613
|
await sendMessageAck(node);
|
|
717
614
|
return;
|
|
718
615
|
}
|
|
719
|
-
const encNode =
|
|
616
|
+
const encNode = getBinaryNodeChild(node, 'enc');
|
|
720
617
|
// TODO: temporary fix for crashes and issues resulting of failed msmsg decryption
|
|
721
618
|
if (encNode && encNode.attrs.type === 'msmsg') {
|
|
722
619
|
logger.debug({ key: node.attrs.key }, 'ignored msmsg');
|
|
@@ -724,9 +621,9 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
724
621
|
return;
|
|
725
622
|
}
|
|
726
623
|
let response;
|
|
727
|
-
if (
|
|
624
|
+
if (getBinaryNodeChild(node, 'unavailable') && !encNode) {
|
|
728
625
|
await sendMessageAck(node);
|
|
729
|
-
const { key } =
|
|
626
|
+
const { key } = decodeMessageNode(node, authState.creds.me.id, authState.creds.me.lid || '').fullMessage;
|
|
730
627
|
response = await requestPlaceholderResend(key);
|
|
731
628
|
if (response === 'RESOLVED') {
|
|
732
629
|
return;
|
|
@@ -738,34 +635,32 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
738
635
|
placeholderResendCache.del(node.attrs.id);
|
|
739
636
|
}
|
|
740
637
|
}
|
|
741
|
-
const { fullMessage: msg, category, author, decrypt } =
|
|
742
|
-
if (response &&
|
|
743
|
-
msg.messageStubParameters = [
|
|
638
|
+
const { fullMessage: msg, category, author, decrypt } = decryptMessageNode(node, authState.creds.me.id, authState.creds.me.lid || '', signalRepository, logger);
|
|
639
|
+
if (response && msg?.messageStubParameters?.[0] === NO_MESSAGE_FOUND_ERROR_TEXT) {
|
|
640
|
+
msg.messageStubParameters = [NO_MESSAGE_FOUND_ERROR_TEXT, response];
|
|
744
641
|
}
|
|
745
|
-
if (
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
}
|
|
642
|
+
if (msg.message?.protocolMessage?.type === proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER &&
|
|
643
|
+
node.attrs.sender_pn) {
|
|
644
|
+
ev.emit('chats.phoneNumberShare', { lid: node.attrs.from, jid: node.attrs.sender_pn });
|
|
749
645
|
}
|
|
750
646
|
try {
|
|
751
647
|
await Promise.all([
|
|
752
648
|
processingMutex.mutex(async () => {
|
|
753
|
-
var _a;
|
|
754
649
|
await decrypt();
|
|
755
650
|
// message failed to decrypt
|
|
756
|
-
if (msg.messageStubType ===
|
|
757
|
-
if (
|
|
758
|
-
return sendMessageAck(node,
|
|
651
|
+
if (msg.messageStubType === proto.WebMessageInfo.StubType.CIPHERTEXT) {
|
|
652
|
+
if (msg?.messageStubParameters?.[0] === MISSING_KEYS_ERROR_TEXT) {
|
|
653
|
+
return sendMessageAck(node, NACK_REASONS.ParsingError);
|
|
759
654
|
}
|
|
760
655
|
retryMutex.mutex(async () => {
|
|
761
656
|
if (ws.isOpen) {
|
|
762
|
-
if (
|
|
657
|
+
if (getBinaryNodeChild(node, 'unavailable')) {
|
|
763
658
|
return;
|
|
764
659
|
}
|
|
765
|
-
const encNode =
|
|
660
|
+
const encNode = getBinaryNodeChild(node, 'enc');
|
|
766
661
|
await sendRetryRequest(node, !encNode);
|
|
767
662
|
if (retryRequestDelayMs) {
|
|
768
|
-
await
|
|
663
|
+
await delay(retryRequestDelayMs);
|
|
769
664
|
}
|
|
770
665
|
}
|
|
771
666
|
else {
|
|
@@ -777,13 +672,15 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
777
672
|
// no type in the receipt => message delivered
|
|
778
673
|
let type = undefined;
|
|
779
674
|
let participant = msg.key.participant;
|
|
780
|
-
if (category === 'peer') {
|
|
675
|
+
if (category === 'peer') {
|
|
676
|
+
// special peer message
|
|
781
677
|
type = 'peer_msg';
|
|
782
678
|
}
|
|
783
|
-
else if (msg.key.fromMe) {
|
|
679
|
+
else if (msg.key.fromMe) {
|
|
680
|
+
// message was sent by us from a different device
|
|
784
681
|
type = 'sender';
|
|
785
682
|
// need to specially handle this case
|
|
786
|
-
if (
|
|
683
|
+
if (isJidUser(msg.key.remoteJid)) {
|
|
787
684
|
participant = author;
|
|
788
685
|
}
|
|
789
686
|
}
|
|
@@ -792,13 +689,13 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
792
689
|
}
|
|
793
690
|
await sendReceipt(msg.key.remoteJid, participant, [msg.key.id], type);
|
|
794
691
|
// send ack for history message
|
|
795
|
-
const isAnyHistoryMsg =
|
|
692
|
+
const isAnyHistoryMsg = getHistoryMsg(msg.message);
|
|
796
693
|
if (isAnyHistoryMsg) {
|
|
797
|
-
const jid =
|
|
694
|
+
const jid = jidNormalizedUser(msg.key.remoteJid);
|
|
798
695
|
await sendReceipt(jid, undefined, [msg.key.id], 'hist_sync');
|
|
799
696
|
}
|
|
800
697
|
}
|
|
801
|
-
|
|
698
|
+
cleanMessage(msg, authState.creds.me.id);
|
|
802
699
|
await sendMessageAck(node);
|
|
803
700
|
await upsertMessage(msg, node.attrs.offline ? 'append' : 'notify');
|
|
804
701
|
})
|
|
@@ -809,9 +706,8 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
809
706
|
}
|
|
810
707
|
};
|
|
811
708
|
const fetchMessageHistory = async (count, oldestMsgKey, oldestMsgTimestamp) => {
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
throw new boom_1.Boom('Not authenticated');
|
|
709
|
+
if (!authState.creds.me?.id) {
|
|
710
|
+
throw new Boom('Not authenticated');
|
|
815
711
|
}
|
|
816
712
|
const pdoMessage = {
|
|
817
713
|
historySyncOnDemandRequest: {
|
|
@@ -821,57 +717,61 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
821
717
|
oldestMsgTimestampMs: oldestMsgTimestamp,
|
|
822
718
|
onDemandMsgCount: count
|
|
823
719
|
},
|
|
824
|
-
peerDataOperationRequestType:
|
|
720
|
+
peerDataOperationRequestType: proto.Message.PeerDataOperationRequestType.HISTORY_SYNC_ON_DEMAND
|
|
825
721
|
};
|
|
826
722
|
return sendPeerDataOperationMessage(pdoMessage);
|
|
827
723
|
};
|
|
828
724
|
const requestPlaceholderResend = async (messageKey) => {
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
throw new boom_1.Boom('Not authenticated');
|
|
725
|
+
if (!authState.creds.me?.id) {
|
|
726
|
+
throw new Boom('Not authenticated');
|
|
832
727
|
}
|
|
833
|
-
if (placeholderResendCache.get(messageKey
|
|
728
|
+
if (placeholderResendCache.get(messageKey?.id)) {
|
|
834
729
|
logger.debug({ messageKey }, 'already requested resend');
|
|
835
730
|
return;
|
|
836
731
|
}
|
|
837
732
|
else {
|
|
838
|
-
placeholderResendCache.set(messageKey
|
|
733
|
+
placeholderResendCache.set(messageKey?.id, true);
|
|
839
734
|
}
|
|
840
|
-
await
|
|
841
|
-
if (!placeholderResendCache.get(messageKey
|
|
735
|
+
await delay(5000);
|
|
736
|
+
if (!placeholderResendCache.get(messageKey?.id)) {
|
|
842
737
|
logger.debug({ messageKey }, 'message received while resend requested');
|
|
843
738
|
return 'RESOLVED';
|
|
844
739
|
}
|
|
845
740
|
const pdoMessage = {
|
|
846
|
-
placeholderMessageResendRequest: [
|
|
741
|
+
placeholderMessageResendRequest: [
|
|
742
|
+
{
|
|
847
743
|
messageKey
|
|
848
|
-
}
|
|
849
|
-
|
|
744
|
+
}
|
|
745
|
+
],
|
|
746
|
+
peerDataOperationRequestType: proto.Message.PeerDataOperationRequestType.PLACEHOLDER_MESSAGE_RESEND
|
|
850
747
|
};
|
|
851
748
|
setTimeout(() => {
|
|
852
|
-
if (placeholderResendCache.get(messageKey
|
|
749
|
+
if (placeholderResendCache.get(messageKey?.id)) {
|
|
853
750
|
logger.debug({ messageKey }, 'PDO message without response after 15 seconds. Phone possibly offline');
|
|
854
|
-
placeholderResendCache.del(messageKey
|
|
751
|
+
placeholderResendCache.del(messageKey?.id);
|
|
855
752
|
}
|
|
856
753
|
}, 15000);
|
|
857
754
|
return sendPeerDataOperationMessage(pdoMessage);
|
|
858
755
|
};
|
|
859
756
|
const handleCall = async (node) => {
|
|
860
757
|
const { attrs } = node;
|
|
861
|
-
const [infoChild] =
|
|
758
|
+
const [infoChild] = getAllBinaryNodeChildren(node);
|
|
759
|
+
if (!infoChild) {
|
|
760
|
+
throw new Boom('Missing call info in call node');
|
|
761
|
+
}
|
|
862
762
|
const callId = infoChild.attrs['call-id'];
|
|
863
763
|
const from = infoChild.attrs.from || infoChild.attrs['call-creator'];
|
|
864
|
-
const status =
|
|
764
|
+
const status = getCallStatusFromNode(infoChild);
|
|
865
765
|
const call = {
|
|
866
766
|
chatId: attrs.from,
|
|
867
767
|
from,
|
|
868
768
|
id: callId,
|
|
869
769
|
date: new Date(+attrs.t * 1000),
|
|
870
770
|
offline: !!attrs.offline,
|
|
871
|
-
status
|
|
771
|
+
status
|
|
872
772
|
};
|
|
873
773
|
if (status === 'offer') {
|
|
874
|
-
call.isVideo = !!
|
|
774
|
+
call.isVideo = !!getBinaryNodeChild(infoChild, 'video');
|
|
875
775
|
call.isGroup = infoChild.attrs.type === 'group' || !!infoChild.attrs['group-jid'];
|
|
876
776
|
call.groupJid = infoChild.attrs['group-jid'];
|
|
877
777
|
callOfferCache.set(call.id, call);
|
|
@@ -890,28 +790,20 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
890
790
|
await sendMessageAck(node);
|
|
891
791
|
};
|
|
892
792
|
const handleBadAck = async ({ attrs }) => {
|
|
893
|
-
const key = { remoteJid: attrs.from, fromMe: true, id: attrs.id
|
|
894
|
-
//
|
|
895
|
-
//
|
|
896
|
-
//
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
if (msg) {
|
|
908
|
-
await relayMessage(key.remoteJid, msg, { messageId: key.id, useUserDevicesCache: false });
|
|
909
|
-
msgRetryCache.set(cacheKey, retryCount + 1);
|
|
910
|
-
}
|
|
911
|
-
else {
|
|
912
|
-
logger.warn({ attrs }, 'could not send message again, as it was not found');
|
|
913
|
-
}
|
|
914
|
-
}
|
|
793
|
+
const key = { remoteJid: attrs.from, fromMe: true, id: attrs.id };
|
|
794
|
+
// WARNING: REFRAIN FROM ENABLING THIS FOR NOW. IT WILL CAUSE A LOOP
|
|
795
|
+
// // current hypothesis is that if pash is sent in the ack
|
|
796
|
+
// // it means -- the message hasn't reached all devices yet
|
|
797
|
+
// // we'll retry sending the message here
|
|
798
|
+
// if(attrs.phash) {
|
|
799
|
+
// logger.info({ attrs }, 'received phash in ack, resending message...')
|
|
800
|
+
// const msg = await getMessage(key)
|
|
801
|
+
// if(msg) {
|
|
802
|
+
// await relayMessage(key.remoteJid!, msg, { messageId: key.id!, useUserDevicesCache: false })
|
|
803
|
+
// } else {
|
|
804
|
+
// logger.warn({ attrs }, 'could not send message again, as it was not found')
|
|
805
|
+
// }
|
|
806
|
+
// }
|
|
915
807
|
// error in acknowledgement,
|
|
916
808
|
// device could not display the message
|
|
917
809
|
if (attrs.error) {
|
|
@@ -920,10 +812,8 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
920
812
|
{
|
|
921
813
|
key,
|
|
922
814
|
update: {
|
|
923
|
-
status:
|
|
924
|
-
messageStubParameters: [
|
|
925
|
-
attrs.error
|
|
926
|
-
]
|
|
815
|
+
status: WAMessageStatus.ERROR,
|
|
816
|
+
messageStubParameters: [attrs.error]
|
|
927
817
|
}
|
|
928
818
|
}
|
|
929
819
|
]);
|
|
@@ -936,8 +826,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
936
826
|
await execTask();
|
|
937
827
|
ev.flush();
|
|
938
828
|
function execTask() {
|
|
939
|
-
return exec(node, false)
|
|
940
|
-
.catch(err => onUnexpectedError(err, identifier));
|
|
829
|
+
return exec(node, false).catch(err => onUnexpectedError(err, identifier));
|
|
941
830
|
}
|
|
942
831
|
};
|
|
943
832
|
const makeOfflineNodeProcessor = () => {
|
|
@@ -981,6 +870,139 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
981
870
|
processNodeWithBuffer(node, identifier, exec);
|
|
982
871
|
}
|
|
983
872
|
};
|
|
873
|
+
// Handles newsletter notifications
|
|
874
|
+
async function handleNewsletterNotification(node) {
|
|
875
|
+
const from = node.attrs.from;
|
|
876
|
+
const child = getAllBinaryNodeChildren(node)[0];
|
|
877
|
+
const author = node.attrs.participant;
|
|
878
|
+
logger.info({ from, child }, 'got newsletter notification');
|
|
879
|
+
switch (child.tag) {
|
|
880
|
+
case 'reaction':
|
|
881
|
+
const reactionUpdate = {
|
|
882
|
+
id: from,
|
|
883
|
+
server_id: child.attrs.message_id,
|
|
884
|
+
reaction: {
|
|
885
|
+
code: getBinaryNodeChildString(child, 'reaction'),
|
|
886
|
+
count: 1
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
ev.emit('newsletter.reaction', reactionUpdate);
|
|
890
|
+
break;
|
|
891
|
+
case 'view':
|
|
892
|
+
const viewUpdate = {
|
|
893
|
+
id: from,
|
|
894
|
+
server_id: child.attrs.message_id,
|
|
895
|
+
count: parseInt(child.content?.toString() || '0', 10)
|
|
896
|
+
};
|
|
897
|
+
ev.emit('newsletter.view', viewUpdate);
|
|
898
|
+
break;
|
|
899
|
+
case 'participant':
|
|
900
|
+
const participantUpdate = {
|
|
901
|
+
id: from,
|
|
902
|
+
author,
|
|
903
|
+
user: child.attrs.jid,
|
|
904
|
+
action: child.attrs.action,
|
|
905
|
+
new_role: child.attrs.role
|
|
906
|
+
};
|
|
907
|
+
ev.emit('newsletter-participants.update', participantUpdate);
|
|
908
|
+
break;
|
|
909
|
+
case 'update':
|
|
910
|
+
const settingsNode = getBinaryNodeChild(child, 'settings');
|
|
911
|
+
if (settingsNode) {
|
|
912
|
+
const update = {};
|
|
913
|
+
const nameNode = getBinaryNodeChild(settingsNode, 'name');
|
|
914
|
+
if (nameNode?.content)
|
|
915
|
+
update.name = nameNode.content.toString();
|
|
916
|
+
const descriptionNode = getBinaryNodeChild(settingsNode, 'description');
|
|
917
|
+
if (descriptionNode?.content)
|
|
918
|
+
update.description = descriptionNode.content.toString();
|
|
919
|
+
ev.emit('newsletter-settings.update', {
|
|
920
|
+
id: from,
|
|
921
|
+
update
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
break;
|
|
925
|
+
case 'message':
|
|
926
|
+
const plaintextNode = getBinaryNodeChild(child, 'plaintext');
|
|
927
|
+
if (plaintextNode?.content) {
|
|
928
|
+
try {
|
|
929
|
+
const contentBuf = typeof plaintextNode.content === 'string'
|
|
930
|
+
? Buffer.from(plaintextNode.content, 'binary')
|
|
931
|
+
: Buffer.from(plaintextNode.content);
|
|
932
|
+
const messageProto = proto.Message.decode(contentBuf);
|
|
933
|
+
const fullMessage = proto.WebMessageInfo.fromObject({
|
|
934
|
+
key: {
|
|
935
|
+
remoteJid: from,
|
|
936
|
+
id: child.attrs.message_id || child.attrs.server_id,
|
|
937
|
+
fromMe: false
|
|
938
|
+
},
|
|
939
|
+
message: messageProto,
|
|
940
|
+
messageTimestamp: +child.attrs.t
|
|
941
|
+
});
|
|
942
|
+
await upsertMessage(fullMessage, 'append');
|
|
943
|
+
logger.info('Processed plaintext newsletter message');
|
|
944
|
+
}
|
|
945
|
+
catch (error) {
|
|
946
|
+
logger.error({ error }, 'Failed to decode plaintext newsletter message');
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
break;
|
|
950
|
+
default:
|
|
951
|
+
logger.warn({ node }, 'Unknown newsletter notification');
|
|
952
|
+
break;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
// Handles mex newsletter notifications
|
|
956
|
+
async function handleMexNewsletterNotification(node) {
|
|
957
|
+
const mexNode = getBinaryNodeChild(node, 'mex');
|
|
958
|
+
if (!mexNode?.content) {
|
|
959
|
+
logger.warn({ node }, 'Invalid mex newsletter notification');
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
let data;
|
|
963
|
+
try {
|
|
964
|
+
data = JSON.parse(mexNode.content.toString());
|
|
965
|
+
}
|
|
966
|
+
catch (error) {
|
|
967
|
+
logger.error({ err: error, node }, 'Failed to parse mex newsletter notification');
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
const operation = data?.operation;
|
|
971
|
+
const updates = data?.updates;
|
|
972
|
+
if (!updates || !operation) {
|
|
973
|
+
logger.warn({ data }, 'Invalid mex newsletter notification content');
|
|
974
|
+
return;
|
|
975
|
+
}
|
|
976
|
+
logger.info({ operation, updates }, 'got mex newsletter notification');
|
|
977
|
+
switch (operation) {
|
|
978
|
+
case 'NotificationNewsletterUpdate':
|
|
979
|
+
for (const update of updates) {
|
|
980
|
+
if (update.jid && update.settings && Object.keys(update.settings).length > 0) {
|
|
981
|
+
ev.emit('newsletter-settings.update', {
|
|
982
|
+
id: update.jid,
|
|
983
|
+
update: update.settings
|
|
984
|
+
});
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
break;
|
|
988
|
+
case 'NotificationNewsletterAdminPromote':
|
|
989
|
+
for (const update of updates) {
|
|
990
|
+
if (update.jid && update.user) {
|
|
991
|
+
ev.emit('newsletter-participants.update', {
|
|
992
|
+
id: update.jid,
|
|
993
|
+
author: node.attrs.from,
|
|
994
|
+
user: update.user,
|
|
995
|
+
new_role: 'ADMIN',
|
|
996
|
+
action: 'promote'
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
break;
|
|
1001
|
+
default:
|
|
1002
|
+
logger.info({ operation, data }, 'Unhandled mex newsletter notification');
|
|
1003
|
+
break;
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
984
1006
|
// recv a message
|
|
985
1007
|
ws.on('CB:message', (node) => {
|
|
986
1008
|
processNode('message', node, 'processing message', handleMessage);
|
|
@@ -995,10 +1017,12 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
995
1017
|
processNode('notification', node, 'handling notification', handleNotification);
|
|
996
1018
|
});
|
|
997
1019
|
ws.on('CB:ack,class:message', (node) => {
|
|
998
|
-
handleBadAck(node)
|
|
999
|
-
.catch(error => onUnexpectedError(error, 'handling bad ack'));
|
|
1020
|
+
handleBadAck(node).catch(error => onUnexpectedError(error, 'handling bad ack'));
|
|
1000
1021
|
});
|
|
1001
1022
|
ev.on('call', ([call]) => {
|
|
1023
|
+
if (!call) {
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1002
1026
|
// missed call + group call notification message generation
|
|
1003
1027
|
if (call.status === 'timeout' || (call.status === 'offer' && call.isGroup)) {
|
|
1004
1028
|
const msg = {
|
|
@@ -1007,20 +1031,22 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
1007
1031
|
id: call.id,
|
|
1008
1032
|
fromMe: false
|
|
1009
1033
|
},
|
|
1010
|
-
messageTimestamp:
|
|
1034
|
+
messageTimestamp: unixTimestampSeconds(call.date)
|
|
1011
1035
|
};
|
|
1012
1036
|
if (call.status === 'timeout') {
|
|
1013
1037
|
if (call.isGroup) {
|
|
1014
|
-
msg.messageStubType = call.isVideo
|
|
1038
|
+
msg.messageStubType = call.isVideo
|
|
1039
|
+
? WAMessageStubType.CALL_MISSED_GROUP_VIDEO
|
|
1040
|
+
: WAMessageStubType.CALL_MISSED_GROUP_VOICE;
|
|
1015
1041
|
}
|
|
1016
1042
|
else {
|
|
1017
|
-
msg.messageStubType = call.isVideo ?
|
|
1043
|
+
msg.messageStubType = call.isVideo ? WAMessageStubType.CALL_MISSED_VIDEO : WAMessageStubType.CALL_MISSED_VOICE;
|
|
1018
1044
|
}
|
|
1019
1045
|
}
|
|
1020
1046
|
else {
|
|
1021
1047
|
msg.message = { call: { callKey: Buffer.from(call.id) } };
|
|
1022
1048
|
}
|
|
1023
|
-
const protoMsg =
|
|
1049
|
+
const protoMsg = proto.WebMessageInfo.fromObject(msg);
|
|
1024
1050
|
upsertMessage(protoMsg, call.offline ? 'append' : 'notify');
|
|
1025
1051
|
}
|
|
1026
1052
|
});
|
|
@@ -1035,9 +1061,8 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
1035
1061
|
sendMessageAck,
|
|
1036
1062
|
sendRetryRequest,
|
|
1037
1063
|
rejectCall,
|
|
1038
|
-
offerCall,
|
|
1039
1064
|
fetchMessageHistory,
|
|
1040
|
-
requestPlaceholderResend
|
|
1065
|
+
requestPlaceholderResend
|
|
1041
1066
|
};
|
|
1042
1067
|
};
|
|
1043
|
-
|
|
1068
|
+
//# sourceMappingURL=messages-recv.js.map
|