@gqb333/based 2.7.71
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 +58 -0
- package/README.MD +611 -0
- package/WAProto/GenerateStatics.sh +4 -0
- package/WAProto/WAProto.proto +5604 -0
- package/WAProto/index.d.ts +63156 -0
- package/WAProto/index.js +195638 -0
- package/WAProto/p.html +1 -0
- package/engine-requirements.js +10 -0
- package/lib/Defaults/baileys-version.json +3 -0
- package/lib/Defaults/index.d.ts +53 -0
- package/lib/Defaults/index.js +108 -0
- package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
- package/lib/Signal/Group/ciphertext-message.js +15 -0
- package/lib/Signal/Group/group-session-builder.d.ts +14 -0
- package/lib/Signal/Group/group-session-builder.js +64 -0
- package/lib/Signal/Group/group_cipher.d.ts +17 -0
- package/lib/Signal/Group/group_cipher.js +96 -0
- package/lib/Signal/Group/index.d.ts +11 -0
- package/lib/Signal/Group/index.js +57 -0
- package/lib/Signal/Group/keyhelper.d.ts +10 -0
- package/lib/Signal/Group/keyhelper.js +55 -0
- 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 +13 -0
- package/lib/Signal/Group/sender-chain-key.js +34 -0
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +66 -0
- package/lib/Signal/Group/sender-key-message.d.ts +18 -0
- package/lib/Signal/Group/sender-key-message.js +69 -0
- package/lib/Signal/Group/sender-key-name.d.ts +17 -0
- package/lib/Signal/Group/sender-key-name.js +51 -0
- package/lib/Signal/Group/sender-key-record.d.ts +30 -0
- package/lib/Signal/Group/sender-key-record.js +53 -0
- package/lib/Signal/Group/sender-key-state.d.ts +38 -0
- package/lib/Signal/Group/sender-key-state.js +99 -0
- package/lib/Signal/Group/sender-message-key.d.ts +11 -0
- package/lib/Signal/Group/sender-message-key.js +29 -0
- package/lib/Signal/libsignal.d.ts +3 -0
- package/lib/Signal/libsignal.js +174 -0
- package/lib/Socket/Client/index.d.ts +2 -0
- package/lib/Socket/Client/index.js +18 -0
- package/lib/Socket/Client/types.d.ts +16 -0
- package/lib/Socket/Client/types.js +13 -0
- package/lib/Socket/Client/websocket.d.ts +13 -0
- package/lib/Socket/Client/websocket.js +111 -0
- package/lib/Socket/business.d.ts +172 -0
- package/lib/Socket/business.js +260 -0
- package/lib/Socket/chats.d.ts +85 -0
- package/lib/Socket/chats.js +1094 -0
- package/lib/Socket/groups.d.ts +124 -0
- package/lib/Socket/groups.js +423 -0
- package/lib/Socket/index.d.ts +172 -0
- package/lib/Socket/index.js +32 -0
- package/lib/Socket/messages-interactive.js +259 -0
- package/lib/Socket/messages-recv.d.ts +161 -0
- package/lib/Socket/messages-recv.js +1474 -0
- package/lib/Socket/messages-send.d.ts +151 -0
- package/lib/Socket/messages-send.js +1085 -0
- package/lib/Socket/newsletter.d.ts +136 -0
- package/lib/Socket/newsletter.js +250 -0
- package/lib/Socket/socket.d.ts +43 -0
- package/lib/Socket/socket.js +1241 -0
- package/lib/Socket/usync.d.ts +36 -0
- package/lib/Socket/usync.js +123 -0
- package/lib/Store/index.d.ts +2 -0
- package/lib/Store/index.js +8 -0
- package/lib/Store/make-in-memory-store.d.ts +118 -0
- package/lib/Store/make-in-memory-store.js +452 -0
- package/lib/Store/make-ordered-dictionary.d.ts +13 -0
- package/lib/Store/make-ordered-dictionary.js +81 -0
- package/lib/Store/object-repository.d.ts +10 -0
- package/lib/Store/object-repository.js +27 -0
- package/lib/Types/Auth.d.ts +114 -0
- package/lib/Types/Auth.js +2 -0
- package/lib/Types/Call.d.ts +13 -0
- package/lib/Types/Call.js +2 -0
- package/lib/Types/Chat.d.ts +109 -0
- package/lib/Types/Chat.js +4 -0
- package/lib/Types/Contact.d.ts +29 -0
- package/lib/Types/Contact.js +2 -0
- package/lib/Types/Events.d.ts +199 -0
- package/lib/Types/Events.js +2 -0
- package/lib/Types/GroupMetadata.d.ts +64 -0
- package/lib/Types/GroupMetadata.js +2 -0
- package/lib/Types/Label.d.ts +35 -0
- package/lib/Types/Label.js +27 -0
- package/lib/Types/LabelAssociation.d.ts +29 -0
- package/lib/Types/LabelAssociation.js +9 -0
- package/lib/Types/Message.d.ts +740 -0
- package/lib/Types/Message.js +7 -0
- package/lib/Types/Newsletter.d.ts +22 -0
- package/lib/Types/Newsletter.js +18 -0
- package/lib/Types/Product.d.ts +78 -0
- package/lib/Types/Product.js +2 -0
- package/lib/Types/Signal.d.ts +63 -0
- package/lib/Types/Signal.js +2 -0
- package/lib/Types/Socket.d.ts +134 -0
- package/lib/Types/Socket.js +2 -0
- package/lib/Types/State.d.ts +27 -0
- package/lib/Types/State.js +2 -0
- package/lib/Types/USync.d.ts +25 -0
- package/lib/Types/USync.js +2 -0
- package/lib/Types/index.d.ts +65 -0
- package/lib/Types/index.js +43 -0
- package/lib/Utils/auth-utils.d.ts +18 -0
- package/lib/Utils/auth-utils.js +209 -0
- 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 +22 -0
- package/lib/Utils/business.js +234 -0
- package/lib/Utils/cache-manager.d.ts +16 -0
- package/lib/Utils/cache-manager.js +114 -0
- package/lib/Utils/chat-utils.d.ts +70 -0
- package/lib/Utils/chat-utils.js +734 -0
- package/lib/Utils/crypto.d.ts +40 -0
- package/lib/Utils/crypto.js +193 -0
- package/lib/Utils/decode-wa-message.d.ts +35 -0
- package/lib/Utils/decode-wa-message.js +207 -0
- package/lib/Utils/event-buffer.d.ts +35 -0
- package/lib/Utils/event-buffer.js +619 -0
- package/lib/Utils/generics.d.ts +89 -0
- package/lib/Utils/generics.js +440 -0
- package/lib/Utils/history.d.ts +19 -0
- package/lib/Utils/history.js +94 -0
- package/lib/Utils/index.d.ts +22 -0
- package/lib/Utils/index.js +38 -0
- package/lib/Utils/jid-validation.d.ts +2 -0
- package/lib/Utils/jid-validation.js +186 -0
- package/lib/Utils/link-preview.d.ts +21 -0
- package/lib/Utils/link-preview.js +152 -0
- package/lib/Utils/logger.d.ts +11 -0
- package/lib/Utils/logger.js +59 -0
- package/lib/Utils/lt-hash.d.ts +12 -0
- package/lib/Utils/lt-hash.js +51 -0
- package/lib/Utils/make-mutex.d.ts +7 -0
- package/lib/Utils/make-mutex.js +43 -0
- package/lib/Utils/messages-media.d.ts +120 -0
- package/lib/Utils/messages-media.js +848 -0
- package/lib/Utils/messages.d.ts +131 -0
- package/lib/Utils/messages.js +1793 -0
- package/lib/Utils/newsletter-utils.d.ts +2 -0
- package/lib/Utils/newsletter-utils.js +48 -0
- package/lib/Utils/noise-handler.d.ts +19 -0
- package/lib/Utils/noise-handler.js +150 -0
- package/lib/Utils/performance-config.d.ts +70 -0
- package/lib/Utils/performance-config.js +183 -0
- package/lib/Utils/process-message.d.ts +42 -0
- package/lib/Utils/process-message.js +498 -0
- package/lib/Utils/rate-limiter.js +90 -0
- package/lib/Utils/retry.js +66 -0
- package/lib/Utils/signal.d.ts +33 -0
- package/lib/Utils/signal.js +153 -0
- package/lib/Utils/use-multi-file-auth-state.d.ts +12 -0
- package/lib/Utils/use-multi-file-auth-state.js +129 -0
- package/lib/Utils/validate-connection.d.ts +10 -0
- package/lib/Utils/validate-connection.js +233 -0
- package/lib/WABinary/constants.d.ts +27 -0
- package/lib/WABinary/constants.js +1303 -0
- package/lib/WABinary/decode.d.ts +6 -0
- package/lib/WABinary/decode.js +279 -0
- package/lib/WABinary/encode.d.ts +2 -0
- package/lib/WABinary/encode.js +264 -0
- package/lib/WABinary/generic-utils.d.ts +14 -0
- package/lib/WABinary/generic-utils.js +114 -0
- package/lib/WABinary/index.d.ts +5 -0
- package/lib/WABinary/index.js +21 -0
- package/lib/WABinary/jid-utils.d.ts +38 -0
- package/lib/WABinary/jid-utils.js +485 -0
- package/lib/WABinary/types.d.ts +18 -0
- package/lib/WABinary/types.js +2 -0
- package/lib/WAM/BinaryInfo.d.ts +8 -0
- package/lib/WAM/BinaryInfo.js +13 -0
- package/lib/WAM/constants.d.ts +38 -0
- package/lib/WAM/constants.js +15350 -0
- package/lib/WAM/encode.d.ts +2 -0
- package/lib/WAM/encode.js +155 -0
- package/lib/WAM/index.d.ts +3 -0
- package/lib/WAM/index.js +19 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +9 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +102 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +22 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +110 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +42 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +25 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +53 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +8 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
- package/lib/WAUSync/Protocols/index.d.ts +4 -0
- package/lib/WAUSync/Protocols/index.js +20 -0
- package/lib/WAUSync/USyncQuery.d.ts +28 -0
- package/lib/WAUSync/USyncQuery.js +147 -0
- package/lib/WAUSync/USyncUser.d.ts +12 -0
- package/lib/WAUSync/USyncUser.js +26 -0
- package/lib/WAUSync/index.d.ts +3 -0
- package/lib/WAUSync/index.js +19 -0
- package/lib/index.d.ts +17 -0
- package/lib/index.js +53 -0
- package/package.json +104 -0
|
@@ -0,0 +1,1085 @@
|
|
|
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("@cacheable/node-cache"));
|
|
9
|
+
const crypto_1 = require("crypto");
|
|
10
|
+
const AbortController = require("abort-controller");
|
|
11
|
+
const WAProto_1 = require("../../WAProto");
|
|
12
|
+
const Defaults_1 = require("../Defaults");
|
|
13
|
+
const Utils_1 = require("../Utils");
|
|
14
|
+
const retry_1 = require("../Utils/retry");
|
|
15
|
+
const link_preview_1 = require("../Utils/link-preview");
|
|
16
|
+
const WABinary_1 = require("../WABinary");
|
|
17
|
+
const WAUSync_1 = require("../WAUSync");
|
|
18
|
+
const newsletter_1 = require("./newsletter");
|
|
19
|
+
const makeMessagesSocket = (config) => {
|
|
20
|
+
const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: axiosOptions, patchMessageBeforeSending, cachedGroupMetadata, } = config;
|
|
21
|
+
const sock = (0, newsletter_1.makeNewsletterSocket)(config);
|
|
22
|
+
const { ev, authState, processingMutex, signalRepository, upsertMessage, query, fetchPrivacySettings, sendNode, groupMetadata, groupToggleEphemeral, } = sock;
|
|
23
|
+
const userDevicesCache = config.userDevicesCache || new node_cache_1.default({
|
|
24
|
+
stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.USER_DEVICES, // 5 minutes
|
|
25
|
+
useClones: false
|
|
26
|
+
});
|
|
27
|
+
const inFlightDeviceFetch = new Map();
|
|
28
|
+
let mediaConn;
|
|
29
|
+
const refreshMediaConn = async (forceGet = false) => {
|
|
30
|
+
const media = await mediaConn;
|
|
31
|
+
if (!media || forceGet || (new Date().getTime() - media.fetchDate.getTime()) > media.ttl * 1000) {
|
|
32
|
+
mediaConn = (async () => {
|
|
33
|
+
const result = await query({
|
|
34
|
+
tag: 'iq',
|
|
35
|
+
attrs: {
|
|
36
|
+
type: 'set',
|
|
37
|
+
xmlns: 'w:m',
|
|
38
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
39
|
+
},
|
|
40
|
+
content: [{ tag: 'media_conn', attrs: {} }]
|
|
41
|
+
});
|
|
42
|
+
const mediaConnNode = (0, WABinary_1.getBinaryNodeChild)(result, 'media_conn');
|
|
43
|
+
const node = {
|
|
44
|
+
hosts: (0, WABinary_1.getBinaryNodeChildren)(mediaConnNode, 'host').map(({ attrs }) => ({
|
|
45
|
+
hostname: attrs.hostname,
|
|
46
|
+
maxContentLengthBytes: +attrs.maxContentLengthBytes,
|
|
47
|
+
})),
|
|
48
|
+
auth: mediaConnNode.attrs.auth,
|
|
49
|
+
ttl: +mediaConnNode.attrs.ttl,
|
|
50
|
+
fetchDate: new Date()
|
|
51
|
+
};
|
|
52
|
+
logger.debug('fetched media conn');
|
|
53
|
+
return node;
|
|
54
|
+
})();
|
|
55
|
+
}
|
|
56
|
+
return mediaConn;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* generic send receipt function
|
|
60
|
+
* used for receipts of phone call, read, delivery etc.
|
|
61
|
+
* */
|
|
62
|
+
const sendReceipt = async (jid, participant, messageIds, type) => {
|
|
63
|
+
const node = {
|
|
64
|
+
tag: 'receipt',
|
|
65
|
+
attrs: {
|
|
66
|
+
id: messageIds[0],
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
const isReadReceipt = type === 'read' || type === 'read-self';
|
|
70
|
+
if (isReadReceipt) {
|
|
71
|
+
node.attrs.t = (0, Utils_1.unixTimestampSeconds)().toString();
|
|
72
|
+
}
|
|
73
|
+
if (type === 'sender' && (0, WABinary_1.isJidUser)(jid)) {
|
|
74
|
+
node.attrs.recipient = jid;
|
|
75
|
+
node.attrs.to = participant;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
node.attrs.to = jid;
|
|
79
|
+
if (participant) {
|
|
80
|
+
node.attrs.participant = participant;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (type) {
|
|
84
|
+
node.attrs.type = (0, WABinary_1.isJidNewsletter)(jid) ? 'read-self' : type;
|
|
85
|
+
}
|
|
86
|
+
const remainingMessageIds = messageIds.slice(1);
|
|
87
|
+
if (remainingMessageIds.length) {
|
|
88
|
+
node.content = [
|
|
89
|
+
{
|
|
90
|
+
tag: 'list',
|
|
91
|
+
attrs: {},
|
|
92
|
+
content: remainingMessageIds.map(id => ({
|
|
93
|
+
tag: 'item',
|
|
94
|
+
attrs: { id }
|
|
95
|
+
}))
|
|
96
|
+
}
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
logger.debug({ attrs: node.attrs, messageIds }, 'sending receipt for messages');
|
|
100
|
+
await sendNode(node);
|
|
101
|
+
};
|
|
102
|
+
/** Correctly bulk send receipts to multiple chats, participants */
|
|
103
|
+
const sendReceipts = async (keys, type) => {
|
|
104
|
+
const recps = (0, Utils_1.aggregateMessageKeysNotFromMe)(keys);
|
|
105
|
+
for (const { jid, participant, messageIds } of recps) {
|
|
106
|
+
await sendReceipt(jid, participant, messageIds, type);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
/** Bulk read messages. Keys can be from different chats & participants */
|
|
110
|
+
const readMessages = async (keys) => {
|
|
111
|
+
const privacySettings = await fetchPrivacySettings();
|
|
112
|
+
// based on privacy settings, we have to change the read type
|
|
113
|
+
const readType = privacySettings.readreceipts === 'all' ? 'read' : 'read-self';
|
|
114
|
+
await sendReceipts(keys, readType);
|
|
115
|
+
};
|
|
116
|
+
/** Fetch all the devices we've to send a message to */
|
|
117
|
+
const getUSyncDevices = async (jids, useCache, ignoreZeroDevices) => {
|
|
118
|
+
var _a;
|
|
119
|
+
const deviceResults = [];
|
|
120
|
+
if (!useCache) {
|
|
121
|
+
logger.debug('not using cache for devices');
|
|
122
|
+
}
|
|
123
|
+
const toFetch = [];
|
|
124
|
+
const usersToFetch = new Set();
|
|
125
|
+
const inFlightPromises = [];
|
|
126
|
+
jids = Array.from(new Set(jids));
|
|
127
|
+
for (let jid of jids) {
|
|
128
|
+
const user = (_a = (0, WABinary_1.jidDecode)(jid)) === null || _a === void 0 ? void 0 : _a.user;
|
|
129
|
+
jid = (0, WABinary_1.jidNormalizedUser)(jid);
|
|
130
|
+
if (useCache) {
|
|
131
|
+
const devices = userDevicesCache.get(user);
|
|
132
|
+
if (devices) {
|
|
133
|
+
deviceResults.push(...devices);
|
|
134
|
+
logger.trace({ user }, 'using cache for devices');
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
const inFlight = user ? inFlightDeviceFetch.get(user) : undefined;
|
|
138
|
+
if (inFlight) {
|
|
139
|
+
inFlightPromises.push(inFlight.then(devs => {
|
|
140
|
+
if (devs && devs.length) {
|
|
141
|
+
deviceResults.push(...devs);
|
|
142
|
+
}
|
|
143
|
+
}));
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
toFetch.push(jid);
|
|
147
|
+
if (user) {
|
|
148
|
+
usersToFetch.add(user);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
toFetch.push(jid);
|
|
155
|
+
if (user) {
|
|
156
|
+
usersToFetch.add(user);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (inFlightPromises.length) {
|
|
161
|
+
await Promise.all(inFlightPromises);
|
|
162
|
+
}
|
|
163
|
+
if (!toFetch.length) {
|
|
164
|
+
return deviceResults;
|
|
165
|
+
}
|
|
166
|
+
const fetchPromise = (async () => {
|
|
167
|
+
const query = new WAUSync_1.USyncQuery()
|
|
168
|
+
.withContext('message')
|
|
169
|
+
.withDeviceProtocol();
|
|
170
|
+
for (const jid of toFetch) {
|
|
171
|
+
query.withUser(new WAUSync_1.USyncUser().withId(jid));
|
|
172
|
+
}
|
|
173
|
+
const result = await sock.executeUSyncQuery(query);
|
|
174
|
+
const deviceMap = {};
|
|
175
|
+
if (result) {
|
|
176
|
+
const extracted = (0, Utils_1.extractDeviceJids)(result === null || result === void 0 ? void 0 : result.list, authState.creds.me.id, ignoreZeroDevices);
|
|
177
|
+
for (const item of extracted) {
|
|
178
|
+
deviceMap[item.user] = deviceMap[item.user] || [];
|
|
179
|
+
deviceMap[item.user].push(item);
|
|
180
|
+
deviceResults.push(item);
|
|
181
|
+
}
|
|
182
|
+
for (const key in deviceMap) {
|
|
183
|
+
userDevicesCache.set(key, deviceMap[key]);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return deviceMap;
|
|
187
|
+
})();
|
|
188
|
+
for (const user of usersToFetch) {
|
|
189
|
+
inFlightDeviceFetch.set(user, fetchPromise.then(deviceMap => deviceMap[user] || []));
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
await fetchPromise;
|
|
193
|
+
}
|
|
194
|
+
finally {
|
|
195
|
+
for (const user of usersToFetch) {
|
|
196
|
+
const current = inFlightDeviceFetch.get(user);
|
|
197
|
+
if (current) {
|
|
198
|
+
inFlightDeviceFetch.delete(user);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return deviceResults;
|
|
203
|
+
};
|
|
204
|
+
// Cache to track JIDs that have failed session fetching to prevent infinite loops
|
|
205
|
+
const failedSessionFetchCache = new Map();
|
|
206
|
+
const FAILED_SESSION_CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
207
|
+
// Cache to track recently sent messages to prevent duplicate sends
|
|
208
|
+
const recentlySentMessagesCache = new node_cache_1.default({
|
|
209
|
+
stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
|
|
210
|
+
useClones: false,
|
|
211
|
+
maxKeys: 1000 // Limit to prevent memory issues
|
|
212
|
+
});
|
|
213
|
+
const inFlightSessionFetch = new Map();
|
|
214
|
+
|
|
215
|
+
// Cleanup function to remove expired entries from the cache
|
|
216
|
+
const cleanupFailedSessionCache = () => {
|
|
217
|
+
const now = Date.now();
|
|
218
|
+
for (const [jid, failureTime] of failedSessionFetchCache.entries()) {
|
|
219
|
+
if (now - failureTime >= FAILED_SESSION_CACHE_TTL) {
|
|
220
|
+
failedSessionFetchCache.delete(jid);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// Run cleanup every 5 minutes
|
|
226
|
+
const cleanupInterval = setInterval(cleanupFailedSessionCache, 5 * 60 * 1000);
|
|
227
|
+
|
|
228
|
+
// Helper function to check if message was recently sent
|
|
229
|
+
const wasMessageRecentlySent = (msgId, jid) => {
|
|
230
|
+
const cacheKey = `${msgId}:${jid}`;
|
|
231
|
+
return recentlySentMessagesCache.has(cacheKey);
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// Helper function to mark message as recently sent
|
|
235
|
+
const markMessageAsSent = (msgId, jid) => {
|
|
236
|
+
const cacheKey = `${msgId}:${jid}`;
|
|
237
|
+
recentlySentMessagesCache.set(cacheKey, true);
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const assertSessions = async (jids, force) => {
|
|
241
|
+
let didFetchNewSession = false;
|
|
242
|
+
let jidsRequiringFetch = [];
|
|
243
|
+
if (force) {
|
|
244
|
+
// Filter out JIDs that have recently failed session fetching
|
|
245
|
+
jidsRequiringFetch = jids.filter(jid => {
|
|
246
|
+
const failureTime = failedSessionFetchCache.get(jid);
|
|
247
|
+
if (failureTime && (Date.now() - failureTime) < FAILED_SESSION_CACHE_TTL) {
|
|
248
|
+
logger.debug({ jid }, 'skipping session fetch for recently failed JID');
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
return true;
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// If all JIDs are filtered out, return early without attempting fetch
|
|
255
|
+
if (jidsRequiringFetch.length === 0 && jids.length > 0) {
|
|
256
|
+
logger.debug({ originalJids: jids }, 'all JIDs recently failed, skipping session fetch entirely');
|
|
257
|
+
return didFetchNewSession;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
const addrs = jids.map(jid => (signalRepository
|
|
262
|
+
.jidToSignalProtocolAddress(jid)));
|
|
263
|
+
const sessions = await authState.keys.get('session', addrs);
|
|
264
|
+
for (const jid of jids) {
|
|
265
|
+
const signalId = signalRepository
|
|
266
|
+
.jidToSignalProtocolAddress(jid);
|
|
267
|
+
if (!sessions[signalId]) {
|
|
268
|
+
// Also check if this JID recently failed
|
|
269
|
+
const failureTime = failedSessionFetchCache.get(jid);
|
|
270
|
+
if (!failureTime || (Date.now() - failureTime) >= FAILED_SESSION_CACHE_TTL) {
|
|
271
|
+
jidsRequiringFetch.push(jid);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (jidsRequiringFetch.length) {
|
|
277
|
+
const awaitingInflight = [];
|
|
278
|
+
const uniqueJids = Array.from(new Set(jidsRequiringFetch));
|
|
279
|
+
jidsRequiringFetch = [];
|
|
280
|
+
for (const jid of uniqueJids) {
|
|
281
|
+
const inFlight = inFlightSessionFetch.get(jid);
|
|
282
|
+
if (inFlight) {
|
|
283
|
+
awaitingInflight.push(inFlight);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
jidsRequiringFetch.push(jid);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
logger.debug({ jidsRequiringFetch }, 'fetching sessions');
|
|
290
|
+
const TOTAL_TIMEOUT_MS = 120000; // 120 seconds
|
|
291
|
+
const abortController = new AbortController();
|
|
292
|
+
const timeout = setTimeout(() => abortController.abort(), TOTAL_TIMEOUT_MS);
|
|
293
|
+
try {
|
|
294
|
+
const BATCH_SIZE = 50;
|
|
295
|
+
for (let i = 0; i < jidsRequiringFetch.length; i += BATCH_SIZE) {
|
|
296
|
+
const batch = jidsRequiringFetch.slice(i, i + BATCH_SIZE);
|
|
297
|
+
try {
|
|
298
|
+
const batchPromise = (0, retry_1.retryWithBackoff)(() => query({
|
|
299
|
+
tag: 'iq',
|
|
300
|
+
attrs: {
|
|
301
|
+
xmlns: 'encrypt',
|
|
302
|
+
type: 'get',
|
|
303
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
304
|
+
},
|
|
305
|
+
content: [
|
|
306
|
+
{
|
|
307
|
+
tag: 'key',
|
|
308
|
+
attrs: {},
|
|
309
|
+
content: batch.map(jid => ({
|
|
310
|
+
tag: 'user',
|
|
311
|
+
attrs: { jid },
|
|
312
|
+
}))
|
|
313
|
+
}
|
|
314
|
+
]
|
|
315
|
+
}), {
|
|
316
|
+
retries: 4,
|
|
317
|
+
baseMs: 2000,
|
|
318
|
+
maxMs: 10000,
|
|
319
|
+
jitter: true,
|
|
320
|
+
timeoutPerAttemptMs: 25000,
|
|
321
|
+
shouldRetry: (err) => {
|
|
322
|
+
var _a;
|
|
323
|
+
const status = ((_a = err.output) === null || _a === void 0 ? void 0 : _a.statusCode) || (err === null || err === void 0 ? void 0 : err.statusCode);
|
|
324
|
+
// Don't retry "not-acceptable" (406) errors as they indicate permission issues
|
|
325
|
+
// Don't retry aborted requests as they were intentionally cancelled
|
|
326
|
+
if (status === 406 || err.message === 'aborted' || err.code === 'ABORT_ERR') {
|
|
327
|
+
return false;
|
|
328
|
+
}
|
|
329
|
+
return !status || (status >= 500 || status === 408 || status === 429) || err.message.includes('WebSocket is not open');
|
|
330
|
+
},
|
|
331
|
+
onRetry: (err, n) => logger === null || logger === void 0 ? void 0 : logger.warn({ err, attempt: n }, 'retrying fetch sessions'),
|
|
332
|
+
signal: abortController.signal
|
|
333
|
+
});
|
|
334
|
+
for (const jid of batch) {
|
|
335
|
+
inFlightSessionFetch.set(jid, batchPromise.then(() => undefined));
|
|
336
|
+
}
|
|
337
|
+
const result = await batchPromise;
|
|
338
|
+
await (0, Utils_1.parseAndInjectE2ESessions)(result, signalRepository);
|
|
339
|
+
didFetchNewSession = true;
|
|
340
|
+
for (const jid of batch) {
|
|
341
|
+
inFlightSessionFetch.delete(jid);
|
|
342
|
+
}
|
|
343
|
+
} catch (err) {
|
|
344
|
+
// Cache failed JIDs to prevent infinite retries
|
|
345
|
+
logger.warn({ err, batch }, 'session fetch failed for batch, caching failed JIDs');
|
|
346
|
+
for (const jid of batch) {
|
|
347
|
+
failedSessionFetchCache.set(jid, Date.now());
|
|
348
|
+
inFlightSessionFetch.delete(jid);
|
|
349
|
+
}
|
|
350
|
+
// Re-throw the error so the caller knows the fetch failed
|
|
351
|
+
throw err;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
if (awaitingInflight.length) {
|
|
355
|
+
await Promise.all(awaitingInflight);
|
|
356
|
+
}
|
|
357
|
+
} finally {
|
|
358
|
+
clearTimeout(timeout);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return didFetchNewSession;
|
|
362
|
+
};
|
|
363
|
+
const sendPeerMessage = async (protocolMessageContent, options = {}) => {
|
|
364
|
+
var _a;
|
|
365
|
+
if (!((_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.id)) {
|
|
366
|
+
throw new boom_1.Boom('Not authenticated');
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const protocolMessage = {
|
|
370
|
+
protocolMessage: protocolMessageContent
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
const meJid = (0, WABinary_1.jidNormalizedUser)(authState.creds.me.id);
|
|
374
|
+
const msgId = await relayMessage(meJid, protocolMessage, {
|
|
375
|
+
additionalAttributes: {
|
|
376
|
+
category: 'peer',
|
|
377
|
+
// eslint-disable-next-line camelcase
|
|
378
|
+
push_priority: 'high_force',
|
|
379
|
+
...options.additionalAttributes
|
|
380
|
+
},
|
|
381
|
+
...options
|
|
382
|
+
});
|
|
383
|
+
return msgId;
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
const sendPeerDataOperationMessage = async (pdoMessage) => {
|
|
387
|
+
return sendPeerMessage({
|
|
388
|
+
peerDataOperationRequestMessage: pdoMessage,
|
|
389
|
+
type: WAProto_1.proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
|
|
390
|
+
});
|
|
391
|
+
};
|
|
392
|
+
const createParticipantNodes = async (jids, message, extraAttrs) => {
|
|
393
|
+
let patched = await patchMessageBeforeSending(message, jids);
|
|
394
|
+
if (!Array.isArray(patched)) {
|
|
395
|
+
patched = jids ? jids.map(jid => ({ recipientJid: jid, ...patched })) : [patched];
|
|
396
|
+
}
|
|
397
|
+
let shouldIncludeDeviceIdentity = false;
|
|
398
|
+
const nodes = await Promise.all(patched.map(async (patchedMessageWithJid) => {
|
|
399
|
+
const { recipientJid: jid, ...patchedMessage } = patchedMessageWithJid;
|
|
400
|
+
if (!jid) {
|
|
401
|
+
return {};
|
|
402
|
+
}
|
|
403
|
+
const bytes = (0, Utils_1.encodeWAMessage)(patchedMessage);
|
|
404
|
+
const { type, ciphertext } = await signalRepository
|
|
405
|
+
.encryptMessage({ jid, data: bytes });
|
|
406
|
+
if (type === 'pkmsg') {
|
|
407
|
+
shouldIncludeDeviceIdentity = true;
|
|
408
|
+
}
|
|
409
|
+
const node = {
|
|
410
|
+
tag: 'to',
|
|
411
|
+
attrs: { jid },
|
|
412
|
+
content: [{
|
|
413
|
+
tag: 'enc',
|
|
414
|
+
attrs: {
|
|
415
|
+
v: '2',
|
|
416
|
+
type,
|
|
417
|
+
...extraAttrs || {}
|
|
418
|
+
},
|
|
419
|
+
content: ciphertext
|
|
420
|
+
}]
|
|
421
|
+
};
|
|
422
|
+
return node;
|
|
423
|
+
}));
|
|
424
|
+
return { nodes, shouldIncludeDeviceIdentity };
|
|
425
|
+
};
|
|
426
|
+
const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList }) => {
|
|
427
|
+
var _a;
|
|
428
|
+
const meId = authState.creds.me.id;
|
|
429
|
+
let shouldIncludeDeviceIdentity = false;
|
|
430
|
+
const { user, server } = (0, WABinary_1.jidDecode)(jid);
|
|
431
|
+
const statusJid = 'status@broadcast';
|
|
432
|
+
const isGroup = server === 'g.us';
|
|
433
|
+
const isNewsletter = server === 'newsletter';
|
|
434
|
+
const isStatus = jid === statusJid;
|
|
435
|
+
const isLid = server === 'lid';
|
|
436
|
+
msgId = msgId || (0, Utils_1.generateMessageIDV2)((_a = sock.user) === null || _a === void 0 ? void 0 : _a.id);
|
|
437
|
+
|
|
438
|
+
// Check if this message was recently sent to prevent duplicate sends
|
|
439
|
+
if (wasMessageRecentlySent(msgId, jid)) {
|
|
440
|
+
logger.debug({ msgId, jid }, 'message recently sent, skipping duplicate send');
|
|
441
|
+
return msgId;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
useUserDevicesCache = useUserDevicesCache !== false;
|
|
445
|
+
useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus;
|
|
446
|
+
const participants = [];
|
|
447
|
+
const destinationJid = (!isStatus) ? (0, WABinary_1.jidEncode)(user, isLid ? 'lid' : isGroup ? 'g.us' : isNewsletter ? 'newsletter' : 's.whatsapp.net') : statusJid;
|
|
448
|
+
const binaryNodeContent = [];
|
|
449
|
+
const devices = [];
|
|
450
|
+
const meMsg = {
|
|
451
|
+
deviceSentMessage: {
|
|
452
|
+
destinationJid,
|
|
453
|
+
message
|
|
454
|
+
},
|
|
455
|
+
messageContextInfo: message.messageContextInfo
|
|
456
|
+
};
|
|
457
|
+
const extraAttrs = {};
|
|
458
|
+
if (participant) {
|
|
459
|
+
// when the retry request is not for a group
|
|
460
|
+
// only send to the specific device that asked for a retry
|
|
461
|
+
// otherwise the message is sent out to every device that should be a recipient
|
|
462
|
+
if (!isGroup && !isStatus) {
|
|
463
|
+
additionalAttributes = { ...additionalAttributes, 'device_fanout': 'false' };
|
|
464
|
+
}
|
|
465
|
+
const { user, device } = (0, WABinary_1.jidDecode)(participant.jid);
|
|
466
|
+
devices.push({ user, device });
|
|
467
|
+
}
|
|
468
|
+
await authState.keys.transaction(async () => {
|
|
469
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
|
470
|
+
const mediaType = getMediaType(message);
|
|
471
|
+
if (mediaType) {
|
|
472
|
+
extraAttrs['mediatype'] = mediaType;
|
|
473
|
+
}
|
|
474
|
+
if ((_a = (0, Utils_1.normalizeMessageContent)(message)) === null || _a === void 0 ? void 0 : _a.pinInChatMessage) {
|
|
475
|
+
extraAttrs['decrypt-fail'] = 'hide';
|
|
476
|
+
}
|
|
477
|
+
if (isGroup || isStatus) {
|
|
478
|
+
const [groupData, senderKeyMap] = await Promise.all([
|
|
479
|
+
(async () => {
|
|
480
|
+
let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined;
|
|
481
|
+
if (groupData && Array.isArray(groupData === null || groupData === void 0 ? void 0 : groupData.participants)) {
|
|
482
|
+
logger.trace({ jid, participants: groupData.participants.length }, 'using cached group metadata');
|
|
483
|
+
}
|
|
484
|
+
else if (!isStatus) {
|
|
485
|
+
groupData = await groupMetadata(jid);
|
|
486
|
+
}
|
|
487
|
+
return groupData;
|
|
488
|
+
})(),
|
|
489
|
+
(async () => {
|
|
490
|
+
if (!participant && !isStatus) {
|
|
491
|
+
const result = await authState.keys.get('sender-key-memory', [jid]);
|
|
492
|
+
return result[jid] || {};
|
|
493
|
+
}
|
|
494
|
+
return {};
|
|
495
|
+
})()
|
|
496
|
+
]);
|
|
497
|
+
if (!participant) {
|
|
498
|
+
const participantsList = (groupData && !isStatus) ? groupData.participants.map(p => p.id) : [];
|
|
499
|
+
if (isStatus && statusJidList) {
|
|
500
|
+
participantsList.push(...statusJidList);
|
|
501
|
+
}
|
|
502
|
+
if (!isStatus) {
|
|
503
|
+
additionalAttributes = {
|
|
504
|
+
...additionalAttributes,
|
|
505
|
+
// eslint-disable-next-line camelcase
|
|
506
|
+
addressing_mode: (groupData === null || groupData === void 0 ? void 0 : groupData.addressingMode) || 'pn'
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false);
|
|
510
|
+
devices.push(...additionalDevices);
|
|
511
|
+
}
|
|
512
|
+
const patched = await patchMessageBeforeSending(message);
|
|
513
|
+
if (Array.isArray(patched)) {
|
|
514
|
+
throw new boom_1.Boom('Per-jid patching is not supported in groups');
|
|
515
|
+
}
|
|
516
|
+
const bytes = (0, Utils_1.encodeWAMessage)(patched);
|
|
517
|
+
const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
|
|
518
|
+
group: destinationJid,
|
|
519
|
+
data: bytes,
|
|
520
|
+
meId,
|
|
521
|
+
});
|
|
522
|
+
const senderKeyJids = [];
|
|
523
|
+
// ensure a connection is established with every device
|
|
524
|
+
for (const { user, device } of devices) {
|
|
525
|
+
const jid = (0, WABinary_1.jidEncode)(user, (groupData === null || groupData === void 0 ? void 0 : groupData.addressingMode) === 'lid' ? 'lid' : 's.whatsapp.net', device);
|
|
526
|
+
if (!senderKeyMap[jid] || !!participant) {
|
|
527
|
+
senderKeyJids.push(jid);
|
|
528
|
+
// store that this person has had the sender keys sent to them
|
|
529
|
+
senderKeyMap[jid] = true;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
// if there are some participants with whom the session has not been established
|
|
533
|
+
// if there are, we re-send the senderkey
|
|
534
|
+
if (senderKeyJids.length) {
|
|
535
|
+
logger.debug({ senderKeyJids }, 'sending new sender key');
|
|
536
|
+
const senderKeyMsg = {
|
|
537
|
+
senderKeyDistributionMessage: {
|
|
538
|
+
axolotlSenderKeyDistributionMessage: senderKeyDistributionMessage,
|
|
539
|
+
groupId: destinationJid
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
await assertSessions(senderKeyJids, false);
|
|
543
|
+
const result = await createParticipantNodes(senderKeyJids, senderKeyMsg, extraAttrs);
|
|
544
|
+
shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || result.shouldIncludeDeviceIdentity;
|
|
545
|
+
participants.push(...result.nodes);
|
|
546
|
+
}
|
|
547
|
+
binaryNodeContent.push({
|
|
548
|
+
tag: 'enc',
|
|
549
|
+
attrs: { v: '2', type: 'skmsg' },
|
|
550
|
+
content: ciphertext
|
|
551
|
+
});
|
|
552
|
+
await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } });
|
|
553
|
+
}
|
|
554
|
+
else if (isNewsletter) {
|
|
555
|
+
// Message edit
|
|
556
|
+
if ((_b = message.protocolMessage) === null || _b === void 0 ? void 0 : _b.editedMessage) {
|
|
557
|
+
msgId = (_c = message.protocolMessage.key) === null || _c === void 0 ? void 0 : _c.id;
|
|
558
|
+
message = message.protocolMessage.editedMessage;
|
|
559
|
+
}
|
|
560
|
+
// Message delete
|
|
561
|
+
if (((_d = message.protocolMessage) === null || _d === void 0 ? void 0 : _d.type) === WAProto_1.proto.Message.ProtocolMessage.Type.REVOKE) {
|
|
562
|
+
msgId = (_e = message.protocolMessage.key) === null || _e === void 0 ? void 0 : _e.id;
|
|
563
|
+
message = {};
|
|
564
|
+
}
|
|
565
|
+
const patched = await patchMessageBeforeSending(message, []);
|
|
566
|
+
if (Array.isArray(patched)) {
|
|
567
|
+
throw new boom_1.Boom('Per-jid patching is not supported in channel');
|
|
568
|
+
}
|
|
569
|
+
const bytes = (0, Utils_1.encodeNewsletterMessage)(patched);
|
|
570
|
+
binaryNodeContent.push({
|
|
571
|
+
tag: 'plaintext',
|
|
572
|
+
attrs: mediaType ? { mediatype: mediaType } : {},
|
|
573
|
+
content: bytes
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
const { user: meUser } = (0, WABinary_1.jidDecode)(meId);
|
|
578
|
+
if (!participant) {
|
|
579
|
+
devices.push({ user });
|
|
580
|
+
if (user !== meUser) {
|
|
581
|
+
devices.push({ user: meUser });
|
|
582
|
+
}
|
|
583
|
+
if ((additionalAttributes === null || additionalAttributes === void 0 ? void 0 : additionalAttributes['category']) !== 'peer') {
|
|
584
|
+
const additionalDevices = await getUSyncDevices([meId, jid], !!useUserDevicesCache, true);
|
|
585
|
+
devices.push(...additionalDevices);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
const allJids = [];
|
|
589
|
+
const meJids = [];
|
|
590
|
+
const otherJids = [];
|
|
591
|
+
for (const { user, device } of devices) {
|
|
592
|
+
const isMe = user === meUser;
|
|
593
|
+
const jid = (0, WABinary_1.jidEncode)(isMe && isLid ? ((_g = (_f = authState.creds) === null || _f === void 0 ? void 0 : _f.me) === null || _g === void 0 ? void 0 : _g.lid.split(':')[0]) || user : user, isLid ? 'lid' : 's.whatsapp.net', device);
|
|
594
|
+
if (isMe) {
|
|
595
|
+
meJids.push(jid);
|
|
596
|
+
}
|
|
597
|
+
else {
|
|
598
|
+
otherJids.push(jid);
|
|
599
|
+
}
|
|
600
|
+
allJids.push(jid);
|
|
601
|
+
}
|
|
602
|
+
await assertSessions(allJids, false);
|
|
603
|
+
const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = await Promise.all([
|
|
604
|
+
createParticipantNodes(meJids, meMsg, extraAttrs),
|
|
605
|
+
createParticipantNodes(otherJids, message, extraAttrs)
|
|
606
|
+
]);
|
|
607
|
+
participants.push(...meNodes);
|
|
608
|
+
participants.push(...otherNodes);
|
|
609
|
+
shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2;
|
|
610
|
+
}
|
|
611
|
+
if (participants.length) {
|
|
612
|
+
if ((additionalAttributes === null || additionalAttributes === void 0 ? void 0 : additionalAttributes['category']) === 'peer') {
|
|
613
|
+
const peerNode = (_j = (_h = participants[0]) === null || _h === void 0 ? void 0 : _h.content) === null || _j === void 0 ? void 0 : _j[0];
|
|
614
|
+
if (peerNode) {
|
|
615
|
+
binaryNodeContent.push(peerNode); // push only enc
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
else {
|
|
619
|
+
binaryNodeContent.push({
|
|
620
|
+
tag: 'participants',
|
|
621
|
+
attrs: {},
|
|
622
|
+
content: participants
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
const stanza = {
|
|
627
|
+
tag: 'message',
|
|
628
|
+
attrs: {
|
|
629
|
+
id: msgId,
|
|
630
|
+
type: isNewsletter ? getTypeMessage(message) : 'text',
|
|
631
|
+
...(additionalAttributes || {})
|
|
632
|
+
},
|
|
633
|
+
content: binaryNodeContent
|
|
634
|
+
};
|
|
635
|
+
// if the participant to send to is explicitly specified (generally retry recp)
|
|
636
|
+
// ensure the message is only sent to that person
|
|
637
|
+
// if a retry receipt is sent to everyone -- it'll fail decryption for everyone else who received the msg
|
|
638
|
+
if (participant) {
|
|
639
|
+
if ((0, WABinary_1.isJidGroup)(destinationJid)) {
|
|
640
|
+
stanza.attrs.to = destinationJid;
|
|
641
|
+
stanza.attrs.participant = participant.jid;
|
|
642
|
+
}
|
|
643
|
+
else if ((0, WABinary_1.areJidsSameUser)(participant.jid, meId)) {
|
|
644
|
+
stanza.attrs.to = participant.jid;
|
|
645
|
+
stanza.attrs.recipient = destinationJid;
|
|
646
|
+
}
|
|
647
|
+
else {
|
|
648
|
+
stanza.attrs.to = participant.jid;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
else {
|
|
652
|
+
stanza.attrs.to = destinationJid;
|
|
653
|
+
}
|
|
654
|
+
if (shouldIncludeDeviceIdentity) {
|
|
655
|
+
stanza.content.push({
|
|
656
|
+
tag: 'device-identity',
|
|
657
|
+
attrs: {},
|
|
658
|
+
content: (0, Utils_1.encodeSignedDeviceIdentity)(authState.creds.account, true)
|
|
659
|
+
});
|
|
660
|
+
logger.debug({ jid }, 'adding device identity');
|
|
661
|
+
}
|
|
662
|
+
if (additionalNodes && additionalNodes.length > 0) {
|
|
663
|
+
stanza.content.push(...additionalNodes);
|
|
664
|
+
}
|
|
665
|
+
const content = (0, Utils_1.normalizeMessageContent)(message);
|
|
666
|
+
const contentType = (0, Utils_1.getContentType)(content);
|
|
667
|
+
if (((0, WABinary_1.isJidGroup)(jid) || (0, WABinary_1.isJidUser)(jid)) && (contentType === 'interactiveMessage' ||
|
|
668
|
+
contentType === 'buttonsMessage' ||
|
|
669
|
+
contentType === 'listMessage')) {
|
|
670
|
+
const bizNode = { tag: 'biz', attrs: {} };
|
|
671
|
+
if ((((_l = (_k = message === null || message === void 0 ? void 0 : message.viewOnceMessage) === null || _k === void 0 ? void 0 : _k.message) === null || _l === void 0 ? void 0 : _l.interactiveMessage) || ((_o = (_m = message === null || message === void 0 ? void 0 : message.viewOnceMessageV2) === null || _m === void 0 ? void 0 : _m.message) === null || _o === void 0 ? void 0 : _o.interactiveMessage) || ((_q = (_p = message === null || message === void 0 ? void 0 : message.viewOnceMessageV2Extension) === null || _p === void 0 ? void 0 : _p.message) === null || _q === void 0 ? void 0 : _q.interactiveMessage) || (message === null || message === void 0 ? void 0 : message.interactiveMessage)) || (((_s = (_r = message === null || message === void 0 ? void 0 : message.viewOnceMessage) === null || _r === void 0 ? void 0 : _r.message) === null || _s === void 0 ? void 0 : _s.buttonsMessage) || ((_u = (_t = message === null || message === void 0 ? void 0 : message.viewOnceMessageV2) === null || _t === void 0 ? void 0 : _t.message) === null || _u === void 0 ? void 0 : _u.buttonsMessage) || ((_w = (_v = message === null || message === void 0 ? void 0 : message.viewOnceMessageV2Extension) === null || _v === void 0 ? void 0 : _v.message) === null || _w === void 0 ? void 0 : _w.buttonsMessage) || (message === null || message === void 0 ? void 0 : message.buttonsMessage))) {
|
|
672
|
+
bizNode.content = [{
|
|
673
|
+
tag: 'interactive',
|
|
674
|
+
attrs: {
|
|
675
|
+
type: 'native_flow',
|
|
676
|
+
v: '1'
|
|
677
|
+
},
|
|
678
|
+
content: [{
|
|
679
|
+
tag: 'native_flow',
|
|
680
|
+
attrs: { v: '9', name: 'mixed' }
|
|
681
|
+
}]
|
|
682
|
+
}];
|
|
683
|
+
}
|
|
684
|
+
else if (message === null || message === void 0 ? void 0 : message.listMessage) {
|
|
685
|
+
// list message only support in private chat
|
|
686
|
+
bizNode.content = [{
|
|
687
|
+
tag: 'list',
|
|
688
|
+
attrs: {
|
|
689
|
+
type: 'product_list',
|
|
690
|
+
v: '2'
|
|
691
|
+
}
|
|
692
|
+
}];
|
|
693
|
+
}
|
|
694
|
+
else if (message?.interactiveMessage?.carouselMessage ||
|
|
695
|
+
message?.viewOnceMessage?.message?.interactiveMessage?.carouselMessage ||
|
|
696
|
+
message?.viewOnceMessageV2?.message?.interactiveMessage?.carouselMessage ||
|
|
697
|
+
message?.viewOnceMessageV2Extension?.message?.interactiveMessage?.carouselMessage) {
|
|
698
|
+
bizNode.content = [{
|
|
699
|
+
tag: 'interactive',
|
|
700
|
+
attrs: {
|
|
701
|
+
type: 'carousel',
|
|
702
|
+
v: '1'
|
|
703
|
+
},
|
|
704
|
+
content: [{
|
|
705
|
+
tag: 'carousel',
|
|
706
|
+
attrs: { v: '1' }
|
|
707
|
+
}]
|
|
708
|
+
}];
|
|
709
|
+
}
|
|
710
|
+
stanza.content.push(bizNode);
|
|
711
|
+
}
|
|
712
|
+
logger.debug({ msgId }, `sending message to ${participants.length} devices`);
|
|
713
|
+
await (0, retry_1.retryWithBackoff)(({ signal }) => sendNode(stanza, { signal }), {
|
|
714
|
+
retries: 2, // Riduci i tentativi
|
|
715
|
+
baseMs: 100, // Riduci l'attesa iniziale
|
|
716
|
+
maxMs: 2000, // Riduci l'attesa massima
|
|
717
|
+
jitter: true,
|
|
718
|
+
timeoutPerAttemptMs: 5000,
|
|
719
|
+
shouldRetry: (err) => {
|
|
720
|
+
const status = err?.output?.statusCode || err?.statusCode;
|
|
721
|
+
// retry on transient failures
|
|
722
|
+
return !status || (status >= 500 || status === 408 || status === 429);
|
|
723
|
+
},
|
|
724
|
+
onRetry: (err, n) => logger?.warn?.({ err, attempt: n }, 'retrying sendNode')
|
|
725
|
+
});
|
|
726
|
+
|
|
727
|
+
// Mark message as successfully sent to prevent duplicate sends
|
|
728
|
+
markMessageAsSent(msgId, jid);
|
|
729
|
+
});
|
|
730
|
+
return msgId;
|
|
731
|
+
};
|
|
732
|
+
const getTypeMessage = (msg) => {
|
|
733
|
+
if (msg.viewOnceMessage) {
|
|
734
|
+
return getTypeMessage(msg.viewOnceMessage.message);
|
|
735
|
+
}
|
|
736
|
+
else if (msg.viewOnceMessageV2) {
|
|
737
|
+
return getTypeMessage(msg.viewOnceMessageV2.message);
|
|
738
|
+
}
|
|
739
|
+
else if (msg.viewOnceMessageV2Extension) {
|
|
740
|
+
return getTypeMessage(msg.viewOnceMessageV2Extension.message);
|
|
741
|
+
}
|
|
742
|
+
else if (msg.ephemeralMessage) {
|
|
743
|
+
return getTypeMessage(msg.ephemeralMessage.message);
|
|
744
|
+
}
|
|
745
|
+
else if (msg.documentWithCaptionMessage) {
|
|
746
|
+
return getTypeMessage(msg.documentWithCaptionMessage.message);
|
|
747
|
+
}
|
|
748
|
+
else if (msg.reactionMessage) {
|
|
749
|
+
return 'reaction';
|
|
750
|
+
}
|
|
751
|
+
else if (msg.pollCreationMessage || msg.pollCreationMessageV2 || msg.pollCreationMessageV3 || msg.pollUpdateMessage) {
|
|
752
|
+
return 'poll';
|
|
753
|
+
}
|
|
754
|
+
else if (getMediaType(msg)) {
|
|
755
|
+
return 'media';
|
|
756
|
+
}
|
|
757
|
+
else {
|
|
758
|
+
return 'text';
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
const getMediaType = (message) => {
|
|
762
|
+
if (message.imageMessage) {
|
|
763
|
+
return 'image';
|
|
764
|
+
}
|
|
765
|
+
else if (message.videoMessage) {
|
|
766
|
+
return message.videoMessage.gifPlayback ? 'gif' : 'video';
|
|
767
|
+
}
|
|
768
|
+
else if (message.audioMessage) {
|
|
769
|
+
return message.audioMessage.ptt ? 'ptt' : 'audio';
|
|
770
|
+
}
|
|
771
|
+
else if (message.contactMessage) {
|
|
772
|
+
return 'vcard';
|
|
773
|
+
}
|
|
774
|
+
else if (message.documentMessage) {
|
|
775
|
+
return 'document';
|
|
776
|
+
}
|
|
777
|
+
else if (message.contactsArrayMessage) {
|
|
778
|
+
return 'contact_array';
|
|
779
|
+
}
|
|
780
|
+
else if (message.liveLocationMessage) {
|
|
781
|
+
return 'livelocation';
|
|
782
|
+
}
|
|
783
|
+
else if (message.stickerMessage) {
|
|
784
|
+
return 'sticker';
|
|
785
|
+
}
|
|
786
|
+
else if (message.listMessage) {
|
|
787
|
+
return 'list';
|
|
788
|
+
}
|
|
789
|
+
else if (message.listResponseMessage) {
|
|
790
|
+
return 'list_response';
|
|
791
|
+
}
|
|
792
|
+
else if (message.buttonsResponseMessage) {
|
|
793
|
+
return 'buttons_response';
|
|
794
|
+
}
|
|
795
|
+
else if (message.orderMessage) {
|
|
796
|
+
return 'order';
|
|
797
|
+
}
|
|
798
|
+
else if (message.productMessage) {
|
|
799
|
+
return 'product';
|
|
800
|
+
}
|
|
801
|
+
else if (message.interactiveResponseMessage) {
|
|
802
|
+
return 'native_flow_response';
|
|
803
|
+
}
|
|
804
|
+
else if (message.groupInviteMessage) {
|
|
805
|
+
return 'url';
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
const getPrivacyTokens = async (jids) => {
|
|
809
|
+
const t = (0, Utils_1.unixTimestampSeconds)().toString();
|
|
810
|
+
const result = await query({
|
|
811
|
+
tag: 'iq',
|
|
812
|
+
attrs: {
|
|
813
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
814
|
+
type: 'set',
|
|
815
|
+
xmlns: 'privacy'
|
|
816
|
+
},
|
|
817
|
+
content: [
|
|
818
|
+
{
|
|
819
|
+
tag: 'tokens',
|
|
820
|
+
attrs: {},
|
|
821
|
+
content: jids.map(jid => ({
|
|
822
|
+
tag: 'token',
|
|
823
|
+
attrs: {
|
|
824
|
+
jid: (0, WABinary_1.jidNormalizedUser)(jid),
|
|
825
|
+
t,
|
|
826
|
+
type: 'trusted_contact'
|
|
827
|
+
}
|
|
828
|
+
}))
|
|
829
|
+
}
|
|
830
|
+
]
|
|
831
|
+
});
|
|
832
|
+
return result;
|
|
833
|
+
};
|
|
834
|
+
const waUploadToServer = (0, Utils_1.getWAUploadToServer)(config, refreshMediaConn);
|
|
835
|
+
const waitForMsgMediaUpdate = (0, Utils_1.bindWaitForEvent)(ev, 'messages.media-update');
|
|
836
|
+
return {
|
|
837
|
+
...sock,
|
|
838
|
+
getPrivacyTokens,
|
|
839
|
+
assertSessions,
|
|
840
|
+
relayMessage,
|
|
841
|
+
sendReceipt,
|
|
842
|
+
sendReceipts,
|
|
843
|
+
readMessages,
|
|
844
|
+
sendPeerDataOperationMessage,
|
|
845
|
+
sendPeerMessage,
|
|
846
|
+
getUSyncDevices,
|
|
847
|
+
getFailedSessionCache: () => failedSessionFetchCache,
|
|
848
|
+
getFailedSessionCacheTTL: () => FAILED_SESSION_CACHE_TTL,
|
|
849
|
+
getRecentlySentMessagesCache: () => recentlySentMessagesCache,
|
|
850
|
+
wasMessageRecentlySent,
|
|
851
|
+
markMessageAsSent,
|
|
852
|
+
sendMessage: async (jid, content, options = {}) => {
|
|
853
|
+
var _a, _b, _c;
|
|
854
|
+
const userJid = authState.creds.me.id;
|
|
855
|
+
if (!options.ephemeralExpiration) {
|
|
856
|
+
if ((0, WABinary_1.isJidGroup)(jid)) {
|
|
857
|
+
const useCache = options.useCachedGroupMetadata !== false;
|
|
858
|
+
const groupData = (useCache && cachedGroupMetadata) ? await cachedGroupMetadata(jid) : await groupMetadata(jid);
|
|
859
|
+
options.ephemeralExpiration = (groupData === null || groupData === void 0 ? void 0 : groupData.ephemeralDuration) || 0;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
if (typeof content === 'object' &&
|
|
863
|
+
'disappearingMessagesInChat' in content &&
|
|
864
|
+
typeof content['disappearingMessagesInChat'] !== 'undefined' &&
|
|
865
|
+
(0, WABinary_1.isJidGroup)(jid)) {
|
|
866
|
+
const { disappearingMessagesInChat } = content;
|
|
867
|
+
const value = typeof disappearingMessagesInChat === 'boolean' ?
|
|
868
|
+
(disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :
|
|
869
|
+
disappearingMessagesInChat;
|
|
870
|
+
await groupToggleEphemeral(jid, value);
|
|
871
|
+
}
|
|
872
|
+
// Handle pin messages
|
|
873
|
+
if (typeof content === 'object' && 'pin' in content && content.pin) {
|
|
874
|
+
const pinData = typeof content.pin === 'object' ? content.pin : { key: content.pin };
|
|
875
|
+
// Map type: 1 = PIN_FOR_ALL, 2 = UNPIN_FOR_ALL
|
|
876
|
+
const pinType = pinData.type !== undefined ? pinData.type : (content.type !== undefined ? content.type : WAProto_1.proto.Message.PinInChatMessage.Type.PIN_FOR_ALL);
|
|
877
|
+
const msgId = (0, Utils_1.generateMessageIDV2)((_c = sock.user) === null || _c === void 0 ? void 0 : _c.id);
|
|
878
|
+
const pinMessage = {
|
|
879
|
+
pinInChatMessage: {
|
|
880
|
+
key: pinData.key,
|
|
881
|
+
type: pinType,
|
|
882
|
+
senderTimestampMs: Date.now()
|
|
883
|
+
}
|
|
884
|
+
};
|
|
885
|
+
// Add messageContextInfo only for PIN (type 1), not for UNPIN (type 2)
|
|
886
|
+
if (pinType === WAProto_1.proto.Message.PinInChatMessage.Type.PIN_FOR_ALL) {
|
|
887
|
+
pinMessage.messageContextInfo = {
|
|
888
|
+
messageAddOnDurationInSecs: pinData.time || content.time || 86400, // Default 24 hours
|
|
889
|
+
messageAddOnExpiryType: WAProto_1.proto.MessageContextInfo.MessageAddonExpiryType.STATIC
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
const fullMsg = {
|
|
893
|
+
key: {
|
|
894
|
+
remoteJid: jid,
|
|
895
|
+
fromMe: true,
|
|
896
|
+
id: msgId,
|
|
897
|
+
participant: userJid
|
|
898
|
+
},
|
|
899
|
+
message: pinMessage,
|
|
900
|
+
messageTimestamp: (0, Utils_1.unixTimestampSeconds)()
|
|
901
|
+
};
|
|
902
|
+
await relayMessage(jid, fullMsg.message, { //oopsie, questo è il fix per il pin 😿
|
|
903
|
+
messageId: fullMsg.key.id,
|
|
904
|
+
useCachedGroupMetadata: options.useCachedGroupMetadata,
|
|
905
|
+
additionalAttributes: {
|
|
906
|
+
edit: '2',
|
|
907
|
+
...(options.additionalAttributes || {})
|
|
908
|
+
}
|
|
909
|
+
});
|
|
910
|
+
if (config.emitOwnEvents) {
|
|
911
|
+
process.nextTick(() => {
|
|
912
|
+
processingMutex.mutex(() => (upsertMessage(fullMsg, 'append')));
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
return fullMsg;
|
|
916
|
+
}
|
|
917
|
+
if (typeof content === 'object' && 'album' in content && content.album) {
|
|
918
|
+
const { album, caption } = content;
|
|
919
|
+
if (caption && !album[0].caption) {
|
|
920
|
+
album[0].caption = caption;
|
|
921
|
+
}
|
|
922
|
+
let mediaHandle;
|
|
923
|
+
let mediaMsg;
|
|
924
|
+
const albumMsg = (0, Utils_1.generateWAMessageFromContent)(jid, {
|
|
925
|
+
albumMessage: {
|
|
926
|
+
expectedImageCount: album.filter(item => 'image' in item).length,
|
|
927
|
+
expectedVideoCount: album.filter(item => 'video' in item).length
|
|
928
|
+
}
|
|
929
|
+
}, { userJid, ...options });
|
|
930
|
+
await relayMessage(jid, albumMsg.message, {
|
|
931
|
+
messageId: albumMsg.key.id
|
|
932
|
+
});
|
|
933
|
+
for (const i in album) {
|
|
934
|
+
const media = album[i];
|
|
935
|
+
if ('image' in media) {
|
|
936
|
+
mediaMsg = await (0, Utils_1.generateWAMessage)(jid, {
|
|
937
|
+
image: media.image,
|
|
938
|
+
...(media.caption ? { caption: media.caption } : {}),
|
|
939
|
+
...options
|
|
940
|
+
}, {
|
|
941
|
+
userJid,
|
|
942
|
+
upload: async (readStream, opts) => {
|
|
943
|
+
const up = await waUploadToServer(readStream, { ...opts, newsletter: (0, WABinary_1.isJidNewsletter)(jid) });
|
|
944
|
+
mediaHandle = up.handle;
|
|
945
|
+
return up;
|
|
946
|
+
},
|
|
947
|
+
...options,
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
else if ('video' in media) {
|
|
951
|
+
mediaMsg = await (0, Utils_1.generateWAMessage)(jid, {
|
|
952
|
+
video: media.video,
|
|
953
|
+
...(media.caption ? { caption: media.caption } : {}),
|
|
954
|
+
...(media.gifPlayback !== undefined ? { gifPlayback: media.gifPlayback } : {}),
|
|
955
|
+
...options
|
|
956
|
+
}, {
|
|
957
|
+
userJid,
|
|
958
|
+
upload: async (readStream, opts) => {
|
|
959
|
+
const up = await waUploadToServer(readStream, { ...opts, newsletter: (0, WABinary_1.isJidNewsletter)(jid) });
|
|
960
|
+
mediaHandle = up.handle;
|
|
961
|
+
return up;
|
|
962
|
+
},
|
|
963
|
+
...options,
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
if (mediaMsg) {
|
|
967
|
+
mediaMsg.message.messageContextInfo = {
|
|
968
|
+
messageSecret: (0, crypto_1.randomBytes)(32),
|
|
969
|
+
messageAssociation: {
|
|
970
|
+
associationType: 1,
|
|
971
|
+
parentMessageKey: albumMsg.key
|
|
972
|
+
}
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
await relayMessage(jid, mediaMsg.message, {
|
|
976
|
+
messageId: mediaMsg.key.id
|
|
977
|
+
});
|
|
978
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
979
|
+
}
|
|
980
|
+
return albumMsg;
|
|
981
|
+
}
|
|
982
|
+
else {
|
|
983
|
+
let mediaHandle;
|
|
984
|
+
const fullMsg = await (0, Utils_1.generateWAMessage)(jid, content, {
|
|
985
|
+
logger,
|
|
986
|
+
userJid,
|
|
987
|
+
getUrlInfo: text => (0, link_preview_1.getUrlInfo)(text, {
|
|
988
|
+
thumbnailWidth: linkPreviewImageThumbnailWidth,
|
|
989
|
+
fetchOpts: {
|
|
990
|
+
timeout: 3000,
|
|
991
|
+
...axiosOptions || {}
|
|
992
|
+
},
|
|
993
|
+
logger,
|
|
994
|
+
uploadImage: generateHighQualityLinkPreview
|
|
995
|
+
? waUploadToServer
|
|
996
|
+
: undefined
|
|
997
|
+
}),
|
|
998
|
+
getProfilePicUrl: sock.profilePictureUrl,
|
|
999
|
+
upload: async (readStream, opts) => {
|
|
1000
|
+
const up = await waUploadToServer(readStream, { ...opts, newsletter: (0, WABinary_1.isJidNewsletter)(jid) });
|
|
1001
|
+
mediaHandle = up.handle;
|
|
1002
|
+
return up;
|
|
1003
|
+
},
|
|
1004
|
+
mediaCache: config.mediaCache,
|
|
1005
|
+
options: config.options,
|
|
1006
|
+
messageId: (0, Utils_1.generateMessageIDV2)((_c = sock.user) === null || _c === void 0 ? void 0 : _c.id),
|
|
1007
|
+
...options,
|
|
1008
|
+
});
|
|
1009
|
+
const isDeleteMsg = 'delete' in content && !!content.delete;
|
|
1010
|
+
const isEditMsg = 'edit' in content && !!content.edit;
|
|
1011
|
+
const isPinMsg = 'pin' in content && !!content.pin;
|
|
1012
|
+
const isKeepMsg = 'keep' in content && content.keep;
|
|
1013
|
+
const isPollMessage = 'poll' in content && !!content.poll;
|
|
1014
|
+
const isAiMsg = 'ai' in content && !!content.ai;
|
|
1015
|
+
const isAiRichResponseMsg = 'richResponse' in content && !!content.richResponse;
|
|
1016
|
+
const additionalAttributes = {};
|
|
1017
|
+
const additionalNodes = [];
|
|
1018
|
+
// required for delete
|
|
1019
|
+
if (isDeleteMsg) {
|
|
1020
|
+
// if the chat is a group, and I am not the author, then delete the message as an admin
|
|
1021
|
+
if (((0, WABinary_1.isJidGroup)(content.delete.remoteJid) && !content.delete.fromMe) || (0, WABinary_1.isJidNewsletter)(jid)) {
|
|
1022
|
+
additionalAttributes.edit = '8';
|
|
1023
|
+
}
|
|
1024
|
+
else {
|
|
1025
|
+
additionalAttributes.edit = '7';
|
|
1026
|
+
}
|
|
1027
|
+
// required for edit message
|
|
1028
|
+
}
|
|
1029
|
+
else if (isEditMsg) {
|
|
1030
|
+
additionalAttributes.edit = (0, WABinary_1.isJidNewsletter)(jid) ? '3' : '1';
|
|
1031
|
+
// required for pin message
|
|
1032
|
+
}
|
|
1033
|
+
else if (isPinMsg) {
|
|
1034
|
+
additionalAttributes.edit = '2';
|
|
1035
|
+
// required for keep message
|
|
1036
|
+
}
|
|
1037
|
+
else if (isKeepMsg) {
|
|
1038
|
+
additionalAttributes.edit = '6';
|
|
1039
|
+
// required for polling message
|
|
1040
|
+
}
|
|
1041
|
+
else if (isPollMessage) {
|
|
1042
|
+
additionalNodes.push({
|
|
1043
|
+
tag: 'meta',
|
|
1044
|
+
attrs: {
|
|
1045
|
+
polltype: 'creation'
|
|
1046
|
+
},
|
|
1047
|
+
});
|
|
1048
|
+
// required to display AI icon on message
|
|
1049
|
+
}
|
|
1050
|
+
else if (isAiMsg || isAiRichResponseMsg) {
|
|
1051
|
+
additionalNodes.push({
|
|
1052
|
+
attrs: {
|
|
1053
|
+
biz_bot: '1'
|
|
1054
|
+
},
|
|
1055
|
+
tag: "bot"
|
|
1056
|
+
});
|
|
1057
|
+
}
|
|
1058
|
+
if (mediaHandle) {
|
|
1059
|
+
additionalAttributes['media_id'] = mediaHandle;
|
|
1060
|
+
}
|
|
1061
|
+
if ('cachedGroupMetadata' in options) {
|
|
1062
|
+
logger.warn('cachedGroupMetadata in sendMessage are deprecated, now cachedGroupMetadata is part of the socket config.');
|
|
1063
|
+
}
|
|
1064
|
+
await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata, additionalAttributes, additionalNodes: (isAiMsg || isAiRichResponseMsg) ? additionalNodes : options.additionalNodes, statusJidList: options.statusJidList });
|
|
1065
|
+
if (config.emitOwnEvents) {
|
|
1066
|
+
process.nextTick(() => {
|
|
1067
|
+
processingMutex.mutex(() => (upsertMessage(fullMsg, 'append')));
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
return fullMsg;
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
};
|
|
1074
|
+
|
|
1075
|
+
// Import interactive methods
|
|
1076
|
+
const { makeInteractiveSocket } = require('./messages-interactive');
|
|
1077
|
+
const interactiveSocket = makeInteractiveSocket(config);
|
|
1078
|
+
|
|
1079
|
+
return {
|
|
1080
|
+
...sock,
|
|
1081
|
+
...interactiveSocket,
|
|
1082
|
+
sendMessage
|
|
1083
|
+
};
|
|
1084
|
+
};
|
|
1085
|
+
exports.makeMessagesSocket = makeMessagesSocket;
|