@alannxd/baileys 6.0.5 → 6.0.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/WAProto/fix-import.js +29 -0
- package/WAProto/index.js +160 -201
- package/engine-requirements.js +1 -1
- package/lib/Defaults/baileys-version.json +3 -0
- package/lib/Defaults/index.d.ts +15 -37
- package/lib/Defaults/index.js +136 -119
- package/lib/Defaults/phonenumber-mcc.json +223 -0
- package/lib/Signal/Group/ciphertext-message.d.ts +0 -1
- package/lib/Signal/Group/ciphertext-message.js +5 -2
- package/lib/Signal/Group/group-session-builder.d.ts +3 -4
- package/lib/Signal/Group/group-session-builder.js +41 -7
- package/lib/Signal/Group/group_cipher.d.ts +4 -4
- package/lib/Signal/Group/group_cipher.js +51 -37
- package/lib/Signal/Group/index.d.ts +11 -12
- package/lib/Signal/Group/index.js +57 -12
- package/lib/Signal/Group/keyhelper.d.ts +1 -2
- package/lib/Signal/Group/keyhelper.js +44 -7
- package/lib/Signal/Group/queue-job.d.ts +1 -0
- package/lib/Signal/Group/queue-job.js +57 -0
- package/lib/Signal/Group/sender-chain-key.d.ts +2 -3
- package/lib/Signal/Group/sender-chain-key.js +15 -7
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +1 -2
- package/lib/Signal/Group/sender-key-distribution-message.js +11 -8
- package/lib/Signal/Group/sender-key-message.d.ts +1 -2
- package/lib/Signal/Group/sender-key-message.js +12 -9
- package/lib/Signal/Group/sender-key-name.d.ts +0 -1
- package/lib/Signal/Group/sender-key-name.js +5 -2
- package/lib/Signal/Group/sender-key-record.d.ts +2 -3
- package/lib/Signal/Group/sender-key-record.js +21 -9
- package/lib/Signal/Group/sender-key-state.d.ts +6 -7
- package/lib/Signal/Group/sender-key-state.js +42 -27
- package/lib/Signal/Group/sender-message-key.d.ts +0 -1
- package/lib/Signal/Group/sender-message-key.js +7 -4
- package/lib/Signal/libsignal.d.ts +3 -5
- package/lib/Signal/libsignal.js +90 -347
- package/lib/Socket/Client/{types.d.ts → abstract-socket-client.d.ts} +5 -4
- package/lib/Socket/Client/abstract-socket-client.js +13 -0
- package/lib/Socket/Client/index.d.ts +3 -3
- package/lib/Socket/Client/index.js +19 -3
- package/lib/Socket/Client/mobile-socket-client.d.ts +13 -0
- package/lib/Socket/Client/mobile-socket-client.js +65 -0
- package/lib/Socket/Client/{websocket.d.ts → web-socket-client.d.ts} +2 -3
- package/lib/Socket/Client/web-socket-client.js +62 -0
- package/lib/Socket/business.d.ts +108 -154
- package/lib/Socket/business.js +43 -162
- package/lib/Socket/chats.d.ts +239 -96
- package/lib/Socket/chats.js +427 -627
- package/lib/Socket/communities.d.ts +146 -239
- package/lib/Socket/communities.js +80 -90
- package/lib/Socket/groups.d.ts +57 -104
- package/lib/Socket/groups.js +161 -154
- package/lib/Socket/index.d.ts +115 -202
- package/lib/Socket/index.js +10 -11
- package/lib/Socket/luxu.d.ts +266 -22
- package/lib/Socket/luxu.js +465 -422
- package/lib/Socket/messages-recv.d.ts +84 -136
- package/lib/Socket/messages-recv.js +615 -1421
- package/lib/Socket/messages-send.d.ts +126 -142
- package/lib/Socket/messages-send.js +671 -878
- package/lib/Socket/newsletter.d.ts +85 -121
- package/lib/Socket/newsletter.js +272 -147
- package/lib/Socket/registration.d.ts +267 -0
- package/lib/Socket/registration.js +166 -0
- package/lib/Socket/socket.d.ts +19 -34
- package/lib/Socket/socket.js +313 -544
- package/lib/Socket/usync.d.ts +36 -0
- package/lib/Socket/usync.js +70 -0
- package/lib/Store/index.d.ts +3 -10
- package/lib/Store/index.js +10 -10
- package/lib/Store/make-cache-manager-store.d.ts +11 -17
- package/lib/Store/make-cache-manager-store.js +41 -43
- package/lib/Store/make-in-memory-store.d.ts +118 -39
- package/lib/Store/make-in-memory-store.js +341 -112
- package/lib/Store/make-ordered-dictionary.d.ts +10 -11
- package/lib/Store/make-ordered-dictionary.js +20 -14
- package/lib/Store/object-repository.d.ts +9 -10
- package/lib/Store/object-repository.js +6 -11
- package/lib/Types/Auth.d.ts +12 -19
- package/lib/Types/Auth.js +2 -2
- package/lib/Types/Call.d.ts +1 -3
- package/lib/Types/Call.js +2 -2
- package/lib/Types/Chat.d.ts +13 -35
- package/lib/Types/Chat.js +4 -8
- package/lib/Types/Contact.d.ts +1 -8
- package/lib/Types/Contact.js +2 -2
- package/lib/Types/Events.d.ts +17 -116
- package/lib/Types/Events.js +2 -2
- package/lib/Types/GroupMetadata.d.ts +5 -21
- package/lib/Types/GroupMetadata.js +2 -2
- package/lib/Types/Label.d.ts +0 -12
- package/lib/Types/Label.js +5 -3
- package/lib/Types/LabelAssociation.d.ts +0 -1
- package/lib/Types/LabelAssociation.js +5 -3
- package/lib/Types/Message.d.ts +58 -105
- package/lib/Types/Message.js +9 -11
- package/lib/Types/Newsletter.d.ts +103 -0
- package/lib/Types/Newsletter.js +38 -0
- package/lib/Types/Product.d.ts +1 -2
- package/lib/Types/Product.js +2 -2
- package/lib/Types/Signal.d.ts +2 -32
- package/lib/Types/Signal.js +2 -2
- package/lib/Types/Socket.d.ts +25 -50
- package/lib/Types/Socket.js +2 -3
- package/lib/Types/State.d.ts +2 -72
- package/lib/Types/State.js +2 -56
- package/lib/Types/USync.d.ts +2 -3
- package/lib/Types/USync.js +2 -2
- package/lib/Types/index.d.ts +14 -22
- package/lib/Types/index.js +31 -15
- package/lib/Utils/auth-utils.d.ts +6 -12
- package/lib/Utils/auth-utils.js +143 -239
- package/lib/Utils/baileys-event-stream.d.ts +16 -0
- package/lib/Utils/baileys-event-stream.js +63 -0
- package/lib/Utils/business.d.ts +2 -3
- package/lib/Utils/business.js +69 -66
- package/lib/Utils/chat-utils.d.ts +23 -52
- package/lib/Utils/chat-utils.js +253 -396
- package/lib/Utils/crypto.d.ts +22 -18
- package/lib/Utils/crypto.js +90 -57
- package/lib/Utils/decode-wa-message.d.ts +8 -55
- package/lib/Utils/decode-wa-message.js +84 -203
- package/lib/Utils/event-buffer.d.ts +8 -9
- package/lib/Utils/event-buffer.js +77 -185
- package/lib/Utils/generics.d.ts +29 -28
- package/lib/Utils/generics.js +210 -180
- package/lib/Utils/history.d.ts +9 -18
- package/lib/Utils/history.js +55 -93
- package/lib/Utils/index.d.ts +17 -22
- package/lib/Utils/index.js +33 -22
- package/lib/Utils/link-preview.d.ts +5 -5
- package/lib/Utils/link-preview.js +24 -16
- package/lib/Utils/logger.d.ts +3 -11
- package/lib/Utils/logger.js +7 -3
- package/lib/Utils/lt-hash.d.ts +12 -8
- package/lib/Utils/lt-hash.js +46 -3
- package/lib/Utils/make-mutex.d.ts +2 -4
- package/lib/Utils/make-mutex.js +34 -24
- package/lib/Utils/messages-media.d.ts +44 -61
- package/lib/Utils/messages-media.js +482 -451
- package/lib/Utils/messages.d.ts +18 -32
- package/lib/Utils/messages.js +369 -458
- package/lib/Utils/noise-handler.d.ts +14 -13
- package/lib/Utils/noise-handler.js +99 -145
- package/lib/Utils/process-message.d.ts +12 -31
- package/lib/Utils/process-message.js +150 -459
- package/lib/Utils/signal.d.ts +5 -20
- package/lib/Utils/signal.js +72 -120
- package/lib/Utils/use-multi-file-auth-state.d.ts +2 -2
- package/lib/Utils/use-multi-file-auth-state.js +27 -29
- package/lib/Utils/validate-connection.d.ts +7 -7
- package/lib/Utils/validate-connection.js +99 -73
- package/lib/WABinary/constants.d.ts +27 -25
- package/lib/WABinary/constants.js +20 -1281
- package/lib/WABinary/decode.d.ts +5 -5
- package/lib/WABinary/decode.js +42 -52
- package/lib/WABinary/encode.d.ts +3 -3
- package/lib/WABinary/encode.js +155 -110
- package/lib/WABinary/generic-utils.d.ts +7 -8
- package/lib/WABinary/generic-utils.js +49 -48
- package/lib/WABinary/index.d.ts +5 -6
- package/lib/WABinary/index.js +21 -6
- package/lib/WABinary/jid-utils.d.ts +8 -25
- package/lib/WABinary/jid-utils.js +40 -74
- package/lib/WABinary/types.d.ts +1 -2
- package/lib/WABinary/types.js +2 -2
- package/lib/WAM/BinaryInfo.d.ts +11 -3
- package/lib/WAM/BinaryInfo.js +5 -2
- package/lib/WAM/constants.d.ts +3 -5
- package/lib/WAM/constants.js +11958 -19461
- package/lib/WAM/encode.d.ts +3 -3
- package/lib/WAM/encode.js +22 -17
- package/lib/WAM/index.d.ts +3 -4
- package/lib/WAM/index.js +19 -4
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +3 -4
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +13 -33
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +2 -3
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +14 -11
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +2 -3
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +12 -9
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +2 -3
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +13 -9
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +3 -4
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +22 -20
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +3 -5
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +8 -13
- package/lib/WAUSync/Protocols/index.d.ts +4 -6
- package/lib/WAUSync/Protocols/index.js +20 -6
- package/lib/WAUSync/USyncQuery.d.ts +4 -6
- package/lib/WAUSync/USyncQuery.js +35 -44
- package/lib/WAUSync/USyncUser.d.ts +5 -10
- package/lib/WAUSync/USyncUser.js +5 -10
- package/lib/WAUSync/index.js +19 -4
- package/lib/index.d.ts +9 -10
- package/lib/index.js +34 -12
- package/package.json +50 -83
- package/WAProto/GenerateStatics.sh +0 -3
- package/WAProto/WAProto.proto +0 -5479
- package/WAProto/fix-imports.js +0 -85
- package/WAProto/index.d.ts +0 -14017
- package/lib/Signal/lid-mapping.d.ts +0 -23
- package/lib/Signal/lid-mapping.js +0 -277
- package/lib/Socket/Client/types.js +0 -11
- package/lib/Socket/Client/websocket.js +0 -54
- package/lib/Socket/mex.d.ts +0 -3
- package/lib/Socket/mex.js +0 -42
- package/lib/Store/keyed-db.d.ts +0 -22
- package/lib/Store/keyed-db.js +0 -108
- package/lib/Types/Bussines.d.ts +0 -25
- package/lib/Types/Bussines.js +0 -2
- package/lib/Types/Mex.d.ts +0 -141
- package/lib/Types/Mex.js +0 -37
- package/lib/Utils/browser-utils.d.ts +0 -4
- package/lib/Utils/browser-utils.js +0 -28
- package/lib/Utils/companion-reg-client-utils.d.ts +0 -17
- package/lib/Utils/companion-reg-client-utils.js +0 -35
- package/lib/Utils/identity-change-handler.d.ts +0 -44
- package/lib/Utils/identity-change-handler.js +0 -50
- package/lib/Utils/message-retry-manager.d.ts +0 -115
- package/lib/Utils/message-retry-manager.js +0 -265
- package/lib/Utils/offline-node-processor.d.ts +0 -17
- package/lib/Utils/offline-node-processor.js +0 -40
- package/lib/Utils/pre-key-manager.d.ts +0 -28
- package/lib/Utils/pre-key-manager.js +0 -106
- package/lib/Utils/reporting-utils.d.ts +0 -11
- package/lib/Utils/reporting-utils.js +0 -258
- package/lib/Utils/stanza-ack.d.ts +0 -11
- package/lib/Utils/stanza-ack.js +0 -38
- package/lib/Utils/sync-action-utils.d.ts +0 -19
- package/lib/Utils/sync-action-utils.js +0 -49
- package/lib/Utils/tc-token-utils.d.ts +0 -37
- package/lib/Utils/tc-token-utils.js +0 -163
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +0 -10
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +0 -25
- package/lib/WAUSync/index.d.ts +0 -4
|
@@ -1,70 +1,75 @@
|
|
|
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
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.makeMessagesSocket = void 0;
|
|
7
|
+
const boom_1 = require("@hapi/boom");
|
|
8
|
+
const node_cache_1 = __importDefault(require("node-cache"));
|
|
9
|
+
const WAProto_1 = require("../../WAProto");
|
|
10
|
+
const Defaults_1 = require("../Defaults");
|
|
11
|
+
const axios_1 = require("axios")
|
|
12
|
+
const Types_1 = require("../Types")
|
|
13
|
+
const Utils_1 = require("../Utils");
|
|
14
|
+
const link_preview_1 = require("../Utils/link-preview");
|
|
15
|
+
const WABinary_1 = require("../WABinary");
|
|
16
|
+
const communities_1 = require("./communities");
|
|
17
|
+
const WAUSync_1 = require("../WAUSync");
|
|
18
|
+
const crypto = require("crypto");
|
|
19
|
+
const imup = require('./luxu');
|
|
20
|
+
var ListType = WAProto_1.proto.Message.ListMessage.ListType;
|
|
21
|
+
const makeMessagesSocket = (config) => {
|
|
22
|
+
const {
|
|
23
|
+
logger,
|
|
24
|
+
linkPreviewImageThumbnailWidth,
|
|
25
|
+
generateHighQualityLinkPreview,
|
|
26
|
+
options: axiosOptions,
|
|
27
|
+
patchMessageBeforeSending
|
|
28
|
+
} = config;
|
|
29
|
+
const sock = (0, communities_1.makeCommunitiesSocket)(config);
|
|
30
|
+
const {
|
|
31
|
+
ev,
|
|
32
|
+
authState,
|
|
33
|
+
processingMutex,
|
|
34
|
+
signalRepository,
|
|
35
|
+
upsertMessage,
|
|
36
|
+
query,
|
|
37
|
+
fetchPrivacySettings,
|
|
38
|
+
generateMessageTag,
|
|
39
|
+
sendNode,
|
|
40
|
+
groupMetadata,
|
|
41
|
+
groupToggleEphemeral,
|
|
42
|
+
executeUSyncQuery
|
|
43
|
+
} = sock;
|
|
44
|
+
const userDevicesCache = config.userDevicesCache || new node_cache_1.default({
|
|
45
|
+
stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.USER_DEVICES,
|
|
46
|
+
useClones: false
|
|
47
|
+
});
|
|
37
48
|
let mediaConn;
|
|
38
|
-
/** Per-socket media host; updated whenever media_conn is fetched. Defaults to the public WhatsApp host. */
|
|
39
|
-
let mediaHost = DEF_MEDIA_HOST;
|
|
40
49
|
const refreshMediaConn = async (forceGet = false) => {
|
|
41
50
|
const media = await mediaConn;
|
|
42
|
-
if (!media || forceGet || new Date().getTime() - media.fetchDate.getTime() > media.ttl * 1000) {
|
|
51
|
+
if (!media || forceGet || (new Date().getTime() - media.fetchDate.getTime()) > media.ttl * 1000) {
|
|
43
52
|
mediaConn = (async () => {
|
|
44
53
|
const result = await query({
|
|
45
54
|
tag: 'iq',
|
|
46
55
|
attrs: {
|
|
47
56
|
type: 'set',
|
|
48
57
|
xmlns: 'w:m',
|
|
49
|
-
to: S_WHATSAPP_NET
|
|
58
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
50
59
|
},
|
|
51
60
|
content: [{ tag: 'media_conn', attrs: {} }]
|
|
52
61
|
});
|
|
53
|
-
const mediaConnNode = getBinaryNodeChild(result, 'media_conn');
|
|
54
|
-
// TODO: explore full length of data that whatsapp provides
|
|
62
|
+
const mediaConnNode = WABinary_1.getBinaryNodeChild(result, 'media_conn');
|
|
55
63
|
const node = {
|
|
56
|
-
hosts: getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
|
|
64
|
+
hosts: WABinary_1.getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
|
|
57
65
|
hostname: attrs.hostname,
|
|
58
|
-
maxContentLengthBytes: +attrs.maxContentLengthBytes
|
|
66
|
+
maxContentLengthBytes: +attrs.maxContentLengthBytes,
|
|
59
67
|
})),
|
|
60
68
|
auth: mediaConnNode.attrs.auth,
|
|
61
69
|
ttl: +mediaConnNode.attrs.ttl,
|
|
62
70
|
fetchDate: new Date()
|
|
63
71
|
};
|
|
64
72
|
logger.debug('fetched media conn');
|
|
65
|
-
if (node.hosts[0]) {
|
|
66
|
-
mediaHost = node.hosts[0].hostname;
|
|
67
|
-
}
|
|
68
73
|
return node;
|
|
69
74
|
})();
|
|
70
75
|
}
|
|
@@ -75,20 +80,17 @@ export const makeMessagesSocket = (config) => {
|
|
|
75
80
|
* used for receipts of phone call, read, delivery etc.
|
|
76
81
|
* */
|
|
77
82
|
const sendReceipt = async (jid, participant, messageIds, type) => {
|
|
78
|
-
if (!messageIds || messageIds.length === 0) {
|
|
79
|
-
throw new Boom('missing ids in receipt');
|
|
80
|
-
}
|
|
81
83
|
const node = {
|
|
82
84
|
tag: 'receipt',
|
|
83
85
|
attrs: {
|
|
84
|
-
id: messageIds[0]
|
|
85
|
-
}
|
|
86
|
+
id: messageIds[0],
|
|
87
|
+
},
|
|
86
88
|
};
|
|
87
89
|
const isReadReceipt = type === 'read' || type === 'read-self';
|
|
88
90
|
if (isReadReceipt) {
|
|
89
|
-
node.attrs.t = unixTimestampSeconds().toString();
|
|
91
|
+
node.attrs.t = (0, Utils_1.unixTimestampSeconds)().toString();
|
|
90
92
|
}
|
|
91
|
-
if (type === 'sender' && (
|
|
93
|
+
if (type === 'sender' && WABinary_1.isJidUser(jid)) {
|
|
92
94
|
node.attrs.recipient = jid;
|
|
93
95
|
node.attrs.to = participant;
|
|
94
96
|
}
|
|
@@ -99,7 +101,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
99
101
|
}
|
|
100
102
|
}
|
|
101
103
|
if (type) {
|
|
102
|
-
node.attrs.type = type;
|
|
104
|
+
node.attrs.type = WABinary_1.isJidNewsLetter(jid) ? 'read-self' : type;
|
|
103
105
|
}
|
|
104
106
|
const remainingMessageIds = messageIds.slice(1);
|
|
105
107
|
if (remainingMessageIds.length) {
|
|
@@ -119,7 +121,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
119
121
|
};
|
|
120
122
|
/** Correctly bulk send receipts to multiple chats, participants */
|
|
121
123
|
const sendReceipts = async (keys, type) => {
|
|
122
|
-
const recps = aggregateMessageKeysNotFromMe(keys);
|
|
124
|
+
const recps = (0, Utils_1.aggregateMessageKeysNotFromMe)(keys);
|
|
123
125
|
for (const { jid, participant, messageIds } of recps) {
|
|
124
126
|
await sendReceipt(jid, participant, messageIds, type);
|
|
125
127
|
}
|
|
@@ -133,450 +135,290 @@ export const makeMessagesSocket = (config) => {
|
|
|
133
135
|
};
|
|
134
136
|
/** Fetch all the devices we've to send a message to */
|
|
135
137
|
const getUSyncDevices = async (jids, useCache, ignoreZeroDevices) => {
|
|
136
|
-
const deviceResults = []
|
|
138
|
+
const deviceResults = []
|
|
139
|
+
|
|
137
140
|
if (!useCache) {
|
|
138
|
-
logger.debug('not using cache for devices')
|
|
141
|
+
logger.debug('not using cache for devices')
|
|
139
142
|
}
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
device,
|
|
151
|
-
jid
|
|
152
|
-
});
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
jid = jidNormalizedUser(jid);
|
|
156
|
-
return { jid, user };
|
|
157
|
-
})
|
|
158
|
-
.filter(jid => jid !== null);
|
|
159
|
-
let mgetDevices;
|
|
160
|
-
if (useCache && userDevicesCache.mget) {
|
|
161
|
-
const usersToFetch = jidsWithUser.map(j => j?.user).filter(Boolean);
|
|
162
|
-
mgetDevices = await userDevicesCache.mget(usersToFetch);
|
|
163
|
-
}
|
|
164
|
-
for (const { jid, user } of jidsWithUser) {
|
|
143
|
+
|
|
144
|
+
const toFetch = []
|
|
145
|
+
|
|
146
|
+
jids = Array.from(new Set(jids))
|
|
147
|
+
|
|
148
|
+
for (let jid of jids) {
|
|
149
|
+
const user = WABinary_1.jidDecode(jid)?.user
|
|
150
|
+
|
|
151
|
+
jid = WABinary_1.jidNormalizedUser(jid)
|
|
152
|
+
|
|
165
153
|
if (useCache) {
|
|
166
|
-
const devices =
|
|
167
|
-
|
|
154
|
+
const devices = userDevicesCache.get(user)
|
|
155
|
+
|
|
168
156
|
if (devices) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
jid: jidEncode(d.user, d.server, d.device)
|
|
172
|
-
}));
|
|
173
|
-
deviceResults.push(...devicesWithJid);
|
|
174
|
-
logger.trace({ user }, 'using cache for devices');
|
|
157
|
+
deviceResults.push(...devices)
|
|
158
|
+
logger.trace({ user }, 'using cache for devices')
|
|
175
159
|
}
|
|
160
|
+
|
|
176
161
|
else {
|
|
177
|
-
toFetch.push(jid)
|
|
162
|
+
toFetch.push(jid)
|
|
178
163
|
}
|
|
179
164
|
}
|
|
165
|
+
|
|
180
166
|
else {
|
|
181
|
-
toFetch.push(jid)
|
|
167
|
+
toFetch.push(jid)
|
|
182
168
|
}
|
|
183
169
|
}
|
|
170
|
+
|
|
184
171
|
if (!toFetch.length) {
|
|
185
|
-
return deviceResults
|
|
186
|
-
}
|
|
187
|
-
const requestedLidUsers = new Set();
|
|
188
|
-
for (const jid of toFetch) {
|
|
189
|
-
if (isLidUser(jid) || isHostedLidUser(jid)) {
|
|
190
|
-
const user = jidDecode(jid)?.user;
|
|
191
|
-
if (user)
|
|
192
|
-
requestedLidUsers.add(user);
|
|
193
|
-
}
|
|
172
|
+
return deviceResults
|
|
194
173
|
}
|
|
195
|
-
|
|
174
|
+
|
|
175
|
+
const query = new WAUSync_1.USyncQuery()
|
|
176
|
+
.withContext('message')
|
|
177
|
+
.withDeviceProtocol()
|
|
178
|
+
|
|
196
179
|
for (const jid of toFetch) {
|
|
197
|
-
query.withUser(new USyncUser().withId(jid))
|
|
180
|
+
query.withUser(new WAUSync_1.USyncUser().withId(jid))
|
|
198
181
|
}
|
|
199
|
-
|
|
182
|
+
|
|
183
|
+
const result = await executeUSyncQuery(query)
|
|
184
|
+
|
|
200
185
|
if (result) {
|
|
201
|
-
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
logger.trace('Storing LID maps from device call');
|
|
205
|
-
await signalRepository.lidMapping.storeLIDPNMappings(lidResults.map(a => ({ lid: a.lid, pn: a.id })));
|
|
206
|
-
// Force-refresh sessions for newly mapped LIDs to align identity addressing
|
|
207
|
-
try {
|
|
208
|
-
const lids = lidResults.map(a => a.lid);
|
|
209
|
-
if (lids.length) {
|
|
210
|
-
await assertSessions(lids, true);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
catch (e) {
|
|
214
|
-
logger.warn({ e, count: lidResults.length }, 'failed to assert sessions for newly mapped LIDs');
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
const extracted = extractDeviceJids(result?.list, authState.creds.me.id, authState.creds.me.lid, ignoreZeroDevices);
|
|
218
|
-
const deviceMap = {};
|
|
186
|
+
const extracted = Utils_1.extractDeviceJids(result?.list, authState.creds.me.id, ignoreZeroDevices)
|
|
187
|
+
const deviceMap = {}
|
|
188
|
+
|
|
219
189
|
for (const item of extracted) {
|
|
220
|
-
deviceMap[item.user] = deviceMap[item.user] || []
|
|
221
|
-
deviceMap[item.user]
|
|
190
|
+
deviceMap[item.user] = deviceMap[item.user] || []
|
|
191
|
+
deviceMap[item.user].push(item)
|
|
192
|
+
deviceResults.push(item)
|
|
222
193
|
}
|
|
223
|
-
|
|
224
|
-
for (const
|
|
225
|
-
|
|
226
|
-
// Process all devices for this user
|
|
227
|
-
for (const item of userDevices) {
|
|
228
|
-
const finalJid = isLidUser
|
|
229
|
-
? jidEncode(user, item.server, item.device)
|
|
230
|
-
: jidEncode(item.user, item.server, item.device);
|
|
231
|
-
deviceResults.push({
|
|
232
|
-
...item,
|
|
233
|
-
jid: finalJid
|
|
234
|
-
});
|
|
235
|
-
logger.debug({
|
|
236
|
-
user: item.user,
|
|
237
|
-
device: item.device,
|
|
238
|
-
finalJid,
|
|
239
|
-
usedLid: isLidUser
|
|
240
|
-
}, 'Processed device with LID priority');
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
await devicesMutex.mutex(async () => {
|
|
244
|
-
if (userDevicesCache.mset) {
|
|
245
|
-
// if the cache supports mset, we can set all devices in one go
|
|
246
|
-
await userDevicesCache.mset(Object.entries(deviceMap).map(([key, value]) => ({ key, value })));
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
for (const key in deviceMap) {
|
|
250
|
-
if (deviceMap[key])
|
|
251
|
-
await userDevicesCache.set(key, deviceMap[key]);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
const userDeviceUpdates = {};
|
|
256
|
-
for (const [userId, devices] of Object.entries(deviceMap)) {
|
|
257
|
-
if (devices && devices.length > 0) {
|
|
258
|
-
userDeviceUpdates[userId] = devices.map(d => d.device?.toString() || '0');
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
if (Object.keys(userDeviceUpdates).length > 0) {
|
|
262
|
-
try {
|
|
263
|
-
await authState.keys.set({ 'device-list': userDeviceUpdates });
|
|
264
|
-
logger.debug({ userCount: Object.keys(userDeviceUpdates).length }, 'stored user device lists for bulk migration');
|
|
265
|
-
}
|
|
266
|
-
catch (error) {
|
|
267
|
-
logger.warn({ error }, 'failed to store user device lists');
|
|
268
|
-
}
|
|
194
|
+
|
|
195
|
+
for (const key in deviceMap) {
|
|
196
|
+
userDevicesCache.set(key, deviceMap[key])
|
|
269
197
|
}
|
|
270
198
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
* Update Member Label
|
|
275
|
-
*/
|
|
276
|
-
const updateMemberLabel = (jid, memberLabel) => {
|
|
277
|
-
return relayMessage(jid, {
|
|
278
|
-
protocolMessage: {
|
|
279
|
-
type: proto.Message.ProtocolMessage.Type.GROUP_MEMBER_LABEL_CHANGE,
|
|
280
|
-
memberLabel: {
|
|
281
|
-
label: memberLabel?.slice(0, 30),
|
|
282
|
-
labelTimestamp: unixTimestampSeconds()
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}, {
|
|
286
|
-
additionalNodes: [
|
|
287
|
-
{
|
|
288
|
-
tag: 'meta',
|
|
289
|
-
attrs: {
|
|
290
|
-
tag_reason: 'user_update',
|
|
291
|
-
appdata: 'member_tag'
|
|
292
|
-
},
|
|
293
|
-
content: undefined
|
|
294
|
-
}
|
|
295
|
-
]
|
|
296
|
-
});
|
|
297
|
-
};
|
|
199
|
+
|
|
200
|
+
return deviceResults
|
|
201
|
+
}
|
|
298
202
|
const assertSessions = async (jids, force) => {
|
|
299
203
|
let didFetchNewSession = false;
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
204
|
+
let jidsRequiringFetch = [];
|
|
205
|
+
if (force) {
|
|
206
|
+
jidsRequiringFetch = jids;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
const addrs = jids.map(jid => (signalRepository
|
|
210
|
+
.jidToSignalProtocolAddress(jid)));
|
|
211
|
+
const sessions = await authState.keys.get('session', addrs);
|
|
212
|
+
for (const jid of jids) {
|
|
213
|
+
const signalId = signalRepository
|
|
214
|
+
.jidToSignalProtocolAddress(jid);
|
|
215
|
+
if (!sessions[signalId]) {
|
|
216
|
+
jidsRequiringFetch.push(jid);
|
|
308
217
|
}
|
|
309
218
|
}
|
|
310
|
-
jidsRequiringFetch.push(jid);
|
|
311
219
|
}
|
|
312
220
|
if (jidsRequiringFetch.length) {
|
|
313
|
-
|
|
314
|
-
const wireJids = [
|
|
315
|
-
...jidsRequiringFetch.filter(jid => !!isLidUser(jid) || !!isHostedLidUser(jid)),
|
|
316
|
-
...((await signalRepository.lidMapping.getLIDsForPNs(jidsRequiringFetch.filter(jid => !!isPnUser(jid) || !!isHostedPnUser(jid)))) || []).map(a => a.lid)
|
|
317
|
-
];
|
|
318
|
-
logger.debug({ jidsRequiringFetch, wireJids }, 'fetching sessions');
|
|
221
|
+
logger.debug({ jidsRequiringFetch }, 'fetching sessions');
|
|
319
222
|
const result = await query({
|
|
320
223
|
tag: 'iq',
|
|
321
224
|
attrs: {
|
|
322
225
|
xmlns: 'encrypt',
|
|
323
226
|
type: 'get',
|
|
324
|
-
to: S_WHATSAPP_NET
|
|
227
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
325
228
|
},
|
|
326
229
|
content: [
|
|
327
230
|
{
|
|
328
231
|
tag: 'key',
|
|
329
232
|
attrs: {},
|
|
330
|
-
content:
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
return { tag: 'user', attrs };
|
|
335
|
-
})
|
|
233
|
+
content: jidsRequiringFetch.map(jid => ({
|
|
234
|
+
tag: 'user',
|
|
235
|
+
attrs: { jid },
|
|
236
|
+
}))
|
|
336
237
|
}
|
|
337
238
|
]
|
|
338
239
|
});
|
|
339
|
-
await parseAndInjectE2ESessions(result, signalRepository);
|
|
240
|
+
await (0, Utils_1.parseAndInjectE2ESessions)(result, signalRepository);
|
|
340
241
|
didFetchNewSession = true;
|
|
341
242
|
}
|
|
342
243
|
return didFetchNewSession;
|
|
343
244
|
};
|
|
245
|
+
|
|
246
|
+
|
|
344
247
|
const sendPeerDataOperationMessage = async (pdoMessage) => {
|
|
345
|
-
//TODO: for later, abstract the logic to send a Peer Message instead of just PDO - useful for App State Key Resync with phone
|
|
346
248
|
if (!authState.creds.me?.id) {
|
|
347
|
-
throw new Boom('Not authenticated')
|
|
249
|
+
throw new boom_1.Boom('Not authenticated')
|
|
348
250
|
}
|
|
251
|
+
|
|
349
252
|
const protocolMessage = {
|
|
350
253
|
protocolMessage: {
|
|
351
254
|
peerDataOperationRequestMessage: pdoMessage,
|
|
352
|
-
type: proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
|
|
255
|
+
type: WAProto_1.proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
|
|
353
256
|
}
|
|
354
257
|
};
|
|
355
|
-
const meJid = jidNormalizedUser(authState.creds.me.id);
|
|
258
|
+
const meJid = WABinary_1.jidNormalizedUser(authState.creds.me.id);
|
|
356
259
|
const msgId = await relayMessage(meJid, protocolMessage, {
|
|
357
260
|
additionalAttributes: {
|
|
358
261
|
category: 'peer',
|
|
359
|
-
|
|
262
|
+
// eslint-disable-next-line camelcase
|
|
263
|
+
push_priority: 'high_force',
|
|
360
264
|
},
|
|
361
|
-
additionalNodes: [
|
|
362
|
-
{
|
|
363
|
-
tag: 'meta',
|
|
364
|
-
attrs: { appdata: 'default' }
|
|
365
|
-
}
|
|
366
|
-
]
|
|
367
265
|
});
|
|
368
266
|
return msgId;
|
|
369
267
|
};
|
|
370
|
-
const createParticipantNodes = async (
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
}
|
|
374
|
-
const patched = await patchMessageBeforeSending(message, recipientJids);
|
|
375
|
-
const patchedMessages = Array.isArray(patched)
|
|
376
|
-
? patched
|
|
377
|
-
: recipientJids.map(jid => ({ recipientJid: jid, message: patched }));
|
|
268
|
+
const createParticipantNodes = async (jids, message, extraAttrs) => {
|
|
269
|
+
const patched = await patchMessageBeforeSending(message, jids);
|
|
270
|
+
const bytes = (0, Utils_1.encodeWAMessage)(patched);
|
|
378
271
|
let shouldIncludeDeviceIdentity = false;
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
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({ jid, data: bytes });
|
|
402
|
-
if (type === 'pkmsg') {
|
|
403
|
-
shouldIncludeDeviceIdentity = true;
|
|
404
|
-
}
|
|
405
|
-
return {
|
|
406
|
-
tag: 'to',
|
|
407
|
-
attrs: { jid },
|
|
408
|
-
content: [
|
|
409
|
-
{
|
|
410
|
-
tag: 'enc',
|
|
411
|
-
attrs: { v: '2', type, ...(extraAttrs || {}) },
|
|
412
|
-
content: ciphertext
|
|
413
|
-
}
|
|
414
|
-
]
|
|
415
|
-
};
|
|
416
|
-
});
|
|
417
|
-
return node;
|
|
418
|
-
}
|
|
419
|
-
catch (err) {
|
|
420
|
-
logger.error({ jid, err }, 'Failed to encrypt for recipient');
|
|
421
|
-
return null;
|
|
272
|
+
const nodes = await Promise.all(jids.map(async (jid) => {
|
|
273
|
+
const { type, ciphertext } = await signalRepository
|
|
274
|
+
.encryptMessage({ jid, data: bytes });
|
|
275
|
+
if (type === 'pkmsg') {
|
|
276
|
+
shouldIncludeDeviceIdentity = true;
|
|
422
277
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
278
|
+
const node = {
|
|
279
|
+
tag: 'to',
|
|
280
|
+
attrs: { jid },
|
|
281
|
+
content: [{
|
|
282
|
+
tag: 'enc',
|
|
283
|
+
attrs: {
|
|
284
|
+
v: '2',
|
|
285
|
+
type,
|
|
286
|
+
...extraAttrs || {}
|
|
287
|
+
},
|
|
288
|
+
content: ciphertext
|
|
289
|
+
}]
|
|
290
|
+
};
|
|
291
|
+
return node;
|
|
292
|
+
}));
|
|
428
293
|
return { nodes, shouldIncludeDeviceIdentity };
|
|
429
294
|
};
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
const
|
|
433
|
-
|
|
434
|
-
let
|
|
295
|
+
|
|
296
|
+
const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, cachedGroupMetadata, useCachedGroupMetadata, statusJidList, AI = true }) => {
|
|
297
|
+
const meId = authState.creds.me.id;
|
|
298
|
+
let shouldIncludeDeviceIdentity = false;
|
|
299
|
+
let didPushAdditional = false
|
|
300
|
+
const { user, server } = WABinary_1.jidDecode(jid);
|
|
435
301
|
const statusJid = 'status@broadcast';
|
|
436
|
-
const { user, server } = jidDecode(jid);
|
|
437
302
|
const isGroup = server === 'g.us';
|
|
438
303
|
const isStatus = jid === statusJid;
|
|
439
304
|
const isLid = server === 'lid';
|
|
305
|
+
const isPrivate = server === 's.whatsapp.net'
|
|
440
306
|
const isNewsletter = server === 'newsletter';
|
|
441
|
-
|
|
442
|
-
const finalJid = jid;
|
|
443
|
-
msgId = msgId || generateMessageIDV2(meId);
|
|
307
|
+
msgId = msgId || (0, Utils_1.generateMessageID)();
|
|
444
308
|
useUserDevicesCache = useUserDevicesCache !== false;
|
|
445
|
-
useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus
|
|
309
|
+
useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus
|
|
446
310
|
const participants = [];
|
|
447
|
-
const destinationJid = !isStatus ?
|
|
311
|
+
const destinationJid = (!isStatus) ? WABinary_1.jidEncode(user, isLid ? 'lid' : isGroup ? 'g.us' : isNewsletter ? 'newsletter' : 's.whatsapp.net') : statusJid;
|
|
448
312
|
const binaryNodeContent = [];
|
|
449
313
|
const devices = [];
|
|
450
|
-
const buttonType = getButtonType(message);
|
|
451
|
-
let didPushAdditional = false;
|
|
452
|
-
let reportingMessage;
|
|
453
314
|
const meMsg = {
|
|
454
315
|
deviceSentMessage: {
|
|
455
316
|
destinationJid,
|
|
456
317
|
message
|
|
457
|
-
}
|
|
458
|
-
messageContextInfo: message.messageContextInfo
|
|
318
|
+
}
|
|
459
319
|
};
|
|
460
|
-
const extraAttrs = {}
|
|
320
|
+
const extraAttrs = {}
|
|
321
|
+
const messages = Utils_1.normalizeMessageContent(message)
|
|
322
|
+
const buttonType = getButtonType(messages);
|
|
461
323
|
if (participant) {
|
|
324
|
+
// when the retry request is not for a group
|
|
325
|
+
// only send to the specific device that asked for a retry
|
|
326
|
+
// otherwise the message is sent out to every device that should be a recipient
|
|
462
327
|
if (!isGroup && !isStatus) {
|
|
463
|
-
additionalAttributes = { ...additionalAttributes, device_fanout: 'false' };
|
|
328
|
+
additionalAttributes = { ...additionalAttributes, 'device_fanout': 'false' };
|
|
464
329
|
}
|
|
465
|
-
const { user, device } = jidDecode(participant.jid);
|
|
466
|
-
devices.push({
|
|
467
|
-
user,
|
|
468
|
-
device,
|
|
469
|
-
jid: participant.jid
|
|
470
|
-
});
|
|
330
|
+
const { user, device } = WABinary_1.jidDecode(participant.jid);
|
|
331
|
+
devices.push({ user, device });
|
|
471
332
|
}
|
|
472
333
|
await authState.keys.transaction(async () => {
|
|
473
|
-
const mediaType = getMediaType(
|
|
334
|
+
const mediaType = getMediaType(messages);
|
|
335
|
+
|
|
474
336
|
if (mediaType) {
|
|
475
|
-
extraAttrs['mediatype'] = mediaType
|
|
476
|
-
}
|
|
477
|
-
if (isNewsletter) {
|
|
478
|
-
const patched = patchMessageBeforeSending ? await patchMessageBeforeSending(message, []) : message;
|
|
479
|
-
const bytes = encodeNewsletterMessage(patched);
|
|
480
|
-
binaryNodeContent.push({
|
|
481
|
-
tag: 'plaintext',
|
|
482
|
-
attrs: {},
|
|
483
|
-
content: bytes
|
|
484
|
-
});
|
|
485
|
-
const stanza = {
|
|
486
|
-
tag: 'message',
|
|
487
|
-
attrs: {
|
|
488
|
-
to: jid,
|
|
489
|
-
id: msgId,
|
|
490
|
-
type: getMessageType(message),
|
|
491
|
-
...(additionalAttributes || {})
|
|
492
|
-
},
|
|
493
|
-
content: binaryNodeContent
|
|
494
|
-
};
|
|
495
|
-
logger.debug({ msgId }, `sending newsletter message to ${jid}`);
|
|
496
|
-
await sendNode(stanza);
|
|
497
|
-
return;
|
|
337
|
+
extraAttrs['mediatype'] = mediaType
|
|
498
338
|
}
|
|
499
|
-
|
|
500
|
-
|
|
339
|
+
|
|
340
|
+
if (messages.pinInChatMessage || messages.keepInChatMessage || message.reactionMessage || message.protocolMessage?.editedMessage) {
|
|
341
|
+
extraAttrs['decrypt-fail'] = 'hide'
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (messages.interactiveResponseMessage?.nativeFlowResponseMessage) {
|
|
345
|
+
extraAttrs['native_flow_name'] = messages.interactiveResponseMessage?.nativeFlowResponseMessage.name
|
|
501
346
|
}
|
|
502
|
-
|
|
347
|
+
|
|
348
|
+
if (isGroup || isStatus) {
|
|
503
349
|
const [groupData, senderKeyMap] = await Promise.all([
|
|
504
350
|
(async () => {
|
|
505
|
-
let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined
|
|
506
|
-
if (groupData
|
|
351
|
+
let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined
|
|
352
|
+
if (groupData) {
|
|
507
353
|
logger.trace({ jid, participants: groupData.participants.length }, 'using cached group metadata');
|
|
508
354
|
}
|
|
355
|
+
|
|
509
356
|
else if (!isStatus) {
|
|
510
|
-
groupData = await groupMetadata(jid)
|
|
357
|
+
groupData = await groupMetadata(jid)
|
|
511
358
|
}
|
|
359
|
+
|
|
512
360
|
return groupData;
|
|
513
361
|
})(),
|
|
514
362
|
(async () => {
|
|
515
363
|
if (!participant && !isStatus) {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
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?
|
|
519
|
-
return result[jid] || {};
|
|
364
|
+
const result = await authState.keys.get('sender-key-memory', [jid])
|
|
365
|
+
return result[jid] || {}
|
|
520
366
|
}
|
|
521
|
-
|
|
522
|
-
|
|
367
|
+
|
|
368
|
+
return {}
|
|
369
|
+
|
|
370
|
+
})()
|
|
523
371
|
]);
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
const patched = await patchMessageBeforeSending(message);
|
|
543
|
-
if (Array.isArray(patched)) {
|
|
544
|
-
throw new Boom('Per-jid patching is not supported in groups');
|
|
372
|
+
if (!participant) {
|
|
373
|
+
const participantsList = (groupData && !isStatus) ? groupData.participants.map(p => p.id) : []
|
|
374
|
+
|
|
375
|
+
if (isStatus && statusJidList) {
|
|
376
|
+
participantsList.push(...statusJidList)
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// if (!isStatus) {
|
|
380
|
+
// const expiration = await getEphemeralGroup(jid)
|
|
381
|
+
// additionalAttributes = {
|
|
382
|
+
// ...additionalAttributes,
|
|
383
|
+
// addressing_mode: 'pn',
|
|
384
|
+
// ...expiration ? { expiration: expiration.toString() } : null
|
|
385
|
+
// }
|
|
386
|
+
// }
|
|
387
|
+
|
|
388
|
+
const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false)
|
|
389
|
+
devices.push(...additionalDevices)
|
|
545
390
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
const
|
|
549
|
-
|
|
391
|
+
|
|
392
|
+
const patched = await patchMessageBeforeSending(message, devices.map(d => WABinary_1.jidEncode(d.user, isLid ? 'lid' : 's.whatsapp.net', d.device)));
|
|
393
|
+
const bytes = Utils_1.encodeWAMessage(patched);
|
|
394
|
+
|
|
550
395
|
const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
|
|
551
396
|
group: destinationJid,
|
|
552
397
|
data: bytes,
|
|
553
|
-
meId
|
|
398
|
+
meId,
|
|
554
399
|
});
|
|
555
|
-
const
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
const
|
|
559
|
-
if (
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
//todo: revamp all this logic
|
|
564
|
-
// 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
|
|
565
|
-
senderKeyRecipients.push(deviceJid);
|
|
566
|
-
senderKeyMap[deviceJid] = true;
|
|
400
|
+
const senderKeyJids = [];
|
|
401
|
+
|
|
402
|
+
for (const { user, device } of devices) {
|
|
403
|
+
const jid = WABinary_1.jidEncode(user, (groupData === null || groupData === void 0 ? void 0 : groupData.addressingMode) === 'lid' ? 'lid' : 's.whatsapp.net', device);
|
|
404
|
+
if (!senderKeyMap[jid] || !!participant) {
|
|
405
|
+
senderKeyJids.push(jid);
|
|
406
|
+
// store that this person has had the sender keys sent to them
|
|
407
|
+
senderKeyMap[jid] = true;
|
|
567
408
|
}
|
|
568
409
|
}
|
|
569
|
-
if
|
|
570
|
-
|
|
410
|
+
// if there are some participants with whom the session has not been established
|
|
411
|
+
// if there are, we re-send the senderkey
|
|
412
|
+
if (senderKeyJids.length) {
|
|
413
|
+
logger.debug({ senderKeyJids }, 'sending new sender key');
|
|
571
414
|
const senderKeyMsg = {
|
|
572
415
|
senderKeyDistributionMessage: {
|
|
573
416
|
axolotlSenderKeyDistributionMessage: senderKeyDistributionMessage,
|
|
574
417
|
groupId: destinationJid
|
|
575
418
|
}
|
|
576
419
|
};
|
|
577
|
-
|
|
578
|
-
await
|
|
579
|
-
const result = await createParticipantNodes(senderKeyRecipients, senderKeyMsg, extraAttrs);
|
|
420
|
+
await assertSessions(senderKeyJids, false);
|
|
421
|
+
const result = await createParticipantNodes(senderKeyJids, senderKeyMsg, extraAttrs)
|
|
580
422
|
shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || result.shouldIncludeDeviceIdentity;
|
|
581
423
|
participants.push(...result.nodes);
|
|
582
424
|
}
|
|
@@ -587,177 +429,104 @@ export const makeMessagesSocket = (config) => {
|
|
|
587
429
|
});
|
|
588
430
|
await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } });
|
|
589
431
|
}
|
|
590
|
-
else {
|
|
591
|
-
//
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
ownId = meLid;
|
|
596
|
-
logger.debug({ to: jid, ownId }, 'Using LID identity for @lid conversation');
|
|
432
|
+
else if (isNewsletter) {
|
|
433
|
+
// Message edit
|
|
434
|
+
if (message.protocolMessage?.editedMessage) {
|
|
435
|
+
msgId = message.protocolMessage.key?.id
|
|
436
|
+
message = message.protocolMessage.editedMessage
|
|
597
437
|
}
|
|
598
|
-
|
|
599
|
-
|
|
438
|
+
|
|
439
|
+
// Message delete
|
|
440
|
+
if (message.protocolMessage?.type === WAProto_1.proto.Message.ProtocolMessage.Type.REVOKE) {
|
|
441
|
+
msgId = message.protocolMessage.key?.id
|
|
442
|
+
message = {}
|
|
600
443
|
}
|
|
601
|
-
|
|
444
|
+
|
|
445
|
+
const patched = await patchMessageBeforeSending(message, [])
|
|
446
|
+
const bytes = Utils_1.encodeNewsletterMessage(patched)
|
|
447
|
+
|
|
448
|
+
binaryNodeContent.push({
|
|
449
|
+
tag: 'plaintext',
|
|
450
|
+
attrs: extraAttrs ? extraAttrs : {},
|
|
451
|
+
content: bytes
|
|
452
|
+
})
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
const { user: meUser } = WABinary_1.jidDecode(meId);
|
|
602
456
|
if (!participant) {
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
: patchedForReporting;
|
|
607
|
-
}
|
|
608
|
-
if (!isRetryResend) {
|
|
609
|
-
const targetUserServer = isLid ? 'lid' : 's.whatsapp.net';
|
|
610
|
-
devices.push({
|
|
611
|
-
user,
|
|
612
|
-
device: 0,
|
|
613
|
-
jid: jidEncode(user, targetUserServer, 0) // rajeh, todo: this entire logic is convoluted and weird.
|
|
614
|
-
});
|
|
615
|
-
if (user !== ownUser) {
|
|
616
|
-
const ownUserServer = isLid ? 'lid' : 's.whatsapp.net';
|
|
617
|
-
const ownUserForAddressing = isLid && meLid ? jidDecode(meLid).user : jidDecode(meId).user;
|
|
618
|
-
devices.push({
|
|
619
|
-
user: ownUserForAddressing,
|
|
620
|
-
device: 0,
|
|
621
|
-
jid: jidEncode(ownUserForAddressing, ownUserServer, 0)
|
|
622
|
-
});
|
|
457
|
+
devices.push({ user })
|
|
458
|
+
if (user !== meUser) {
|
|
459
|
+
devices.push({ user: meUser })
|
|
623
460
|
}
|
|
461
|
+
|
|
624
462
|
if (additionalAttributes?.['category'] !== 'peer') {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
const senderIdentity = isLid && meLid
|
|
629
|
-
? jidEncode(jidDecode(meLid)?.user, 'lid', undefined)
|
|
630
|
-
: jidEncode(jidDecode(meId)?.user, 's.whatsapp.net', undefined);
|
|
631
|
-
// Enumerate devices for sender and target with consistent addressing
|
|
632
|
-
const sessionDevices = await getUSyncDevices([senderIdentity, jid], true, false);
|
|
633
|
-
devices.push(...sessionDevices);
|
|
634
|
-
logger.debug({
|
|
635
|
-
deviceCount: devices.length,
|
|
636
|
-
devices: devices.map(d => `${d.user}:${d.device}@${jidDecode(d.jid)?.server}`)
|
|
637
|
-
}, 'Device enumeration complete with unified addressing');
|
|
463
|
+
const additionalDevices = await getUSyncDevices([meId, jid], !!useUserDevicesCache, true)
|
|
464
|
+
|
|
465
|
+
devices.push(...additionalDevices)
|
|
638
466
|
}
|
|
639
467
|
}
|
|
640
|
-
const
|
|
641
|
-
const
|
|
642
|
-
const
|
|
643
|
-
const { user
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
if (isExactSenderDevice) {
|
|
648
|
-
logger.debug({ jid, meId, meLid }, 'Skipping exact sender device (whatsmeow pattern)');
|
|
649
|
-
continue;
|
|
650
|
-
}
|
|
651
|
-
// Check if this is our device (could match either PN or LID user)
|
|
652
|
-
const isMe = user === mePnUser || user === meLidUser;
|
|
468
|
+
const allJids = [];
|
|
469
|
+
const meJids = [];
|
|
470
|
+
const otherJids = [];
|
|
471
|
+
for (const { user, device } of devices) {
|
|
472
|
+
const isMe = user === meUser
|
|
473
|
+
const jid = WABinary_1.jidEncode(isMe && isLid ? authState.creds?.me?.lid?.split(':')[0] || user : user, isLid ? 'lid' : 's.whatsapp.net', device)
|
|
474
|
+
|
|
653
475
|
if (isMe) {
|
|
654
|
-
|
|
476
|
+
meJids.push(jid)
|
|
655
477
|
}
|
|
478
|
+
|
|
656
479
|
else {
|
|
657
|
-
|
|
480
|
+
otherJids.push(jid)
|
|
658
481
|
}
|
|
659
|
-
|
|
482
|
+
|
|
483
|
+
allJids.push(jid)
|
|
660
484
|
}
|
|
661
|
-
await assertSessions(
|
|
485
|
+
await assertSessions(allJids, false);
|
|
662
486
|
const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = await Promise.all([
|
|
663
|
-
|
|
664
|
-
createParticipantNodes(
|
|
665
|
-
|
|
666
|
-
]);
|
|
487
|
+
createParticipantNodes(meJids, meMsg, extraAttrs),
|
|
488
|
+
createParticipantNodes(otherJids, message, extraAttrs)
|
|
489
|
+
])
|
|
667
490
|
participants.push(...meNodes);
|
|
668
491
|
participants.push(...otherNodes);
|
|
669
|
-
if (meRecipients.length > 0 || otherRecipients.length > 0) {
|
|
670
|
-
extraAttrs['phash'] = generateParticipantHashV2([...meRecipients, ...otherRecipients]);
|
|
671
|
-
}
|
|
672
492
|
shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2;
|
|
673
493
|
}
|
|
674
|
-
if (isRetryResend) {
|
|
675
|
-
const isParticipantLid = isLidUser(participant.jid);
|
|
676
|
-
const isMe = areJidsSameUser(participant.jid, isParticipantLid ? meLid : meId);
|
|
677
|
-
let messageToSend = message;
|
|
678
|
-
if (isGroupOrStatus) {
|
|
679
|
-
let groupSenderIdentity;
|
|
680
|
-
if (meLid && (await signalRepository.hasSenderKey({ group: destinationJid, meId: meLid }))) {
|
|
681
|
-
groupSenderIdentity = meLid;
|
|
682
|
-
}
|
|
683
|
-
else if (await signalRepository.hasSenderKey({ group: destinationJid, meId })) {
|
|
684
|
-
groupSenderIdentity = meId;
|
|
685
|
-
}
|
|
686
|
-
if (groupSenderIdentity) {
|
|
687
|
-
try {
|
|
688
|
-
const skdm = await signalRepository.getSenderKeyDistributionMessage({
|
|
689
|
-
group: destinationJid,
|
|
690
|
-
meId: groupSenderIdentity
|
|
691
|
-
});
|
|
692
|
-
messageToSend = {
|
|
693
|
-
...message,
|
|
694
|
-
senderKeyDistributionMessage: {
|
|
695
|
-
groupId: destinationJid,
|
|
696
|
-
axolotlSenderKeyDistributionMessage: skdm
|
|
697
|
-
}
|
|
698
|
-
};
|
|
699
|
-
}
|
|
700
|
-
catch (err) {
|
|
701
|
-
logger.warn({ err, jid: destinationJid }, 'failed to build SKDM for retry, sending without it');
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
const encodedMessageToSend = isMe
|
|
706
|
-
? encodeWAMessage({
|
|
707
|
-
deviceSentMessage: {
|
|
708
|
-
destinationJid,
|
|
709
|
-
message: messageToSend
|
|
710
|
-
}
|
|
711
|
-
})
|
|
712
|
-
: encodeWAMessage(messageToSend);
|
|
713
|
-
const { type, ciphertext: encryptedContent } = await signalRepository.encryptMessage({
|
|
714
|
-
data: encodedMessageToSend,
|
|
715
|
-
jid: participant.jid
|
|
716
|
-
});
|
|
717
|
-
binaryNodeContent.push({
|
|
718
|
-
tag: 'enc',
|
|
719
|
-
attrs: {
|
|
720
|
-
v: '2',
|
|
721
|
-
type,
|
|
722
|
-
count: participant.count.toString()
|
|
723
|
-
},
|
|
724
|
-
content: encryptedContent
|
|
725
|
-
});
|
|
726
|
-
}
|
|
727
494
|
if (participants.length) {
|
|
728
495
|
if (additionalAttributes?.['category'] === 'peer') {
|
|
729
|
-
const peerNode = participants[0]?.content?.[0]
|
|
496
|
+
const peerNode = participants[0]?.content?.[0]
|
|
497
|
+
|
|
730
498
|
if (peerNode) {
|
|
731
|
-
binaryNodeContent.push(peerNode)
|
|
499
|
+
binaryNodeContent.push(peerNode) // push only enc
|
|
732
500
|
}
|
|
733
501
|
}
|
|
502
|
+
|
|
734
503
|
else {
|
|
735
504
|
binaryNodeContent.push({
|
|
736
505
|
tag: 'participants',
|
|
737
506
|
attrs: {},
|
|
738
507
|
content: participants
|
|
739
|
-
})
|
|
508
|
+
})
|
|
740
509
|
}
|
|
741
510
|
}
|
|
511
|
+
|
|
742
512
|
const stanza = {
|
|
743
513
|
tag: 'message',
|
|
744
514
|
attrs: {
|
|
745
515
|
id: msgId,
|
|
746
|
-
|
|
747
|
-
type: getMessageType(message),
|
|
516
|
+
type: getTypeMessage(messages),
|
|
748
517
|
...(additionalAttributes || {})
|
|
749
518
|
},
|
|
750
519
|
content: binaryNodeContent
|
|
751
|
-
}
|
|
520
|
+
}
|
|
752
521
|
// if the participant to send to is explicitly specified (generally retry recp)
|
|
753
522
|
// ensure the message is only sent to that person
|
|
754
523
|
// if a retry receipt is sent to everyone -- it'll fail decryption for everyone else who received the msg
|
|
755
524
|
if (participant) {
|
|
756
|
-
if (isJidGroup(destinationJid)) {
|
|
525
|
+
if (WABinary_1.isJidGroup(destinationJid)) {
|
|
757
526
|
stanza.attrs.to = destinationJid;
|
|
758
527
|
stanza.attrs.participant = participant.jid;
|
|
759
528
|
}
|
|
760
|
-
else if (areJidsSameUser(participant.jid, meId)) {
|
|
529
|
+
else if (WABinary_1.areJidsSameUser(participant.jid, meId)) {
|
|
761
530
|
stanza.attrs.to = participant.jid;
|
|
762
531
|
stanza.attrs.recipient = destinationJid;
|
|
763
532
|
}
|
|
@@ -769,221 +538,170 @@ export const makeMessagesSocket = (config) => {
|
|
|
769
538
|
stanza.attrs.to = destinationJid;
|
|
770
539
|
}
|
|
771
540
|
if (shouldIncludeDeviceIdentity) {
|
|
772
|
-
;
|
|
773
541
|
stanza.content.push({
|
|
774
542
|
tag: 'device-identity',
|
|
775
543
|
attrs: {},
|
|
776
|
-
content: encodeSignedDeviceIdentity(authState.creds.account, true)
|
|
544
|
+
content: (0, Utils_1.encodeSignedDeviceIdentity)(authState.creds.account, true)
|
|
777
545
|
});
|
|
778
546
|
logger.debug({ jid }, 'adding device identity');
|
|
779
547
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
const filteredNode = getBinaryNodeFilter(additionalNodes)
|
|
783
|
-
|
|
784
|
-
if (filteredNode) {
|
|
785
|
-
didPushAdditional = true
|
|
786
|
-
stanza.content.push(...additionalNodes)
|
|
787
|
-
}
|
|
788
|
-
else {
|
|
789
|
-
stanza.content.push(...content)
|
|
790
|
-
}
|
|
791
|
-
logger.debug({ jid }, 'adding business node')
|
|
792
|
-
}
|
|
793
|
-
if (!isNewsletter && !isGroupOrStatus && aiLabel) {
|
|
548
|
+
|
|
549
|
+
if (AI && isPrivate) {
|
|
794
550
|
const botNode = {
|
|
795
551
|
tag: 'bot',
|
|
796
552
|
attrs: {
|
|
797
553
|
biz_bot: '1'
|
|
798
554
|
}
|
|
799
555
|
}
|
|
800
|
-
|
|
556
|
+
|
|
557
|
+
const filteredBizBot = WABinary_1.getBinaryNodeFilter(additionalNodes ? additionalNodes : [])
|
|
558
|
+
|
|
801
559
|
if (filteredBizBot) {
|
|
802
560
|
stanza.content.push(...additionalNodes)
|
|
803
561
|
didPushAdditional = true
|
|
804
562
|
}
|
|
563
|
+
|
|
805
564
|
else {
|
|
806
565
|
stanza.content.push(botNode)
|
|
807
566
|
}
|
|
808
567
|
}
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
};
|
|
821
|
-
const reportingNode = await getMessageReportingToken(encoded, reportingMessage, reportingKey);
|
|
822
|
-
if (reportingNode) {
|
|
823
|
-
;
|
|
824
|
-
stanza.content.push(reportingNode);
|
|
825
|
-
logger.trace({ jid }, 'added reporting token to message');
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
catch (error) {
|
|
829
|
-
logger.warn({ jid, trace: error?.stack }, 'failed to attach reporting token');
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
// WA Web never attaches tctoken to peer (AppStateSync) messages — server rejects with 479
|
|
833
|
-
const isPeerMessage = additionalAttributes?.['category'] === 'peer';
|
|
834
|
-
const is1on1Send = !isGroup && !isRetryResend && !isStatus && !isNewsletter && !isPeerMessage;
|
|
835
|
-
// Resolve destination to LID for tctoken storage — matches Signal session key pattern
|
|
836
|
-
const tcTokenJid = is1on1Send ? await resolveTcTokenJid(destinationJid, getLIDForPN) : destinationJid;
|
|
837
|
-
const contactTcTokenData = is1on1Send ? await authState.keys.get('tctoken', [tcTokenJid]) : {};
|
|
838
|
-
const existingTokenEntry = contactTcTokenData[tcTokenJid];
|
|
839
|
-
let tcTokenBuffer = existingTokenEntry?.token;
|
|
840
|
-
// Treat expired tokens the same as missing — clear from cache
|
|
841
|
-
if (tcTokenBuffer?.length && isTcTokenExpired(existingTokenEntry?.timestamp)) {
|
|
842
|
-
logger.debug({ jid: destinationJid, timestamp: existingTokenEntry?.timestamp }, 'tctoken expired, clearing');
|
|
843
|
-
tcTokenBuffer = undefined;
|
|
844
|
-
// Preserve senderTimestamp so the fire-and-forget issuance dedupe survives cleanup.
|
|
845
|
-
const cleared = existingTokenEntry?.senderTimestamp !== undefined
|
|
846
|
-
? { token: Buffer.alloc(0), senderTimestamp: existingTokenEntry.senderTimestamp }
|
|
847
|
-
: null;
|
|
848
|
-
try {
|
|
849
|
-
await authState.keys.set({ tctoken: { [tcTokenJid]: cleared } });
|
|
850
|
-
}
|
|
851
|
-
catch (err) {
|
|
852
|
-
logger.debug({ jid: destinationJid, err: err?.message }, 'failed to persist tctoken expiry cleanup');
|
|
568
|
+
|
|
569
|
+
if(!isNewsletter && buttonType && !isStatus) {
|
|
570
|
+
const content = WABinary_1.getAdditionalNode(buttonType)
|
|
571
|
+
const filteredNode = WABinary_1.getBinaryNodeFilter(additionalNodes)
|
|
572
|
+
|
|
573
|
+
if (filteredNode) {
|
|
574
|
+
didPushAdditional = true
|
|
575
|
+
stanza.content.push(...additionalNodes)
|
|
576
|
+
}
|
|
577
|
+
else {
|
|
578
|
+
stanza.content.push(...content)
|
|
853
579
|
}
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
stanza.content.push({
|
|
858
|
-
tag: 'tctoken',
|
|
859
|
-
attrs: {},
|
|
860
|
-
content: tcTokenBuffer
|
|
861
|
-
});
|
|
862
|
-
}
|
|
580
|
+
logger.debug({ jid }, 'adding business node')
|
|
581
|
+
}
|
|
582
|
+
|
|
863
583
|
if (!didPushAdditional && additionalNodes && additionalNodes.length > 0) {
|
|
864
|
-
;
|
|
865
584
|
stanza.content.push(...additionalNodes);
|
|
866
585
|
}
|
|
586
|
+
|
|
867
587
|
logger.debug({ msgId }, `sending message to ${participants.length} devices`);
|
|
868
588
|
await sendNode(stanza);
|
|
869
|
-
|
|
870
|
-
// WA Web skips protocol messages and PSA/bot contacts (TcTokenChatAction: isRegularUser)
|
|
871
|
-
const isProtocolMsg = !!normalizeMessageContent(message)?.protocolMessage;
|
|
872
|
-
const isBotOrPSA = destinationJid === PSA_WID || isJidBot(destinationJid) || isJidMetaAI(destinationJid);
|
|
873
|
-
if (is1on1Send &&
|
|
874
|
-
!isProtocolMsg &&
|
|
875
|
-
!isBotOrPSA &&
|
|
876
|
-
shouldSendNewTcToken(existingTokenEntry?.senderTimestamp) &&
|
|
877
|
-
!inFlightTcTokenIssuance.has(tcTokenJid)) {
|
|
878
|
-
inFlightTcTokenIssuance.add(tcTokenJid);
|
|
879
|
-
const issueTimestamp = unixTimestampSeconds();
|
|
880
|
-
const getPNForLID = signalRepository.lidMapping.getPNForLID.bind(signalRepository.lidMapping);
|
|
881
|
-
resolveIssuanceJid(destinationJid, sock.serverProps.lidTrustedTokenIssueToLid, getLIDForPN, getPNForLID)
|
|
882
|
-
.then(issueJid => issuePrivacyTokens([issueJid], issueTimestamp))
|
|
883
|
-
.then(async (result) => {
|
|
884
|
-
await storeTcTokensFromIqResult({
|
|
885
|
-
result,
|
|
886
|
-
fallbackJid: tcTokenJid,
|
|
887
|
-
keys: authState.keys,
|
|
888
|
-
getLIDForPN
|
|
889
|
-
});
|
|
890
|
-
const currentData = await authState.keys.get('tctoken', [tcTokenJid]);
|
|
891
|
-
const currentEntry = currentData[tcTokenJid];
|
|
892
|
-
const indexWrite = await buildMergedTcTokenIndexWrite(authState.keys, [tcTokenJid]);
|
|
893
|
-
await authState.keys.set({
|
|
894
|
-
tctoken: {
|
|
895
|
-
[tcTokenJid]: {
|
|
896
|
-
token: Buffer.alloc(0),
|
|
897
|
-
...currentEntry,
|
|
898
|
-
senderTimestamp: issueTimestamp
|
|
899
|
-
},
|
|
900
|
-
...indexWrite
|
|
901
|
-
}
|
|
902
|
-
});
|
|
903
|
-
})
|
|
904
|
-
.catch(err => {
|
|
905
|
-
logger.debug({ jid: destinationJid, err: err?.message }, 'fire-and-forget tctoken issuance failed');
|
|
906
|
-
})
|
|
907
|
-
.finally(() => {
|
|
908
|
-
inFlightTcTokenIssuance.delete(tcTokenJid);
|
|
909
|
-
});
|
|
910
|
-
}
|
|
911
|
-
// Add message to retry cache if enabled
|
|
912
|
-
if (messageRetryManager && !participant) {
|
|
913
|
-
messageRetryManager.addRecentMessage(destinationJid, msgId, message);
|
|
914
|
-
}
|
|
915
|
-
}, meId);
|
|
589
|
+
});
|
|
916
590
|
return msgId;
|
|
917
591
|
};
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
592
|
+
|
|
593
|
+
const sendMessageMembers = async (jid, message, options = {}) => {
|
|
594
|
+
const {
|
|
595
|
+
messageId: idm,
|
|
596
|
+
quoted,
|
|
597
|
+
delayMs = 1500,
|
|
598
|
+
useUserDevicesCache = true,
|
|
599
|
+
cachedGroupMetadata
|
|
600
|
+
} = options;
|
|
601
|
+
|
|
602
|
+
const { server } = WABinary_1.jidDecode(jid);
|
|
603
|
+
if (server !== "g.us") throw new Error("@g.us server required");
|
|
604
|
+
|
|
605
|
+
const meId = authState.creds.me.id;
|
|
606
|
+
const messages = Utils_1.normalizeMessageContent(message);
|
|
607
|
+
const groupData = cachedGroupMetadata? await cachedGroupMetadata(jid) : await groupMetadata(jid);
|
|
608
|
+
const isLid = groupData.addressingMode === "lid";
|
|
609
|
+
const participantJids = groupData.participants.map(p => p.id);
|
|
610
|
+
|
|
611
|
+
logger.info(`Sending message to ${participantJids.length} members from ${jid}`);
|
|
612
|
+
|
|
613
|
+
for (let i = 0; i < participantJids.length; i++) {
|
|
614
|
+
const jid = participantJids[i];
|
|
615
|
+
if (WABinary_1.areJidsSameUser(jid, meId)) continue;
|
|
616
|
+
|
|
617
|
+
try {
|
|
618
|
+
const msgId = `${idm || Utils_1.generateMessageID()}_${i}`;
|
|
619
|
+
const fullMsg = await Utils_1.generateWAMessageFromContent(jid, message, {
|
|
620
|
+
messageId: msgId,
|
|
621
|
+
quoted
|
|
622
|
+
})
|
|
623
|
+
await relayMessage(jid, fullMsg.message, {
|
|
624
|
+
messageId: fullMsg.key.id
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
logger.debug(`Message successfully sent to ${jid}`);
|
|
628
|
+
if (delayMs && i < participantJids.length - 1) {
|
|
629
|
+
await new Promise(z => setTimeout(z, delayMs));
|
|
630
|
+
}
|
|
631
|
+
} catch (e) {
|
|
632
|
+
logger.error({ jid, e }, "Error sending message to");
|
|
936
633
|
}
|
|
937
|
-
|
|
634
|
+
}
|
|
635
|
+
return JSON.stringify({
|
|
636
|
+
members_total: participantJids.length,
|
|
637
|
+
message
|
|
638
|
+
}, null, 4);
|
|
938
639
|
};
|
|
640
|
+
|
|
641
|
+
const getTypeMessage = (msg) => {
|
|
642
|
+
const message = Utils_1.normalizeMessageContent(msg)
|
|
643
|
+
if (message.reactionMessage) {
|
|
644
|
+
return 'reaction'
|
|
645
|
+
}
|
|
646
|
+
else if (getMediaType(message)) {
|
|
647
|
+
return 'media'
|
|
648
|
+
}
|
|
649
|
+
else {
|
|
650
|
+
return 'text'
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
939
654
|
const getMediaType = (message) => {
|
|
940
655
|
if (message.imageMessage) {
|
|
941
|
-
return 'image'
|
|
656
|
+
return 'image'
|
|
942
657
|
}
|
|
943
658
|
else if (message.videoMessage) {
|
|
944
|
-
return message.videoMessage.gifPlayback ? 'gif' : 'video'
|
|
659
|
+
return message.videoMessage.gifPlayback ? 'gif' : 'video'
|
|
945
660
|
}
|
|
946
661
|
else if (message.audioMessage) {
|
|
947
|
-
return message.audioMessage.ptt ? 'ptt' : 'audio'
|
|
662
|
+
return message.audioMessage.ptt ? 'ptt' : 'audio'
|
|
948
663
|
}
|
|
949
664
|
else if (message.contactMessage) {
|
|
950
|
-
return 'vcard'
|
|
665
|
+
return 'vcard'
|
|
951
666
|
}
|
|
952
667
|
else if (message.documentMessage) {
|
|
953
|
-
return 'document'
|
|
668
|
+
return 'document'
|
|
954
669
|
}
|
|
955
670
|
else if (message.contactsArrayMessage) {
|
|
956
|
-
return 'contact_array'
|
|
671
|
+
return 'contact_array'
|
|
957
672
|
}
|
|
958
673
|
else if (message.liveLocationMessage) {
|
|
959
|
-
return 'livelocation'
|
|
674
|
+
return 'livelocation'
|
|
960
675
|
}
|
|
961
676
|
else if (message.stickerMessage) {
|
|
962
|
-
return 'sticker'
|
|
677
|
+
return 'sticker'
|
|
963
678
|
}
|
|
964
679
|
else if (message.listMessage) {
|
|
965
|
-
return 'list'
|
|
680
|
+
return 'list'
|
|
966
681
|
}
|
|
967
682
|
else if (message.listResponseMessage) {
|
|
968
|
-
return 'list_response'
|
|
683
|
+
return 'list_response'
|
|
969
684
|
}
|
|
970
685
|
else if (message.buttonsResponseMessage) {
|
|
971
|
-
return 'buttons_response'
|
|
686
|
+
return 'buttons_response'
|
|
972
687
|
}
|
|
973
688
|
else if (message.orderMessage) {
|
|
974
|
-
return 'order'
|
|
689
|
+
return 'order'
|
|
975
690
|
}
|
|
976
691
|
else if (message.productMessage) {
|
|
977
|
-
return 'product'
|
|
692
|
+
return 'product'
|
|
978
693
|
}
|
|
979
694
|
else if (message.interactiveResponseMessage) {
|
|
980
|
-
return 'native_flow_response'
|
|
695
|
+
return 'native_flow_response'
|
|
981
696
|
}
|
|
982
697
|
else if (message.groupInviteMessage) {
|
|
983
|
-
return 'url'
|
|
698
|
+
return 'url'
|
|
984
699
|
}
|
|
985
|
-
|
|
986
|
-
|
|
700
|
+
else if (/https:\/\/wa\.me\/p\/\d+\/\d+/.test(message.extendedTextMessage?.text)) {
|
|
701
|
+
return 'productlink'
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
|
|
987
705
|
const getButtonType = (message) => {
|
|
988
706
|
if (message.listMessage) {
|
|
989
707
|
return 'list'
|
|
@@ -1013,13 +731,13 @@ export const makeMessagesSocket = (config) => {
|
|
|
1013
731
|
else if (message.interactiveMessage?.nativeFlowMessage) {
|
|
1014
732
|
return 'native_flow'
|
|
1015
733
|
}
|
|
1016
|
-
}
|
|
1017
|
-
const
|
|
1018
|
-
const t =
|
|
734
|
+
}
|
|
735
|
+
const getPrivacyTokens = async (jids) => {
|
|
736
|
+
const t = Utils_1.unixTimestampSeconds().toString();
|
|
1019
737
|
const result = await query({
|
|
1020
738
|
tag: 'iq',
|
|
1021
739
|
attrs: {
|
|
1022
|
-
to: S_WHATSAPP_NET,
|
|
740
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
1023
741
|
type: 'set',
|
|
1024
742
|
xmlns: 'privacy'
|
|
1025
743
|
},
|
|
@@ -1030,7 +748,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
1030
748
|
content: jids.map(jid => ({
|
|
1031
749
|
tag: 'token',
|
|
1032
750
|
attrs: {
|
|
1033
|
-
jid: jidNormalizedUser(jid),
|
|
751
|
+
jid: WABinary_1.jidNormalizedUser(jid),
|
|
1034
752
|
t,
|
|
1035
753
|
type: 'trusted_contact'
|
|
1036
754
|
}
|
|
@@ -1039,47 +757,158 @@ export const makeMessagesSocket = (config) => {
|
|
|
1039
757
|
]
|
|
1040
758
|
});
|
|
1041
759
|
return result;
|
|
1042
|
-
}
|
|
1043
|
-
const waUploadToServer = getWAUploadToServer(config, refreshMediaConn);
|
|
1044
|
-
const
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
760
|
+
}
|
|
761
|
+
const waUploadToServer = (0, Utils_1.getWAUploadToServer)(config, refreshMediaConn);
|
|
762
|
+
const luki = new imup(Utils_1, waUploadToServer, relayMessage, authState);
|
|
763
|
+
const waitForMsgMediaUpdate = (0, Utils_1.bindWaitForEvent)(ev, 'messages.media-update');
|
|
764
|
+
const sendMessage = async (jid, content, options = {}) => {
|
|
765
|
+
const userJid = authState.creds.me.id;
|
|
766
|
+
delete options.ephemeralExpiration
|
|
767
|
+
const { ptcp = false, quoted } = options;
|
|
768
|
+
const getParticipantAttr = () => ptcp ? { participant: { jid } } : {};
|
|
769
|
+
const messageType = luki.detectType(content);
|
|
770
|
+
if (typeof content === 'object' && 'disappearingMessagesInChat' in content &&
|
|
771
|
+
typeof content['disappearingMessagesInChat'] !== 'undefined' && WABinary_1.isJidGroup(jid)) {
|
|
772
|
+
const { disappearingMessagesInChat } = content
|
|
773
|
+
|
|
774
|
+
const value = typeof disappearingMessagesInChat === 'boolean' ?
|
|
775
|
+
(disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :
|
|
776
|
+
disappearingMessagesInChat
|
|
777
|
+
|
|
778
|
+
await groupToggleEphemeral(jid, value)
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
else {
|
|
782
|
+
let mediaHandle
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
if (messageType) {
|
|
786
|
+
switch(messageType) {
|
|
787
|
+
case 'PAYMENT':
|
|
788
|
+
const paymentContent = await luki.handlePayment(content, quoted);
|
|
789
|
+
return await relayMessage(jid, paymentContent, {
|
|
790
|
+
messageId: Utils_1.generateMessageID(),
|
|
791
|
+
...getParticipantAttr()
|
|
792
|
+
});
|
|
793
|
+
|
|
794
|
+
case 'PRODUCT':
|
|
795
|
+
const productContent = await luki.handleProduct(content, jid, quoted);
|
|
796
|
+
const productMsg = await Utils_1.generateWAMessageFromContent(jid, productContent, { quoted });
|
|
797
|
+
return await relayMessage(jid, productMsg.message, {
|
|
798
|
+
messageId: productMsg.key.id,
|
|
799
|
+
...getParticipantAttr()
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
case 'INTERACTIVE':
|
|
803
|
+
const interactiveContent = await luki.handleInteractive(content, jid, quoted);
|
|
804
|
+
const interactiveMsg = await Utils_1.generateWAMessageFromContent(jid, interactiveContent, { quoted });
|
|
805
|
+
return await relayMessage(jid, interactiveMsg.message, {
|
|
806
|
+
messageId: interactiveMsg.key.id,
|
|
807
|
+
...getParticipantAttr()
|
|
808
|
+
});
|
|
809
|
+
|
|
810
|
+
case 'ALBUM':
|
|
811
|
+
return await luki.handleAlbum(content, jid, quoted)
|
|
812
|
+
case 'EVENT':
|
|
813
|
+
return await luki.handleEvent(content, jid, quoted)
|
|
814
|
+
case 'POLL_RESULT':
|
|
815
|
+
return await luki.handlePollResult(content, jid, quoted)
|
|
816
|
+
case 'ORDER':
|
|
817
|
+
return await luki.handleOrderMessage(content, jid, quoted)
|
|
818
|
+
case 'GROUP_STATUS':
|
|
819
|
+
return await luki.handleGroupStory(content, jid, quoted)
|
|
820
|
+
case 'GROUP_LABEL':
|
|
821
|
+
return await luki.handleGbLabel(content, jid)
|
|
822
|
+
}
|
|
1048
823
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
824
|
+
const fullMsg = await Utils_1.generateWAMessage(jid, content, {
|
|
825
|
+
logger,
|
|
826
|
+
userJid,
|
|
827
|
+
quoted,
|
|
828
|
+
getUrlInfo: text => link_preview_1.getUrlInfo(text, {
|
|
829
|
+
thumbnailWidth: linkPreviewImageThumbnailWidth,
|
|
830
|
+
fetchOpts: {
|
|
831
|
+
timeout: 3000,
|
|
832
|
+
...axiosOptions || {}
|
|
833
|
+
},
|
|
834
|
+
logger,
|
|
835
|
+
uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
|
|
836
|
+
}),
|
|
837
|
+
upload: async (readStream, opts) => {
|
|
838
|
+
const up = await waUploadToServer(readStream, {
|
|
839
|
+
...opts,
|
|
840
|
+
newsletter: WABinary_1.isJidNewsLetter(jid)
|
|
841
|
+
});
|
|
842
|
+
return up;
|
|
843
|
+
},
|
|
844
|
+
mediaCache: config.mediaCache,
|
|
845
|
+
options: config.options,
|
|
846
|
+
...options
|
|
847
|
+
});
|
|
848
|
+
|
|
849
|
+
const isDeleteMsg = 'delete' in content && !!content.delete;
|
|
850
|
+
const isEditMsg = 'edit' in content && !!content.edit;
|
|
851
|
+
const isAiMsg = 'ai' in content && !!content.ai;
|
|
852
|
+
|
|
853
|
+
const additionalAttributes = {};
|
|
854
|
+
const additionalNodes = [];
|
|
855
|
+
|
|
856
|
+
if (isDeleteMsg) {
|
|
857
|
+
const fromMe = content.delete?.fromMe;
|
|
858
|
+
const isGroup = WABinary_1.isJidGroup(content.delete?.remoteJid);
|
|
859
|
+
additionalAttributes.edit = (isGroup && !fromMe) || WABinary_1.isJidNewsLetter(jid) ? '8' : '7';
|
|
860
|
+
} else if (isEditMsg) {
|
|
861
|
+
additionalAttributes.edit = WABinary_1.isJidNewsLetter(jid) ? '3' : '1';
|
|
862
|
+
} else if (isAiMsg) {
|
|
863
|
+
additionalNodes.push({
|
|
864
|
+
attrs: {
|
|
865
|
+
biz_bot: '1'
|
|
866
|
+
}, tag: "bot"
|
|
867
|
+
});
|
|
1052
868
|
}
|
|
1053
|
-
|
|
869
|
+
|
|
870
|
+
await relayMessage(jid, fullMsg.message, {
|
|
871
|
+
messageId: fullMsg.key.id,
|
|
872
|
+
cachedGroupMetadata: options.cachedGroupMetadata,
|
|
873
|
+
additionalNodes: isAiMsg ? additionalNodes : options.additionalNodes,
|
|
874
|
+
additionalAttributes,
|
|
875
|
+
statusJidList: options.statusJidList
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
if (config.emitOwnEvents) {
|
|
879
|
+
process.nextTick(() => {
|
|
880
|
+
processingMutex.mutex(() => upsertMessage(fullMsg, 'append'));
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
return fullMsg;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
1054
886
|
return {
|
|
1055
887
|
...sock,
|
|
1056
|
-
|
|
1057
|
-
devicesMutex,
|
|
1058
|
-
issuePrivacyTokens,
|
|
888
|
+
getPrivacyTokens,
|
|
1059
889
|
assertSessions,
|
|
1060
890
|
relayMessage,
|
|
891
|
+
sendMessageMembers,
|
|
1061
892
|
sendReceipt,
|
|
1062
893
|
sendReceipts,
|
|
894
|
+
luki,
|
|
895
|
+
sendMessage,
|
|
1063
896
|
readMessages,
|
|
1064
897
|
refreshMediaConn,
|
|
1065
|
-
|
|
1066
|
-
|
|
898
|
+
getUSyncDevices,
|
|
899
|
+
createParticipantNodes,
|
|
1067
900
|
waUploadToServer,
|
|
1068
|
-
fetchPrivacySettings,
|
|
1069
901
|
sendPeerDataOperationMessage,
|
|
1070
|
-
|
|
1071
|
-
getUSyncDevices,
|
|
1072
|
-
messageRetryManager,
|
|
1073
|
-
updateMemberLabel,
|
|
902
|
+
fetchPrivacySettings,
|
|
1074
903
|
updateMediaMessage: async (message) => {
|
|
1075
|
-
const content = assertMediaContent(message.message);
|
|
904
|
+
const content = (0, Utils_1.assertMediaContent)(message.message);
|
|
1076
905
|
const mediaKey = content.mediaKey;
|
|
1077
906
|
const meId = authState.creds.me.id;
|
|
1078
|
-
const node = encryptMediaRetryRequest(message.key, mediaKey, meId);
|
|
907
|
+
const node = (0, Utils_1.encryptMediaRetryRequest)(message.key, mediaKey, meId);
|
|
1079
908
|
let error = undefined;
|
|
1080
909
|
await Promise.all([
|
|
1081
910
|
sendNode(node),
|
|
1082
|
-
waitForMsgMediaUpdate(
|
|
911
|
+
waitForMsgMediaUpdate(update => {
|
|
1083
912
|
const result = update.find(c => c.key.id === message.key.id);
|
|
1084
913
|
if (result) {
|
|
1085
914
|
if (result.error) {
|
|
@@ -1087,16 +916,13 @@ export const makeMessagesSocket = (config) => {
|
|
|
1087
916
|
}
|
|
1088
917
|
else {
|
|
1089
918
|
try {
|
|
1090
|
-
const media = decryptMediaRetryData(result.media, mediaKey, result.key.id);
|
|
1091
|
-
if (media.result !== proto.MediaRetryNotification.ResultType.SUCCESS) {
|
|
1092
|
-
const resultStr = proto.MediaRetryNotification.ResultType[media.result];
|
|
1093
|
-
throw new Boom(`Media re-upload failed by device (${resultStr})`, {
|
|
1094
|
-
data: media,
|
|
1095
|
-
statusCode: getStatusCodeForMediaRetry(media.result) || 404
|
|
1096
|
-
});
|
|
919
|
+
const media = (0, Utils_1.decryptMediaRetryData)(result.media, mediaKey, result.key.id);
|
|
920
|
+
if (media.result !== WAProto_1.proto.MediaRetryNotification.ResultType.SUCCESS) {
|
|
921
|
+
const resultStr = WAProto_1.proto.MediaRetryNotification.ResultType[media.result];
|
|
922
|
+
throw new boom_1.Boom(`Media re-upload failed by device (${resultStr})`, { data: media, statusCode: (0, Utils_1.getStatusCodeForMediaRetry)(media.result) || 404 });
|
|
1097
923
|
}
|
|
1098
924
|
content.directPath = media.directPath;
|
|
1099
|
-
content.url = getUrlFromDirectPath(content.directPath
|
|
925
|
+
content.url = (0, Utils_1.getUrlFromDirectPath)(content.directPath);
|
|
1100
926
|
logger.debug({ directPath: media.directPath, key: result.key }, 'media update successful');
|
|
1101
927
|
}
|
|
1102
928
|
catch (err) {
|
|
@@ -1110,182 +936,149 @@ export const makeMessagesSocket = (config) => {
|
|
|
1110
936
|
if (error) {
|
|
1111
937
|
throw error;
|
|
1112
938
|
}
|
|
1113
|
-
ev.emit('messages.update', [
|
|
939
|
+
ev.emit('messages.update', [
|
|
940
|
+
{
|
|
941
|
+
key: message.key,
|
|
942
|
+
update: {
|
|
943
|
+
message: message.message
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
]);
|
|
1114
947
|
return message;
|
|
1115
948
|
},
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
949
|
+
sendText: async (jid, text, options, quoted = null) => {
|
|
950
|
+
return sendMessage(jid, {
|
|
951
|
+
text,
|
|
952
|
+
...options
|
|
953
|
+
}, { quoted })
|
|
954
|
+
},
|
|
955
|
+
sendImage: async (jid, image, caption, options, quoted = null) => {
|
|
956
|
+
return sendMessage(jid, {
|
|
957
|
+
image,
|
|
958
|
+
caption,
|
|
959
|
+
...options
|
|
960
|
+
}, { quoted })
|
|
961
|
+
},
|
|
962
|
+
sendVideo: async (jid, video, caption, options, quoted = null) => {
|
|
963
|
+
return sendMessage(jid, {
|
|
964
|
+
video,
|
|
965
|
+
caption,
|
|
966
|
+
...options
|
|
967
|
+
}, { quoted })
|
|
968
|
+
},
|
|
969
|
+
sendDocument: async (jid, document, caption, options, quoted = null) => {
|
|
970
|
+
return sendMessage(jid, {
|
|
971
|
+
document,
|
|
972
|
+
caption,
|
|
973
|
+
...options
|
|
974
|
+
}, { quoted })
|
|
975
|
+
},
|
|
976
|
+
sendAudio: async (jid, audio, options, quoted = null) => {
|
|
977
|
+
return sendMessage(jid, {
|
|
978
|
+
audio,
|
|
979
|
+
...options
|
|
980
|
+
}, { quoted })
|
|
981
|
+
},
|
|
982
|
+
sendLocation: async (jid, name, degreesLongitude, degreesLatitude, url, address, options, quoted = null) => {
|
|
983
|
+
return sendMessage(jid, {
|
|
984
|
+
location: {
|
|
985
|
+
degreesLongitude,
|
|
986
|
+
degreesLatitude,
|
|
987
|
+
name,
|
|
988
|
+
url,
|
|
989
|
+
address
|
|
990
|
+
},
|
|
991
|
+
...options
|
|
992
|
+
}, { quoted })
|
|
993
|
+
},
|
|
994
|
+
sendPoll: async (jid, name, pollVote = [], multiSelect = false, options, quoted = null) => {
|
|
995
|
+
const selectableCount = multiSelect ? pollVote.length : 1;
|
|
996
|
+
|
|
997
|
+
return sendMessage(jid, {
|
|
998
|
+
poll: {
|
|
999
|
+
name,
|
|
1000
|
+
values: pollVote,
|
|
1001
|
+
selectableCount
|
|
1002
|
+
},
|
|
1003
|
+
...options
|
|
1004
|
+
}, { quoted });
|
|
1005
|
+
},
|
|
1006
|
+
sendQuiz: (
|
|
1007
|
+
jid,
|
|
1008
|
+
name,
|
|
1009
|
+
pollVote = [],
|
|
1010
|
+
answer,
|
|
1011
|
+
options,
|
|
1012
|
+
quoted
|
|
1013
|
+
) => {
|
|
1014
|
+
const poll = {
|
|
1015
|
+
name,
|
|
1016
|
+
values: pollVote,
|
|
1017
|
+
selectableCount: 1,
|
|
1018
|
+
type: "QUIZ",
|
|
1019
|
+
answer: { optionName: answer }
|
|
1132
1020
|
}
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
}
|
|
1168
|
-
const fullMsg = await generateWAMessage(jid, content, {
|
|
1169
|
-
logger,
|
|
1170
|
-
userJid,
|
|
1171
|
-
getUrlInfo: text => getUrlInfo(text, {
|
|
1172
|
-
thumbnailWidth: linkPreviewImageThumbnailWidth,
|
|
1173
|
-
fetchOpts: {
|
|
1174
|
-
timeout: 3000,
|
|
1175
|
-
...(httpRequestOptions || {})
|
|
1176
|
-
},
|
|
1177
|
-
logger,
|
|
1178
|
-
uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
|
|
1179
|
-
}),
|
|
1180
|
-
//TODO: CACHE
|
|
1181
|
-
getProfilePicUrl: sock.profilePictureUrl,
|
|
1182
|
-
getCallLink: sock.createCallLink,
|
|
1183
|
-
upload: waUploadToServer,
|
|
1184
|
-
mediaCache: config.mediaCache,
|
|
1185
|
-
options: config.options,
|
|
1186
|
-
messageId: generateMessageIDV2(sock.user?.id),
|
|
1187
|
-
...options
|
|
1188
|
-
});
|
|
1189
|
-
const isEventMsg = 'event' in content && !!content.event;
|
|
1190
|
-
const isDeleteMsg = 'delete' in content && !!content.delete;
|
|
1191
|
-
const isEditMsg = 'edit' in content && !!content.edit;
|
|
1192
|
-
const isPinMsg = 'pin' in content && !!content.pin;
|
|
1193
|
-
const isPollMessage = 'poll' in content && !!content.poll;
|
|
1194
|
-
const additionalAttributes = {};
|
|
1195
|
-
const additionalNodes = [];
|
|
1196
|
-
// required for delete
|
|
1197
|
-
if (isDeleteMsg) {
|
|
1198
|
-
// if the chat is a group, and I am not the author, then delete the message as an admin
|
|
1199
|
-
if (isJidGroup(content.delete?.remoteJid) && !content.delete?.fromMe) {
|
|
1200
|
-
additionalAttributes.edit = '8';
|
|
1201
|
-
}
|
|
1202
|
-
else {
|
|
1203
|
-
additionalAttributes.edit = '7';
|
|
1021
|
+
return sendMessage(jid, {
|
|
1022
|
+
poll,
|
|
1023
|
+
...options
|
|
1024
|
+
}, { quoted })
|
|
1025
|
+
},
|
|
1026
|
+
sendPtv: (jid, ptv, options, quoted = null) => {
|
|
1027
|
+
return sendMessage(jid, {
|
|
1028
|
+
ptv,
|
|
1029
|
+
...options
|
|
1030
|
+
}, { quoted })
|
|
1031
|
+
},
|
|
1032
|
+
statusMention: async (jid, content) => {
|
|
1033
|
+
const msg = Utils_1.generateWAMessageFromContent("status@broadcast", content, {})
|
|
1034
|
+
|
|
1035
|
+
await relayMessage("status@broadcast", msg.message, {
|
|
1036
|
+
messageId: msg.key.id,
|
|
1037
|
+
statusJidList: [jid, authState.creds.me.id],
|
|
1038
|
+
additionalNodes: [
|
|
1039
|
+
{
|
|
1040
|
+
tag: "meta",
|
|
1041
|
+
attrs: {},
|
|
1042
|
+
content: [
|
|
1043
|
+
{
|
|
1044
|
+
tag: "mentioned_users",
|
|
1045
|
+
attrs: {},
|
|
1046
|
+
content: [
|
|
1047
|
+
{
|
|
1048
|
+
tag: "to",
|
|
1049
|
+
attrs: { jid },
|
|
1050
|
+
content: undefined
|
|
1051
|
+
}
|
|
1052
|
+
]
|
|
1053
|
+
}
|
|
1054
|
+
]
|
|
1204
1055
|
}
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
attrs: {
|
|
1216
|
-
polltype: 'creation'
|
|
1217
|
-
}
|
|
1218
|
-
});
|
|
1219
|
-
}
|
|
1220
|
-
else if (isEventMsg) {
|
|
1221
|
-
additionalNodes.push({
|
|
1222
|
-
tag: 'meta',
|
|
1223
|
-
attrs: {
|
|
1224
|
-
event_type: 'creation'
|
|
1056
|
+
]
|
|
1057
|
+
})
|
|
1058
|
+
|
|
1059
|
+
const mentionMsg = {
|
|
1060
|
+
statusMentionMessage: {
|
|
1061
|
+
message: {
|
|
1062
|
+
protocolMessage: {
|
|
1063
|
+
key: msg.key,
|
|
1064
|
+
type: "STATUS_MENTION_MESSAGE",
|
|
1065
|
+
timestamp: Math.floor(Date.now() / 1000)
|
|
1225
1066
|
}
|
|
1226
|
-
});
|
|
1227
|
-
}
|
|
1228
|
-
await relayMessage(jid, fullMsg.message, {
|
|
1229
|
-
messageId: fullMsg.key.id,
|
|
1230
|
-
useCachedGroupMetadata: options.useCachedGroupMetadata,
|
|
1231
|
-
additionalAttributes,
|
|
1232
|
-
statusJidList: options.statusJidList,
|
|
1233
|
-
additionalNodes: aiLabel ? additionalNodes : options.additionalNodes
|
|
1234
|
-
});
|
|
1235
|
-
if (config.emitOwnEvents) {
|
|
1236
|
-
process.nextTick(async () => {
|
|
1237
|
-
await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
|
|
1238
|
-
});
|
|
1239
|
-
}
|
|
1240
|
-
return fullMsg;
|
|
1241
|
-
}
|
|
1242
|
-
},
|
|
1243
|
-
sendMessageMembers: async (jid, message, options = {}) => {
|
|
1244
|
-
const {
|
|
1245
|
-
messageId: idm,
|
|
1246
|
-
quoted,
|
|
1247
|
-
delayMs = 1500,
|
|
1248
|
-
useUserDevicesCache = true,
|
|
1249
|
-
cachedGroupMetadata,
|
|
1250
|
-
onlyMember = true
|
|
1251
|
-
} = options;
|
|
1252
|
-
const { server } = jidDecode(jid);
|
|
1253
|
-
if (server !== "g.us") throw new Error("@g.us server required");
|
|
1254
|
-
const meId = authState.creds.me.id;
|
|
1255
|
-
const messages = Utils_1.normalizeMessageContent(message);
|
|
1256
|
-
const groupData = cachedGroupMetadata? await cachedGroupMetadata(jid) : await groupMetadata(jid);
|
|
1257
|
-
const isLid = groupData.addressingMode === "lid";
|
|
1258
|
-
const isAdmin = groupData.participants.filter((x) => x.admin !== null).map((y) => y.id)
|
|
1259
|
-
let participantJids = groupData.participants.map(z => z.id);
|
|
1260
|
-
if (onlyMember) {
|
|
1261
|
-
participantJids = isAdmin ? isAdmin : participantJids;
|
|
1262
|
-
}
|
|
1263
|
-
logger.info(`Sending message to ${participantJids.length} members from ${jid}`);
|
|
1264
|
-
for (let i = 0; i < participantJids.length; i++) {
|
|
1265
|
-
const jid = participantJids[i];
|
|
1266
|
-
if (areJidsSameUser(jid, meId)) continue;
|
|
1267
|
-
try {
|
|
1268
|
-
const msgId = `${idm || Utils_1.generateMessageID()}_${i}`;
|
|
1269
|
-
const fullMsg = await Utils_1.generateWAMessageFromContent(jid, message, {
|
|
1270
|
-
messageId: msgId,
|
|
1271
|
-
quoted
|
|
1272
|
-
})
|
|
1273
|
-
await relayMessage(jid, fullMsg.message, {
|
|
1274
|
-
messageId: fullMsg.key.id
|
|
1275
|
-
});
|
|
1276
|
-
logger.debug(`Message successfully sent to ${jid}`);
|
|
1277
|
-
if (delayMs && i < participantJids.length - 1) {
|
|
1278
|
-
await new Promise(z => setTimeout(z, delayMs));
|
|
1279
1067
|
}
|
|
1280
|
-
} catch (e) {
|
|
1281
|
-
logger.error({ jid, e }, "Error sending message to");
|
|
1282
1068
|
}
|
|
1283
1069
|
}
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1070
|
+
|
|
1071
|
+
const x = Utils_1.generateWAMessageFromContent(jid, mentionMsg, {})
|
|
1072
|
+
return relayMessage(jid, x.message, {
|
|
1073
|
+
messageId: x.key.id,
|
|
1074
|
+
additionalNodes: [
|
|
1075
|
+
{
|
|
1076
|
+
tag: "meta",
|
|
1077
|
+
attrs: { is_status_mention: "true" }
|
|
1078
|
+
}
|
|
1079
|
+
]
|
|
1080
|
+
})
|
|
1288
1081
|
}
|
|
1289
|
-
}
|
|
1082
|
+
}
|
|
1290
1083
|
};
|
|
1291
|
-
|
|
1084
|
+
exports.makeMessagesSocket = makeMessagesSocket;
|