@ryuu-reinzz/baileys 3.5.0 → 5.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/README.md +30 -25
- package/WAProto/fix-imports.js +22 -18
- package/WAProto/index.js +22 -18
- package/lib/Defaults/index.js +10 -9
- package/lib/Signal/libsignal.js +46 -19
- package/lib/Signal/lid-mapping.js +6 -0
- package/lib/Socket/chats.js +241 -39
- package/lib/Socket/groups.js +20 -0
- package/lib/Socket/messages-recv.js +736 -314
- package/lib/Socket/messages-send.js +279 -129
- package/lib/Socket/newsletter.js +2 -2
- package/lib/Socket/socket.js +56 -25
- package/lib/Types/{Newsletter.js → Mex.js} +9 -3
- package/lib/Types/State.js +43 -0
- package/lib/Types/index.js +1 -1
- package/lib/Utils/auth-utils.js +12 -0
- package/lib/Utils/chat-utils.js +80 -20
- package/lib/Utils/companion-reg-client-utils.js +35 -0
- package/lib/Utils/decode-wa-message.js +34 -0
- package/lib/Utils/event-buffer.js +49 -1
- package/lib/Utils/generics.js +12 -3
- package/lib/Utils/history.js +12 -9
- package/lib/Utils/identity-change-handler.js +1 -0
- package/lib/Utils/index.js +3 -1
- package/lib/Utils/link-preview.js +2 -2
- package/lib/Utils/message-retry-manager.js +40 -0
- package/lib/Utils/messages-media.js +21 -7
- package/lib/Utils/messages.js +28 -5
- package/lib/Utils/offline-node-processor.js +40 -0
- package/lib/Utils/process-message.js +103 -1
- package/lib/Utils/signal.js +42 -0
- package/lib/Utils/stanza-ack.js +38 -0
- package/lib/Utils/sync-action-utils.js +1 -0
- package/lib/Utils/tc-token-utils.js +149 -4
- package/lib/Utils/validate-connection.js +3 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +26 -3
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -0
- package/lib/WAUSync/Protocols/index.js +1 -0
- package/lib/WAUSync/USyncQuery.js +6 -2
- package/lib/WAUSync/USyncUser.js +8 -0
- package/package.json +39 -12
|
@@ -13,8 +13,10 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
aggregateMessageKeysNotFromMe,
|
|
15
15
|
assertMediaContent,
|
|
16
|
+
assertMeId,
|
|
16
17
|
bindWaitForEvent,
|
|
17
18
|
decryptMediaRetryData,
|
|
19
|
+
DEF_MEDIA_HOST,
|
|
18
20
|
encodeNewsletterMessage,
|
|
19
21
|
encodeSignedDeviceIdentity,
|
|
20
22
|
encodeWAMessage,
|
|
@@ -36,29 +38,41 @@ import {
|
|
|
36
38
|
downloadContentFromMessage,
|
|
37
39
|
prepareWAMessageMedia,
|
|
38
40
|
generateMessageID
|
|
39
|
-
} from '
|
|
41
|
+
} from '../index.js';
|
|
40
42
|
import {
|
|
41
43
|
getUrlInfo
|
|
42
44
|
} from '../Utils/link-preview.js';
|
|
43
45
|
import {
|
|
44
|
-
makeKeyedMutex
|
|
46
|
+
makeKeyedMutex,
|
|
47
|
+
makeMutex
|
|
45
48
|
} from '../Utils/make-mutex.js';
|
|
46
49
|
import {
|
|
47
50
|
getMessageReportingToken,
|
|
48
51
|
shouldIncludeReportingToken
|
|
49
52
|
} from '../Utils/reporting-utils.js';
|
|
53
|
+
import {
|
|
54
|
+
buildMergedTcTokenIndexWrite,
|
|
55
|
+
isTcTokenExpired,
|
|
56
|
+
resolveIssuanceJid,
|
|
57
|
+
resolveTcTokenJid,
|
|
58
|
+
shouldSendNewTcToken,
|
|
59
|
+
storeTcTokensFromIqResult
|
|
60
|
+
} from '../Utils/tc-token-utils.js';
|
|
50
61
|
import {
|
|
51
62
|
areJidsSameUser,
|
|
52
63
|
getBinaryNodeChild,
|
|
53
64
|
getBinaryNodeChildren,
|
|
54
65
|
isHostedLidUser,
|
|
55
66
|
isHostedPnUser,
|
|
67
|
+
isJidBot,
|
|
56
68
|
isJidGroup,
|
|
69
|
+
isJidMetaAI,
|
|
57
70
|
isLidUser,
|
|
58
71
|
isPnUser,
|
|
59
72
|
jidDecode,
|
|
60
73
|
jidEncode,
|
|
61
74
|
jidNormalizedUser,
|
|
75
|
+
PSA_WID,
|
|
62
76
|
S_WHATSAPP_NET
|
|
63
77
|
} from '../WABinary/index.js';
|
|
64
78
|
import {
|
|
@@ -100,22 +114,30 @@ export const makeMessagesSocket = (config) => {
|
|
|
100
114
|
fetchPrivacySettings,
|
|
101
115
|
sendNode,
|
|
102
116
|
groupMetadata,
|
|
103
|
-
groupToggleEphemeral
|
|
117
|
+
groupToggleEphemeral,
|
|
118
|
+
registerSocketEndHandler
|
|
104
119
|
} = sock;
|
|
120
|
+
const getLIDForPN = signalRepository.lidMapping.getLIDForPN.bind(signalRepository.lidMapping);
|
|
121
|
+
/**
|
|
122
|
+
* Set of tctoken storage JIDs with a fire-and-forget `issuePrivacyTokens` IQ in flight.
|
|
123
|
+
* Prevents duplicate IQs from rapid back-to-back sends before `senderTimestamp` persists.
|
|
124
|
+
* Entries are always removed in `.finally()`, so the set is bounded by concurrency.
|
|
125
|
+
*/
|
|
126
|
+
const inFlightTcTokenIssuance = new Set();
|
|
105
127
|
const userDevicesCache = config.userDevicesCache ||
|
|
106
128
|
new NodeCache({
|
|
107
129
|
stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES, // 5 minutes
|
|
108
130
|
useClones: false
|
|
109
131
|
});
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
useClones: false
|
|
113
|
-
});
|
|
132
|
+
/** Serializes writes to userDevicesCache across USync refresh and device-notification handling. */
|
|
133
|
+
const devicesMutex = makeMutex();
|
|
114
134
|
// Initialize message retry manager if enabled
|
|
115
135
|
const messageRetryManager = enableRecentMessageCache ? new MessageRetryManager(logger, maxMsgRetryCount) : null;
|
|
116
136
|
// Prevent race conditions in Signal session encryption by user
|
|
117
137
|
const encryptionMutex = makeKeyedMutex();
|
|
118
138
|
let mediaConn;
|
|
139
|
+
/** Per-socket media host; updated whenever media_conn is fetched. Defaults to the public WhatsApp host. */
|
|
140
|
+
let mediaHost = DEF_MEDIA_HOST;
|
|
119
141
|
const refreshMediaConn = async (forceGet = false) => {
|
|
120
142
|
const media = await mediaConn;
|
|
121
143
|
if (!media || forceGet || new Date().getTime() - media.fetchDate.getTime() > media.ttl * 1000) {
|
|
@@ -146,6 +168,9 @@ export const makeMessagesSocket = (config) => {
|
|
|
146
168
|
fetchDate: new Date()
|
|
147
169
|
};
|
|
148
170
|
logger.debug('fetched media conn');
|
|
171
|
+
if (node.hosts[0]) {
|
|
172
|
+
mediaHost = node.hosts[0].hostname;
|
|
173
|
+
}
|
|
149
174
|
return node;
|
|
150
175
|
})();
|
|
151
176
|
}
|
|
@@ -340,18 +365,20 @@ export const makeMessagesSocket = (config) => {
|
|
|
340
365
|
}, 'Processed device with LID priority');
|
|
341
366
|
}
|
|
342
367
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
key,
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
368
|
+
await devicesMutex.mutex(async () => {
|
|
369
|
+
if (userDevicesCache.mset) {
|
|
370
|
+
// if the cache supports mset, we can set all devices in one go
|
|
371
|
+
await userDevicesCache.mset(Object.entries(deviceMap).map(([key, value]) => ({
|
|
372
|
+
key,
|
|
373
|
+
value
|
|
374
|
+
})));
|
|
375
|
+
} else {
|
|
376
|
+
for (const key in deviceMap) {
|
|
377
|
+
if (deviceMap[key])
|
|
378
|
+
await userDevicesCache.set(key, deviceMap[key]);
|
|
379
|
+
}
|
|
353
380
|
}
|
|
354
|
-
}
|
|
381
|
+
});
|
|
355
382
|
const userDeviceUpdates = {};
|
|
356
383
|
for (const [userId, devices] of Object.entries(deviceMap)) {
|
|
357
384
|
if (devices && devices.length > 0) {
|
|
@@ -400,24 +427,15 @@ export const makeMessagesSocket = (config) => {
|
|
|
400
427
|
};
|
|
401
428
|
const assertSessions = async (jids, force) => {
|
|
402
429
|
let didFetchNewSession = false;
|
|
403
|
-
const uniqueJids = [...new Set(jids)];
|
|
430
|
+
const uniqueJids = [...new Set(jids)];
|
|
404
431
|
const jidsRequiringFetch = [];
|
|
405
432
|
logger.debug({
|
|
406
433
|
jids
|
|
407
434
|
}, 'assertSessions call with jids');
|
|
408
|
-
// Check peerSessionsCache and validate sessions using libsignal loadSession
|
|
409
435
|
for (const jid of uniqueJids) {
|
|
410
|
-
|
|
411
|
-
const cachedSession = peerSessionsCache.get(signalId);
|
|
412
|
-
if (cachedSession !== undefined) {
|
|
413
|
-
if (cachedSession && !force) {
|
|
414
|
-
continue; // Session exists in cache
|
|
415
|
-
}
|
|
416
|
-
} else {
|
|
436
|
+
if (!force) {
|
|
417
437
|
const sessionValidation = await signalRepository.validateSession(jid);
|
|
418
|
-
|
|
419
|
-
peerSessionsCache.set(signalId, hasSession);
|
|
420
|
-
if (hasSession && !force) {
|
|
438
|
+
if (sessionValidation.exists) {
|
|
421
439
|
continue;
|
|
422
440
|
}
|
|
423
441
|
}
|
|
@@ -458,11 +476,6 @@ export const makeMessagesSocket = (config) => {
|
|
|
458
476
|
});
|
|
459
477
|
await parseAndInjectE2ESessions(result, signalRepository);
|
|
460
478
|
didFetchNewSession = true;
|
|
461
|
-
// Cache fetched sessions using wire JIDs
|
|
462
|
-
for (const wireJid of wireJids) {
|
|
463
|
-
const signalId = signalRepository.jidToSignalProtocolAddress(wireJid);
|
|
464
|
-
peerSessionsCache.set(signalId, true);
|
|
465
|
-
}
|
|
466
479
|
}
|
|
467
480
|
return didFetchNewSession;
|
|
468
481
|
};
|
|
@@ -594,7 +607,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
594
607
|
useCachedGroupMetadata,
|
|
595
608
|
statusJidList
|
|
596
609
|
}) => {
|
|
597
|
-
const meId = authState.creds
|
|
610
|
+
const meId = assertMeId(authState.creds);
|
|
598
611
|
const meLid = authState.creds.me?.lid;
|
|
599
612
|
const isRetryResend = Boolean(participant?.jid);
|
|
600
613
|
let shouldIncludeDeviceIdentity = isRetryResend;
|
|
@@ -889,14 +902,49 @@ export const makeMessagesSocket = (config) => {
|
|
|
889
902
|
if (isRetryResend) {
|
|
890
903
|
const isParticipantLid = isLidUser(participant.jid);
|
|
891
904
|
const isMe = areJidsSameUser(participant.jid, isParticipantLid ? meLid : meId);
|
|
905
|
+
let messageToSend = message;
|
|
906
|
+
if (isGroupOrStatus) {
|
|
907
|
+
let groupSenderIdentity;
|
|
908
|
+
if (meLid && (await signalRepository.hasSenderKey({
|
|
909
|
+
group: destinationJid,
|
|
910
|
+
meId: meLid
|
|
911
|
+
}))) {
|
|
912
|
+
groupSenderIdentity = meLid;
|
|
913
|
+
} else if (await signalRepository.hasSenderKey({
|
|
914
|
+
group: destinationJid,
|
|
915
|
+
meId
|
|
916
|
+
})) {
|
|
917
|
+
groupSenderIdentity = meId;
|
|
918
|
+
}
|
|
919
|
+
if (groupSenderIdentity) {
|
|
920
|
+
try {
|
|
921
|
+
const skdm = await signalRepository.getSenderKeyDistributionMessage({
|
|
922
|
+
group: destinationJid,
|
|
923
|
+
meId: groupSenderIdentity
|
|
924
|
+
});
|
|
925
|
+
messageToSend = {
|
|
926
|
+
...message,
|
|
927
|
+
senderKeyDistributionMessage: {
|
|
928
|
+
groupId: destinationJid,
|
|
929
|
+
axolotlSenderKeyDistributionMessage: skdm
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
} catch (err) {
|
|
933
|
+
logger.warn({
|
|
934
|
+
err,
|
|
935
|
+
jid: destinationJid
|
|
936
|
+
}, 'failed to build SKDM for retry, sending without it');
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
}
|
|
892
940
|
const encodedMessageToSend = isMe ?
|
|
893
941
|
encodeWAMessage({
|
|
894
942
|
deviceSentMessage: {
|
|
895
943
|
destinationJid,
|
|
896
|
-
message
|
|
944
|
+
message: messageToSend
|
|
897
945
|
}
|
|
898
946
|
}) :
|
|
899
|
-
encodeWAMessage(
|
|
947
|
+
encodeWAMessage(messageToSend);
|
|
900
948
|
const {
|
|
901
949
|
type,
|
|
902
950
|
ciphertext: encryptedContent
|
|
@@ -992,9 +1040,41 @@ export const makeMessagesSocket = (config) => {
|
|
|
992
1040
|
}, 'failed to attach reporting token');
|
|
993
1041
|
}
|
|
994
1042
|
}
|
|
995
|
-
|
|
996
|
-
const
|
|
997
|
-
|
|
1043
|
+
// WA Web never attaches tctoken to peer (AppStateSync) messages — server rejects with 479
|
|
1044
|
+
const isPeerMessage = additionalAttributes?.['category'] === 'peer';
|
|
1045
|
+
const is1on1Send = !isGroup && !isRetryResend && !isStatus && !isNewsletter && !isPeerMessage;
|
|
1046
|
+
// Resolve destination to LID for tctoken storage — matches Signal session key pattern
|
|
1047
|
+
const tcTokenJid = is1on1Send ? await resolveTcTokenJid(destinationJid, getLIDForPN) : destinationJid;
|
|
1048
|
+
const contactTcTokenData = is1on1Send ? await authState.keys.get('tctoken', [tcTokenJid]) : {};
|
|
1049
|
+
const existingTokenEntry = contactTcTokenData[tcTokenJid];
|
|
1050
|
+
let tcTokenBuffer = existingTokenEntry?.token;
|
|
1051
|
+
// Treat expired tokens the same as missing — clear from cache
|
|
1052
|
+
if (tcTokenBuffer?.length && isTcTokenExpired(existingTokenEntry?.timestamp)) {
|
|
1053
|
+
logger.debug({
|
|
1054
|
+
jid: destinationJid,
|
|
1055
|
+
timestamp: existingTokenEntry?.timestamp
|
|
1056
|
+
}, 'tctoken expired, clearing');
|
|
1057
|
+
tcTokenBuffer = undefined;
|
|
1058
|
+
// Preserve senderTimestamp so the fire-and-forget issuance dedupe survives cleanup.
|
|
1059
|
+
const cleared = existingTokenEntry?.senderTimestamp !== undefined ? {
|
|
1060
|
+
token: Buffer.alloc(0),
|
|
1061
|
+
senderTimestamp: existingTokenEntry.senderTimestamp
|
|
1062
|
+
} :
|
|
1063
|
+
null;
|
|
1064
|
+
try {
|
|
1065
|
+
await authState.keys.set({
|
|
1066
|
+
tctoken: {
|
|
1067
|
+
[tcTokenJid]: cleared
|
|
1068
|
+
}
|
|
1069
|
+
});
|
|
1070
|
+
} catch (err) {
|
|
1071
|
+
logger.debug({
|
|
1072
|
+
jid: destinationJid,
|
|
1073
|
+
err: err?.message
|
|
1074
|
+
}, 'failed to persist tctoken expiry cleanup');
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
if (tcTokenBuffer?.length && sock.serverProps.privacyTokenOn1to1) {
|
|
998
1078
|
;
|
|
999
1079
|
stanza.content.push({
|
|
1000
1080
|
tag: 'tctoken',
|
|
@@ -1010,6 +1090,51 @@ export const makeMessagesSocket = (config) => {
|
|
|
1010
1090
|
msgId
|
|
1011
1091
|
}, `sending message to ${participants.length} devices`);
|
|
1012
1092
|
await sendNode(stanza);
|
|
1093
|
+
// Fire-and-forget: issue our token to the contact AFTER message send.
|
|
1094
|
+
// WA Web skips protocol messages and PSA/bot contacts (TcTokenChatAction: isRegularUser)
|
|
1095
|
+
const isProtocolMsg = !!normalizeMessageContent(message)?.protocolMessage;
|
|
1096
|
+
const isBotOrPSA = destinationJid === PSA_WID || isJidBot(destinationJid) || isJidMetaAI(destinationJid);
|
|
1097
|
+
if (is1on1Send &&
|
|
1098
|
+
!isProtocolMsg &&
|
|
1099
|
+
!isBotOrPSA &&
|
|
1100
|
+
shouldSendNewTcToken(existingTokenEntry?.senderTimestamp) &&
|
|
1101
|
+
!inFlightTcTokenIssuance.has(tcTokenJid)) {
|
|
1102
|
+
inFlightTcTokenIssuance.add(tcTokenJid);
|
|
1103
|
+
const issueTimestamp = unixTimestampSeconds();
|
|
1104
|
+
const getPNForLID = signalRepository.lidMapping.getPNForLID.bind(signalRepository.lidMapping);
|
|
1105
|
+
resolveIssuanceJid(destinationJid, sock.serverProps.lidTrustedTokenIssueToLid, getLIDForPN, getPNForLID)
|
|
1106
|
+
.then(issueJid => issuePrivacyTokens([issueJid], issueTimestamp))
|
|
1107
|
+
.then(async (result) => {
|
|
1108
|
+
await storeTcTokensFromIqResult({
|
|
1109
|
+
result,
|
|
1110
|
+
fallbackJid: tcTokenJid,
|
|
1111
|
+
keys: authState.keys,
|
|
1112
|
+
getLIDForPN
|
|
1113
|
+
});
|
|
1114
|
+
const currentData = await authState.keys.get('tctoken', [tcTokenJid]);
|
|
1115
|
+
const currentEntry = currentData[tcTokenJid];
|
|
1116
|
+
const indexWrite = await buildMergedTcTokenIndexWrite(authState.keys, [tcTokenJid]);
|
|
1117
|
+
await authState.keys.set({
|
|
1118
|
+
tctoken: {
|
|
1119
|
+
[tcTokenJid]: {
|
|
1120
|
+
token: Buffer.alloc(0),
|
|
1121
|
+
...currentEntry,
|
|
1122
|
+
senderTimestamp: issueTimestamp
|
|
1123
|
+
},
|
|
1124
|
+
...indexWrite
|
|
1125
|
+
}
|
|
1126
|
+
});
|
|
1127
|
+
})
|
|
1128
|
+
.catch(err => {
|
|
1129
|
+
logger.debug({
|
|
1130
|
+
jid: destinationJid,
|
|
1131
|
+
err: err?.message
|
|
1132
|
+
}, 'fire-and-forget tctoken issuance failed');
|
|
1133
|
+
})
|
|
1134
|
+
.finally(() => {
|
|
1135
|
+
inFlightTcTokenIssuance.delete(tcTokenJid);
|
|
1136
|
+
});
|
|
1137
|
+
}
|
|
1013
1138
|
// Add message to retry cache if enabled
|
|
1014
1139
|
if (messageRetryManager && !participant) {
|
|
1015
1140
|
messageRetryManager.addRecentMessage(destinationJid, msgId, message);
|
|
@@ -1072,8 +1197,8 @@ export const makeMessagesSocket = (config) => {
|
|
|
1072
1197
|
}
|
|
1073
1198
|
return '';
|
|
1074
1199
|
};
|
|
1075
|
-
const
|
|
1076
|
-
const t = unixTimestampSeconds().toString();
|
|
1200
|
+
const issuePrivacyTokens = async (jids, timestamp) => {
|
|
1201
|
+
const t = (timestamp ?? unixTimestampSeconds()).toString();
|
|
1077
1202
|
const result = await query({
|
|
1078
1203
|
tag: 'iq',
|
|
1079
1204
|
attrs: {
|
|
@@ -1097,17 +1222,42 @@ export const makeMessagesSocket = (config) => {
|
|
|
1097
1222
|
return result;
|
|
1098
1223
|
};
|
|
1099
1224
|
const waUploadToServer = getWAUploadToServer(config, refreshMediaConn);
|
|
1100
|
-
const waitForMsgMediaUpdate = bindWaitForEvent(ev, 'messages.media-update');
|
|
1101
|
-
sock
|
|
1102
|
-
|
|
1225
|
+
const waitForMsgMediaUpdate = bindWaitForEvent(ev, 'messages.media-update');
|
|
1226
|
+
Object.defineProperties(sock, {
|
|
1227
|
+
waUploadToServer: {
|
|
1228
|
+
value: waUploadToServer,
|
|
1229
|
+
writable: false,
|
|
1230
|
+
enumerable: false,
|
|
1231
|
+
configurable: true
|
|
1232
|
+
},
|
|
1233
|
+
relayMessage: {
|
|
1234
|
+
value: relayMessage,
|
|
1235
|
+
writable: false,
|
|
1236
|
+
enumerable: false,
|
|
1237
|
+
configurable: true
|
|
1238
|
+
}
|
|
1239
|
+
});
|
|
1240
|
+
registerSocketEndHandler(() => {
|
|
1241
|
+
if (!config.userDevicesCache && userDevicesCache.close) {
|
|
1242
|
+
userDevicesCache.close();
|
|
1243
|
+
}
|
|
1244
|
+
mediaConn = undefined;
|
|
1245
|
+
if (messageRetryManager) {
|
|
1246
|
+
messageRetryManager.clear();
|
|
1247
|
+
}
|
|
1248
|
+
});
|
|
1103
1249
|
return {
|
|
1104
1250
|
...sock,
|
|
1105
|
-
|
|
1251
|
+
userDevicesCache,
|
|
1252
|
+
devicesMutex,
|
|
1253
|
+
issuePrivacyTokens,
|
|
1106
1254
|
assertSessions,
|
|
1107
1255
|
sendReceipt,
|
|
1108
1256
|
sendReceipts,
|
|
1109
1257
|
readMessages,
|
|
1110
1258
|
refreshMediaConn,
|
|
1259
|
+
// Function (not getter) so the spread in chats.ts preserves the live closure binding.
|
|
1260
|
+
getMediaHost: () => mediaHost,
|
|
1111
1261
|
fetchPrivacySettings,
|
|
1112
1262
|
sendPeerDataOperationMessage,
|
|
1113
1263
|
createParticipantNodes,
|
|
@@ -1138,7 +1288,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
1138
1288
|
});
|
|
1139
1289
|
}
|
|
1140
1290
|
content.directPath = media.directPath;
|
|
1141
|
-
content.url = getUrlFromDirectPath(content.directPath);
|
|
1291
|
+
content.url = getUrlFromDirectPath(content.directPath, mediaHost);
|
|
1142
1292
|
logger.debug({
|
|
1143
1293
|
directPath: media.directPath,
|
|
1144
1294
|
key: result.key
|
|
@@ -1163,92 +1313,92 @@ export const makeMessagesSocket = (config) => {
|
|
|
1163
1313
|
return message;
|
|
1164
1314
|
},
|
|
1165
1315
|
sendMessage: async (jid, content, options = {}) => {
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
} else {
|
|
1169
|
-
const userJid = authState.creds.me.id;
|
|
1170
|
-
if (typeof content === 'object' &&
|
|
1171
|
-
'disappearingMessagesInChat' in content &&
|
|
1172
|
-
typeof content['disappearingMessagesInChat'] !== 'undefined' &&
|
|
1173
|
-
isJidGroup(jid)) {
|
|
1174
|
-
const {
|
|
1175
|
-
disappearingMessagesInChat
|
|
1176
|
-
} = content;
|
|
1177
|
-
const value = typeof disappearingMessagesInChat === 'boolean' ?
|
|
1178
|
-
disappearingMessagesInChat ?
|
|
1179
|
-
WA_DEFAULT_EPHEMERAL :
|
|
1180
|
-
0 :
|
|
1181
|
-
disappearingMessagesInChat;
|
|
1182
|
-
await groupToggleEphemeral(jid, value);
|
|
1316
|
+
if (Array.isArray(content.buttons)) {
|
|
1317
|
+
return await sock.sendButton(jid, content, options);
|
|
1183
1318
|
} else {
|
|
1184
|
-
const
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1319
|
+
const userJid = authState.creds.me.id;
|
|
1320
|
+
if (typeof content === 'object' &&
|
|
1321
|
+
'disappearingMessagesInChat' in content &&
|
|
1322
|
+
typeof content['disappearingMessagesInChat'] !== 'undefined' &&
|
|
1323
|
+
isJidGroup(jid)) {
|
|
1324
|
+
const {
|
|
1325
|
+
disappearingMessagesInChat
|
|
1326
|
+
} = content;
|
|
1327
|
+
const value = typeof disappearingMessagesInChat === 'boolean' ?
|
|
1328
|
+
disappearingMessagesInChat ?
|
|
1329
|
+
WA_DEFAULT_EPHEMERAL :
|
|
1330
|
+
0 :
|
|
1331
|
+
disappearingMessagesInChat;
|
|
1332
|
+
await groupToggleEphemeral(jid, value);
|
|
1333
|
+
} else {
|
|
1334
|
+
const fullMsg = await generateWAMessage(jid, content, {
|
|
1193
1335
|
logger,
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
// required for delete
|
|
1213
|
-
if (isDeleteMsg) {
|
|
1214
|
-
// if the chat is a group, and I am not the author, then delete the message as an admin
|
|
1215
|
-
if (isJidGroup(content.delete?.remoteJid) && !content.delete?.fromMe) {
|
|
1216
|
-
additionalAttributes.edit = '8';
|
|
1217
|
-
} else {
|
|
1218
|
-
additionalAttributes.edit = '7';
|
|
1219
|
-
}
|
|
1220
|
-
} else if (isEditMsg) {
|
|
1221
|
-
additionalAttributes.edit = '1';
|
|
1222
|
-
} else if (isPinMsg) {
|
|
1223
|
-
additionalAttributes.edit = '2';
|
|
1224
|
-
} else if (isPollMessage) {
|
|
1225
|
-
additionalNodes.push({
|
|
1226
|
-
tag: 'meta',
|
|
1227
|
-
attrs: {
|
|
1228
|
-
polltype: 'creation'
|
|
1229
|
-
}
|
|
1336
|
+
userJid,
|
|
1337
|
+
getUrlInfo: text => getUrlInfo(text, {
|
|
1338
|
+
thumbnailWidth: linkPreviewImageThumbnailWidth,
|
|
1339
|
+
fetchOpts: {
|
|
1340
|
+
timeout: 3000,
|
|
1341
|
+
...(httpRequestOptions || {})
|
|
1342
|
+
},
|
|
1343
|
+
logger,
|
|
1344
|
+
uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
|
|
1345
|
+
}),
|
|
1346
|
+
//TODO: CACHE
|
|
1347
|
+
getProfilePicUrl: sock.profilePictureUrl,
|
|
1348
|
+
getCallLink: sock.createCallLink,
|
|
1349
|
+
upload: waUploadToServer,
|
|
1350
|
+
mediaCache: config.mediaCache,
|
|
1351
|
+
options: config.options,
|
|
1352
|
+
messageId: generateMessageIDV2(sock.user?.id),
|
|
1353
|
+
...options
|
|
1230
1354
|
});
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1355
|
+
const isEventMsg = 'event' in content && !!content.event;
|
|
1356
|
+
const isDeleteMsg = 'delete' in content && !!content.delete;
|
|
1357
|
+
const isEditMsg = 'edit' in content && !!content.edit;
|
|
1358
|
+
const isPinMsg = 'pin' in content && !!content.pin;
|
|
1359
|
+
const isPollMessage = 'poll' in content && !!content.poll;
|
|
1360
|
+
const additionalAttributes = {};
|
|
1361
|
+
const additionalNodes = [];
|
|
1362
|
+
// required for delete
|
|
1363
|
+
if (isDeleteMsg) {
|
|
1364
|
+
// if the chat is a group, and I am not the author, then delete the message as an admin
|
|
1365
|
+
if (isJidGroup(content.delete?.remoteJid) && !content.delete?.fromMe) {
|
|
1366
|
+
additionalAttributes.edit = '8';
|
|
1367
|
+
} else {
|
|
1368
|
+
additionalAttributes.edit = '7';
|
|
1236
1369
|
}
|
|
1370
|
+
} else if (isEditMsg) {
|
|
1371
|
+
additionalAttributes.edit = '1';
|
|
1372
|
+
} else if (isPinMsg) {
|
|
1373
|
+
additionalAttributes.edit = '2';
|
|
1374
|
+
} else if (isPollMessage) {
|
|
1375
|
+
additionalNodes.push({
|
|
1376
|
+
tag: 'meta',
|
|
1377
|
+
attrs: {
|
|
1378
|
+
polltype: 'creation'
|
|
1379
|
+
}
|
|
1380
|
+
});
|
|
1381
|
+
} else if (isEventMsg) {
|
|
1382
|
+
additionalNodes.push({
|
|
1383
|
+
tag: 'meta',
|
|
1384
|
+
attrs: {
|
|
1385
|
+
event_type: 'creation'
|
|
1386
|
+
}
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
await relayMessage(jid, fullMsg.message, {
|
|
1390
|
+
messageId: fullMsg.key.id,
|
|
1391
|
+
useCachedGroupMetadata: options.useCachedGroupMetadata,
|
|
1392
|
+
additionalAttributes,
|
|
1393
|
+
statusJidList: options.statusJidList,
|
|
1394
|
+
additionalNodes
|
|
1237
1395
|
});
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
additionalNodes
|
|
1245
|
-
});
|
|
1246
|
-
if (config.emitOwnEvents) {
|
|
1247
|
-
process.nextTick(async () => {
|
|
1248
|
-
await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
|
|
1249
|
-
});
|
|
1250
|
-
}
|
|
1251
|
-
return fullMsg;
|
|
1396
|
+
if (config.emitOwnEvents) {
|
|
1397
|
+
process.nextTick(async () => {
|
|
1398
|
+
await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
|
|
1399
|
+
});
|
|
1400
|
+
}
|
|
1401
|
+
return fullMsg;
|
|
1252
1402
|
}
|
|
1253
1403
|
}
|
|
1254
1404
|
}
|
package/lib/Socket/newsletter.js
CHANGED
|
@@ -79,10 +79,10 @@ export const makeNewsletterSocket = (config) => {
|
|
|
79
79
|
return parseNewsletterMetadata(result);
|
|
80
80
|
},
|
|
81
81
|
newsletterFollow: (jid) => {
|
|
82
|
-
return executeWMexQuery({ newsletter_id: jid }, QueryIds.FOLLOW, XWAPaths.
|
|
82
|
+
return executeWMexQuery({ newsletter_id: jid }, QueryIds.FOLLOW, XWAPaths.xwa2_newsletter_join_v2);
|
|
83
83
|
},
|
|
84
84
|
newsletterUnfollow: (jid) => {
|
|
85
|
-
return executeWMexQuery({ newsletter_id: jid }, QueryIds.UNFOLLOW, XWAPaths.
|
|
85
|
+
return executeWMexQuery({ newsletter_id: jid }, QueryIds.UNFOLLOW, XWAPaths.xwa2_newsletter_leave_v2);
|
|
86
86
|
},
|
|
87
87
|
newsletterMute: (jid) => {
|
|
88
88
|
return executeWMexQuery({ newsletter_id: jid }, QueryIds.MUTE, XWAPaths.xwa2_newsletter_mute_v2);
|