@d0v3riz/baileys 6.7.24 → 7.0.0-rc.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -8
- package/WAProto/GenerateStatics.sh +2 -2
- package/WAProto/WAProto.proto +1339 -493
- package/WAProto/fix-imports.js +1 -1
- package/WAProto/index.d.ts +4585 -44041
- package/WAProto/index.js +80831 -148208
- package/lib/Defaults/index.d.ts +13 -3
- package/lib/Defaults/index.d.ts.map +1 -1
- package/lib/Defaults/index.js +27 -13
- package/lib/Defaults/index.js.map +1 -1
- package/lib/Signal/Group/group_cipher.d.ts +1 -2
- package/lib/Signal/Group/group_cipher.d.ts.map +1 -1
- package/lib/Signal/Group/group_cipher.js +29 -41
- package/lib/Signal/Group/group_cipher.js.map +1 -1
- package/lib/Signal/Group/keyhelper.d.ts.map +1 -1
- package/lib/Signal/Group/keyhelper.js +0 -1
- package/lib/Signal/Group/keyhelper.js.map +1 -1
- package/lib/Signal/Group/sender-chain-key.d.ts +1 -1
- package/lib/Signal/Group/sender-chain-key.d.ts.map +1 -1
- package/lib/Signal/Group/sender-chain-key.js +1 -7
- package/lib/Signal/Group/sender-chain-key.js.map +1 -1
- package/lib/Signal/Group/sender-key-distribution-message.js +2 -2
- package/lib/Signal/Group/sender-key-distribution-message.js.map +1 -1
- package/lib/Signal/Group/sender-key-message.d.ts.map +1 -1
- package/lib/Signal/Group/sender-key-message.js +0 -1
- package/lib/Signal/Group/sender-key-message.js.map +1 -1
- package/lib/Signal/Group/sender-key-record.d.ts +1 -1
- package/lib/Signal/Group/sender-key-record.d.ts.map +1 -1
- package/lib/Signal/Group/sender-key-record.js +2 -11
- package/lib/Signal/Group/sender-key-record.js.map +1 -1
- package/lib/Signal/Group/sender-key-state.d.ts +4 -4
- package/lib/Signal/Group/sender-key-state.d.ts.map +1 -1
- package/lib/Signal/Group/sender-key-state.js +21 -33
- package/lib/Signal/Group/sender-key-state.js.map +1 -1
- package/lib/Signal/Group/sender-message-key.d.ts.map +1 -1
- package/lib/Signal/Group/sender-message-key.js +0 -1
- package/lib/Signal/Group/sender-message-key.js.map +1 -1
- package/lib/Signal/libsignal.d.ts +4 -3
- package/lib/Signal/libsignal.d.ts.map +1 -1
- package/lib/Signal/libsignal.js +243 -42
- package/lib/Signal/libsignal.js.map +1 -1
- package/lib/Signal/lid-mapping.d.ts +23 -0
- package/lib/Signal/lid-mapping.d.ts.map +1 -0
- package/lib/Signal/lid-mapping.js +171 -0
- package/lib/Signal/lid-mapping.js.map +1 -0
- package/lib/Socket/business.d.ts +29 -17
- package/lib/Socket/business.d.ts.map +1 -1
- package/lib/Socket/business.js +122 -1
- package/lib/Socket/business.js.map +1 -1
- package/lib/Socket/chats.d.ts +15 -9
- package/lib/Socket/chats.d.ts.map +1 -1
- package/lib/Socket/chats.js +49 -20
- package/lib/Socket/chats.js.map +1 -1
- package/lib/Socket/communities.d.ts +39 -14
- package/lib/Socket/communities.d.ts.map +1 -1
- package/lib/Socket/communities.js +82 -2
- package/lib/Socket/communities.js.map +1 -1
- package/lib/Socket/groups.d.ts +14 -9
- package/lib/Socket/groups.d.ts.map +1 -1
- package/lib/Socket/groups.js +14 -11
- package/lib/Socket/groups.js.map +1 -1
- package/lib/Socket/index.d.ts +39 -14
- package/lib/Socket/index.d.ts.map +1 -1
- package/lib/Socket/index.js +1 -0
- package/lib/Socket/index.js.map +1 -1
- package/lib/Socket/messages-recv.d.ts +24 -16
- package/lib/Socket/messages-recv.d.ts.map +1 -1
- package/lib/Socket/messages-recv.js +463 -319
- package/lib/Socket/messages-recv.js.map +1 -1
- package/lib/Socket/messages-send.d.ts +25 -16
- package/lib/Socket/messages-send.d.ts.map +1 -1
- package/lib/Socket/messages-send.js +365 -125
- package/lib/Socket/messages-send.js.map +1 -1
- package/lib/Socket/newsletter.d.ts +16 -12
- package/lib/Socket/newsletter.d.ts.map +1 -1
- package/lib/Socket/newsletter.js +3 -1
- package/lib/Socket/newsletter.js.map +1 -1
- package/lib/Socket/socket.d.ts +11 -3
- package/lib/Socket/socket.d.ts.map +1 -1
- package/lib/Socket/socket.js +305 -71
- package/lib/Socket/socket.js.map +1 -1
- package/lib/Types/Auth.d.ts +8 -1
- package/lib/Types/Auth.d.ts.map +1 -1
- package/lib/Types/Bussines.d.ts +25 -0
- package/lib/Types/Bussines.d.ts.map +1 -0
- package/lib/Types/Bussines.js +2 -0
- package/lib/Types/Bussines.js.map +1 -0
- package/lib/Types/Chat.d.ts +5 -0
- package/lib/Types/Chat.d.ts.map +1 -1
- package/lib/Types/Chat.js.map +1 -1
- package/lib/Types/Contact.d.ts +4 -4
- package/lib/Types/Contact.d.ts.map +1 -1
- package/lib/Types/Events.d.ts +8 -5
- package/lib/Types/Events.d.ts.map +1 -1
- package/lib/Types/GroupMetadata.d.ts +7 -4
- package/lib/Types/GroupMetadata.d.ts.map +1 -1
- package/lib/Types/Message.d.ts +38 -12
- package/lib/Types/Message.d.ts.map +1 -1
- package/lib/Types/Message.js +5 -1
- package/lib/Types/Message.js.map +1 -1
- package/lib/Types/Signal.d.ts +18 -0
- package/lib/Types/Signal.d.ts.map +1 -1
- package/lib/Types/Socket.d.ts +24 -13
- package/lib/Types/Socket.d.ts.map +1 -1
- package/lib/Types/Socket.js.map +1 -1
- package/lib/Utils/auth-utils.d.ts +2 -2
- package/lib/Utils/auth-utils.d.ts.map +1 -1
- package/lib/Utils/auth-utils.js +178 -111
- package/lib/Utils/auth-utils.js.map +1 -1
- package/lib/Utils/browser-utils.d.ts +4 -0
- package/lib/Utils/browser-utils.d.ts.map +1 -0
- package/lib/Utils/browser-utils.js +28 -0
- package/lib/Utils/browser-utils.js.map +1 -0
- package/lib/Utils/chat-utils.d.ts +6 -7
- package/lib/Utils/chat-utils.d.ts.map +1 -1
- package/lib/Utils/chat-utils.js +19 -2
- package/lib/Utils/chat-utils.js.map +1 -1
- package/lib/Utils/crypto.d.ts +6 -6
- package/lib/Utils/crypto.d.ts.map +1 -1
- package/lib/Utils/crypto.js +16 -12
- package/lib/Utils/crypto.js.map +1 -1
- package/lib/Utils/decode-wa-message.d.ts +14 -2
- package/lib/Utils/decode-wa-message.d.ts.map +1 -1
- package/lib/Utils/decode-wa-message.js +99 -14
- package/lib/Utils/decode-wa-message.js.map +1 -1
- package/lib/Utils/event-buffer.d.ts +0 -1
- package/lib/Utils/event-buffer.d.ts.map +1 -1
- package/lib/Utils/event-buffer.js +63 -18
- package/lib/Utils/event-buffer.js.map +1 -1
- package/lib/Utils/generics.d.ts +5 -7
- package/lib/Utils/generics.d.ts.map +1 -1
- package/lib/Utils/generics.js +58 -50
- package/lib/Utils/generics.js.map +1 -1
- package/lib/Utils/history.d.ts +8 -9
- package/lib/Utils/history.d.ts.map +1 -1
- package/lib/Utils/history.js +8 -3
- package/lib/Utils/history.js.map +1 -1
- package/lib/Utils/index.d.ts +2 -0
- package/lib/Utils/index.d.ts.map +1 -1
- package/lib/Utils/index.js +2 -0
- package/lib/Utils/index.js.map +1 -1
- package/lib/Utils/link-preview.d.ts +1 -2
- package/lib/Utils/link-preview.d.ts.map +1 -1
- package/lib/Utils/link-preview.js +1 -1
- package/lib/Utils/link-preview.js.map +1 -1
- package/lib/Utils/message-retry-manager.d.ts +82 -0
- package/lib/Utils/message-retry-manager.d.ts.map +1 -0
- package/lib/Utils/message-retry-manager.js +149 -0
- package/lib/Utils/message-retry-manager.js.map +1 -0
- package/lib/Utils/messages-media.d.ts +14 -12
- package/lib/Utils/messages-media.d.ts.map +1 -1
- package/lib/Utils/messages-media.js +47 -23
- package/lib/Utils/messages-media.js.map +1 -1
- package/lib/Utils/messages.d.ts +4 -4
- package/lib/Utils/messages.d.ts.map +1 -1
- package/lib/Utils/messages.js +55 -21
- package/lib/Utils/messages.js.map +1 -1
- package/lib/Utils/noise-handler.js +2 -1
- package/lib/Utils/noise-handler.js.map +1 -1
- package/lib/Utils/pre-key-manager.d.ts +28 -0
- package/lib/Utils/pre-key-manager.d.ts.map +1 -0
- package/lib/Utils/pre-key-manager.js +106 -0
- package/lib/Utils/pre-key-manager.js.map +1 -0
- package/lib/Utils/process-message.d.ts +8 -8
- package/lib/Utils/process-message.d.ts.map +1 -1
- package/lib/Utils/process-message.js +68 -23
- package/lib/Utils/process-message.js.map +1 -1
- package/lib/Utils/signal.d.ts +4 -4
- package/lib/Utils/signal.d.ts.map +1 -1
- package/lib/Utils/signal.js +21 -12
- package/lib/Utils/signal.js.map +1 -1
- package/lib/Utils/validate-connection.d.ts.map +1 -1
- package/lib/Utils/validate-connection.js +50 -14
- package/lib/Utils/validate-connection.js.map +1 -1
- package/lib/WABinary/decode.d.ts.map +1 -1
- package/lib/WABinary/decode.js +12 -2
- package/lib/WABinary/decode.js.map +1 -1
- package/lib/WABinary/generic-utils.js +1 -1
- package/lib/WABinary/generic-utils.js.map +1 -1
- package/lib/WABinary/jid-utils.d.ts +18 -6
- package/lib/WABinary/jid-utils.d.ts.map +1 -1
- package/lib/WABinary/jid-utils.js +52 -8
- package/lib/WABinary/jid-utils.js.map +1 -1
- package/lib/WAM/constants.d.ts +1 -1
- package/lib/WAM/constants.d.ts.map +1 -1
- package/lib/WAM/constants.js +18516 -10904
- package/lib/WAM/constants.js.map +1 -1
- package/lib/WAM/encode.d.ts.map +1 -1
- package/lib/WAM/encode.js +0 -1
- package/lib/WAM/encode.js.map +1 -1
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +2 -1
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts.map +1 -1
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +10 -2
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js.map +1 -1
- package/lib/WAUSync/USyncQuery.d.ts +1 -1
- package/lib/WAUSync/USyncQuery.d.ts.map +1 -1
- package/lib/WAUSync/USyncQuery.js +23 -20
- package/lib/WAUSync/USyncQuery.js.map +1 -1
- package/package.json +16 -11
- package/lib/Defaults/baileys-version.json +0 -3
- package/lib/Signal/Group/queue-job.d.ts +0 -2
- package/lib/Signal/Group/queue-job.d.ts.map +0 -1
- package/lib/Signal/Group/queue-job.js +0 -54
- package/lib/Signal/Group/queue-job.js.map +0 -1
- package/lib/Socket/usync.d.ts +0 -37
- package/lib/Socket/usync.d.ts.map +0 -1
- package/lib/Socket/usync.js +0 -63
- package/lib/Socket/usync.js.map +0 -1
|
@@ -2,21 +2,29 @@ import NodeCache from '@cacheable/node-cache';
|
|
|
2
2
|
import { Boom } from '@hapi/boom';
|
|
3
3
|
import { proto } from '../../WAProto/index.js';
|
|
4
4
|
import { DEFAULT_CACHE_TTLS, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
|
|
5
|
-
import { aggregateMessageKeysNotFromMe, assertMediaContent, bindWaitForEvent, decryptMediaRetryData, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, generateMessageIDV2, generateWAMessage, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, normalizeMessageContent, parseAndInjectE2ESessions, unixTimestampSeconds } from '../Utils/index.js';
|
|
5
|
+
import { aggregateMessageKeysNotFromMe, assertMediaContent, bindWaitForEvent, decryptMediaRetryData, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, generateMessageIDV2, generateParticipantHashV2, generateWAMessage, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, MessageRetryManager, normalizeMessageContent, parseAndInjectE2ESessions, unixTimestampSeconds } from '../Utils/index.js';
|
|
6
6
|
import { getUrlInfo } from '../Utils/link-preview.js';
|
|
7
|
-
import {
|
|
7
|
+
import { makeKeyedMutex } from '../Utils/make-mutex.js';
|
|
8
|
+
import { areJidsSameUser, getBinaryNodeChild, getBinaryNodeChildren, isHostedLidUser, isHostedPnUser, isJidGroup, isLidUser, isPnUser, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
8
9
|
import { USyncQuery, USyncUser } from '../WAUSync/index.js';
|
|
9
|
-
import { makeGroupsSocket } from './groups.js';
|
|
10
10
|
import { makeNewsletterSocket } from './newsletter.js';
|
|
11
11
|
export const makeMessagesSocket = (config) => {
|
|
12
|
-
const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options:
|
|
13
|
-
const sock = makeNewsletterSocket(
|
|
12
|
+
const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: httpRequestOptions, patchMessageBeforeSending, cachedGroupMetadata, enableRecentMessageCache, maxMsgRetryCount } = config;
|
|
13
|
+
const sock = makeNewsletterSocket(config);
|
|
14
14
|
const { ev, authState, processingMutex, signalRepository, upsertMessage, query, fetchPrivacySettings, sendNode, groupMetadata, groupToggleEphemeral } = sock;
|
|
15
15
|
const userDevicesCache = config.userDevicesCache ||
|
|
16
16
|
new NodeCache({
|
|
17
17
|
stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES, // 5 minutes
|
|
18
18
|
useClones: false
|
|
19
19
|
});
|
|
20
|
+
const peerSessionsCache = new NodeCache({
|
|
21
|
+
stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES,
|
|
22
|
+
useClones: false
|
|
23
|
+
});
|
|
24
|
+
// Initialize message retry manager if enabled
|
|
25
|
+
const messageRetryManager = enableRecentMessageCache ? new MessageRetryManager(logger, maxMsgRetryCount) : null;
|
|
26
|
+
// Prevent race conditions in Signal session encryption by user
|
|
27
|
+
const encryptionMutex = makeKeyedMutex();
|
|
20
28
|
let mediaConn;
|
|
21
29
|
const refreshMediaConn = async (forceGet = false) => {
|
|
22
30
|
const media = await mediaConn;
|
|
@@ -32,6 +40,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
32
40
|
content: [{ tag: 'media_conn', attrs: {} }]
|
|
33
41
|
});
|
|
34
42
|
const mediaConnNode = getBinaryNodeChild(result, 'media_conn');
|
|
43
|
+
// TODO: explore full length of data that whatsapp provides
|
|
35
44
|
const node = {
|
|
36
45
|
hosts: getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
|
|
37
46
|
hostname: attrs.hostname,
|
|
@@ -65,7 +74,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
65
74
|
if (isReadReceipt) {
|
|
66
75
|
node.attrs.t = unixTimestampSeconds().toString();
|
|
67
76
|
}
|
|
68
|
-
if (type === 'sender' &&
|
|
77
|
+
if (type === 'sender' && (isPnUser(jid) || isLidUser(jid))) {
|
|
69
78
|
node.attrs.recipient = jid;
|
|
70
79
|
node.attrs.to = participant;
|
|
71
80
|
}
|
|
@@ -115,14 +124,39 @@ export const makeMessagesSocket = (config) => {
|
|
|
115
124
|
logger.debug('not using cache for devices');
|
|
116
125
|
}
|
|
117
126
|
const toFetch = [];
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const
|
|
127
|
+
const jidsWithUser = jids
|
|
128
|
+
.map(jid => {
|
|
129
|
+
const decoded = jidDecode(jid);
|
|
130
|
+
const user = decoded?.user;
|
|
131
|
+
const device = decoded?.device;
|
|
132
|
+
const isExplicitDevice = typeof device === 'number' && device >= 0;
|
|
133
|
+
if (isExplicitDevice && user) {
|
|
134
|
+
deviceResults.push({
|
|
135
|
+
user,
|
|
136
|
+
device,
|
|
137
|
+
jid
|
|
138
|
+
});
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
121
141
|
jid = jidNormalizedUser(jid);
|
|
142
|
+
return { jid, user };
|
|
143
|
+
})
|
|
144
|
+
.filter(jid => jid !== null);
|
|
145
|
+
let mgetDevices;
|
|
146
|
+
if (useCache && userDevicesCache.mget) {
|
|
147
|
+
const usersToFetch = jidsWithUser.map(j => j?.user).filter(Boolean);
|
|
148
|
+
mgetDevices = await userDevicesCache.mget(usersToFetch);
|
|
149
|
+
}
|
|
150
|
+
for (const { jid, user } of jidsWithUser) {
|
|
122
151
|
if (useCache) {
|
|
123
|
-
const devices =
|
|
152
|
+
const devices = mgetDevices?.[user] ||
|
|
153
|
+
(userDevicesCache.mget ? undefined : (await userDevicesCache.get(user)));
|
|
124
154
|
if (devices) {
|
|
125
|
-
|
|
155
|
+
const devicesWithJid = devices.map(d => ({
|
|
156
|
+
...d,
|
|
157
|
+
jid: jidEncode(d.user, d.server, d.device)
|
|
158
|
+
}));
|
|
159
|
+
deviceResults.push(...devicesWithJid);
|
|
126
160
|
logger.trace({ user }, 'using cache for devices');
|
|
127
161
|
}
|
|
128
162
|
else {
|
|
@@ -136,43 +170,111 @@ export const makeMessagesSocket = (config) => {
|
|
|
136
170
|
if (!toFetch.length) {
|
|
137
171
|
return deviceResults;
|
|
138
172
|
}
|
|
139
|
-
const
|
|
173
|
+
const requestedLidUsers = new Set();
|
|
174
|
+
for (const jid of toFetch) {
|
|
175
|
+
if (isLidUser(jid) || isHostedLidUser(jid)) {
|
|
176
|
+
const user = jidDecode(jid)?.user;
|
|
177
|
+
if (user)
|
|
178
|
+
requestedLidUsers.add(user);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const query = new USyncQuery().withContext('message').withDeviceProtocol().withLIDProtocol();
|
|
140
182
|
for (const jid of toFetch) {
|
|
141
|
-
query.withUser(new USyncUser().withId(jid));
|
|
183
|
+
query.withUser(new USyncUser().withId(jid)); // todo: investigate - the idea here is that <user> should have an inline lid field with the lid being the pn equivalent
|
|
142
184
|
}
|
|
143
185
|
const result = await sock.executeUSyncQuery(query);
|
|
144
186
|
if (result) {
|
|
145
|
-
|
|
187
|
+
// TODO: LID MAP this stuff (lid protocol will now return lid with devices)
|
|
188
|
+
const lidResults = result.list.filter(a => !!a.lid);
|
|
189
|
+
if (lidResults.length > 0) {
|
|
190
|
+
logger.trace('Storing LID maps from device call');
|
|
191
|
+
await signalRepository.lidMapping.storeLIDPNMappings(lidResults.map(a => ({ lid: a.lid, pn: a.id })));
|
|
192
|
+
}
|
|
193
|
+
const extracted = extractDeviceJids(result?.list, authState.creds.me.id, authState.creds.me.lid, ignoreZeroDevices);
|
|
146
194
|
const deviceMap = {};
|
|
147
195
|
for (const item of extracted) {
|
|
148
196
|
deviceMap[item.user] = deviceMap[item.user] || [];
|
|
149
197
|
deviceMap[item.user]?.push(item);
|
|
150
|
-
deviceResults.push(item);
|
|
151
198
|
}
|
|
152
|
-
|
|
153
|
-
|
|
199
|
+
// Process each user's devices as a group for bulk LID migration
|
|
200
|
+
for (const [user, userDevices] of Object.entries(deviceMap)) {
|
|
201
|
+
const isLidUser = requestedLidUsers.has(user);
|
|
202
|
+
// Process all devices for this user
|
|
203
|
+
for (const item of userDevices) {
|
|
204
|
+
const finalJid = isLidUser
|
|
205
|
+
? jidEncode(user, item.server, item.device)
|
|
206
|
+
: jidEncode(item.user, item.server, item.device);
|
|
207
|
+
deviceResults.push({
|
|
208
|
+
...item,
|
|
209
|
+
jid: finalJid
|
|
210
|
+
});
|
|
211
|
+
logger.debug({
|
|
212
|
+
user: item.user,
|
|
213
|
+
device: item.device,
|
|
214
|
+
finalJid,
|
|
215
|
+
usedLid: isLidUser
|
|
216
|
+
}, 'Processed device with LID priority');
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (userDevicesCache.mset) {
|
|
220
|
+
// if the cache supports mset, we can set all devices in one go
|
|
221
|
+
await userDevicesCache.mset(Object.entries(deviceMap).map(([key, value]) => ({ key, value })));
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
for (const key in deviceMap) {
|
|
225
|
+
if (deviceMap[key])
|
|
226
|
+
await userDevicesCache.set(key, deviceMap[key]);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const userDeviceUpdates = {};
|
|
230
|
+
for (const [userId, devices] of Object.entries(deviceMap)) {
|
|
231
|
+
if (devices && devices.length > 0) {
|
|
232
|
+
userDeviceUpdates[userId] = devices.map(d => d.device?.toString() || '0');
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (Object.keys(userDeviceUpdates).length > 0) {
|
|
236
|
+
try {
|
|
237
|
+
await authState.keys.set({ 'device-list': userDeviceUpdates });
|
|
238
|
+
logger.debug({ userCount: Object.keys(userDeviceUpdates).length }, 'stored user device lists for bulk migration');
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
logger.warn({ error }, 'failed to store user device lists');
|
|
242
|
+
}
|
|
154
243
|
}
|
|
155
244
|
}
|
|
156
245
|
return deviceResults;
|
|
157
246
|
};
|
|
158
|
-
const assertSessions = async (jids
|
|
247
|
+
const assertSessions = async (jids) => {
|
|
159
248
|
let didFetchNewSession = false;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
jidsRequiringFetch.push(jid);
|
|
249
|
+
const uniqueJids = [...new Set(jids)]; // Deduplicate JIDs
|
|
250
|
+
const jidsRequiringFetch = [];
|
|
251
|
+
logger.debug({ jids }, 'assertSessions call with jids');
|
|
252
|
+
// Check peerSessionsCache and validate sessions using libsignal loadSession
|
|
253
|
+
for (const jid of uniqueJids) {
|
|
254
|
+
const signalId = signalRepository.jidToSignalProtocolAddress(jid);
|
|
255
|
+
const cachedSession = peerSessionsCache.get(signalId);
|
|
256
|
+
if (cachedSession !== undefined) {
|
|
257
|
+
if (cachedSession) {
|
|
258
|
+
continue; // Session exists in cache
|
|
171
259
|
}
|
|
172
260
|
}
|
|
261
|
+
else {
|
|
262
|
+
const sessionValidation = await signalRepository.validateSession(jid);
|
|
263
|
+
const hasSession = sessionValidation.exists;
|
|
264
|
+
peerSessionsCache.set(signalId, hasSession);
|
|
265
|
+
if (hasSession) {
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
jidsRequiringFetch.push(jid);
|
|
173
270
|
}
|
|
174
271
|
if (jidsRequiringFetch.length) {
|
|
175
|
-
|
|
272
|
+
// LID if mapped, otherwise original
|
|
273
|
+
const wireJids = [
|
|
274
|
+
...jidsRequiringFetch.filter(jid => !!isLidUser(jid) || !!isHostedLidUser(jid)),
|
|
275
|
+
...((await signalRepository.lidMapping.getLIDsForPNs(jidsRequiringFetch.filter(jid => !!isPnUser(jid) || !!isHostedPnUser(jid)))) || []).map(a => a.lid)
|
|
276
|
+
];
|
|
277
|
+
logger.debug({ jidsRequiringFetch, wireJids }, 'fetching sessions');
|
|
176
278
|
const result = await query({
|
|
177
279
|
tag: 'iq',
|
|
178
280
|
attrs: {
|
|
@@ -184,7 +286,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
184
286
|
{
|
|
185
287
|
tag: 'key',
|
|
186
288
|
attrs: {},
|
|
187
|
-
content:
|
|
289
|
+
content: wireJids.map(jid => ({
|
|
188
290
|
tag: 'user',
|
|
189
291
|
attrs: { jid }
|
|
190
292
|
}))
|
|
@@ -193,6 +295,11 @@ export const makeMessagesSocket = (config) => {
|
|
|
193
295
|
});
|
|
194
296
|
await parseAndInjectE2ESessions(result, signalRepository);
|
|
195
297
|
didFetchNewSession = true;
|
|
298
|
+
// Cache fetched sessions using wire JIDs
|
|
299
|
+
for (const wireJid of wireJids) {
|
|
300
|
+
const signalId = signalRepository.jidToSignalProtocolAddress(wireJid);
|
|
301
|
+
peerSessionsCache.set(signalId, true);
|
|
302
|
+
}
|
|
196
303
|
}
|
|
197
304
|
return didFetchNewSession;
|
|
198
305
|
};
|
|
@@ -212,59 +319,91 @@ export const makeMessagesSocket = (config) => {
|
|
|
212
319
|
additionalAttributes: {
|
|
213
320
|
category: 'peer',
|
|
214
321
|
push_priority: 'high_force'
|
|
215
|
-
}
|
|
322
|
+
},
|
|
323
|
+
additionalNodes: [
|
|
324
|
+
{
|
|
325
|
+
tag: 'meta',
|
|
326
|
+
attrs: { appdata: 'default' }
|
|
327
|
+
}
|
|
328
|
+
]
|
|
216
329
|
});
|
|
217
330
|
return msgId;
|
|
218
331
|
};
|
|
219
|
-
const createParticipantNodes = async (
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
332
|
+
const createParticipantNodes = async (recipientJids, message, extraAttrs, dsmMessage) => {
|
|
333
|
+
if (!recipientJids.length) {
|
|
334
|
+
return { nodes: [], shouldIncludeDeviceIdentity: false };
|
|
335
|
+
}
|
|
336
|
+
const patched = await patchMessageBeforeSending(message, recipientJids);
|
|
337
|
+
const patchedMessages = Array.isArray(patched)
|
|
338
|
+
? patched
|
|
339
|
+
: recipientJids.map(jid => ({ recipientJid: jid, message: patched }));
|
|
224
340
|
let shouldIncludeDeviceIdentity = false;
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
341
|
+
const meId = authState.creds.me.id;
|
|
342
|
+
const meLid = authState.creds.me?.lid;
|
|
343
|
+
const meLidUser = meLid ? jidDecode(meLid)?.user : null;
|
|
344
|
+
const encryptionPromises = patchedMessages.map(async ({ recipientJid: jid, message: patchedMessage }) => {
|
|
345
|
+
if (!jid)
|
|
346
|
+
return null;
|
|
347
|
+
let msgToEncrypt = patchedMessage;
|
|
348
|
+
if (dsmMessage) {
|
|
349
|
+
const { user: targetUser } = jidDecode(jid);
|
|
350
|
+
const { user: ownPnUser } = jidDecode(meId);
|
|
351
|
+
const ownLidUser = meLidUser;
|
|
352
|
+
const isOwnUser = targetUser === ownPnUser || (ownLidUser && targetUser === ownLidUser);
|
|
353
|
+
const isExactSenderDevice = jid === meId || (meLid && jid === meLid);
|
|
354
|
+
if (isOwnUser && !isExactSenderDevice) {
|
|
355
|
+
msgToEncrypt = dsmMessage;
|
|
356
|
+
logger.debug({ jid, targetUser }, 'Using DSM for own device');
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
const bytes = encodeWAMessage(msgToEncrypt);
|
|
360
|
+
const mutexKey = jid;
|
|
361
|
+
const node = await encryptionMutex.mutex(mutexKey, async () => {
|
|
362
|
+
const { type, ciphertext } = await signalRepository.encryptMessage({
|
|
363
|
+
jid,
|
|
364
|
+
data: bytes
|
|
365
|
+
});
|
|
366
|
+
if (type === 'pkmsg') {
|
|
367
|
+
shouldIncludeDeviceIdentity = true;
|
|
368
|
+
}
|
|
369
|
+
return {
|
|
370
|
+
tag: 'to',
|
|
371
|
+
attrs: { jid },
|
|
372
|
+
content: [
|
|
373
|
+
{
|
|
374
|
+
tag: 'enc',
|
|
375
|
+
attrs: {
|
|
376
|
+
v: '2',
|
|
377
|
+
type,
|
|
378
|
+
...(extraAttrs || {})
|
|
379
|
+
},
|
|
380
|
+
content: ciphertext
|
|
381
|
+
}
|
|
382
|
+
]
|
|
383
|
+
};
|
|
384
|
+
});
|
|
250
385
|
return node;
|
|
251
|
-
})
|
|
386
|
+
});
|
|
387
|
+
const nodes = (await Promise.all(encryptionPromises)).filter(node => node !== null);
|
|
252
388
|
return { nodes, shouldIncludeDeviceIdentity };
|
|
253
389
|
};
|
|
254
390
|
const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList }) => {
|
|
255
391
|
const meId = authState.creds.me.id;
|
|
256
|
-
|
|
257
|
-
const
|
|
392
|
+
const meLid = authState.creds.me?.lid;
|
|
393
|
+
const isRetryResend = Boolean(participant?.jid);
|
|
394
|
+
let shouldIncludeDeviceIdentity = isRetryResend;
|
|
258
395
|
const statusJid = 'status@broadcast';
|
|
396
|
+
const { user, server } = jidDecode(jid);
|
|
259
397
|
const isGroup = server === 'g.us';
|
|
260
398
|
const isStatus = jid === statusJid;
|
|
261
399
|
const isLid = server === 'lid';
|
|
262
400
|
const isNewsletter = server === 'newsletter';
|
|
263
|
-
|
|
401
|
+
const finalJid = jid;
|
|
402
|
+
msgId = msgId || generateMessageIDV2(meId);
|
|
264
403
|
useUserDevicesCache = useUserDevicesCache !== false;
|
|
265
404
|
useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus;
|
|
266
405
|
const participants = [];
|
|
267
|
-
const destinationJid = !isStatus ?
|
|
406
|
+
const destinationJid = !isStatus ? finalJid : statusJid;
|
|
268
407
|
const binaryNodeContent = [];
|
|
269
408
|
const devices = [];
|
|
270
409
|
const meMsg = {
|
|
@@ -276,14 +415,15 @@ export const makeMessagesSocket = (config) => {
|
|
|
276
415
|
};
|
|
277
416
|
const extraAttrs = {};
|
|
278
417
|
if (participant) {
|
|
279
|
-
// when the retry request is not for a group
|
|
280
|
-
// only send to the specific device that asked for a retry
|
|
281
|
-
// otherwise the message is sent out to every device that should be a recipient
|
|
282
418
|
if (!isGroup && !isStatus) {
|
|
283
419
|
additionalAttributes = { ...additionalAttributes, device_fanout: 'false' };
|
|
284
420
|
}
|
|
285
421
|
const { user, device } = jidDecode(participant.jid);
|
|
286
|
-
devices.push({
|
|
422
|
+
devices.push({
|
|
423
|
+
user,
|
|
424
|
+
device,
|
|
425
|
+
jid: participant.jid
|
|
426
|
+
});
|
|
287
427
|
}
|
|
288
428
|
await authState.keys.transaction(async () => {
|
|
289
429
|
const mediaType = getMediaType(message);
|
|
@@ -291,7 +431,6 @@ export const makeMessagesSocket = (config) => {
|
|
|
291
431
|
extraAttrs['mediatype'] = mediaType;
|
|
292
432
|
}
|
|
293
433
|
if (isNewsletter) {
|
|
294
|
-
// Patch message if needed, then encode as plaintext
|
|
295
434
|
const patched = patchMessageBeforeSending ? await patchMessageBeforeSending(message, []) : message;
|
|
296
435
|
const bytes = encodeNewsletterMessage(patched);
|
|
297
436
|
binaryNodeContent.push({
|
|
@@ -314,117 +453,198 @@ export const makeMessagesSocket = (config) => {
|
|
|
314
453
|
return;
|
|
315
454
|
}
|
|
316
455
|
if (normalizeMessageContent(message)?.pinInChatMessage) {
|
|
317
|
-
extraAttrs['decrypt-fail'] = 'hide';
|
|
456
|
+
extraAttrs['decrypt-fail'] = 'hide'; // todo: expand for reactions and other types
|
|
318
457
|
}
|
|
319
458
|
if (isGroup || isStatus) {
|
|
320
459
|
const [groupData, senderKeyMap] = await Promise.all([
|
|
321
460
|
(async () => {
|
|
322
|
-
let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined;
|
|
461
|
+
let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined; // todo: should we rely on the cache specially if the cache is outdated and the metadata has new fields?
|
|
323
462
|
if (groupData && Array.isArray(groupData?.participants)) {
|
|
324
463
|
logger.trace({ jid, participants: groupData.participants.length }, 'using cached group metadata');
|
|
325
464
|
}
|
|
326
465
|
else if (!isStatus) {
|
|
327
|
-
groupData = await groupMetadata(jid);
|
|
466
|
+
groupData = await groupMetadata(jid); // TODO: start storing group participant list + addr mode in Signal & stop relying on this
|
|
328
467
|
}
|
|
329
468
|
return groupData;
|
|
330
469
|
})(),
|
|
331
470
|
(async () => {
|
|
332
471
|
if (!participant && !isStatus) {
|
|
333
|
-
|
|
472
|
+
// what if sender memory is less accurate than the cached metadata
|
|
473
|
+
// on participant change in group, we should do sender memory manipulation
|
|
474
|
+
const result = await authState.keys.get('sender-key-memory', [jid]); // TODO: check out what if the sender key memory doesn't include the LID stuff now?
|
|
334
475
|
return result[jid] || {};
|
|
335
476
|
}
|
|
336
477
|
return {};
|
|
337
478
|
})()
|
|
338
479
|
]);
|
|
339
480
|
if (!participant) {
|
|
340
|
-
const participantsList =
|
|
341
|
-
if (isStatus
|
|
342
|
-
|
|
481
|
+
const participantsList = [];
|
|
482
|
+
if (isStatus) {
|
|
483
|
+
if (statusJidList?.length)
|
|
484
|
+
participantsList.push(...statusJidList);
|
|
343
485
|
}
|
|
344
|
-
|
|
486
|
+
else {
|
|
487
|
+
// default to LID based groups
|
|
488
|
+
let groupAddressingMode = 'lid';
|
|
489
|
+
if (groupData) {
|
|
490
|
+
participantsList.push(...groupData.participants.map(p => p.id));
|
|
491
|
+
groupAddressingMode = groupData?.addressingMode || groupAddressingMode;
|
|
492
|
+
}
|
|
493
|
+
// default to lid addressing mode in a group
|
|
345
494
|
additionalAttributes = {
|
|
346
495
|
...additionalAttributes,
|
|
347
|
-
addressing_mode:
|
|
496
|
+
addressing_mode: groupAddressingMode
|
|
348
497
|
};
|
|
349
498
|
}
|
|
350
499
|
const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false);
|
|
351
500
|
devices.push(...additionalDevices);
|
|
352
501
|
}
|
|
502
|
+
if (groupData?.ephemeralDuration && groupData.ephemeralDuration > 0) {
|
|
503
|
+
additionalAttributes = {
|
|
504
|
+
...additionalAttributes,
|
|
505
|
+
expiration: groupData.ephemeralDuration.toString()
|
|
506
|
+
};
|
|
507
|
+
}
|
|
353
508
|
const patched = await patchMessageBeforeSending(message);
|
|
354
509
|
if (Array.isArray(patched)) {
|
|
355
510
|
throw new Boom('Per-jid patching is not supported in groups');
|
|
356
511
|
}
|
|
357
512
|
const bytes = encodeWAMessage(patched);
|
|
513
|
+
const groupAddressingMode = additionalAttributes?.['addressing_mode'] || groupData?.addressingMode || 'lid';
|
|
514
|
+
const groupSenderIdentity = groupAddressingMode === 'lid' && meLid ? meLid : meId;
|
|
358
515
|
const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
|
|
359
516
|
group: destinationJid,
|
|
360
517
|
data: bytes,
|
|
361
|
-
meId
|
|
518
|
+
meId: groupSenderIdentity
|
|
362
519
|
});
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
const
|
|
367
|
-
if (!
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
520
|
+
const senderKeyRecipients = [];
|
|
521
|
+
for (const device of devices) {
|
|
522
|
+
const deviceJid = device.jid;
|
|
523
|
+
const hasKey = !!senderKeyMap[deviceJid];
|
|
524
|
+
if ((!hasKey || !!participant) &&
|
|
525
|
+
!isHostedLidUser(deviceJid) &&
|
|
526
|
+
!isHostedPnUser(deviceJid) &&
|
|
527
|
+
device.device !== 99) {
|
|
528
|
+
//todo: revamp all this logic
|
|
529
|
+
// the goal is to follow with what I said above for each group, and instead of a true false map of ids, we can set an array full of those the app has already sent pkmsgs
|
|
530
|
+
senderKeyRecipients.push(deviceJid);
|
|
531
|
+
senderKeyMap[deviceJid] = true;
|
|
371
532
|
}
|
|
372
533
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
if (senderKeyJids.length) {
|
|
376
|
-
logger.debug({ senderKeyJids }, 'sending new sender key');
|
|
534
|
+
if (senderKeyRecipients.length) {
|
|
535
|
+
logger.debug({ senderKeyJids: senderKeyRecipients }, 'sending new sender key');
|
|
377
536
|
const senderKeyMsg = {
|
|
378
537
|
senderKeyDistributionMessage: {
|
|
379
538
|
axolotlSenderKeyDistributionMessage: senderKeyDistributionMessage,
|
|
380
539
|
groupId: destinationJid
|
|
381
540
|
}
|
|
382
541
|
};
|
|
383
|
-
|
|
384
|
-
|
|
542
|
+
const senderKeySessionTargets = senderKeyRecipients;
|
|
543
|
+
await assertSessions(senderKeySessionTargets);
|
|
544
|
+
const result = await createParticipantNodes(senderKeyRecipients, senderKeyMsg, extraAttrs);
|
|
385
545
|
shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || result.shouldIncludeDeviceIdentity;
|
|
386
546
|
participants.push(...result.nodes);
|
|
387
547
|
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
548
|
+
if (isRetryResend) {
|
|
549
|
+
const { type, ciphertext: encryptedContent } = await signalRepository.encryptMessage({
|
|
550
|
+
data: bytes,
|
|
551
|
+
jid: participant?.jid
|
|
552
|
+
});
|
|
553
|
+
binaryNodeContent.push({
|
|
554
|
+
tag: 'enc',
|
|
555
|
+
attrs: {
|
|
556
|
+
v: '2',
|
|
557
|
+
type,
|
|
558
|
+
count: participant.count.toString()
|
|
559
|
+
},
|
|
560
|
+
content: encryptedContent
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
else {
|
|
564
|
+
binaryNodeContent.push({
|
|
565
|
+
tag: 'enc',
|
|
566
|
+
attrs: { v: '2', type: 'skmsg', ...extraAttrs },
|
|
567
|
+
content: ciphertext
|
|
568
|
+
});
|
|
569
|
+
await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } });
|
|
570
|
+
}
|
|
394
571
|
}
|
|
395
572
|
else {
|
|
396
|
-
|
|
573
|
+
// ADDRESSING CONSISTENCY: Match own identity to conversation context
|
|
574
|
+
// TODO: investigate if this is true
|
|
575
|
+
let ownId = meId;
|
|
576
|
+
if (isLid && meLid) {
|
|
577
|
+
ownId = meLid;
|
|
578
|
+
logger.debug({ to: jid, ownId }, 'Using LID identity for @lid conversation');
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
logger.debug({ to: jid, ownId }, 'Using PN identity for @s.whatsapp.net conversation');
|
|
582
|
+
}
|
|
583
|
+
const { user: ownUser } = jidDecode(ownId);
|
|
397
584
|
if (!participant) {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
585
|
+
const targetUserServer = isLid ? 'lid' : 's.whatsapp.net';
|
|
586
|
+
devices.push({
|
|
587
|
+
user,
|
|
588
|
+
device: 0,
|
|
589
|
+
jid: jidEncode(user, targetUserServer, 0) // rajeh, todo: this entire logic is convoluted and weird.
|
|
590
|
+
});
|
|
591
|
+
if (user !== ownUser) {
|
|
592
|
+
const ownUserServer = isLid ? 'lid' : 's.whatsapp.net';
|
|
593
|
+
const ownUserForAddressing = isLid && meLid ? jidDecode(meLid).user : jidDecode(meId).user;
|
|
594
|
+
devices.push({
|
|
595
|
+
user: ownUserForAddressing,
|
|
596
|
+
device: 0,
|
|
597
|
+
jid: jidEncode(ownUserForAddressing, ownUserServer, 0)
|
|
598
|
+
});
|
|
401
599
|
}
|
|
402
600
|
if (additionalAttributes?.['category'] !== 'peer') {
|
|
403
|
-
|
|
404
|
-
devices.
|
|
601
|
+
// Clear placeholders and enumerate actual devices
|
|
602
|
+
devices.length = 0;
|
|
603
|
+
// Use conversation-appropriate sender identity
|
|
604
|
+
const senderIdentity = isLid && meLid
|
|
605
|
+
? jidEncode(jidDecode(meLid)?.user, 'lid', undefined)
|
|
606
|
+
: jidEncode(jidDecode(meId)?.user, 's.whatsapp.net', undefined);
|
|
607
|
+
// Enumerate devices for sender and target with consistent addressing
|
|
608
|
+
const sessionDevices = await getUSyncDevices([senderIdentity, jid], true, false);
|
|
609
|
+
devices.push(...sessionDevices);
|
|
610
|
+
logger.debug({
|
|
611
|
+
deviceCount: devices.length,
|
|
612
|
+
devices: devices.map(d => `${d.user}:${d.device}@${jidDecode(d.jid)?.server}`)
|
|
613
|
+
}, 'Device enumeration complete with unified addressing');
|
|
405
614
|
}
|
|
406
615
|
}
|
|
407
|
-
const
|
|
408
|
-
const
|
|
409
|
-
const
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
616
|
+
const allRecipients = [];
|
|
617
|
+
const meRecipients = [];
|
|
618
|
+
const otherRecipients = [];
|
|
619
|
+
const { user: mePnUser } = jidDecode(meId);
|
|
620
|
+
const { user: meLidUser } = meLid ? jidDecode(meLid) : { user: null };
|
|
621
|
+
for (const { user, jid } of devices) {
|
|
622
|
+
const isExactSenderDevice = jid === meId || (meLid && jid === meLid);
|
|
623
|
+
if (isExactSenderDevice) {
|
|
624
|
+
logger.debug({ jid, meId, meLid }, 'Skipping exact sender device (whatsmeow pattern)');
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
// Check if this is our device (could match either PN or LID user)
|
|
628
|
+
const isMe = user === mePnUser || user === meLidUser;
|
|
413
629
|
if (isMe) {
|
|
414
|
-
|
|
630
|
+
meRecipients.push(jid);
|
|
415
631
|
}
|
|
416
632
|
else {
|
|
417
|
-
|
|
633
|
+
otherRecipients.push(jid);
|
|
418
634
|
}
|
|
419
|
-
|
|
635
|
+
allRecipients.push(jid);
|
|
420
636
|
}
|
|
421
|
-
await assertSessions(
|
|
637
|
+
await assertSessions(allRecipients);
|
|
422
638
|
const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = await Promise.all([
|
|
423
|
-
|
|
424
|
-
createParticipantNodes(
|
|
639
|
+
// For own devices: use DSM if available (1:1 chats only)
|
|
640
|
+
createParticipantNodes(meRecipients, meMsg || message, extraAttrs),
|
|
641
|
+
createParticipantNodes(otherRecipients, message, extraAttrs, meMsg)
|
|
425
642
|
]);
|
|
426
643
|
participants.push(...meNodes);
|
|
427
644
|
participants.push(...otherNodes);
|
|
645
|
+
if (meRecipients.length > 0 || otherRecipients.length > 0) {
|
|
646
|
+
extraAttrs['phash'] = generateParticipantHashV2([...meRecipients, ...otherRecipients]);
|
|
647
|
+
}
|
|
428
648
|
shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2;
|
|
429
649
|
}
|
|
430
650
|
if (participants.length) {
|
|
@@ -446,6 +666,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
446
666
|
tag: 'message',
|
|
447
667
|
attrs: {
|
|
448
668
|
id: msgId,
|
|
669
|
+
to: destinationJid,
|
|
449
670
|
type: getMessageType(message),
|
|
450
671
|
...(additionalAttributes || {})
|
|
451
672
|
},
|
|
@@ -485,13 +706,23 @@ export const makeMessagesSocket = (config) => {
|
|
|
485
706
|
}
|
|
486
707
|
logger.debug({ msgId }, `sending message to ${participants.length} devices`);
|
|
487
708
|
await sendNode(stanza);
|
|
488
|
-
|
|
709
|
+
// Add message to retry cache if enabled
|
|
710
|
+
if (messageRetryManager && !participant) {
|
|
711
|
+
messageRetryManager.addRecentMessage(destinationJid, msgId, message);
|
|
712
|
+
}
|
|
713
|
+
}, meId);
|
|
489
714
|
return msgId;
|
|
490
715
|
};
|
|
491
716
|
const getMessageType = (message) => {
|
|
492
717
|
if (message.pollCreationMessage || message.pollCreationMessageV2 || message.pollCreationMessageV3) {
|
|
493
718
|
return 'poll';
|
|
494
719
|
}
|
|
720
|
+
if (message.eventMessage) {
|
|
721
|
+
return 'event';
|
|
722
|
+
}
|
|
723
|
+
if (getMediaType(message) !== '') {
|
|
724
|
+
return 'media';
|
|
725
|
+
}
|
|
495
726
|
return 'text';
|
|
496
727
|
};
|
|
497
728
|
const getMediaType = (message) => {
|
|
@@ -540,6 +771,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
540
771
|
else if (message.groupInviteMessage) {
|
|
541
772
|
return 'url';
|
|
542
773
|
}
|
|
774
|
+
return '';
|
|
543
775
|
};
|
|
544
776
|
const getPrivacyTokens = async (jids) => {
|
|
545
777
|
const t = unixTimestampSeconds().toString();
|
|
@@ -583,6 +815,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
583
815
|
sendPeerDataOperationMessage,
|
|
584
816
|
createParticipantNodes,
|
|
585
817
|
getUSyncDevices,
|
|
818
|
+
messageRetryManager,
|
|
586
819
|
updateMediaMessage: async (message) => {
|
|
587
820
|
const content = assertMediaContent(message.message);
|
|
588
821
|
const mediaKey = content.mediaKey;
|
|
@@ -647,19 +880,21 @@ export const makeMessagesSocket = (config) => {
|
|
|
647
880
|
thumbnailWidth: linkPreviewImageThumbnailWidth,
|
|
648
881
|
fetchOpts: {
|
|
649
882
|
timeout: 3000,
|
|
650
|
-
...(
|
|
883
|
+
...(httpRequestOptions || {})
|
|
651
884
|
},
|
|
652
885
|
logger,
|
|
653
886
|
uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
|
|
654
887
|
}),
|
|
655
888
|
//TODO: CACHE
|
|
656
889
|
getProfilePicUrl: sock.profilePictureUrl,
|
|
890
|
+
getCallLink: sock.createCallLink,
|
|
657
891
|
upload: waUploadToServer,
|
|
658
892
|
mediaCache: config.mediaCache,
|
|
659
893
|
options: config.options,
|
|
660
|
-
messageId: generateMessageIDV2(sock.user?.id),
|
|
894
|
+
messageId: options.messageId || generateMessageIDV2(sock.user?.id),
|
|
661
895
|
...options
|
|
662
896
|
});
|
|
897
|
+
const isEventMsg = 'event' in content && !!content.event;
|
|
663
898
|
const isDeleteMsg = 'delete' in content && !!content.delete;
|
|
664
899
|
const isEditMsg = 'edit' in content && !!content.edit;
|
|
665
900
|
const isPinMsg = 'pin' in content && !!content.pin;
|
|
@@ -690,8 +925,13 @@ export const makeMessagesSocket = (config) => {
|
|
|
690
925
|
}
|
|
691
926
|
});
|
|
692
927
|
}
|
|
693
|
-
if (
|
|
694
|
-
|
|
928
|
+
else if (isEventMsg) {
|
|
929
|
+
additionalNodes.push({
|
|
930
|
+
tag: 'meta',
|
|
931
|
+
attrs: {
|
|
932
|
+
event_type: 'creation'
|
|
933
|
+
}
|
|
934
|
+
});
|
|
695
935
|
}
|
|
696
936
|
await relayMessage(jid, fullMsg.message, {
|
|
697
937
|
messageId: fullMsg.key.id,
|