@dyyxyzz/baileys-mod 6.0.53 → 7.0.4
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 +21 -0
- package/WAProto/WAProto.proto +5311 -0
- package/WAProto/index.js +65801 -141371
- package/lib/Defaults/index.js +117 -141
- package/lib/Defaults/index.js.bak +123 -0
- package/lib/KeyDB/BinarySearch.js +20 -0
- package/lib/KeyDB/KeyedDB.js +167 -0
- package/lib/KeyDB/index.js +4 -0
- package/lib/Signal/Group/ciphertext-message.js +12 -14
- package/lib/Signal/Group/group-session-builder.js +10 -42
- package/lib/Signal/Group/group_cipher.js +75 -87
- package/lib/Signal/Group/index.js +13 -57
- package/lib/Signal/Group/keyhelper.js +17 -52
- package/lib/Signal/Group/sender-chain-key.js +27 -33
- package/lib/Signal/Group/sender-key-distribution-message.js +62 -63
- package/lib/Signal/Group/sender-key-message.js +65 -66
- package/lib/Signal/Group/sender-key-name.js +45 -44
- package/lib/Signal/Group/sender-key-record.js +39 -49
- package/lib/Signal/Group/sender-key-state.js +80 -93
- package/lib/Signal/Group/sender-message-key.js +27 -28
- package/lib/Signal/libsignal.js +313 -163
- package/lib/Signal/lid-mapping.js +155 -0
- package/lib/Socket/Client/index.js +4 -19
- package/lib/Socket/Client/types.js +13 -0
- package/lib/Socket/Client/websocket.js +52 -0
- package/lib/Socket/Client/websocket.js.bak +53 -0
- package/lib/Socket/business.js +359 -242
- package/lib/Socket/chats.js +839 -943
- package/lib/Socket/communities.js +413 -0
- package/lib/Socket/groups.js +304 -309
- package/lib/Socket/index.js +15 -10
- package/lib/Socket/messages-recv.js +1107 -1054
- package/lib/Socket/messages-send.js +639 -449
- package/lib/Socket/mex.js +45 -0
- package/lib/Socket/newsletter.js +197 -311
- package/lib/Socket/socket.js +5 -3
- package/lib/Store/index.js +6 -10
- package/lib/Store/make-cache-manager-store.js +73 -81
- package/lib/Store/make-in-memory-store.js +286 -423
- package/lib/Store/make-ordered-dictionary.js +77 -79
- package/lib/Store/object-repository.js +24 -26
- package/lib/Types/Auth.js +3 -2
- package/lib/Types/Bussines.js +3 -0
- package/lib/Types/Call.js +3 -2
- package/lib/Types/Chat.js +9 -4
- package/lib/Types/Contact.js +3 -2
- package/lib/Types/Events.js +3 -2
- package/lib/Types/GroupMetadata.js +3 -2
- package/lib/Types/Label.js +24 -26
- package/lib/Types/LabelAssociation.js +6 -8
- package/lib/Types/Message.js +12 -9
- package/lib/Types/Newsletter.js +33 -38
- package/lib/Types/Newsletter.js.bak +33 -0
- package/lib/Types/Product.js +3 -2
- package/lib/Types/Signal.js +3 -2
- package/lib/Types/Socket.js +4 -2
- package/lib/Types/State.js +11 -2
- package/lib/Types/USync.js +3 -2
- package/lib/Types/index.js +27 -41
- package/lib/Utils/auth-utils.js +211 -198
- package/lib/Utils/baileys-event-stream.js +42 -61
- package/lib/Utils/browser-utils.js +5 -1
- package/lib/Utils/business.js +213 -214
- package/lib/Utils/chat-utils.js +703 -689
- package/lib/Utils/crypto.js +112 -133
- package/lib/Utils/decode-wa-message.js +252 -183
- package/lib/Utils/event-buffer.js +510 -496
- package/lib/Utils/generics.js +319 -392
- package/lib/Utils/history.js +83 -92
- package/lib/Utils/index.js +21 -33
- package/lib/Utils/link-preview.js +71 -83
- package/lib/Utils/logger.js +5 -7
- package/lib/Utils/lt-hash.js +40 -46
- package/lib/Utils/make-mutex.js +34 -41
- package/lib/Utils/message-retry-manager.js +113 -0
- package/lib/Utils/messages-media.js +550 -768
- package/lib/Utils/messages.js +371 -270
- package/lib/Utils/noise-handler.js +138 -149
- package/lib/Utils/pre-key-manager.js +85 -0
- package/lib/Utils/process-message.js +323 -303
- package/lib/Utils/signal.js +149 -141
- package/lib/Utils/use-multi-file-auth-state.js +95 -103
- package/lib/Utils/validate-connection.js +183 -214
- package/lib/WABinary/constants.js +1298 -35
- package/lib/WABinary/decode.js +237 -249
- package/lib/WABinary/encode.js +213 -260
- package/lib/WABinary/generic-utils.js +56 -65
- package/lib/WABinary/index.js +7 -21
- package/lib/WABinary/jid-utils.js +89 -58
- package/lib/WABinary/types.js +3 -2
- package/lib/WAM/BinaryInfo.js +10 -12
- package/lib/WAM/constants.js +22851 -15348
- package/lib/WAM/encode.js +135 -136
- package/lib/WAM/index.js +5 -19
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +28 -30
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +49 -53
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +27 -28
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +36 -39
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +50 -50
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +26 -20
- package/lib/WAUSync/Protocols/index.js +6 -20
- package/lib/WAUSync/USyncQuery.js +86 -85
- package/lib/WAUSync/USyncUser.js +23 -25
- package/lib/WAUSync/index.js +5 -19
- package/lib/index.js +19 -34
- package/package.json +89 -106
- package/engine-requirements.js +0 -10
- package/lib/Defaults/baileys-version.json +0 -3
- package/lib/Defaults/index.d.ts +0 -53
- package/lib/Defaults/phonenumber-mcc.json +0 -223
- package/lib/Signal/Group/ciphertext-message.d.ts +0 -9
- package/lib/Signal/Group/group-session-builder.d.ts +0 -14
- package/lib/Signal/Group/group_cipher.d.ts +0 -17
- package/lib/Signal/Group/index.d.ts +0 -11
- package/lib/Signal/Group/keyhelper.d.ts +0 -10
- package/lib/Signal/Group/queue-job.d.ts +0 -1
- package/lib/Signal/Group/queue-job.js +0 -57
- package/lib/Signal/Group/sender-chain-key.d.ts +0 -13
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +0 -16
- package/lib/Signal/Group/sender-key-message.d.ts +0 -18
- package/lib/Signal/Group/sender-key-name.d.ts +0 -17
- package/lib/Signal/Group/sender-key-record.d.ts +0 -30
- package/lib/Signal/Group/sender-key-state.d.ts +0 -38
- package/lib/Signal/Group/sender-message-key.d.ts +0 -11
- package/lib/Signal/libsignal.d.ts +0 -3
- package/lib/Socket/Client/abstract-socket-client.d.ts +0 -17
- package/lib/Socket/Client/abstract-socket-client.js +0 -13
- package/lib/Socket/Client/index.d.ts +0 -3
- package/lib/Socket/Client/mobile-socket-client.d.ts +0 -13
- package/lib/Socket/Client/mobile-socket-client.js +0 -65
- package/lib/Socket/Client/web-socket-client.d.ts +0 -12
- package/lib/Socket/Client/web-socket-client.js +0 -62
- package/lib/Socket/business.d.ts +0 -171
- package/lib/Socket/chats.d.ts +0 -267
- package/lib/Socket/chats.js.bak +0 -981
- package/lib/Socket/dugong.d.ts +0 -254
- package/lib/Socket/dugong.js +0 -484
- package/lib/Socket/groups.d.ts +0 -115
- package/lib/Socket/index.d.ts +0 -173
- package/lib/Socket/messages-recv.d.ts +0 -161
- package/lib/Socket/messages-send.d.ts +0 -149
- package/lib/Socket/newsletter.d.ts +0 -134
- package/lib/Socket/registration.d.ts +0 -267
- package/lib/Socket/registration.js +0 -166
- package/lib/Socket/socket.d.ts +0 -43
- package/lib/Socket/usync.d.ts +0 -36
- package/lib/Socket/usync.js +0 -70
- package/lib/Store/index.d.ts +0 -3
- package/lib/Store/make-cache-manager-store.d.ts +0 -13
- package/lib/Store/make-in-memory-store.d.ts +0 -118
- package/lib/Store/make-ordered-dictionary.d.ts +0 -13
- package/lib/Store/object-repository.d.ts +0 -10
- package/lib/Types/Auth.d.ts +0 -110
- package/lib/Types/Call.d.ts +0 -13
- package/lib/Types/Chat.d.ts +0 -102
- package/lib/Types/Contact.d.ts +0 -19
- package/lib/Types/Events.d.ts +0 -157
- package/lib/Types/GroupMetadata.d.ts +0 -55
- package/lib/Types/Label.d.ts +0 -35
- package/lib/Types/LabelAssociation.d.ts +0 -29
- package/lib/Types/Message.d.ts +0 -273
- package/lib/Types/Newsletter.d.ts +0 -103
- package/lib/Types/Product.d.ts +0 -78
- package/lib/Types/Signal.d.ts +0 -57
- package/lib/Types/Socket.d.ts +0 -111
- package/lib/Types/State.d.ts +0 -27
- package/lib/Types/USync.d.ts +0 -25
- package/lib/Types/index.d.ts +0 -57
- package/lib/Utils/auth-utils.d.ts +0 -18
- package/lib/Utils/baileys-event-stream.d.ts +0 -16
- package/lib/Utils/business.d.ts +0 -22
- package/lib/Utils/chat-utils.d.ts +0 -71
- package/lib/Utils/crypto.d.ts +0 -41
- package/lib/Utils/decode-wa-message.d.ts +0 -19
- package/lib/Utils/event-buffer.d.ts +0 -35
- package/lib/Utils/generics.d.ts +0 -92
- package/lib/Utils/generics.js.bak +0 -433
- package/lib/Utils/history.d.ts +0 -15
- package/lib/Utils/index.d.ts +0 -17
- package/lib/Utils/link-preview.d.ts +0 -21
- package/lib/Utils/logger.d.ts +0 -4
- package/lib/Utils/lt-hash.d.ts +0 -12
- package/lib/Utils/make-mutex.d.ts +0 -7
- package/lib/Utils/messages-media.d.ts +0 -116
- package/lib/Utils/messages.d.ts +0 -77
- package/lib/Utils/noise-handler.d.ts +0 -21
- package/lib/Utils/process-message.d.ts +0 -41
- package/lib/Utils/signal.d.ts +0 -32
- package/lib/Utils/use-multi-file-auth-state.d.ts +0 -13
- package/lib/Utils/validate-connection.d.ts +0 -11
- package/lib/Utils/validate-connection.js.bak +0 -237
- package/lib/WABinary/constants.d.ts +0 -30
- package/lib/WABinary/decode.d.ts +0 -7
- package/lib/WABinary/encode.d.ts +0 -3
- package/lib/WABinary/generic-utils.d.ts +0 -17
- package/lib/WABinary/index.d.ts +0 -5
- package/lib/WABinary/jid-utils.d.ts +0 -31
- package/lib/WABinary/types.d.ts +0 -18
- package/lib/WAM/BinaryInfo.d.ts +0 -17
- package/lib/WAM/constants.d.ts +0 -38
- package/lib/WAM/encode.d.ts +0 -3
- package/lib/WAM/index.d.ts +0 -3
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +0 -9
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +0 -22
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +0 -12
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +0 -12
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +0 -25
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +0 -8
- package/lib/WAUSync/Protocols/index.d.ts +0 -4
- package/lib/WAUSync/USyncQuery.d.ts +0 -28
- package/lib/WAUSync/USyncUser.d.ts +0 -12
- package/lib/WAUSync/index.d.ts +0 -3
- package/lib/index.d.ts +0 -12
|
@@ -1,69 +1,89 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
1
|
+
import NodeCache from '@cacheable/node-cache';
|
|
2
|
+
import { Boom } from '@hapi/boom';
|
|
3
|
+
import { proto } from '../../WAProto/index.js';
|
|
4
|
+
import {
|
|
5
|
+
DEFAULT_CACHE_TTLS,
|
|
6
|
+
WA_DEFAULT_EPHEMERAL
|
|
7
|
+
} from '../Defaults/index.js';
|
|
8
|
+
import {
|
|
9
|
+
aggregateMessageKeysNotFromMe,
|
|
10
|
+
assertMediaContent,
|
|
11
|
+
bindWaitForEvent,
|
|
12
|
+
decryptMediaRetryData,
|
|
13
|
+
encodeNewsletterMessage,
|
|
14
|
+
encodeSignedDeviceIdentity,
|
|
15
|
+
encodeWAMessage,
|
|
16
|
+
encryptMediaRetryRequest,
|
|
17
|
+
extractDeviceJids,
|
|
18
|
+
generateMessageIDV2,
|
|
19
|
+
generateParticipantHashV2,
|
|
20
|
+
generateWAMessage,
|
|
21
|
+
getStatusCodeForMediaRetry,
|
|
22
|
+
getUrlFromDirectPath,
|
|
23
|
+
getWAUploadToServer,
|
|
24
|
+
MessageRetryManager,
|
|
25
|
+
normalizeMessageContent,
|
|
26
|
+
parseAndInjectE2ESessions,
|
|
27
|
+
unixTimestampSeconds
|
|
28
|
+
} from '../Utils/index.js';
|
|
29
|
+
import {
|
|
30
|
+
areJidsSameUser,
|
|
31
|
+
getBinaryNodeChild,
|
|
32
|
+
getBinaryNodeChildren,
|
|
33
|
+
getAdditionalNode,
|
|
34
|
+
getBinaryNodeFilter,
|
|
35
|
+
isHostedLidUser,
|
|
36
|
+
isHostedPnUser,
|
|
37
|
+
isJidGroup,
|
|
38
|
+
isLidUser,
|
|
39
|
+
isPnUser,
|
|
40
|
+
jidDecode,
|
|
41
|
+
jidEncode,
|
|
42
|
+
isJidNewsletter,
|
|
43
|
+
jidNormalizedUser,
|
|
44
|
+
S_WHATSAPP_NET
|
|
45
|
+
} from '../WABinary/index.js';
|
|
46
|
+
import { getUrlInfo } from '../Utils/link-preview.js';
|
|
47
|
+
import { makeKeyedMutex } from '../Utils/make-mutex.js';
|
|
48
|
+
import { USyncQuery, USyncUser } from '../WAUSync/index.js';
|
|
49
|
+
import { makeNewsletterSocket } from './newsletter.js';
|
|
50
|
+
export const makeMessagesSocket = (config) => {
|
|
51
|
+
const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: httpRequestOptions, patchMessageBeforeSending, cachedGroupMetadata, enableRecentMessageCache, maxMsgRetryCount } = config;
|
|
52
|
+
const sock = makeNewsletterSocket(config);
|
|
53
|
+
const { ev, authState, processingMutex, signalRepository, upsertMessage, query, fetchPrivacySettings, sendNode, groupMetadata, groupToggleEphemeral } = sock;
|
|
54
|
+
const userDevicesCache = config.userDevicesCache ||
|
|
55
|
+
new NodeCache({
|
|
56
|
+
stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES, // 5 minutes
|
|
57
|
+
useClones: false
|
|
58
|
+
});
|
|
59
|
+
const peerSessionsCache = new NodeCache({
|
|
60
|
+
stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES,
|
|
46
61
|
useClones: false
|
|
47
62
|
});
|
|
63
|
+
// Initialize message retry manager if enabled
|
|
64
|
+
const messageRetryManager = enableRecentMessageCache ? new MessageRetryManager(logger, maxMsgRetryCount) : null;
|
|
65
|
+
// Prevent race conditions in Signal session encryption by user
|
|
66
|
+
const encryptionMutex = makeKeyedMutex();
|
|
48
67
|
let mediaConn;
|
|
49
68
|
const refreshMediaConn = async (forceGet = false) => {
|
|
50
69
|
const media = await mediaConn;
|
|
51
|
-
if (!media || forceGet ||
|
|
70
|
+
if (!media || forceGet || new Date().getTime() - media.fetchDate.getTime() > media.ttl * 1000) {
|
|
52
71
|
mediaConn = (async () => {
|
|
53
72
|
const result = await query({
|
|
54
73
|
tag: 'iq',
|
|
55
74
|
attrs: {
|
|
56
75
|
type: 'set',
|
|
57
76
|
xmlns: 'w:m',
|
|
58
|
-
to:
|
|
77
|
+
to: S_WHATSAPP_NET
|
|
59
78
|
},
|
|
60
79
|
content: [{ tag: 'media_conn', attrs: {} }]
|
|
61
80
|
});
|
|
62
|
-
const mediaConnNode =
|
|
81
|
+
const mediaConnNode = getBinaryNodeChild(result, 'media_conn');
|
|
82
|
+
// TODO: explore full length of data that whatsapp provides
|
|
63
83
|
const node = {
|
|
64
|
-
hosts:
|
|
84
|
+
hosts: getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
|
|
65
85
|
hostname: attrs.hostname,
|
|
66
|
-
maxContentLengthBytes: +attrs.maxContentLengthBytes
|
|
86
|
+
maxContentLengthBytes: +attrs.maxContentLengthBytes
|
|
67
87
|
})),
|
|
68
88
|
auth: mediaConnNode.attrs.auth,
|
|
69
89
|
ttl: +mediaConnNode.attrs.ttl,
|
|
@@ -80,17 +100,20 @@ const makeMessagesSocket = (config) => {
|
|
|
80
100
|
* used for receipts of phone call, read, delivery etc.
|
|
81
101
|
* */
|
|
82
102
|
const sendReceipt = async (jid, participant, messageIds, type) => {
|
|
103
|
+
if (!messageIds || messageIds.length === 0) {
|
|
104
|
+
throw new Boom('missing ids in receipt');
|
|
105
|
+
}
|
|
83
106
|
const node = {
|
|
84
107
|
tag: 'receipt',
|
|
85
108
|
attrs: {
|
|
86
|
-
id: messageIds[0]
|
|
87
|
-
}
|
|
109
|
+
id: messageIds[0]
|
|
110
|
+
}
|
|
88
111
|
};
|
|
89
112
|
const isReadReceipt = type === 'read' || type === 'read-self';
|
|
90
113
|
if (isReadReceipt) {
|
|
91
|
-
node.attrs.t =
|
|
114
|
+
node.attrs.t = unixTimestampSeconds().toString();
|
|
92
115
|
}
|
|
93
|
-
if (type === 'sender' &&
|
|
116
|
+
if (type === 'sender' && (isPnUser(jid) || isLidUser(jid))) {
|
|
94
117
|
node.attrs.recipient = jid;
|
|
95
118
|
node.attrs.to = participant;
|
|
96
119
|
}
|
|
@@ -101,7 +124,7 @@ const makeMessagesSocket = (config) => {
|
|
|
101
124
|
}
|
|
102
125
|
}
|
|
103
126
|
if (type) {
|
|
104
|
-
node.attrs.type =
|
|
127
|
+
node.attrs.type = type;
|
|
105
128
|
}
|
|
106
129
|
const remainingMessageIds = messageIds.slice(1);
|
|
107
130
|
if (remainingMessageIds.length) {
|
|
@@ -121,7 +144,7 @@ const makeMessagesSocket = (config) => {
|
|
|
121
144
|
};
|
|
122
145
|
/** Correctly bulk send receipts to multiple chats, participants */
|
|
123
146
|
const sendReceipts = async (keys, type) => {
|
|
124
|
-
const recps =
|
|
147
|
+
const recps = aggregateMessageKeysNotFromMe(keys);
|
|
125
148
|
for (const { jid, participant, messageIds } of recps) {
|
|
126
149
|
await sendReceipt(jid, participant, messageIds, type);
|
|
127
150
|
}
|
|
@@ -135,207 +158,349 @@ const makeMessagesSocket = (config) => {
|
|
|
135
158
|
};
|
|
136
159
|
/** Fetch all the devices we've to send a message to */
|
|
137
160
|
const getUSyncDevices = async (jids, useCache, ignoreZeroDevices) => {
|
|
138
|
-
const deviceResults = []
|
|
139
|
-
|
|
161
|
+
const deviceResults = [];
|
|
140
162
|
if (!useCache) {
|
|
141
|
-
logger.debug('not using cache for devices')
|
|
163
|
+
logger.debug('not using cache for devices');
|
|
142
164
|
}
|
|
143
|
-
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
165
|
+
const toFetch = [];
|
|
166
|
+
const jidsWithUser = jids
|
|
167
|
+
.map(jid => {
|
|
168
|
+
const decoded = jidDecode(jid);
|
|
169
|
+
const user = decoded?.user;
|
|
170
|
+
const device = decoded?.device;
|
|
171
|
+
const isExplicitDevice = typeof device === 'number' && device >= 0;
|
|
172
|
+
if (isExplicitDevice && user) {
|
|
173
|
+
deviceResults.push({
|
|
174
|
+
user,
|
|
175
|
+
device,
|
|
176
|
+
jid
|
|
177
|
+
});
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
jid = jidNormalizedUser(jid);
|
|
181
|
+
return { jid, user };
|
|
182
|
+
})
|
|
183
|
+
.filter(jid => jid !== null);
|
|
184
|
+
let mgetDevices;
|
|
185
|
+
if (useCache && userDevicesCache.mget) {
|
|
186
|
+
const usersToFetch = jidsWithUser.map(j => j?.user).filter(Boolean);
|
|
187
|
+
mgetDevices = await userDevicesCache.mget(usersToFetch);
|
|
188
|
+
}
|
|
189
|
+
for (const { jid, user } of jidsWithUser) {
|
|
153
190
|
if (useCache) {
|
|
154
|
-
const devices =
|
|
155
|
-
|
|
191
|
+
const devices = mgetDevices?.[user] ||
|
|
192
|
+
(userDevicesCache.mget ? undefined : (await userDevicesCache.get(user)));
|
|
156
193
|
if (devices) {
|
|
157
|
-
|
|
158
|
-
|
|
194
|
+
const devicesWithJid = devices.map(d => ({
|
|
195
|
+
...d,
|
|
196
|
+
jid: jidEncode(d.user, d.server, d.device)
|
|
197
|
+
}));
|
|
198
|
+
deviceResults.push(...devicesWithJid);
|
|
199
|
+
logger.trace({ user }, 'using cache for devices');
|
|
159
200
|
}
|
|
160
|
-
|
|
161
201
|
else {
|
|
162
|
-
toFetch.push(jid)
|
|
202
|
+
toFetch.push(jid);
|
|
163
203
|
}
|
|
164
204
|
}
|
|
165
|
-
|
|
166
205
|
else {
|
|
167
|
-
toFetch.push(jid)
|
|
206
|
+
toFetch.push(jid);
|
|
168
207
|
}
|
|
169
208
|
}
|
|
170
|
-
|
|
171
209
|
if (!toFetch.length) {
|
|
172
|
-
return deviceResults
|
|
210
|
+
return deviceResults;
|
|
173
211
|
}
|
|
174
|
-
|
|
175
|
-
const query = new WAUSync_1.USyncQuery()
|
|
176
|
-
.withContext('message')
|
|
177
|
-
.withDeviceProtocol()
|
|
178
|
-
|
|
212
|
+
const requestedLidUsers = new Set();
|
|
179
213
|
for (const jid of toFetch) {
|
|
180
|
-
|
|
214
|
+
if (isLidUser(jid) || isHostedLidUser(jid)) {
|
|
215
|
+
const user = jidDecode(jid)?.user;
|
|
216
|
+
if (user)
|
|
217
|
+
requestedLidUsers.add(user);
|
|
218
|
+
}
|
|
181
219
|
}
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
|
|
220
|
+
const query = new USyncQuery().withContext('message').withDeviceProtocol().withLIDProtocol();
|
|
221
|
+
for (const jid of toFetch) {
|
|
222
|
+
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
|
|
223
|
+
}
|
|
224
|
+
const result = await sock.executeUSyncQuery(query);
|
|
185
225
|
if (result) {
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
|
|
226
|
+
// TODO: LID MAP this stuff (lid protocol will now return lid with devices)
|
|
227
|
+
const lidResults = result.list.filter(a => !!a.lid);
|
|
228
|
+
if (lidResults.length > 0) {
|
|
229
|
+
logger.trace('Storing LID maps from device call');
|
|
230
|
+
await signalRepository.lidMapping.storeLIDPNMappings(lidResults.map(a => ({ lid: a.lid, pn: a.id })));
|
|
231
|
+
}
|
|
232
|
+
const extracted = extractDeviceJids(result?.list, authState.creds.me.id, authState.creds.me.lid, ignoreZeroDevices);
|
|
233
|
+
const deviceMap = {};
|
|
189
234
|
for (const item of extracted) {
|
|
190
|
-
deviceMap[item.user] = deviceMap[item.user] || []
|
|
191
|
-
deviceMap[item.user]
|
|
192
|
-
deviceResults.push(item)
|
|
235
|
+
deviceMap[item.user] = deviceMap[item.user] || [];
|
|
236
|
+
deviceMap[item.user]?.push(item);
|
|
193
237
|
}
|
|
194
|
-
|
|
195
|
-
for (const
|
|
196
|
-
|
|
238
|
+
// Process each user's devices as a group for bulk LID migration
|
|
239
|
+
for (const [user, userDevices] of Object.entries(deviceMap)) {
|
|
240
|
+
const isLidUser = requestedLidUsers.has(user);
|
|
241
|
+
// Process all devices for this user
|
|
242
|
+
for (const item of userDevices) {
|
|
243
|
+
const finalJid = isLidUser
|
|
244
|
+
? jidEncode(user, item.server, item.device)
|
|
245
|
+
: jidEncode(item.user, item.server, item.device);
|
|
246
|
+
deviceResults.push({
|
|
247
|
+
...item,
|
|
248
|
+
jid: finalJid
|
|
249
|
+
});
|
|
250
|
+
logger.debug({
|
|
251
|
+
user: item.user,
|
|
252
|
+
device: item.device,
|
|
253
|
+
finalJid,
|
|
254
|
+
usedLid: isLidUser
|
|
255
|
+
}, 'Processed device with LID priority');
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (userDevicesCache.mset) {
|
|
259
|
+
// if the cache supports mset, we can set all devices in one go
|
|
260
|
+
await userDevicesCache.mset(Object.entries(deviceMap).map(([key, value]) => ({ key, value })));
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
for (const key in deviceMap) {
|
|
264
|
+
if (deviceMap[key])
|
|
265
|
+
await userDevicesCache.set(key, deviceMap[key]);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
const userDeviceUpdates = {};
|
|
269
|
+
for (const [userId, devices] of Object.entries(deviceMap)) {
|
|
270
|
+
if (devices && devices.length > 0) {
|
|
271
|
+
userDeviceUpdates[userId] = devices.map(d => d.device?.toString() || '0');
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (Object.keys(userDeviceUpdates).length > 0) {
|
|
275
|
+
try {
|
|
276
|
+
await authState.keys.set({ 'device-list': userDeviceUpdates });
|
|
277
|
+
logger.debug({ userCount: Object.keys(userDeviceUpdates).length }, 'stored user device lists for bulk migration');
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
logger.warn({ error }, 'failed to store user device lists');
|
|
281
|
+
}
|
|
197
282
|
}
|
|
198
283
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const assertSessions = async (jids, force) => {
|
|
284
|
+
return deviceResults;
|
|
285
|
+
};
|
|
286
|
+
const assertSessions = async (jids) => {
|
|
203
287
|
let didFetchNewSession = false;
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
.jidToSignalProtocolAddress(jid);
|
|
215
|
-
if (!sessions[signalId]) {
|
|
216
|
-
jidsRequiringFetch.push(jid);
|
|
288
|
+
const uniqueJids = [...new Set(jids)]; // Deduplicate JIDs
|
|
289
|
+
const jidsRequiringFetch = [];
|
|
290
|
+
logger.debug({ jids }, 'assertSessions call with jids');
|
|
291
|
+
// Check peerSessionsCache and validate sessions using libsignal loadSession
|
|
292
|
+
for (const jid of uniqueJids) {
|
|
293
|
+
const signalId = signalRepository.jidToSignalProtocolAddress(jid);
|
|
294
|
+
const cachedSession = peerSessionsCache.get(signalId);
|
|
295
|
+
if (cachedSession !== undefined) {
|
|
296
|
+
if (cachedSession) {
|
|
297
|
+
continue; // Session exists in cache
|
|
217
298
|
}
|
|
218
299
|
}
|
|
300
|
+
else {
|
|
301
|
+
const sessionValidation = await signalRepository.validateSession(jid);
|
|
302
|
+
const hasSession = sessionValidation.exists;
|
|
303
|
+
peerSessionsCache.set(signalId, hasSession);
|
|
304
|
+
if (hasSession) {
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
jidsRequiringFetch.push(jid);
|
|
219
309
|
}
|
|
220
310
|
if (jidsRequiringFetch.length) {
|
|
221
|
-
|
|
311
|
+
// LID if mapped, otherwise original
|
|
312
|
+
const wireJids = [
|
|
313
|
+
...jidsRequiringFetch.filter(jid => !!isLidUser(jid) || !!isHostedLidUser(jid)),
|
|
314
|
+
...((await signalRepository.lidMapping.getLIDsForPNs(jidsRequiringFetch.filter(jid => !!isPnUser(jid) || !!isHostedPnUser(jid)))) || []).map(a => a.lid)
|
|
315
|
+
];
|
|
316
|
+
logger.debug({ jidsRequiringFetch, wireJids }, 'fetching sessions');
|
|
222
317
|
const result = await query({
|
|
223
318
|
tag: 'iq',
|
|
224
319
|
attrs: {
|
|
225
320
|
xmlns: 'encrypt',
|
|
226
321
|
type: 'get',
|
|
227
|
-
to:
|
|
322
|
+
to: S_WHATSAPP_NET
|
|
228
323
|
},
|
|
229
324
|
content: [
|
|
230
325
|
{
|
|
231
326
|
tag: 'key',
|
|
232
327
|
attrs: {},
|
|
233
|
-
content:
|
|
328
|
+
content: wireJids.map(jid => ({
|
|
234
329
|
tag: 'user',
|
|
235
|
-
attrs: { jid }
|
|
330
|
+
attrs: { jid }
|
|
236
331
|
}))
|
|
237
332
|
}
|
|
238
333
|
]
|
|
239
334
|
});
|
|
240
|
-
await
|
|
335
|
+
await parseAndInjectE2ESessions(result, signalRepository);
|
|
241
336
|
didFetchNewSession = true;
|
|
337
|
+
// Cache fetched sessions using wire JIDs
|
|
338
|
+
for (const wireJid of wireJids) {
|
|
339
|
+
const signalId = signalRepository.jidToSignalProtocolAddress(wireJid);
|
|
340
|
+
peerSessionsCache.set(signalId, true);
|
|
341
|
+
}
|
|
242
342
|
}
|
|
243
343
|
return didFetchNewSession;
|
|
244
344
|
};
|
|
245
|
-
|
|
246
|
-
|
|
247
345
|
const sendPeerDataOperationMessage = async (pdoMessage) => {
|
|
346
|
+
//TODO: for later, abstract the logic to send a Peer Message instead of just PDO - useful for App State Key Resync with phone
|
|
248
347
|
if (!authState.creds.me?.id) {
|
|
249
|
-
throw new
|
|
348
|
+
throw new Boom('Not authenticated');
|
|
250
349
|
}
|
|
251
|
-
|
|
252
350
|
const protocolMessage = {
|
|
253
351
|
protocolMessage: {
|
|
254
352
|
peerDataOperationRequestMessage: pdoMessage,
|
|
255
|
-
type:
|
|
353
|
+
type: proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
|
|
256
354
|
}
|
|
257
355
|
};
|
|
258
|
-
const meJid =
|
|
356
|
+
const meJid = jidNormalizedUser(authState.creds.me.id);
|
|
259
357
|
const msgId = await relayMessage(meJid, protocolMessage, {
|
|
260
358
|
additionalAttributes: {
|
|
261
359
|
category: 'peer',
|
|
262
|
-
|
|
263
|
-
push_priority: 'high_force',
|
|
360
|
+
push_priority: 'high_force'
|
|
264
361
|
},
|
|
362
|
+
additionalNodes: [
|
|
363
|
+
{
|
|
364
|
+
tag: 'meta',
|
|
365
|
+
attrs: { appdata: 'default' }
|
|
366
|
+
}
|
|
367
|
+
]
|
|
265
368
|
});
|
|
266
369
|
return msgId;
|
|
267
370
|
};
|
|
268
|
-
const createParticipantNodes = async (
|
|
269
|
-
|
|
270
|
-
|
|
371
|
+
const createParticipantNodes = async (recipientJids, message, extraAttrs, dsmMessage) => {
|
|
372
|
+
if (!recipientJids.length) {
|
|
373
|
+
return { nodes: [], shouldIncludeDeviceIdentity: false };
|
|
374
|
+
}
|
|
375
|
+
const patched = await patchMessageBeforeSending(message, recipientJids);
|
|
376
|
+
const patchedMessages = Array.isArray(patched)
|
|
377
|
+
? patched
|
|
378
|
+
: recipientJids.map(jid => ({ recipientJid: jid, message: patched }));
|
|
271
379
|
let shouldIncludeDeviceIdentity = false;
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
380
|
+
const meId = authState.creds.me.id;
|
|
381
|
+
const meLid = authState.creds.me?.lid;
|
|
382
|
+
const meLidUser = meLid ? jidDecode(meLid)?.user : null;
|
|
383
|
+
const encryptionPromises = patchedMessages.map(async ({ recipientJid: jid, message: patchedMessage }) => {
|
|
384
|
+
if (!jid)
|
|
385
|
+
return null;
|
|
386
|
+
let msgToEncrypt = patchedMessage;
|
|
387
|
+
if (dsmMessage) {
|
|
388
|
+
const { user: targetUser } = jidDecode(jid);
|
|
389
|
+
const { user: ownPnUser } = jidDecode(meId);
|
|
390
|
+
const ownLidUser = meLidUser;
|
|
391
|
+
const isOwnUser = targetUser === ownPnUser || (ownLidUser && targetUser === ownLidUser);
|
|
392
|
+
const isExactSenderDevice = jid === meId || (meLid && jid === meLid);
|
|
393
|
+
if (isOwnUser && !isExactSenderDevice) {
|
|
394
|
+
msgToEncrypt = dsmMessage;
|
|
395
|
+
logger.debug({ jid, targetUser }, 'Using DSM for own device');
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
const bytes = encodeWAMessage(msgToEncrypt);
|
|
399
|
+
const mutexKey = jid;
|
|
400
|
+
const node = await encryptionMutex.mutex(mutexKey, async () => {
|
|
401
|
+
const { type, ciphertext } = await signalRepository.encryptMessage({
|
|
402
|
+
jid,
|
|
403
|
+
data: bytes
|
|
404
|
+
});
|
|
405
|
+
if (type === 'pkmsg') {
|
|
406
|
+
shouldIncludeDeviceIdentity = true;
|
|
407
|
+
}
|
|
408
|
+
return {
|
|
409
|
+
tag: 'to',
|
|
410
|
+
attrs: { jid },
|
|
411
|
+
content: [
|
|
412
|
+
{
|
|
413
|
+
tag: 'enc',
|
|
414
|
+
attrs: {
|
|
415
|
+
v: '2',
|
|
416
|
+
type,
|
|
417
|
+
...(extraAttrs || {})
|
|
418
|
+
},
|
|
419
|
+
content: ciphertext
|
|
420
|
+
}
|
|
421
|
+
]
|
|
422
|
+
};
|
|
423
|
+
});
|
|
291
424
|
return node;
|
|
292
|
-
})
|
|
425
|
+
});
|
|
426
|
+
const nodes = (await Promise.all(encryptionPromises)).filter(node => node !== null);
|
|
293
427
|
return { nodes, shouldIncludeDeviceIdentity };
|
|
294
|
-
};
|
|
295
|
-
const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache,
|
|
296
|
-
|
|
297
|
-
let shouldIncludeDeviceIdentity = false;
|
|
428
|
+
};
|
|
429
|
+
const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList, AI = false }) => {
|
|
430
|
+
// let shouldIncludeDeviceIdentity = false;
|
|
298
431
|
let didPushAdditional = false
|
|
299
|
-
const
|
|
432
|
+
const meId = authState.creds.me.id;
|
|
433
|
+
const meLid = authState.creds.me?.lid;
|
|
434
|
+
const isRetryResend = Boolean(participant?.jid);
|
|
435
|
+
let shouldIncludeDeviceIdentity = isRetryResend;
|
|
300
436
|
const statusJid = 'status@broadcast';
|
|
437
|
+
const { user, server } = jidDecode(jid);
|
|
301
438
|
const isGroup = server === 'g.us';
|
|
302
439
|
const isStatus = jid === statusJid;
|
|
303
440
|
const isLid = server === 'lid';
|
|
304
|
-
const isPrivate = server === 's.whatsapp.net'
|
|
305
441
|
const isNewsletter = server === 'newsletter';
|
|
306
|
-
|
|
442
|
+
const isPrivate = server === 's.whatsapp.net'
|
|
443
|
+
const finalJid = jid;
|
|
444
|
+
msgId = msgId || generateMessageIDV2(meId);
|
|
307
445
|
useUserDevicesCache = useUserDevicesCache !== false;
|
|
308
|
-
useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus
|
|
446
|
+
useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus;
|
|
309
447
|
const participants = [];
|
|
310
|
-
const destinationJid =
|
|
448
|
+
const destinationJid = !isStatus ? finalJid : statusJid;
|
|
311
449
|
const binaryNodeContent = [];
|
|
312
450
|
const devices = [];
|
|
313
451
|
const meMsg = {
|
|
314
452
|
deviceSentMessage: {
|
|
315
453
|
destinationJid,
|
|
316
454
|
message
|
|
317
|
-
}
|
|
455
|
+
},
|
|
456
|
+
messageContextInfo: message.messageContextInfo
|
|
318
457
|
};
|
|
319
|
-
const extraAttrs = {}
|
|
320
|
-
const messages =
|
|
458
|
+
const extraAttrs = {};
|
|
459
|
+
const messages = normalizeMessageContent(message)
|
|
321
460
|
const buttonType = getButtonType(messages);
|
|
322
461
|
if (participant) {
|
|
323
|
-
// when the retry request is not for a group
|
|
324
|
-
// only send to the specific device that asked for a retry
|
|
325
|
-
// otherwise the message is sent out to every device that should be a recipient
|
|
326
462
|
if (!isGroup && !isStatus) {
|
|
327
|
-
additionalAttributes = {
|
|
463
|
+
additionalAttributes = {
|
|
464
|
+
...additionalAttributes,
|
|
465
|
+
device_fanout: 'false'
|
|
466
|
+
};
|
|
328
467
|
}
|
|
329
|
-
const { user, device } =
|
|
330
|
-
devices.push({
|
|
468
|
+
const { user, device } = jidDecode(participant.jid);
|
|
469
|
+
devices.push({
|
|
470
|
+
user,
|
|
471
|
+
device,
|
|
472
|
+
jid: participant.jid
|
|
473
|
+
});
|
|
331
474
|
}
|
|
332
475
|
await authState.keys.transaction(async () => {
|
|
333
|
-
const mediaType = getMediaType(
|
|
334
|
-
|
|
476
|
+
const mediaType = getMediaType(message);
|
|
335
477
|
if (mediaType) {
|
|
336
|
-
extraAttrs['mediatype'] = mediaType
|
|
478
|
+
extraAttrs['mediatype'] = mediaType;
|
|
337
479
|
}
|
|
338
480
|
|
|
481
|
+
if (isNewsletter) {
|
|
482
|
+
const patched = patchMessageBeforeSending ? await patchMessageBeforeSending(message, []) : message;
|
|
483
|
+
const bytes = encodeNewsletterMessage(patched);
|
|
484
|
+
binaryNodeContent.push({
|
|
485
|
+
tag: "plaintext",
|
|
486
|
+
attrs: mediaType ? { mediatype: mediaType } : {},
|
|
487
|
+
content: bytes
|
|
488
|
+
});
|
|
489
|
+
const stanza = {
|
|
490
|
+
tag: "message",
|
|
491
|
+
attrs: {
|
|
492
|
+
to: jid,
|
|
493
|
+
id: msgId,
|
|
494
|
+
type: getTypeMessage(message),
|
|
495
|
+
...(additionalAttributes || {})
|
|
496
|
+
},
|
|
497
|
+
content: binaryNodeContent
|
|
498
|
+
};
|
|
499
|
+
logger.debug({ msgId }, `sending newsletter message to ${jid}`);
|
|
500
|
+
await sendNode(stanza);
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
|
|
339
504
|
if (messages.pinInChatMessage || messages.keepInChatMessage || message.reactionMessage || message.protocolMessage?.editedMessage) {
|
|
340
505
|
extraAttrs['decrypt-fail'] = 'hide'
|
|
341
506
|
}
|
|
@@ -347,185 +512,228 @@ const makeMessagesSocket = (config) => {
|
|
|
347
512
|
if (isGroup || isStatus) {
|
|
348
513
|
const [groupData, senderKeyMap] = await Promise.all([
|
|
349
514
|
(async () => {
|
|
350
|
-
let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined
|
|
351
|
-
if (groupData) {
|
|
352
|
-
logger.trace({
|
|
515
|
+
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?
|
|
516
|
+
if (groupData && Array.isArray(groupData?.participants)) {
|
|
517
|
+
logger.trace({
|
|
518
|
+
jid,
|
|
519
|
+
participants: groupData.participants.length
|
|
520
|
+
}, 'using cached group metadata');
|
|
353
521
|
}
|
|
354
|
-
|
|
355
522
|
else if (!isStatus) {
|
|
356
|
-
groupData = await groupMetadata(jid)
|
|
523
|
+
groupData = await groupMetadata(jid); // TODO: start storing group participant list + addr mode in Signal & stop relying on this
|
|
357
524
|
}
|
|
358
|
-
|
|
359
525
|
return groupData;
|
|
360
526
|
})(),
|
|
361
527
|
(async () => {
|
|
362
528
|
if (!participant && !isStatus) {
|
|
363
|
-
|
|
364
|
-
|
|
529
|
+
// what if sender memory is less accurate than the cached metadata
|
|
530
|
+
// on participant change in group, we should do sender memory manipulation
|
|
531
|
+
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?
|
|
532
|
+
return result[jid] || {};
|
|
365
533
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
})()
|
|
534
|
+
return {};
|
|
535
|
+
})()
|
|
370
536
|
]);
|
|
371
537
|
if (!participant) {
|
|
372
|
-
const participantsList =
|
|
373
|
-
|
|
538
|
+
const participantsList = groupData && !isStatus ? groupData.participants.map(p => p.id) : [];
|
|
374
539
|
if (isStatus && statusJidList) {
|
|
375
|
-
participantsList.push(...statusJidList)
|
|
540
|
+
participantsList.push(...statusJidList);
|
|
376
541
|
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
542
|
+
// if (!isStatus) {
|
|
543
|
+
// additionalAttributes = {
|
|
544
|
+
// ...additionalAttributes,
|
|
545
|
+
// addressing_mode: groupData?.addressingMode || 'pn'
|
|
546
|
+
// };
|
|
547
|
+
// }
|
|
548
|
+
const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false);
|
|
549
|
+
devices.push(...additionalDevices);
|
|
550
|
+
}
|
|
551
|
+
if (groupData?.ephemeralDuration && groupData.ephemeralDuration > 0) {
|
|
552
|
+
additionalAttributes = {
|
|
553
|
+
...additionalAttributes,
|
|
554
|
+
expiration: groupData.ephemeralDuration.toString()
|
|
555
|
+
};
|
|
389
556
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
557
|
+
const patched = await patchMessageBeforeSending(message);
|
|
558
|
+
if (Array.isArray(patched)) {
|
|
559
|
+
throw new Boom('Per-jid patching is not supported in groups');
|
|
560
|
+
}
|
|
561
|
+
const bytes = encodeWAMessage(patched);
|
|
562
|
+
const groupAddressingMode = additionalAttributes?.['addressing_mode'] || groupData?.addressingMode || 'lid';
|
|
563
|
+
const groupSenderIdentity = groupAddressingMode === 'lid' && meLid ? meLid : meId;
|
|
394
564
|
const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
|
|
395
565
|
group: destinationJid,
|
|
396
566
|
data: bytes,
|
|
397
|
-
meId
|
|
567
|
+
meId: groupSenderIdentity
|
|
398
568
|
});
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
const
|
|
403
|
-
if (!
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
569
|
+
const senderKeyRecipients = [];
|
|
570
|
+
for (const device of devices) {
|
|
571
|
+
const deviceJid = device.jid;
|
|
572
|
+
const hasKey = !!senderKeyMap[deviceJid];
|
|
573
|
+
if ((!hasKey || !!participant) &&
|
|
574
|
+
!isHostedLidUser(deviceJid) &&
|
|
575
|
+
!isHostedPnUser(deviceJid) &&
|
|
576
|
+
device.device !== 99) {
|
|
577
|
+
//todo: revamp all this logic
|
|
578
|
+
// 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
|
|
579
|
+
senderKeyRecipients.push(deviceJid);
|
|
580
|
+
senderKeyMap[deviceJid] = true;
|
|
407
581
|
}
|
|
408
582
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
if (senderKeyJids.length) {
|
|
412
|
-
logger.debug({ senderKeyJids }, 'sending new sender key');
|
|
583
|
+
if (senderKeyRecipients.length) {
|
|
584
|
+
logger.debug({ senderKeyJids: senderKeyRecipients }, 'sending new sender key');
|
|
413
585
|
const senderKeyMsg = {
|
|
414
586
|
senderKeyDistributionMessage: {
|
|
415
587
|
axolotlSenderKeyDistributionMessage: senderKeyDistributionMessage,
|
|
416
588
|
groupId: destinationJid
|
|
417
589
|
}
|
|
418
590
|
};
|
|
419
|
-
|
|
420
|
-
|
|
591
|
+
const senderKeySessionTargets = senderKeyRecipients;
|
|
592
|
+
await assertSessions(senderKeySessionTargets);
|
|
593
|
+
const result = await createParticipantNodes(senderKeyRecipients, senderKeyMsg, extraAttrs);
|
|
421
594
|
shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || result.shouldIncludeDeviceIdentity;
|
|
422
595
|
participants.push(...result.nodes);
|
|
423
596
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
597
|
+
if (isRetryResend) {
|
|
598
|
+
const { type, ciphertext: encryptedContent } = await signalRepository.encryptMessage({
|
|
599
|
+
data: bytes,
|
|
600
|
+
jid: participant?.jid
|
|
601
|
+
});
|
|
602
|
+
binaryNodeContent.push({
|
|
603
|
+
tag: 'enc',
|
|
604
|
+
attrs: {
|
|
605
|
+
v: '2',
|
|
606
|
+
type,
|
|
607
|
+
count: participant.count.toString()
|
|
608
|
+
},
|
|
609
|
+
content: encryptedContent
|
|
610
|
+
});
|
|
436
611
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
612
|
+
else {
|
|
613
|
+
binaryNodeContent.push({
|
|
614
|
+
tag: 'enc',
|
|
615
|
+
attrs: {
|
|
616
|
+
v: '2',
|
|
617
|
+
type: 'skmsg',
|
|
618
|
+
...extraAttrs
|
|
619
|
+
},
|
|
620
|
+
content: ciphertext
|
|
621
|
+
});
|
|
622
|
+
await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } });
|
|
442
623
|
}
|
|
443
|
-
|
|
444
|
-
const patched = await patchMessageBeforeSending(message, [])
|
|
445
|
-
const bytes = Utils_1.encodeNewsletterMessage(patched)
|
|
446
|
-
|
|
447
|
-
binaryNodeContent.push({
|
|
448
|
-
tag: 'plaintext',
|
|
449
|
-
attrs: extraAttrs ? extraAttrs : {},
|
|
450
|
-
content: bytes
|
|
451
|
-
})
|
|
452
624
|
}
|
|
453
625
|
else {
|
|
454
|
-
|
|
626
|
+
// ADDRESSING CONSISTENCY: Match own identity to conversation context
|
|
627
|
+
// TODO: investigate if this is true
|
|
628
|
+
let ownId = meId;
|
|
629
|
+
if (isLid && meLid) {
|
|
630
|
+
ownId = meLid;
|
|
631
|
+
logger.debug({ to: jid, ownId }, 'Using LID identity for @lid conversation');
|
|
632
|
+
}
|
|
633
|
+
else {
|
|
634
|
+
logger.debug({ to: jid, ownId }, 'Using PN identity for @s.whatsapp.net conversation');
|
|
635
|
+
}
|
|
636
|
+
const { user: ownUser } = jidDecode(ownId);
|
|
455
637
|
if (!participant) {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
638
|
+
const targetUserServer = isLid ? 'lid' : 's.whatsapp.net';
|
|
639
|
+
devices.push({
|
|
640
|
+
user,
|
|
641
|
+
device: 0,
|
|
642
|
+
jid: jidEncode(user, targetUserServer, 0) // rajeh, todo: this entire logic is convoluted and weird.
|
|
643
|
+
});
|
|
644
|
+
if (user !== ownUser) {
|
|
645
|
+
const ownUserServer = isLid ? 'lid' : 's.whatsapp.net';
|
|
646
|
+
const ownUserForAddressing = isLid && meLid ? jidDecode(meLid).user : jidDecode(meId).user;
|
|
647
|
+
devices.push({
|
|
648
|
+
user: ownUserForAddressing,
|
|
649
|
+
device: 0,
|
|
650
|
+
jid: jidEncode(ownUserForAddressing, ownUserServer, 0)
|
|
651
|
+
});
|
|
459
652
|
}
|
|
460
|
-
|
|
461
653
|
if (additionalAttributes?.['category'] !== 'peer') {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
654
|
+
// Clear placeholders and enumerate actual devices
|
|
655
|
+
devices.length = 0;
|
|
656
|
+
// Use conversation-appropriate sender identity
|
|
657
|
+
const senderIdentity = isLid && meLid
|
|
658
|
+
? jidEncode(jidDecode(meLid)?.user, 'lid', undefined)
|
|
659
|
+
: jidEncode(jidDecode(meId)?.user, 's.whatsapp.net', undefined);
|
|
660
|
+
// Enumerate devices for sender and target with consistent addressing
|
|
661
|
+
const sessionDevices = await getUSyncDevices([senderIdentity, jid], true, false);
|
|
662
|
+
devices.push(...sessionDevices);
|
|
663
|
+
logger.debug({
|
|
664
|
+
deviceCount: devices.length,
|
|
665
|
+
devices: devices.map(d => `${d.user}:${d.device}@${jidDecode(d.jid)?.server}`)
|
|
666
|
+
}, 'Device enumeration complete with unified addressing');
|
|
465
667
|
}
|
|
466
668
|
}
|
|
467
|
-
const
|
|
468
|
-
const
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
669
|
+
const allRecipients = [];
|
|
670
|
+
const meRecipients = [];
|
|
671
|
+
const otherRecipients = [];
|
|
672
|
+
const { user: mePnUser } = jidDecode(meId);
|
|
673
|
+
const { user: meLidUser } = meLid ? jidDecode(meLid) : { user: null };
|
|
674
|
+
for (const { user, jid } of devices) {
|
|
675
|
+
const isExactSenderDevice = jid === meId || (meLid && jid === meLid);
|
|
676
|
+
if (isExactSenderDevice) {
|
|
677
|
+
logger.debug({ jid, meId, meLid }, 'Skipping exact sender device (whatsmeow pattern)');
|
|
678
|
+
continue;
|
|
679
|
+
}
|
|
680
|
+
// Check if this is our device (could match either PN or LID user)
|
|
681
|
+
const isMe = user === mePnUser || user === meLidUser;
|
|
474
682
|
if (isMe) {
|
|
475
|
-
|
|
683
|
+
meRecipients.push(jid);
|
|
476
684
|
}
|
|
477
|
-
|
|
478
685
|
else {
|
|
479
|
-
|
|
686
|
+
otherRecipients.push(jid);
|
|
480
687
|
}
|
|
481
|
-
|
|
482
|
-
allJids.push(jid)
|
|
688
|
+
allRecipients.push(jid);
|
|
483
689
|
}
|
|
484
|
-
await assertSessions(
|
|
690
|
+
await assertSessions(allRecipients);
|
|
485
691
|
const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = await Promise.all([
|
|
486
|
-
|
|
487
|
-
createParticipantNodes(
|
|
488
|
-
|
|
692
|
+
// For own devices: use DSM if available (1:1 chats only)
|
|
693
|
+
createParticipantNodes(meRecipients, meMsg || message, extraAttrs),
|
|
694
|
+
createParticipantNodes(otherRecipients, message, extraAttrs, meMsg)
|
|
695
|
+
]);
|
|
489
696
|
participants.push(...meNodes);
|
|
490
697
|
participants.push(...otherNodes);
|
|
698
|
+
/* if (meRecipients.length > 0 || otherRecipients.length > 0) {
|
|
699
|
+
extraAttrs['phash'] = generateParticipantHashV2([...meRecipients, ...otherRecipients]);
|
|
700
|
+
}*/
|
|
491
701
|
shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2;
|
|
492
702
|
}
|
|
493
703
|
if (participants.length) {
|
|
494
704
|
if (additionalAttributes?.['category'] === 'peer') {
|
|
495
|
-
const peerNode = participants[0]?.content?.[0]
|
|
496
|
-
|
|
705
|
+
const peerNode = participants[0]?.content?.[0];
|
|
497
706
|
if (peerNode) {
|
|
498
|
-
binaryNodeContent.push(peerNode) // push only enc
|
|
707
|
+
binaryNodeContent.push(peerNode); // push only enc
|
|
499
708
|
}
|
|
500
709
|
}
|
|
501
|
-
|
|
502
710
|
else {
|
|
503
711
|
binaryNodeContent.push({
|
|
504
712
|
tag: 'participants',
|
|
505
713
|
attrs: {},
|
|
506
714
|
content: participants
|
|
507
|
-
})
|
|
715
|
+
});
|
|
508
716
|
}
|
|
509
717
|
}
|
|
510
|
-
|
|
511
718
|
const stanza = {
|
|
512
719
|
tag: 'message',
|
|
513
720
|
attrs: {
|
|
514
721
|
id: msgId,
|
|
515
|
-
|
|
722
|
+
to: destinationJid,
|
|
723
|
+
type: getTypeMessage(messages),
|
|
516
724
|
...(additionalAttributes || {})
|
|
517
725
|
},
|
|
518
726
|
content: binaryNodeContent
|
|
519
|
-
}
|
|
727
|
+
};
|
|
520
728
|
// if the participant to send to is explicitly specified (generally retry recp)
|
|
521
729
|
// ensure the message is only sent to that person
|
|
522
730
|
// if a retry receipt is sent to everyone -- it'll fail decryption for everyone else who received the msg
|
|
523
731
|
if (participant) {
|
|
524
|
-
if (
|
|
732
|
+
if (isJidGroup(destinationJid)) {
|
|
525
733
|
stanza.attrs.to = destinationJid;
|
|
526
734
|
stanza.attrs.participant = participant.jid;
|
|
527
735
|
}
|
|
528
|
-
else if (
|
|
736
|
+
else if (areJidsSameUser(participant.jid, meId)) {
|
|
529
737
|
stanza.attrs.to = participant.jid;
|
|
530
738
|
stanza.attrs.recipient = destinationJid;
|
|
531
739
|
}
|
|
@@ -537,14 +745,14 @@ const makeMessagesSocket = (config) => {
|
|
|
537
745
|
stanza.attrs.to = destinationJid;
|
|
538
746
|
}
|
|
539
747
|
if (shouldIncludeDeviceIdentity) {
|
|
748
|
+
;
|
|
540
749
|
stanza.content.push({
|
|
541
750
|
tag: 'device-identity',
|
|
542
751
|
attrs: {},
|
|
543
|
-
content:
|
|
752
|
+
content: encodeSignedDeviceIdentity(authState.creds.account, true)
|
|
544
753
|
});
|
|
545
754
|
logger.debug({ jid }, 'adding device identity');
|
|
546
755
|
}
|
|
547
|
-
|
|
548
756
|
if (AI && isPrivate) {
|
|
549
757
|
const botNode = {
|
|
550
758
|
tag: 'bot',
|
|
@@ -553,7 +761,7 @@ const makeMessagesSocket = (config) => {
|
|
|
553
761
|
}
|
|
554
762
|
}
|
|
555
763
|
|
|
556
|
-
const filteredBizBot =
|
|
764
|
+
const filteredBizBot = getBinaryNodeFilter(additionalNodes ? additionalNodes : [])
|
|
557
765
|
|
|
558
766
|
if (filteredBizBot) {
|
|
559
767
|
stanza.content.push(...additionalNodes)
|
|
@@ -565,9 +773,9 @@ const makeMessagesSocket = (config) => {
|
|
|
565
773
|
}
|
|
566
774
|
}
|
|
567
775
|
|
|
568
|
-
if(
|
|
569
|
-
const content =
|
|
570
|
-
const filteredNode =
|
|
776
|
+
if(buttonType && !isStatus) {
|
|
777
|
+
const content = getAdditionalNode(buttonType)
|
|
778
|
+
const filteredNode = getBinaryNodeFilter(additionalNodes)
|
|
571
779
|
|
|
572
780
|
if (filteredNode) {
|
|
573
781
|
didPushAdditional = true
|
|
@@ -582,42 +790,44 @@ const makeMessagesSocket = (config) => {
|
|
|
582
790
|
if (!didPushAdditional && additionalNodes && additionalNodes.length > 0) {
|
|
583
791
|
stanza.content.push(...additionalNodes);
|
|
584
792
|
}
|
|
585
|
-
|
|
586
793
|
logger.debug({ msgId }, `sending message to ${participants.length} devices`);
|
|
587
794
|
await sendNode(stanza);
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
remoteJid: jid,
|
|
595
|
-
fromMe: true,
|
|
596
|
-
id: msgId
|
|
597
|
-
},
|
|
598
|
-
message: message,
|
|
599
|
-
messageTimestamp: Utils_1.unixTimestampSeconds(new Date()),
|
|
600
|
-
messageStubParameters: [],
|
|
601
|
-
participant: WABinary_1.isJidGroup(jid) || WABinary_1.isJidStatusBroadcast(jid) ? meId : undefined,
|
|
602
|
-
status: Types_1.WAMessageStatus.PENDING
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
return Types_1.WAProto.WebMessageInfo.fromObject(messageJSON)
|
|
606
|
-
// return msgId;
|
|
795
|
+
// Add message to retry cache if enabled
|
|
796
|
+
if (messageRetryManager && !participant) {
|
|
797
|
+
messageRetryManager.addRecentMessage(destinationJid, msgId, message);
|
|
798
|
+
}
|
|
799
|
+
}, meId);
|
|
800
|
+
return msgId;
|
|
607
801
|
};
|
|
608
802
|
const getTypeMessage = (msg) => {
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
803
|
+
if (msg.viewOnceMessage) {
|
|
804
|
+
return getTypeMessage(msg.viewOnceMessage.message);
|
|
805
|
+
}
|
|
806
|
+
else if (msg.viewOnceMessageV2) {
|
|
807
|
+
return getTypeMessage(msg.viewOnceMessageV2.message);
|
|
808
|
+
}
|
|
809
|
+
else if (msg.viewOnceMessageV2Extension) {
|
|
810
|
+
return getTypeMessage(msg.viewOnceMessageV2Extension.message);
|
|
811
|
+
}
|
|
812
|
+
else if (msg.ephemeralMessage) {
|
|
813
|
+
return getTypeMessage(msg.ephemeralMessage.message);
|
|
814
|
+
}
|
|
815
|
+
else if (msg.documentWithCaptionMessage) {
|
|
816
|
+
return getTypeMessage(msg.documentWithCaptionMessage.message);
|
|
817
|
+
}
|
|
818
|
+
else if (msg.reactionMessage) {
|
|
819
|
+
return 'reaction';
|
|
820
|
+
}
|
|
821
|
+
else if (msg.pollCreationMessage || msg.pollCreationMessageV2 || msg.pollCreationMessageV3 || msg.pollUpdateMessage) {
|
|
822
|
+
return 'poll';
|
|
823
|
+
}
|
|
824
|
+
else if (getMediaType(msg)) {
|
|
825
|
+
return 'media';
|
|
826
|
+
}
|
|
616
827
|
else {
|
|
617
|
-
return 'text'
|
|
828
|
+
return 'text';
|
|
618
829
|
}
|
|
619
|
-
}
|
|
620
|
-
|
|
830
|
+
};
|
|
621
831
|
const getMediaType = (message) => {
|
|
622
832
|
if (message.imageMessage) {
|
|
623
833
|
return 'image'
|
|
@@ -667,8 +877,7 @@ const makeMessagesSocket = (config) => {
|
|
|
667
877
|
else if (/https:\/\/wa\.me\/p\/\d+\/\d+/.test(message.extendedTextMessage?.text)) {
|
|
668
878
|
return 'productlink'
|
|
669
879
|
}
|
|
670
|
-
}
|
|
671
|
-
|
|
880
|
+
}
|
|
672
881
|
const getButtonType = (message) => {
|
|
673
882
|
if (message.listMessage) {
|
|
674
883
|
return 'list'
|
|
@@ -699,11 +908,11 @@ const makeMessagesSocket = (config) => {
|
|
|
699
908
|
}
|
|
700
909
|
}
|
|
701
910
|
const getPrivacyTokens = async (jids) => {
|
|
702
|
-
const t =
|
|
911
|
+
const t = unixTimestampSeconds().toString();
|
|
703
912
|
const result = await query({
|
|
704
913
|
tag: 'iq',
|
|
705
914
|
attrs: {
|
|
706
|
-
to:
|
|
915
|
+
to: S_WHATSAPP_NET,
|
|
707
916
|
type: 'set',
|
|
708
917
|
xmlns: 'privacy'
|
|
709
918
|
},
|
|
@@ -714,7 +923,7 @@ const makeMessagesSocket = (config) => {
|
|
|
714
923
|
content: jids.map(jid => ({
|
|
715
924
|
tag: 'token',
|
|
716
925
|
attrs: {
|
|
717
|
-
jid:
|
|
926
|
+
jid: jidNormalizedUser(jid),
|
|
718
927
|
t,
|
|
719
928
|
type: 'trusted_contact'
|
|
720
929
|
}
|
|
@@ -723,10 +932,9 @@ const makeMessagesSocket = (config) => {
|
|
|
723
932
|
]
|
|
724
933
|
});
|
|
725
934
|
return result;
|
|
726
|
-
}
|
|
727
|
-
const waUploadToServer =
|
|
728
|
-
const
|
|
729
|
-
const waitForMsgMediaUpdate = (0, Utils_1.bindWaitForEvent)(ev, 'messages.media-update');
|
|
935
|
+
};
|
|
936
|
+
const waUploadToServer = getWAUploadToServer(config, refreshMediaConn);
|
|
937
|
+
const waitForMsgMediaUpdate = bindWaitForEvent(ev, 'messages.media-update');
|
|
730
938
|
return {
|
|
731
939
|
...sock,
|
|
732
940
|
getPrivacyTokens,
|
|
@@ -734,23 +942,23 @@ const makeMessagesSocket = (config) => {
|
|
|
734
942
|
relayMessage,
|
|
735
943
|
sendReceipt,
|
|
736
944
|
sendReceipts,
|
|
737
|
-
rahmi,
|
|
738
945
|
readMessages,
|
|
739
946
|
refreshMediaConn,
|
|
740
|
-
getUSyncDevices,
|
|
741
|
-
createParticipantNodes,
|
|
742
947
|
waUploadToServer,
|
|
743
|
-
sendPeerDataOperationMessage,
|
|
744
948
|
fetchPrivacySettings,
|
|
949
|
+
sendPeerDataOperationMessage,
|
|
950
|
+
createParticipantNodes,
|
|
951
|
+
getUSyncDevices,
|
|
952
|
+
messageRetryManager,
|
|
745
953
|
updateMediaMessage: async (message) => {
|
|
746
|
-
const content =
|
|
954
|
+
const content = assertMediaContent(message.message);
|
|
747
955
|
const mediaKey = content.mediaKey;
|
|
748
956
|
const meId = authState.creds.me.id;
|
|
749
|
-
const node =
|
|
957
|
+
const node = await encryptMediaRetryRequest(message.key, mediaKey, meId);
|
|
750
958
|
let error = undefined;
|
|
751
959
|
await Promise.all([
|
|
752
960
|
sendNode(node),
|
|
753
|
-
waitForMsgMediaUpdate(update => {
|
|
961
|
+
waitForMsgMediaUpdate(async (update) => {
|
|
754
962
|
const result = update.find(c => c.key.id === message.key.id);
|
|
755
963
|
if (result) {
|
|
756
964
|
if (result.error) {
|
|
@@ -758,13 +966,16 @@ const makeMessagesSocket = (config) => {
|
|
|
758
966
|
}
|
|
759
967
|
else {
|
|
760
968
|
try {
|
|
761
|
-
const media =
|
|
762
|
-
if (media.result !==
|
|
763
|
-
const resultStr =
|
|
764
|
-
throw new
|
|
969
|
+
const media = await decryptMediaRetryData(result.media, mediaKey, result.key.id);
|
|
970
|
+
if (media.result !== proto.MediaRetryNotification.ResultType.SUCCESS) {
|
|
971
|
+
const resultStr = proto.MediaRetryNotification.ResultType[media.result];
|
|
972
|
+
throw new Boom(`Media re-upload failed by device (${resultStr})`, {
|
|
973
|
+
data: media,
|
|
974
|
+
statusCode: getStatusCodeForMediaRetry(media.result) || 404
|
|
975
|
+
});
|
|
765
976
|
}
|
|
766
977
|
content.directPath = media.directPath;
|
|
767
|
-
content.url =
|
|
978
|
+
content.url = getUrlFromDirectPath(content.directPath);
|
|
768
979
|
logger.debug({ directPath: media.directPath, key: result.key }, 'media update successful');
|
|
769
980
|
}
|
|
770
981
|
catch (err) {
|
|
@@ -778,133 +989,112 @@ const makeMessagesSocket = (config) => {
|
|
|
778
989
|
if (error) {
|
|
779
990
|
throw error;
|
|
780
991
|
}
|
|
781
|
-
ev.emit('messages.update', [
|
|
782
|
-
{
|
|
783
|
-
key: message.key,
|
|
784
|
-
update: {
|
|
785
|
-
message: message.message
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
]);
|
|
992
|
+
ev.emit('messages.update', [{ key: message.key, update: { message: message.message } }]);
|
|
789
993
|
return message;
|
|
790
994
|
},
|
|
791
995
|
sendMessage: async (jid, content, options = {}) => {
|
|
792
996
|
const userJid = authState.creds.me.id;
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
typeof
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
await groupToggleEphemeral(jid, value)
|
|
997
|
+
if (typeof content === 'object' &&
|
|
998
|
+
'disappearingMessagesInChat' in content &&
|
|
999
|
+
typeof content['disappearingMessagesInChat'] !== 'undefined' &&
|
|
1000
|
+
isJidGroup(jid)) {
|
|
1001
|
+
const { disappearingMessagesInChat } = content;
|
|
1002
|
+
const value = typeof disappearingMessagesInChat === 'boolean'
|
|
1003
|
+
? disappearingMessagesInChat
|
|
1004
|
+
? WA_DEFAULT_EPHEMERAL
|
|
1005
|
+
: 0
|
|
1006
|
+
: disappearingMessagesInChat;
|
|
1007
|
+
await groupToggleEphemeral(jid, value);
|
|
806
1008
|
}
|
|
807
|
-
|
|
808
1009
|
else {
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
...
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
case 'INTERACTIVE':
|
|
830
|
-
const interactiveContent = await rahmi.handleInteractive(content, jid, quoted);
|
|
831
|
-
const interactiveMsg = await Utils_1.generateWAMessageFromContent(jid, interactiveContent, { quoted });
|
|
832
|
-
return await relayMessage(jid, interactiveMsg.message, {
|
|
833
|
-
messageId: interactiveMsg.key.id,
|
|
834
|
-
...getParticipantAttr()
|
|
1010
|
+
const fullMsg = await generateWAMessage(jid, content, {
|
|
1011
|
+
logger,
|
|
1012
|
+
userJid,
|
|
1013
|
+
getUrlInfo: text => getUrlInfo(text, {
|
|
1014
|
+
thumbnailWidth: linkPreviewImageThumbnailWidth,
|
|
1015
|
+
fetchOpts: {
|
|
1016
|
+
timeout: 3000,
|
|
1017
|
+
...(httpRequestOptions || {})
|
|
1018
|
+
},
|
|
1019
|
+
logger,
|
|
1020
|
+
uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
|
|
1021
|
+
}),
|
|
1022
|
+
//TODO: CACHE
|
|
1023
|
+
getProfilePicUrl: sock.profilePictureUrl,
|
|
1024
|
+
getCallLink: sock.createCallLink,
|
|
1025
|
+
upload: async (readStream, opts) => {
|
|
1026
|
+
const up = await waUploadToServer(readStream, {
|
|
1027
|
+
...opts,
|
|
1028
|
+
newsletter: isJidNewsletter(jid)
|
|
835
1029
|
});
|
|
836
|
-
|
|
837
|
-
return await rahmi.handleAlbum(content, jid, quoted)
|
|
838
|
-
case 'EVENT':
|
|
839
|
-
return await rahmi.handleEvent(content, jid, quoted)
|
|
840
|
-
case 'POLL_RESULT':
|
|
841
|
-
return await rahmi.handlePollResult(content, jid, quoted)
|
|
842
|
-
case 'GROUP_STORY':
|
|
843
|
-
return await rahmi.handleGroupStory(content, jid, quoted)
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
const fullMsg = await Utils_1.generateWAMessage(jid, content, {
|
|
847
|
-
logger,
|
|
848
|
-
userJid,
|
|
849
|
-
quoted,
|
|
850
|
-
getUrlInfo: text => link_preview_1.getUrlInfo(text, {
|
|
851
|
-
thumbnailWidth: linkPreviewImageThumbnailWidth,
|
|
852
|
-
fetchOpts: {
|
|
853
|
-
timeout: 3000,
|
|
854
|
-
...axiosOptions || {}
|
|
1030
|
+
return up;
|
|
855
1031
|
},
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
} else if (isAiMsg) {
|
|
885
|
-
additionalNodes.push({
|
|
1032
|
+
mediaCache: config.mediaCache,
|
|
1033
|
+
options: config.options,
|
|
1034
|
+
messageId: generateMessageIDV2(sock.user?.id),
|
|
1035
|
+
...options
|
|
1036
|
+
});
|
|
1037
|
+
const isAiMsg = 'ai' in content && !!content.ai;
|
|
1038
|
+
const isEventMsg = 'event' in content && !!content.event;
|
|
1039
|
+
const isDeleteMsg = 'delete' in content && !!content.delete;
|
|
1040
|
+
const isEditMsg = 'edit' in content && !!content.edit;
|
|
1041
|
+
const isPinMsg = 'pin' in content && !!content.pin;
|
|
1042
|
+
const isPollMessage = 'poll' in content && !!content.poll;
|
|
1043
|
+
const additionalAttributes = {};
|
|
1044
|
+
const additionalNodes = [];
|
|
1045
|
+
// required for delete
|
|
1046
|
+
if (isDeleteMsg) {
|
|
1047
|
+
// if the chat is a group, and I am not the author, then delete the message as an admin
|
|
1048
|
+
if (isJidGroup(content.delete?.remoteJid) && !content.delete?.fromMe) {
|
|
1049
|
+
additionalAttributes.edit = '8';
|
|
1050
|
+
}
|
|
1051
|
+
else {
|
|
1052
|
+
additionalAttributes.edit = '7';
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
else if (isEditMsg) {
|
|
1056
|
+
additionalAttributes.edit = '1';
|
|
1057
|
+
}
|
|
1058
|
+
else if (isAiMsg) {
|
|
1059
|
+
additionalNodes.push({
|
|
886
1060
|
attrs: {
|
|
887
1061
|
biz_bot: '1'
|
|
888
1062
|
}, tag: "bot"
|
|
889
1063
|
});
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
1064
|
+
}
|
|
1065
|
+
else if (isPinMsg) {
|
|
1066
|
+
additionalAttributes.edit = '2';
|
|
1067
|
+
}
|
|
1068
|
+
else if (isPollMessage) {
|
|
1069
|
+
additionalNodes.push({
|
|
1070
|
+
tag: 'meta',
|
|
1071
|
+
attrs: {
|
|
1072
|
+
polltype: 'creation'
|
|
1073
|
+
}
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
else if (isEventMsg) {
|
|
1077
|
+
additionalNodes.push({
|
|
1078
|
+
tag: 'meta',
|
|
1079
|
+
attrs: {
|
|
1080
|
+
event_type: 'creation'
|
|
1081
|
+
}
|
|
1082
|
+
});
|
|
1083
|
+
}
|
|
1084
|
+
await relayMessage(jid, fullMsg.message, {
|
|
1085
|
+
messageId: fullMsg.key.id,
|
|
1086
|
+
useCachedGroupMetadata: options.useCachedGroupMetadata,
|
|
1087
|
+
additionalAttributes,
|
|
1088
|
+
statusJidList: options.statusJidList,
|
|
1089
|
+
additionalNodes: isAiMsg ? additionalNodes : options.additionalNodes
|
|
903
1090
|
});
|
|
904
|
-
|
|
905
|
-
|
|
1091
|
+
if (config.emitOwnEvents) {
|
|
1092
|
+
process.nextTick(() => {
|
|
1093
|
+
processingMutex.mutex(() => upsertMessage(fullMsg, 'append'));
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
1096
|
+
return fullMsg;
|
|
906
1097
|
}
|
|
907
1098
|
}
|
|
908
|
-
}
|
|
909
|
-
};
|
|
910
|
-
exports.makeMessagesSocket = makeMessagesSocket;
|
|
1099
|
+
};
|
|
1100
|
+
};
|