@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.
Files changed (201) hide show
  1. package/LICENSE +58 -0
  2. package/README.MD +611 -0
  3. package/WAProto/GenerateStatics.sh +4 -0
  4. package/WAProto/WAProto.proto +5604 -0
  5. package/WAProto/index.d.ts +63156 -0
  6. package/WAProto/index.js +195638 -0
  7. package/WAProto/p.html +1 -0
  8. package/engine-requirements.js +10 -0
  9. package/lib/Defaults/baileys-version.json +3 -0
  10. package/lib/Defaults/index.d.ts +53 -0
  11. package/lib/Defaults/index.js +108 -0
  12. package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
  13. package/lib/Signal/Group/ciphertext-message.js +15 -0
  14. package/lib/Signal/Group/group-session-builder.d.ts +14 -0
  15. package/lib/Signal/Group/group-session-builder.js +64 -0
  16. package/lib/Signal/Group/group_cipher.d.ts +17 -0
  17. package/lib/Signal/Group/group_cipher.js +96 -0
  18. package/lib/Signal/Group/index.d.ts +11 -0
  19. package/lib/Signal/Group/index.js +57 -0
  20. package/lib/Signal/Group/keyhelper.d.ts +10 -0
  21. package/lib/Signal/Group/keyhelper.js +55 -0
  22. package/lib/Signal/Group/queue-job.d.ts +1 -0
  23. package/lib/Signal/Group/queue-job.js +57 -0
  24. package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
  25. package/lib/Signal/Group/sender-chain-key.js +34 -0
  26. package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
  27. package/lib/Signal/Group/sender-key-distribution-message.js +66 -0
  28. package/lib/Signal/Group/sender-key-message.d.ts +18 -0
  29. package/lib/Signal/Group/sender-key-message.js +69 -0
  30. package/lib/Signal/Group/sender-key-name.d.ts +17 -0
  31. package/lib/Signal/Group/sender-key-name.js +51 -0
  32. package/lib/Signal/Group/sender-key-record.d.ts +30 -0
  33. package/lib/Signal/Group/sender-key-record.js +53 -0
  34. package/lib/Signal/Group/sender-key-state.d.ts +38 -0
  35. package/lib/Signal/Group/sender-key-state.js +99 -0
  36. package/lib/Signal/Group/sender-message-key.d.ts +11 -0
  37. package/lib/Signal/Group/sender-message-key.js +29 -0
  38. package/lib/Signal/libsignal.d.ts +3 -0
  39. package/lib/Signal/libsignal.js +174 -0
  40. package/lib/Socket/Client/index.d.ts +2 -0
  41. package/lib/Socket/Client/index.js +18 -0
  42. package/lib/Socket/Client/types.d.ts +16 -0
  43. package/lib/Socket/Client/types.js +13 -0
  44. package/lib/Socket/Client/websocket.d.ts +13 -0
  45. package/lib/Socket/Client/websocket.js +111 -0
  46. package/lib/Socket/business.d.ts +172 -0
  47. package/lib/Socket/business.js +260 -0
  48. package/lib/Socket/chats.d.ts +85 -0
  49. package/lib/Socket/chats.js +1094 -0
  50. package/lib/Socket/groups.d.ts +124 -0
  51. package/lib/Socket/groups.js +423 -0
  52. package/lib/Socket/index.d.ts +172 -0
  53. package/lib/Socket/index.js +32 -0
  54. package/lib/Socket/messages-interactive.js +259 -0
  55. package/lib/Socket/messages-recv.d.ts +161 -0
  56. package/lib/Socket/messages-recv.js +1474 -0
  57. package/lib/Socket/messages-send.d.ts +151 -0
  58. package/lib/Socket/messages-send.js +1085 -0
  59. package/lib/Socket/newsletter.d.ts +136 -0
  60. package/lib/Socket/newsletter.js +250 -0
  61. package/lib/Socket/socket.d.ts +43 -0
  62. package/lib/Socket/socket.js +1241 -0
  63. package/lib/Socket/usync.d.ts +36 -0
  64. package/lib/Socket/usync.js +123 -0
  65. package/lib/Store/index.d.ts +2 -0
  66. package/lib/Store/index.js +8 -0
  67. package/lib/Store/make-in-memory-store.d.ts +118 -0
  68. package/lib/Store/make-in-memory-store.js +452 -0
  69. package/lib/Store/make-ordered-dictionary.d.ts +13 -0
  70. package/lib/Store/make-ordered-dictionary.js +81 -0
  71. package/lib/Store/object-repository.d.ts +10 -0
  72. package/lib/Store/object-repository.js +27 -0
  73. package/lib/Types/Auth.d.ts +114 -0
  74. package/lib/Types/Auth.js +2 -0
  75. package/lib/Types/Call.d.ts +13 -0
  76. package/lib/Types/Call.js +2 -0
  77. package/lib/Types/Chat.d.ts +109 -0
  78. package/lib/Types/Chat.js +4 -0
  79. package/lib/Types/Contact.d.ts +29 -0
  80. package/lib/Types/Contact.js +2 -0
  81. package/lib/Types/Events.d.ts +199 -0
  82. package/lib/Types/Events.js +2 -0
  83. package/lib/Types/GroupMetadata.d.ts +64 -0
  84. package/lib/Types/GroupMetadata.js +2 -0
  85. package/lib/Types/Label.d.ts +35 -0
  86. package/lib/Types/Label.js +27 -0
  87. package/lib/Types/LabelAssociation.d.ts +29 -0
  88. package/lib/Types/LabelAssociation.js +9 -0
  89. package/lib/Types/Message.d.ts +740 -0
  90. package/lib/Types/Message.js +7 -0
  91. package/lib/Types/Newsletter.d.ts +22 -0
  92. package/lib/Types/Newsletter.js +18 -0
  93. package/lib/Types/Product.d.ts +78 -0
  94. package/lib/Types/Product.js +2 -0
  95. package/lib/Types/Signal.d.ts +63 -0
  96. package/lib/Types/Signal.js +2 -0
  97. package/lib/Types/Socket.d.ts +134 -0
  98. package/lib/Types/Socket.js +2 -0
  99. package/lib/Types/State.d.ts +27 -0
  100. package/lib/Types/State.js +2 -0
  101. package/lib/Types/USync.d.ts +25 -0
  102. package/lib/Types/USync.js +2 -0
  103. package/lib/Types/index.d.ts +65 -0
  104. package/lib/Types/index.js +43 -0
  105. package/lib/Utils/auth-utils.d.ts +18 -0
  106. package/lib/Utils/auth-utils.js +209 -0
  107. package/lib/Utils/baileys-event-stream.d.ts +16 -0
  108. package/lib/Utils/baileys-event-stream.js +63 -0
  109. package/lib/Utils/business.d.ts +22 -0
  110. package/lib/Utils/business.js +234 -0
  111. package/lib/Utils/cache-manager.d.ts +16 -0
  112. package/lib/Utils/cache-manager.js +114 -0
  113. package/lib/Utils/chat-utils.d.ts +70 -0
  114. package/lib/Utils/chat-utils.js +734 -0
  115. package/lib/Utils/crypto.d.ts +40 -0
  116. package/lib/Utils/crypto.js +193 -0
  117. package/lib/Utils/decode-wa-message.d.ts +35 -0
  118. package/lib/Utils/decode-wa-message.js +207 -0
  119. package/lib/Utils/event-buffer.d.ts +35 -0
  120. package/lib/Utils/event-buffer.js +619 -0
  121. package/lib/Utils/generics.d.ts +89 -0
  122. package/lib/Utils/generics.js +440 -0
  123. package/lib/Utils/history.d.ts +19 -0
  124. package/lib/Utils/history.js +94 -0
  125. package/lib/Utils/index.d.ts +22 -0
  126. package/lib/Utils/index.js +38 -0
  127. package/lib/Utils/jid-validation.d.ts +2 -0
  128. package/lib/Utils/jid-validation.js +186 -0
  129. package/lib/Utils/link-preview.d.ts +21 -0
  130. package/lib/Utils/link-preview.js +152 -0
  131. package/lib/Utils/logger.d.ts +11 -0
  132. package/lib/Utils/logger.js +59 -0
  133. package/lib/Utils/lt-hash.d.ts +12 -0
  134. package/lib/Utils/lt-hash.js +51 -0
  135. package/lib/Utils/make-mutex.d.ts +7 -0
  136. package/lib/Utils/make-mutex.js +43 -0
  137. package/lib/Utils/messages-media.d.ts +120 -0
  138. package/lib/Utils/messages-media.js +848 -0
  139. package/lib/Utils/messages.d.ts +131 -0
  140. package/lib/Utils/messages.js +1793 -0
  141. package/lib/Utils/newsletter-utils.d.ts +2 -0
  142. package/lib/Utils/newsletter-utils.js +48 -0
  143. package/lib/Utils/noise-handler.d.ts +19 -0
  144. package/lib/Utils/noise-handler.js +150 -0
  145. package/lib/Utils/performance-config.d.ts +70 -0
  146. package/lib/Utils/performance-config.js +183 -0
  147. package/lib/Utils/process-message.d.ts +42 -0
  148. package/lib/Utils/process-message.js +498 -0
  149. package/lib/Utils/rate-limiter.js +90 -0
  150. package/lib/Utils/retry.js +66 -0
  151. package/lib/Utils/signal.d.ts +33 -0
  152. package/lib/Utils/signal.js +153 -0
  153. package/lib/Utils/use-multi-file-auth-state.d.ts +12 -0
  154. package/lib/Utils/use-multi-file-auth-state.js +129 -0
  155. package/lib/Utils/validate-connection.d.ts +10 -0
  156. package/lib/Utils/validate-connection.js +233 -0
  157. package/lib/WABinary/constants.d.ts +27 -0
  158. package/lib/WABinary/constants.js +1303 -0
  159. package/lib/WABinary/decode.d.ts +6 -0
  160. package/lib/WABinary/decode.js +279 -0
  161. package/lib/WABinary/encode.d.ts +2 -0
  162. package/lib/WABinary/encode.js +264 -0
  163. package/lib/WABinary/generic-utils.d.ts +14 -0
  164. package/lib/WABinary/generic-utils.js +114 -0
  165. package/lib/WABinary/index.d.ts +5 -0
  166. package/lib/WABinary/index.js +21 -0
  167. package/lib/WABinary/jid-utils.d.ts +38 -0
  168. package/lib/WABinary/jid-utils.js +485 -0
  169. package/lib/WABinary/types.d.ts +18 -0
  170. package/lib/WABinary/types.js +2 -0
  171. package/lib/WAM/BinaryInfo.d.ts +8 -0
  172. package/lib/WAM/BinaryInfo.js +13 -0
  173. package/lib/WAM/constants.d.ts +38 -0
  174. package/lib/WAM/constants.js +15350 -0
  175. package/lib/WAM/encode.d.ts +2 -0
  176. package/lib/WAM/encode.js +155 -0
  177. package/lib/WAM/index.d.ts +3 -0
  178. package/lib/WAM/index.js +19 -0
  179. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +9 -0
  180. package/lib/WAUSync/Protocols/USyncContactProtocol.js +102 -0
  181. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +22 -0
  182. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +110 -0
  183. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
  184. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
  185. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
  186. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +42 -0
  187. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +25 -0
  188. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +53 -0
  189. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +8 -0
  190. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
  191. package/lib/WAUSync/Protocols/index.d.ts +4 -0
  192. package/lib/WAUSync/Protocols/index.js +20 -0
  193. package/lib/WAUSync/USyncQuery.d.ts +28 -0
  194. package/lib/WAUSync/USyncQuery.js +147 -0
  195. package/lib/WAUSync/USyncUser.d.ts +12 -0
  196. package/lib/WAUSync/USyncUser.js +26 -0
  197. package/lib/WAUSync/index.d.ts +3 -0
  198. package/lib/WAUSync/index.js +19 -0
  199. package/lib/index.d.ts +17 -0
  200. package/lib/index.js +53 -0
  201. 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;