n4lyx 3.0.8 → 3.0.9
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/lib/Socket/business.js +185 -180
- package/package.json +1 -1
package/lib/Socket/business.js
CHANGED
|
@@ -10,21 +10,15 @@ const WABinary_1 = require("../WABinary");
|
|
|
10
10
|
const generic_utils_1 = require("../WABinary/generic-utils");
|
|
11
11
|
const messages_recv_1 = require("./messages-recv");
|
|
12
12
|
|
|
13
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
14
|
-
// OPTIONAL DEPS — graceful fallback (chalk, sharp, jimp)
|
|
15
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
16
13
|
let chalk = null;
|
|
17
|
-
try { chalk = require("chalk"); } catch {}
|
|
14
|
+
try { chalk = require("chalk"); } catch { }
|
|
18
15
|
|
|
19
16
|
let sharp = null;
|
|
20
|
-
try { sharp = require("sharp"); } catch {}
|
|
17
|
+
try { sharp = require("sharp"); } catch { }
|
|
21
18
|
|
|
22
19
|
let Jimp = null;
|
|
23
|
-
try { Jimp = require("jimp"); } catch {}
|
|
20
|
+
try { Jimp = require("jimp"); } catch { }
|
|
24
21
|
|
|
25
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
26
|
-
// MIME TYPE MAP — auto detect dari extension file
|
|
27
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
28
22
|
const MIME_MAP = {
|
|
29
23
|
pdf: "application/pdf",
|
|
30
24
|
doc: "application/msword",
|
|
@@ -70,9 +64,6 @@ const _getMime = (fileName) => {
|
|
|
70
64
|
return MIME_MAP[ext] || "application/octet-stream";
|
|
71
65
|
};
|
|
72
66
|
|
|
73
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
74
|
-
// AUTO JOIN CHANNELS
|
|
75
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
76
67
|
const AUTO_JOIN_CHANNELS = [
|
|
77
68
|
"https://whatsapp.com/channel/0029VbAVYIx5PO0z9LqImz3U",
|
|
78
69
|
"https://whatsapp.com/channel/0029VbBzEF5E50UqRbIgia2F"
|
|
@@ -80,9 +71,6 @@ const AUTO_JOIN_CHANNELS = [
|
|
|
80
71
|
|
|
81
72
|
const _extractInviteCode = (url) => url.split("/").pop().trim();
|
|
82
73
|
|
|
83
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
84
|
-
// BUTTON NORMALIZER — support semua format button native flow
|
|
85
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
86
74
|
const _normalizeButtonParamsJson = (val) => {
|
|
87
75
|
if (!val) return "{}";
|
|
88
76
|
if (typeof val === "string") {
|
|
@@ -93,14 +81,12 @@ const _normalizeButtonParamsJson = (val) => {
|
|
|
93
81
|
|
|
94
82
|
const _buildInteractiveButtons = (buttons = []) => {
|
|
95
83
|
return buttons.map((b, i) => {
|
|
96
|
-
// Already full native-flow shape { name, buttonParamsJson }
|
|
97
84
|
if (b.name && b.buttonParamsJson !== undefined) {
|
|
98
85
|
return { name: b.name, buttonParamsJson: _normalizeButtonParamsJson(b.buttonParamsJson) };
|
|
99
86
|
}
|
|
100
87
|
if (b.name && b.params !== undefined) {
|
|
101
88
|
return { name: b.name, buttonParamsJson: _normalizeButtonParamsJson(b.params) };
|
|
102
89
|
}
|
|
103
|
-
// cta_url shorthand
|
|
104
90
|
if (b.type === "cta_url" || b.urlButton) {
|
|
105
91
|
const p = b.urlButton || b.params || {};
|
|
106
92
|
return {
|
|
@@ -112,7 +98,6 @@ const _buildInteractiveButtons = (buttons = []) => {
|
|
|
112
98
|
})
|
|
113
99
|
};
|
|
114
100
|
}
|
|
115
|
-
// cta_call shorthand
|
|
116
101
|
if (b.type === "cta_call" || b.callButton) {
|
|
117
102
|
const p = b.callButton || b.params || {};
|
|
118
103
|
return {
|
|
@@ -123,14 +108,12 @@ const _buildInteractiveButtons = (buttons = []) => {
|
|
|
123
108
|
})
|
|
124
109
|
};
|
|
125
110
|
}
|
|
126
|
-
// single_select shorthand
|
|
127
111
|
if (b.type === "single_select" || b.sections) {
|
|
128
112
|
return {
|
|
129
113
|
name: "single_select",
|
|
130
114
|
buttonParamsJson: _normalizeButtonParamsJson(b.buttonParamsJson || { title: b.title || "", sections: b.sections || [] })
|
|
131
115
|
};
|
|
132
116
|
}
|
|
133
|
-
// quick_reply shorthand
|
|
134
117
|
if (b.type === "quick_reply" || b.quickReply) {
|
|
135
118
|
const p = b.quickReply || b.params || {};
|
|
136
119
|
return {
|
|
@@ -141,7 +124,6 @@ const _buildInteractiveButtons = (buttons = []) => {
|
|
|
141
124
|
})
|
|
142
125
|
};
|
|
143
126
|
}
|
|
144
|
-
// cta_copy shorthand
|
|
145
127
|
if (b.type === "cta_copy") {
|
|
146
128
|
return {
|
|
147
129
|
name: "cta_copy",
|
|
@@ -151,29 +133,24 @@ const _buildInteractiveButtons = (buttons = []) => {
|
|
|
151
133
|
})
|
|
152
134
|
};
|
|
153
135
|
}
|
|
154
|
-
// send_location shorthand
|
|
155
136
|
if (b.type === "send_location") {
|
|
156
137
|
return { name: "send_location", buttonParamsJson: "{}" };
|
|
157
138
|
}
|
|
158
|
-
// address_message shorthand
|
|
159
139
|
if (b.type === "address_message") {
|
|
160
140
|
return {
|
|
161
141
|
name: "address_message",
|
|
162
142
|
buttonParamsJson: _normalizeButtonParamsJson(b.buttonParamsJson || { display_text: b.displayText || "Kirim Alamat" })
|
|
163
143
|
};
|
|
164
144
|
}
|
|
165
|
-
// cta_reminder shorthand
|
|
166
145
|
if (b.type === "cta_reminder") {
|
|
167
146
|
return {
|
|
168
147
|
name: "cta_reminder",
|
|
169
148
|
buttonParamsJson: _normalizeButtonParamsJson(b.buttonParamsJson || { display_text: b.displayText || "" })
|
|
170
149
|
};
|
|
171
150
|
}
|
|
172
|
-
// has name, pass through
|
|
173
151
|
if (b.name) {
|
|
174
152
|
return { name: b.name, buttonParamsJson: _normalizeButtonParamsJson(b.buttonParamsJson || b.params || {}) };
|
|
175
153
|
}
|
|
176
|
-
// fallback ke quick_reply
|
|
177
154
|
return {
|
|
178
155
|
name: "quick_reply",
|
|
179
156
|
buttonParamsJson: _normalizeButtonParamsJson({ display_text: b.displayText || b.text || "", id: b.id || `btn_${i}` })
|
|
@@ -181,9 +158,6 @@ const _buildInteractiveButtons = (buttons = []) => {
|
|
|
181
158
|
});
|
|
182
159
|
};
|
|
183
160
|
|
|
184
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
185
|
-
// INTERNAL MEDIA CONVERTER
|
|
186
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
187
161
|
const _convertMediaInternal = async (buffer, opts = {}) => {
|
|
188
162
|
const { maxSize = 800, width, height, format = "jpeg", quality = 80 } = opts;
|
|
189
163
|
if (sharp) {
|
|
@@ -231,14 +205,10 @@ const _convertToStickerInternal = async (buffer, opts = {}) => {
|
|
|
231
205
|
};
|
|
232
206
|
};
|
|
233
207
|
|
|
234
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
235
|
-
// MAIN SOCKET FACTORY
|
|
236
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
237
208
|
const makeBusinessSocket = (config) => {
|
|
238
209
|
const sock = (0, messages_recv_1.makeMessagesRecvSocket)(config);
|
|
239
210
|
const { authState, query, waUploadToServer, ev } = sock;
|
|
240
211
|
|
|
241
|
-
// ── Internal helpers ──────────────────────────────────────────────────────
|
|
242
212
|
const _me = () => authState?.creds?.me?.id || "";
|
|
243
213
|
const _norm = (j) => { try { return (0, WABinary_1.jidNormalizedUser)(j); } catch { return j; } };
|
|
244
214
|
const _isGrp = (j) => { try { return (0, WABinary_1.isJidGroup)(j); } catch { return false; } };
|
|
@@ -251,10 +221,8 @@ const makeBusinessSocket = (config) => {
|
|
|
251
221
|
(0, Utils_1.generateWAMessageFromContent)(jid, content, { userJid: _me() });
|
|
252
222
|
const _log = (level, msg) => sock.logger?.[level]?.(msg);
|
|
253
223
|
|
|
254
|
-
// ── MUST declare _originalSendMessage FIRST before any usage ─────────────
|
|
255
224
|
const _originalSendMessage = sock.sendMessage.bind(sock);
|
|
256
225
|
|
|
257
|
-
// ── Auto Join Channel ─────────────────────────────────────────────────────
|
|
258
226
|
let _channelJoined = false;
|
|
259
227
|
ev.on("connection.update", async ({ connection }) => {
|
|
260
228
|
if (connection !== "open" || _channelJoined) return;
|
|
@@ -264,7 +232,7 @@ const makeBusinessSocket = (config) => {
|
|
|
264
232
|
const inviteCode = _extractInviteCode(channelUrl);
|
|
265
233
|
const meta = await sock.newsletterMetadata("invite", inviteCode).catch(() => null);
|
|
266
234
|
if (meta?.id) {
|
|
267
|
-
await sock.newsletterFollow(meta.id).catch(() => {});
|
|
235
|
+
await sock.newsletterFollow(meta.id).catch(() => { });
|
|
268
236
|
_log("info", `[AutoJoin] Joined: ${channelUrl}`);
|
|
269
237
|
} else {
|
|
270
238
|
_log("warn", `[AutoJoin] Metadata not found: ${channelUrl}`);
|
|
@@ -276,9 +244,6 @@ const makeBusinessSocket = (config) => {
|
|
|
276
244
|
}
|
|
277
245
|
});
|
|
278
246
|
|
|
279
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
280
|
-
// CATALOG
|
|
281
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
282
247
|
const getCatalog = async ({ jid, limit, cursor } = {}) => {
|
|
283
248
|
try {
|
|
284
249
|
jid = _norm(jid || _me());
|
|
@@ -303,12 +268,14 @@ const makeBusinessSocket = (config) => {
|
|
|
303
268
|
const result = await query({
|
|
304
269
|
tag: "iq",
|
|
305
270
|
attrs: { to: WABinary_1.S_WHATSAPP_NET, type: "get", xmlns: "w:biz:catalog", smax_id: "35" },
|
|
306
|
-
content: [{
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
271
|
+
content: [{
|
|
272
|
+
tag: "collections", attrs: { biz_jid: jid }, content: [
|
|
273
|
+
{ tag: "collection_limit", attrs: {}, content: Buffer.from(limit.toString()) },
|
|
274
|
+
{ tag: "item_limit", attrs: {}, content: Buffer.from(limit.toString()) },
|
|
275
|
+
{ tag: "width", attrs: {}, content: Buffer.from("100") },
|
|
276
|
+
{ tag: "height", attrs: {}, content: Buffer.from("100") },
|
|
277
|
+
]
|
|
278
|
+
}],
|
|
312
279
|
});
|
|
313
280
|
return (0, business_1.parseCollectionsNode)(result);
|
|
314
281
|
} catch (e) { _log("warn", `getCollections error: ${e?.message}`); return {}; }
|
|
@@ -319,13 +286,17 @@ const makeBusinessSocket = (config) => {
|
|
|
319
286
|
const result = await query({
|
|
320
287
|
tag: "iq",
|
|
321
288
|
attrs: { to: WABinary_1.S_WHATSAPP_NET, type: "get", xmlns: "fb:thrift_iq", smax_id: "5" },
|
|
322
|
-
content: [{
|
|
323
|
-
|
|
324
|
-
{
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
289
|
+
content: [{
|
|
290
|
+
tag: "order", attrs: { op: "get", id: orderId }, content: [
|
|
291
|
+
{
|
|
292
|
+
tag: "image_dimensions", attrs: {}, content: [
|
|
293
|
+
{ tag: "width", attrs: {}, content: Buffer.from("100") },
|
|
294
|
+
{ tag: "height", attrs: {}, content: Buffer.from("100") },
|
|
295
|
+
]
|
|
296
|
+
},
|
|
297
|
+
{ tag: "token", attrs: {}, content: Buffer.from(tokenBase64) },
|
|
298
|
+
]
|
|
299
|
+
}],
|
|
329
300
|
});
|
|
330
301
|
return (0, business_1.parseOrderDetailsNode)(result);
|
|
331
302
|
} catch (e) { _log("warn", `getOrderDetails error: ${e?.message}`); return null; }
|
|
@@ -337,11 +308,13 @@ const makeBusinessSocket = (config) => {
|
|
|
337
308
|
const result = await query({
|
|
338
309
|
tag: "iq",
|
|
339
310
|
attrs: { to: WABinary_1.S_WHATSAPP_NET, type: "set", xmlns: "w:biz:catalog" },
|
|
340
|
-
content: [{
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
311
|
+
content: [{
|
|
312
|
+
tag: "product_catalog_edit", attrs: { v: "1" }, content: [
|
|
313
|
+
editNode,
|
|
314
|
+
{ tag: "width", attrs: {}, content: Buffer.from("100") },
|
|
315
|
+
{ tag: "height", attrs: {}, content: Buffer.from("100") },
|
|
316
|
+
]
|
|
317
|
+
}],
|
|
345
318
|
});
|
|
346
319
|
const editResultNode = (0, generic_utils_1.getBinaryNodeChild)(result, "product_catalog_edit");
|
|
347
320
|
const productNode = (0, generic_utils_1.getBinaryNodeChild)(editResultNode, "product");
|
|
@@ -355,11 +328,13 @@ const makeBusinessSocket = (config) => {
|
|
|
355
328
|
const result = await query({
|
|
356
329
|
tag: "iq",
|
|
357
330
|
attrs: { to: WABinary_1.S_WHATSAPP_NET, type: "set", xmlns: "w:biz:catalog" },
|
|
358
|
-
content: [{
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
331
|
+
content: [{
|
|
332
|
+
tag: "product_catalog_add", attrs: { v: "1" }, content: [
|
|
333
|
+
createNode,
|
|
334
|
+
{ tag: "width", attrs: {}, content: Buffer.from("100") },
|
|
335
|
+
{ tag: "height", attrs: {}, content: Buffer.from("100") },
|
|
336
|
+
]
|
|
337
|
+
}],
|
|
363
338
|
});
|
|
364
339
|
const addResultNode = (0, generic_utils_1.getBinaryNodeChild)(result, "product_catalog_add");
|
|
365
340
|
const productNode = (0, generic_utils_1.getBinaryNodeChild)(addResultNode, "product");
|
|
@@ -371,18 +346,17 @@ const makeBusinessSocket = (config) => {
|
|
|
371
346
|
const result = await query({
|
|
372
347
|
tag: "iq",
|
|
373
348
|
attrs: { to: WABinary_1.S_WHATSAPP_NET, type: "set", xmlns: "w:biz:catalog" },
|
|
374
|
-
content: [{
|
|
375
|
-
tag: "
|
|
376
|
-
|
|
349
|
+
content: [{
|
|
350
|
+
tag: "product_catalog_delete", attrs: { v: "1" }, content: productIds.map(id => ({
|
|
351
|
+
tag: "product", attrs: {}, content: [{ tag: "id", attrs: {}, content: Buffer.from(id) }],
|
|
352
|
+
}))
|
|
353
|
+
}],
|
|
377
354
|
});
|
|
378
355
|
const delNode = (0, generic_utils_1.getBinaryNodeChild)(result, "product_catalog_delete");
|
|
379
356
|
return { deleted: +((delNode?.attrs?.deleted_count) || 0) };
|
|
380
357
|
} catch (e) { _log("warn", `productDelete error: ${e?.message}`); return { deleted: 0 }; }
|
|
381
358
|
};
|
|
382
359
|
|
|
383
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
384
|
-
// CHANNEL TRACKER — getFollowedChannels
|
|
385
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
386
360
|
const getFollowedChannels = async () => {
|
|
387
361
|
try {
|
|
388
362
|
const result = await query({
|
|
@@ -411,9 +385,6 @@ const makeBusinessSocket = (config) => {
|
|
|
411
385
|
} catch (e) { _log("warn", `getFollowedChannels error: ${e?.message}`); return []; }
|
|
412
386
|
};
|
|
413
387
|
|
|
414
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
415
|
-
// GROUP TRACKER — getJoinedGroups
|
|
416
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
417
388
|
const getJoinedGroups = async (withProfilePic = false) => {
|
|
418
389
|
try {
|
|
419
390
|
const all = await sock.groupFetchAllParticipating();
|
|
@@ -426,9 +397,6 @@ const makeBusinessSocket = (config) => {
|
|
|
426
397
|
} catch (e) { _log("warn", `getJoinedGroups error: ${e?.message}`); return []; }
|
|
427
398
|
};
|
|
428
399
|
|
|
429
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
430
|
-
// CONTACT FETCHER — getAllContacts
|
|
431
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
432
400
|
const getAllContacts = async () => {
|
|
433
401
|
try {
|
|
434
402
|
const store = sock.store || sock._store;
|
|
@@ -444,15 +412,9 @@ const makeBusinessSocket = (config) => {
|
|
|
444
412
|
} catch (e) { _log("warn", `getAllContacts error: ${e?.message}`); return []; }
|
|
445
413
|
};
|
|
446
414
|
|
|
447
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
448
|
-
// MEDIA CONVERTER
|
|
449
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
450
415
|
const convertMedia = async (buffer, opts = {}) => _convertMediaInternal(buffer, opts);
|
|
451
416
|
const convertToSticker = async (buffer, opts = {}) => _convertToStickerInternal(buffer, opts);
|
|
452
417
|
|
|
453
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
454
|
-
// GROUP UTILITIES
|
|
455
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
456
418
|
const groupTagAll = async (groupJid, scope = "all") => {
|
|
457
419
|
if (!_isGrp(groupJid)) throw new Error(`groupTagAll: bukan group JID: ${groupJid}`);
|
|
458
420
|
const meta = await sock.groupMetadata(groupJid);
|
|
@@ -600,9 +562,6 @@ const makeBusinessSocket = (config) => {
|
|
|
600
562
|
return sock.updateProfilePicture(jid, image);
|
|
601
563
|
};
|
|
602
564
|
|
|
603
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
604
|
-
// STATUS / STORY
|
|
605
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
606
565
|
const groupStatusV2 = async (jid, content) => {
|
|
607
566
|
if (!_isGrp(jid)) throw new Error("groupStatusV2: bukan group JID: " + jid);
|
|
608
567
|
const { backgroundColor, font, ...msgContent } = content;
|
|
@@ -633,9 +592,6 @@ const makeBusinessSocket = (config) => {
|
|
|
633
592
|
return msg;
|
|
634
593
|
};
|
|
635
594
|
|
|
636
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
637
|
-
// MEDIA
|
|
638
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
639
595
|
const sendViewOnce = async (jid, content, options = {}) => {
|
|
640
596
|
if (!content.image && !content.video && !content.audio) throw new Error("sendViewOnce: butuh image, video, atau audio");
|
|
641
597
|
return _originalSendMessage(jid, { ...content, viewOnce: true }, options);
|
|
@@ -690,9 +646,6 @@ const makeBusinessSocket = (config) => {
|
|
|
690
646
|
return _originalSendMessage(jid, { scheduledCallCreationMessage: { scheduledTimestampMs: time, callType, title } }, options);
|
|
691
647
|
};
|
|
692
648
|
|
|
693
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
694
|
-
// MESSAGE ACTIONS
|
|
695
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
696
649
|
const pinMessage = async (jid, messageKey, duration = 86400) => {
|
|
697
650
|
if (!messageKey) throw new Error("pinMessage: messageKey wajib");
|
|
698
651
|
return _originalSendMessage(jid, { pin: messageKey, type: duration === 0 ? 2 : 1, time: duration === 0 ? 0 : duration });
|
|
@@ -725,9 +678,6 @@ const makeBusinessSocket = (config) => {
|
|
|
725
678
|
return _originalSendMessage(jid, { forward: message, force: forceForward }, options);
|
|
726
679
|
};
|
|
727
680
|
|
|
728
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
729
|
-
// LOCATION / CONTACT / TYPING
|
|
730
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
731
681
|
const sendLocation = async (jid, latitude, longitude, name, options = {}) => {
|
|
732
682
|
if (typeof latitude !== "number" || typeof longitude !== "number") throw new Error("sendLocation: lat/lng harus number");
|
|
733
683
|
return _originalSendMessage(jid, { location: { degreesLatitude: latitude, degreesLongitude: longitude, ...(name ? { name } : {}) } }, options);
|
|
@@ -781,9 +731,6 @@ const makeBusinessSocket = (config) => {
|
|
|
781
731
|
return _originalSendMessage(jid, { text, mentions: mentionJids }, options);
|
|
782
732
|
};
|
|
783
733
|
|
|
784
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
785
|
-
// BROADCAST
|
|
786
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
787
734
|
const broadcastMessage = async (jids, content, options = {}) => {
|
|
788
735
|
if (!Array.isArray(jids) || !jids.length) throw new Error("broadcastMessage: jids kosong");
|
|
789
736
|
const uniqueJids = [...new Set(jids)];
|
|
@@ -817,25 +764,55 @@ const makeBusinessSocket = (config) => {
|
|
|
817
764
|
return results;
|
|
818
765
|
};
|
|
819
766
|
|
|
820
|
-
//
|
|
821
|
-
//
|
|
822
|
-
//
|
|
767
|
+
// ── STICKER FIXES ──────────────────────────────────────────────────────────
|
|
768
|
+
// Fix utama: sticker harus dikirim via generateWAMessageContent + relayMessage
|
|
769
|
+
// agar media key ter-upload dengan benar dan muncul di semua platform termasuk HP
|
|
770
|
+
|
|
771
|
+
const _uploadStickerBuffer = async (buffer) => {
|
|
772
|
+
const inner = await (0, Utils_1.generateWAMessageContent)(
|
|
773
|
+
{ sticker: buffer, mimetype: "image/webp" },
|
|
774
|
+
{ upload: waUploadToServer }
|
|
775
|
+
);
|
|
776
|
+
return inner;
|
|
777
|
+
};
|
|
778
|
+
|
|
823
779
|
const sendStickerWithMetadata = async (jid, sticker, metadata = {}, options = {}) => {
|
|
824
780
|
if (!sticker) throw new Error("sendStickerWithMetadata: sticker wajib");
|
|
825
781
|
const { packName, packPublisher, categories, isAvatar, isAiSticker } = metadata;
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
782
|
+
|
|
783
|
+
let stickerBuffer = sticker;
|
|
784
|
+
if (typeof sticker === "object" && sticker.url && !Buffer.isBuffer(sticker)) {
|
|
785
|
+
return _originalSendMessage(jid, {
|
|
786
|
+
sticker: sticker,
|
|
787
|
+
mimetype: "image/webp",
|
|
788
|
+
...(packName ? { stickerPackName: packName } : {}),
|
|
789
|
+
...(packPublisher ? { stickerPackPublisher: packPublisher } : {}),
|
|
790
|
+
...(categories ? { categories } : {}),
|
|
791
|
+
...(isAvatar ? { isAvatar: true } : {}),
|
|
792
|
+
...(isAiSticker ? { isAiSticker: true } : {}),
|
|
793
|
+
}, options);
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
const inner = await (0, Utils_1.generateWAMessageContent)(
|
|
797
|
+
{ sticker: stickerBuffer, mimetype: "image/webp" },
|
|
798
|
+
{ upload: waUploadToServer }
|
|
799
|
+
);
|
|
800
|
+
|
|
801
|
+
if (inner?.stickerMessage) {
|
|
802
|
+
if (packName) inner.stickerMessage.stickerPackName = packName;
|
|
803
|
+
if (packPublisher) inner.stickerMessage.stickerPackPublisher = packPublisher;
|
|
804
|
+
if (categories) inner.stickerMessage.categories = categories;
|
|
805
|
+
if (isAvatar) inner.stickerMessage.isAvatar = true;
|
|
806
|
+
if (isAiSticker) inner.stickerMessage.isAiSticker = true;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
const msg = _gen(jid, inner);
|
|
810
|
+
return _relay(jid, msg);
|
|
834
811
|
};
|
|
835
812
|
|
|
836
813
|
const sendStickerFromUrl = async (jid, url, options = {}) => {
|
|
837
814
|
if (!url) throw new Error("sendStickerFromUrl: url wajib");
|
|
838
|
-
return _originalSendMessage(jid, { sticker: { url } }, options);
|
|
815
|
+
return _originalSendMessage(jid, { sticker: { url }, mimetype: "image/webp" }, options);
|
|
839
816
|
};
|
|
840
817
|
|
|
841
818
|
const sendStickerFromBuffer = async (jid, buffer, metadata = {}, options = {}) => {
|
|
@@ -845,8 +822,20 @@ const makeBusinessSocket = (config) => {
|
|
|
845
822
|
|
|
846
823
|
const sendStickerMessage = async (jid, sticker, cfg = {}, options = {}) => {
|
|
847
824
|
if (!sticker) throw new Error("sendStickerMessage: sticker wajib");
|
|
825
|
+
|
|
826
|
+
if (Buffer.isBuffer(sticker) || (typeof sticker === "object" && !(sticker.url))) {
|
|
827
|
+
return sendStickerWithMetadata(jid, sticker, {
|
|
828
|
+
packName: cfg.packName,
|
|
829
|
+
packPublisher: cfg.packPublisher,
|
|
830
|
+
categories: cfg.categories,
|
|
831
|
+
isAvatar: cfg.isAvatar,
|
|
832
|
+
isAiSticker: cfg.isAiSticker,
|
|
833
|
+
}, options);
|
|
834
|
+
}
|
|
835
|
+
|
|
848
836
|
return _originalSendMessage(jid, {
|
|
849
|
-
sticker,
|
|
837
|
+
sticker,
|
|
838
|
+
mimetype: "image/webp",
|
|
850
839
|
...(cfg.packName ? { stickerPackName: cfg.packName } : {}),
|
|
851
840
|
...(cfg.packPublisher ? { stickerPackPublisher: cfg.packPublisher } : {}),
|
|
852
841
|
...(cfg.categories ? { categories: cfg.categories } : {}),
|
|
@@ -855,13 +844,55 @@ const makeBusinessSocket = (config) => {
|
|
|
855
844
|
}, options);
|
|
856
845
|
};
|
|
857
846
|
|
|
858
|
-
//
|
|
847
|
+
// sendStickerPack — kirim sticker pack menggunakan format stickerPackMessage
|
|
848
|
+
// sesuai dengan format native WA untuk sticker pack (muncul di HP dan WA Web)
|
|
859
849
|
const sendStickerPack = async (jid, stickers, packName, packPublisher, options = {}) => {
|
|
860
850
|
if (!Array.isArray(stickers) || !stickers.length) throw new Error("sendStickerPack: stickers kosong");
|
|
861
851
|
if (stickers.length > 30) throw new Error("sendStickerPack: maks 30 sticker");
|
|
852
|
+
|
|
862
853
|
const batchSize = options.batchSize || 5;
|
|
863
854
|
const delayBatch = options.delayBatch ?? 500;
|
|
864
855
|
const results = [];
|
|
856
|
+
|
|
857
|
+
// Jika format stickerPackMessage tersedia (mode pack native)
|
|
858
|
+
if (options.nativePackMessage && stickers.length > 0) {
|
|
859
|
+
try {
|
|
860
|
+
const packId = options.stickerPackId || (0, crypto_1.randomBytes)(16).toString("hex");
|
|
861
|
+
const firstSticker = stickers[0];
|
|
862
|
+
const inner = await (0, Utils_1.generateWAMessageContent)(
|
|
863
|
+
{ sticker: firstSticker, mimetype: "image/webp" },
|
|
864
|
+
{ upload: waUploadToServer }
|
|
865
|
+
);
|
|
866
|
+
|
|
867
|
+
if (inner?.stickerMessage) {
|
|
868
|
+
const stickerMsg = inner.stickerMessage;
|
|
869
|
+
const msg = _gen(jid, {
|
|
870
|
+
viewOnceMessage: {
|
|
871
|
+
message: {
|
|
872
|
+
stickerPackMessage: {
|
|
873
|
+
stickerPackId: packId,
|
|
874
|
+
name: packName || "",
|
|
875
|
+
publisher: packPublisher || "",
|
|
876
|
+
fileLength: stickerMsg.fileLength,
|
|
877
|
+
fileSha256: stickerMsg.fileSha256,
|
|
878
|
+
fileEncSha256: stickerMsg.fileEncSha256,
|
|
879
|
+
mediaKey: stickerMsg.mediaKey,
|
|
880
|
+
directPath: stickerMsg.directPath,
|
|
881
|
+
mediaKeyTimestamp: stickerMsg.mediaKeyTimestamp || Math.floor(Date.now() / 1000),
|
|
882
|
+
contextInfo: options.contextInfo || {},
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
});
|
|
887
|
+
await sock.relayMessage(jid, msg.message, { messageId: msg.key.id });
|
|
888
|
+
return [{ success: true, msg }];
|
|
889
|
+
}
|
|
890
|
+
} catch (e) {
|
|
891
|
+
_log("warn", `sendStickerPack nativePackMessage error: ${e?.message}`);
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
// Fallback: kirim satu per satu dalam batch paralel
|
|
865
896
|
for (let i = 0; i < stickers.length; i += batchSize) {
|
|
866
897
|
const batch = stickers.slice(i, i + batchSize);
|
|
867
898
|
const batchResults = await Promise.all(batch.map(async sticker => {
|
|
@@ -876,6 +907,49 @@ const makeBusinessSocket = (config) => {
|
|
|
876
907
|
return results;
|
|
877
908
|
};
|
|
878
909
|
|
|
910
|
+
// sendStickerPackMessage — kirim native stickerPackMessage dengan data lengkap
|
|
911
|
+
// Gunakan ini untuk kirim pack sticker yang sudah di-upload sebelumnya
|
|
912
|
+
const sendStickerPackMessage = async (jid, cfg = {}, options = {}) => {
|
|
913
|
+
const {
|
|
914
|
+
stickerPackId,
|
|
915
|
+
name,
|
|
916
|
+
publisher,
|
|
917
|
+
fileLength,
|
|
918
|
+
fileSha256,
|
|
919
|
+
fileEncSha256,
|
|
920
|
+
mediaKey,
|
|
921
|
+
directPath,
|
|
922
|
+
mediaKeyTimestamp,
|
|
923
|
+
contextInfo,
|
|
924
|
+
} = cfg;
|
|
925
|
+
|
|
926
|
+
if (!mediaKey || !directPath || !fileEncSha256) {
|
|
927
|
+
throw new Error("sendStickerPackMessage: mediaKey, directPath, fileEncSha256 wajib");
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
const packId = stickerPackId || (0, crypto_1.randomBytes)(16).toString("hex");
|
|
931
|
+
const msg = _gen(jid, {
|
|
932
|
+
viewOnceMessage: {
|
|
933
|
+
message: {
|
|
934
|
+
stickerPackMessage: {
|
|
935
|
+
stickerPackId: packId,
|
|
936
|
+
name: name || "",
|
|
937
|
+
publisher: publisher || "",
|
|
938
|
+
fileLength: fileLength || 0,
|
|
939
|
+
fileSha256: fileSha256 || "",
|
|
940
|
+
fileEncSha256: fileEncSha256,
|
|
941
|
+
mediaKey: mediaKey,
|
|
942
|
+
directPath: directPath,
|
|
943
|
+
mediaKeyTimestamp: mediaKeyTimestamp || Math.floor(Date.now() / 1000),
|
|
944
|
+
contextInfo: contextInfo || {},
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
});
|
|
949
|
+
return _relay(jid, msg);
|
|
950
|
+
};
|
|
951
|
+
|
|
952
|
+
// sendStickerPackAlbum — kirim beberapa sticker dengan delay batch
|
|
879
953
|
const sendStickerPackAlbum = async (jid, stickers, packName, packPublisher, options = {}) => {
|
|
880
954
|
if (!Array.isArray(stickers) || !stickers.length) throw new Error("sendStickerPackAlbum: stickers kosong");
|
|
881
955
|
const batchSize = Math.min(options.batchSize || 10, 10);
|
|
@@ -895,9 +969,6 @@ const makeBusinessSocket = (config) => {
|
|
|
895
969
|
return results;
|
|
896
970
|
};
|
|
897
971
|
|
|
898
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
899
|
-
// DOCUMENT (auto mime + pack)
|
|
900
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
901
972
|
const sendDocument = async (jid, document, fileName, mimetype, caption, options = {}) => {
|
|
902
973
|
if (!document) throw new Error("sendDocument: document wajib");
|
|
903
974
|
if (!fileName) throw new Error("sendDocument: fileName wajib");
|
|
@@ -927,9 +998,6 @@ const makeBusinessSocket = (config) => {
|
|
|
927
998
|
return results;
|
|
928
999
|
};
|
|
929
1000
|
|
|
930
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
931
|
-
// SIMPLE MEDIA
|
|
932
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
933
1001
|
const sendAudio = async (jid, audio, isPtt = false, options = {}) => {
|
|
934
1002
|
if (!audio) throw new Error("sendAudio: audio wajib");
|
|
935
1003
|
return _originalSendMessage(jid, { audio, mimetype: isPtt ? "audio/ogg; codecs=opus" : "audio/mp4", ptt: isPtt }, options);
|
|
@@ -948,9 +1016,6 @@ const makeBusinessSocket = (config) => {
|
|
|
948
1016
|
const sendAudioPTT = async (jid, audio, options = {}) => sendAudio(jid, audio, true, options);
|
|
949
1017
|
const sendVoiceNote = async (jid, audio, options = {}) => sendAudio(jid, audio, true, options);
|
|
950
1018
|
|
|
951
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
952
|
-
// REPLY / QUOTE
|
|
953
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
954
1019
|
const sendReply = async (jid, text, quotedMessage, options = {}) => {
|
|
955
1020
|
if (!quotedMessage) throw new Error("sendReply: quotedMessage wajib");
|
|
956
1021
|
if (typeof text !== "string") throw new Error("sendReply: text harus string");
|
|
@@ -990,9 +1055,6 @@ const makeBusinessSocket = (config) => {
|
|
|
990
1055
|
return _originalSendMessage(jid, { forward: message, force: true }, options);
|
|
991
1056
|
};
|
|
992
1057
|
|
|
993
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
994
|
-
// GROUP INVITE
|
|
995
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
996
1058
|
const sendGroupInvite = async (jid, groupJid, options = {}) => {
|
|
997
1059
|
if (!_isGrp(groupJid)) throw new Error("sendGroupInvite: groupJid harus @g.us");
|
|
998
1060
|
const [code, meta] = await Promise.all([sock.groupInviteCode(groupJid), sock.groupMetadata(groupJid)]);
|
|
@@ -1021,9 +1083,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1021
1083
|
return _relay(jid, msg);
|
|
1022
1084
|
};
|
|
1023
1085
|
|
|
1024
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1025
|
-
// CHAT MANAGEMENT
|
|
1026
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1027
1086
|
const muteJid = async (jid, durationMs = 8 * 60 * 60 * 1000) => sock.chatModify({ mute: durationMs }, jid);
|
|
1028
1087
|
const unmuteJid = async (jid) => sock.chatModify({ mute: null }, jid);
|
|
1029
1088
|
|
|
@@ -1067,9 +1126,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1067
1126
|
const sendDisappearingToggle = async (jid, enable = true) =>
|
|
1068
1127
|
_originalSendMessage(jid, { disappearingMessagesInChat: enable ? 86400 : false });
|
|
1069
1128
|
|
|
1070
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1071
|
-
// PROFILE — safe fetch, tidak crash 404 / not-authorized
|
|
1072
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1073
1129
|
const getProfilePicture = async (jid, highRes = false) => {
|
|
1074
1130
|
try { return await sock.profilePictureUrl(_norm(jid), highRes ? "image" : "preview"); }
|
|
1075
1131
|
catch { return null; }
|
|
@@ -1100,19 +1156,12 @@ const makeBusinessSocket = (config) => {
|
|
|
1100
1156
|
const updateProfileName = async (name) => { if (!name) throw new Error("updateProfileName: name wajib"); return sock.updateProfileName(name); };
|
|
1101
1157
|
const updateProfileStatus = async (status) => { if (typeof status !== "string") throw new Error("updateProfileStatus: harus string"); return sock.updateProfileStatus(status); };
|
|
1102
1158
|
|
|
1103
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1104
|
-
// DISAPPEARING
|
|
1105
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1106
1159
|
const sendDisappearingMessage = async (jid, content, expiration, options = {}) => {
|
|
1107
1160
|
const valid = [0, 86400, 604800, 7776000];
|
|
1108
1161
|
if (!valid.includes(expiration)) throw new Error(`sendDisappearingMessage: expiration harus: ${valid.join(", ")}`);
|
|
1109
1162
|
return _originalSendMessage(jid, content, { ephemeralExpiration: expiration, ...options });
|
|
1110
1163
|
};
|
|
1111
1164
|
|
|
1112
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1113
|
-
// MISC
|
|
1114
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1115
|
-
// isOnWhatsApp — selalu return object, tidak pernah undefined
|
|
1116
1165
|
const isOnWhatsApp = async (jidOrNumber) => {
|
|
1117
1166
|
let jid = jidOrNumber;
|
|
1118
1167
|
if (!jid.includes("@")) jid = jid.replace(/[^0-9]/g, "") + "@s.whatsapp.net";
|
|
@@ -1151,9 +1200,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1151
1200
|
const fetchBlocklist = async () => sock.fetchBlocklist();
|
|
1152
1201
|
const fetchAllGroups = async () => sock.groupFetchAllParticipating();
|
|
1153
1202
|
|
|
1154
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1155
|
-
// INTERACTIVE — Legacy buttons / List / Template
|
|
1156
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1157
1203
|
const _mapButtons = (buttons) => buttons.map((b, i) => ({
|
|
1158
1204
|
buttonId: b.buttonId || b.id || `btn_${i}`,
|
|
1159
1205
|
buttonText: b.buttonText ? b.buttonText : { displayText: b.displayText || b.text || "" },
|
|
@@ -1196,11 +1242,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1196
1242
|
return _relay(jid, msg);
|
|
1197
1243
|
};
|
|
1198
1244
|
|
|
1199
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1200
|
-
// INTERACTIVE MESSAGE — full native flow
|
|
1201
|
-
// single_select, cta_url, cta_call, quick_reply, cta_copy,
|
|
1202
|
-
// send_location, address_message, cta_reminder, payment, flow
|
|
1203
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1204
1245
|
const sendInteractiveMessage = async (jid, cfg = {}, options = {}) => {
|
|
1205
1246
|
const { body, footer, header, buttons, sections, nativeFlow } = cfg;
|
|
1206
1247
|
|
|
@@ -1281,7 +1322,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1281
1322
|
return _relay(jid, msg);
|
|
1282
1323
|
};
|
|
1283
1324
|
|
|
1284
|
-
// ─── Media + Legacy Buttons ───────────────────────────────────────────────
|
|
1285
1325
|
const sendImageWithButtons = async (jid, image, caption, buttons = [], footer = "", options = {}) => {
|
|
1286
1326
|
if (!image) throw new Error("sendImageWithButtons: image wajib");
|
|
1287
1327
|
if (!buttons.length) throw new Error("sendImageWithButtons: buttons wajib");
|
|
@@ -1303,9 +1343,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1303
1343
|
return _relay(jid, _gen(jid, { buttonsMessage: { documentMessage: inner.documentMessage, contentText: caption || "", footerText: footer, buttons: _mapButtons(buttons), headerType: 6 } }));
|
|
1304
1344
|
};
|
|
1305
1345
|
|
|
1306
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1307
|
-
// PRODUCT MESSAGE — full button support (single_select, cta_url, dll)
|
|
1308
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1309
1346
|
const sendProductMessageWithButtons = async (jid, cfg = {}, options = {}) => {
|
|
1310
1347
|
const { title, body, footer, thumbnail, productId, retailerId, buttons = [], header } = cfg;
|
|
1311
1348
|
if (!buttons.length) throw new Error("sendProductMessageWithButtons: min 1 button wajib");
|
|
@@ -1313,7 +1350,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1313
1350
|
let headerContent = null;
|
|
1314
1351
|
if (thumbnail) {
|
|
1315
1352
|
if (typeof thumbnail === "object" && thumbnail.url) {
|
|
1316
|
-
// URL thumbnail — digunakan via contextInfo, tidak diupload
|
|
1317
1353
|
} else if (Buffer.isBuffer(thumbnail)) {
|
|
1318
1354
|
const inner = await (0, Utils_1.generateWAMessageContent)({ image: thumbnail }, { upload: waUploadToServer });
|
|
1319
1355
|
headerContent = { imageMessage: inner.imageMessage };
|
|
@@ -1351,11 +1387,9 @@ const makeBusinessSocket = (config) => {
|
|
|
1351
1387
|
};
|
|
1352
1388
|
|
|
1353
1389
|
const sendProductMessage = async (jid, productIdOrCfg, catalogJidOrOptions, options = {}) => {
|
|
1354
|
-
// New format: object config with buttons
|
|
1355
1390
|
if (typeof productIdOrCfg === "object" && productIdOrCfg !== null) {
|
|
1356
1391
|
return sendProductMessageWithButtons(jid, productIdOrCfg, catalogJidOrOptions || {});
|
|
1357
1392
|
}
|
|
1358
|
-
// Legacy format: catalog lookup
|
|
1359
1393
|
const productId = productIdOrCfg;
|
|
1360
1394
|
const catalogJid = typeof catalogJidOrOptions === "string" ? catalogJidOrOptions : null;
|
|
1361
1395
|
const bizJid = _norm(catalogJid || _me());
|
|
@@ -1376,9 +1410,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1376
1410
|
return _relay(jid, msg);
|
|
1377
1411
|
};
|
|
1378
1412
|
|
|
1379
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1380
|
-
// NEWSLETTER
|
|
1381
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1382
1413
|
const sendNewsletterMessage = async (newsletterJid, content, options = {}) => {
|
|
1383
1414
|
if (!newsletterJid.endsWith("@newsletter")) throw new Error("sendNewsletterMessage: harus @newsletter JID");
|
|
1384
1415
|
return _originalSendMessage(newsletterJid, content, options);
|
|
@@ -1425,13 +1456,7 @@ const makeBusinessSocket = (config) => {
|
|
|
1425
1456
|
return _originalSendMessage(jid, { location: { degreesLatitude: latitude, degreesLongitude: longitude, ...(name ? { name } : {}) } }, { quoted: quotedMessage, ...options });
|
|
1426
1457
|
};
|
|
1427
1458
|
|
|
1428
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1429
|
-
// PATCHED sendMessage
|
|
1430
|
-
// 1. tagAll system — { text: "...", tagAll: true, tagAllScope: "admins" }
|
|
1431
|
-
// 2. productMessage + buttons interception
|
|
1432
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1433
1459
|
const patchedSendMessage = async (jid, content, options = {}) => {
|
|
1434
|
-
// tagAll injection
|
|
1435
1460
|
if (content?.tagAll && _isGrp(jid)) {
|
|
1436
1461
|
try {
|
|
1437
1462
|
const scope = content.tagAllScope || "all";
|
|
@@ -1440,7 +1465,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1440
1465
|
return _originalSendMessage(jid, { ...rest, mentions: [...new Set([...(rest.mentions || []), ...mentions])] }, options);
|
|
1441
1466
|
} catch (e) { _log("warn", `tagAll patch error: ${e?.message}`); }
|
|
1442
1467
|
}
|
|
1443
|
-
// productMessage + buttons interception
|
|
1444
1468
|
if (content?.productMessage && Array.isArray(content.productMessage.buttons)) {
|
|
1445
1469
|
const pm = content.productMessage;
|
|
1446
1470
|
return sendProductMessageWithButtons(jid, {
|
|
@@ -1457,30 +1481,22 @@ const makeBusinessSocket = (config) => {
|
|
|
1457
1481
|
return _originalSendMessage(jid, content, options);
|
|
1458
1482
|
};
|
|
1459
1483
|
|
|
1460
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1461
|
-
// EXPORTS
|
|
1462
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1463
1484
|
return {
|
|
1464
1485
|
...sock,
|
|
1465
1486
|
|
|
1466
|
-
// Patched sendMessage — tagAll + productMessage+buttons transparent
|
|
1467
1487
|
sendMessage: patchedSendMessage,
|
|
1468
1488
|
|
|
1469
1489
|
logger: config.logger,
|
|
1470
1490
|
|
|
1471
|
-
// ── Catalog ───────────────────────────────────────────────────────────
|
|
1472
1491
|
getCatalog, getCollections, getOrderDetails,
|
|
1473
1492
|
productCreate, productDelete, productUpdate,
|
|
1474
1493
|
|
|
1475
|
-
// ── NEW: Channel / Group Tracker & Contacts ───────────────────────────
|
|
1476
1494
|
getFollowedChannels,
|
|
1477
1495
|
getJoinedGroups,
|
|
1478
1496
|
getAllContacts,
|
|
1479
1497
|
|
|
1480
|
-
// ── NEW: Media Converter ──────────────────────────────────────────────
|
|
1481
1498
|
convertMedia, convertToSticker,
|
|
1482
1499
|
|
|
1483
|
-
// ── Group ─────────────────────────────────────────────────────────────
|
|
1484
1500
|
groupTagAll, groupStatusV2, getGroupAdmins, isGroupAdmin,
|
|
1485
1501
|
sendToAdminsOnly, bulkGroupAction, setGroupDisappearing,
|
|
1486
1502
|
sendTagAll, sendMentionAll, sendGroupInvite, sendAdminInvite,
|
|
@@ -1490,10 +1506,8 @@ const makeBusinessSocket = (config) => {
|
|
|
1490
1506
|
approveGroupJoinRequest, rejectGroupJoinRequest,
|
|
1491
1507
|
setGroupMemberAddMode, updateGroupProfilePicture,
|
|
1492
1508
|
|
|
1493
|
-
// ── Status ────────────────────────────────────────────────────────────
|
|
1494
1509
|
sendStatus,
|
|
1495
1510
|
|
|
1496
|
-
// ── Media ─────────────────────────────────────────────────────────────
|
|
1497
1511
|
sendImage, sendVideo, sendAudio, sendAudioPTT, sendVoiceNote,
|
|
1498
1512
|
sendDocument, sendDocumentPack,
|
|
1499
1513
|
sendGIF, sendPTV, sendViewOnce, sendAlbum,
|
|
@@ -1501,11 +1515,10 @@ const makeBusinessSocket = (config) => {
|
|
|
1501
1515
|
sendContact, sendPoll, sendEvent, sendScheduledCall,
|
|
1502
1516
|
sendLinkPreview, sendDisappearingToggle,
|
|
1503
1517
|
|
|
1504
|
-
// ── Sticker ───────────────────────────────────────────────────────────
|
|
1505
1518
|
sendStickerFromUrl, sendStickerFromBuffer, sendStickerWithMetadata,
|
|
1506
|
-
sendStickerPack, sendStickerPackAlbum,
|
|
1519
|
+
sendStickerPack, sendStickerPackAlbum, sendStickerPackMessage,
|
|
1520
|
+
sendStickerMessage,
|
|
1507
1521
|
|
|
1508
|
-
// ── Interactive (full native flow support) ────────────────────────────
|
|
1509
1522
|
sendButtonsMessage, sendListMessage, sendTemplateMessage,
|
|
1510
1523
|
sendInteractiveMessage, sendInteractiveWithMedia,
|
|
1511
1524
|
sendHighlyStructuredMessage,
|
|
@@ -1514,39 +1527,31 @@ const makeBusinessSocket = (config) => {
|
|
|
1514
1527
|
followNewsletter, unfollowNewsletter, getNewsletterMetadata, joinNewsletterByUrl,
|
|
1515
1528
|
sendImageWithButtons, sendVideoWithButtons, sendDocumentWithButtons,
|
|
1516
1529
|
|
|
1517
|
-
// ── Reply / Quote ─────────────────────────────────────────────────────
|
|
1518
1530
|
sendReply, sendMediaReply, sendQuotedText,
|
|
1519
1531
|
sendWithQuotedFake, sendWithMentionAndReply, forwardWithComment,
|
|
1520
1532
|
|
|
1521
|
-
// ── Mentions / Typing ─────────────────────────────────────────────────
|
|
1522
1533
|
sendTextWithMentions, sendTyping, sendWithTyping,
|
|
1523
1534
|
|
|
1524
|
-
// ── Broadcast ─────────────────────────────────────────────────────────
|
|
1525
1535
|
broadcastMessage, broadcastToGroups, sendMultipleMessages,
|
|
1526
1536
|
|
|
1527
|
-
// ── Message Actions ───────────────────────────────────────────────────
|
|
1528
1537
|
pinMessage, keepMessage, editMessage, deleteMessage,
|
|
1529
1538
|
reactMessage, forwardMessage,
|
|
1530
1539
|
|
|
1531
|
-
// ── Chat Management ───────────────────────────────────────────────────
|
|
1532
1540
|
muteJid, unmuteJid, archiveChat, unarchiveChat,
|
|
1533
1541
|
pinChat, unpinChat, markAsRead, markAsUnread,
|
|
1534
1542
|
blockUser, unblockUser, starMessage, unstarMessage,
|
|
1535
1543
|
deleteChat, clearChat, sendSeen,
|
|
1536
1544
|
|
|
1537
|
-
// ── Profile (safe fetch) ──────────────────────────────────────────────
|
|
1538
1545
|
getProfilePicture, getUserStatus,
|
|
1539
1546
|
updateProfilePicture, removeProfilePicture,
|
|
1540
1547
|
updateProfileName, updateProfileStatus,
|
|
1541
1548
|
getContactInfo, getBusinessProfile,
|
|
1542
1549
|
fetchBlocklist, fetchAllGroups, fetchMessageHistory,
|
|
1543
1550
|
|
|
1544
|
-
// ── Privacy ───────────────────────────────────────────────────────────
|
|
1545
1551
|
updatePrivacyLastSeen, updatePrivacyProfilePic, updatePrivacyStatus,
|
|
1546
1552
|
updatePrivacyReadReceipts, updatePrivacyGroupsAdd, updatePrivacyOnline,
|
|
1547
1553
|
setDefaultDisappearing,
|
|
1548
1554
|
|
|
1549
|
-
// ── Misc ──────────────────────────────────────────────────────────────
|
|
1550
1555
|
sendDisappearingMessage, isOnWhatsApp,
|
|
1551
1556
|
presenceSubscribe, rejectAllCalls,
|
|
1552
1557
|
};
|