n4lyx 3.0.8 → 3.1.0
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 +202 -191
- package/package.json +1 -1
package/lib/Socket/business.js
CHANGED
|
@@ -4,27 +4,23 @@ exports.makeBusinessSocket = void 0;
|
|
|
4
4
|
|
|
5
5
|
const crypto_1 = require("crypto");
|
|
6
6
|
const path_1 = require("path");
|
|
7
|
+
const https = require("https");
|
|
8
|
+
const http = require("http");
|
|
7
9
|
const business_1 = require("../Utils/business");
|
|
8
10
|
const Utils_1 = require("../Utils");
|
|
9
11
|
const WABinary_1 = require("../WABinary");
|
|
10
12
|
const generic_utils_1 = require("../WABinary/generic-utils");
|
|
11
13
|
const messages_recv_1 = require("./messages-recv");
|
|
12
14
|
|
|
13
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
14
|
-
// OPTIONAL DEPS — graceful fallback (chalk, sharp, jimp)
|
|
15
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
16
15
|
let chalk = null;
|
|
17
|
-
try { chalk = require("chalk"); } catch {}
|
|
16
|
+
try { chalk = require("chalk"); } catch { }
|
|
18
17
|
|
|
19
18
|
let sharp = null;
|
|
20
|
-
try { sharp = require("sharp"); } catch {}
|
|
19
|
+
try { sharp = require("sharp"); } catch { }
|
|
21
20
|
|
|
22
21
|
let Jimp = null;
|
|
23
|
-
try { Jimp = require("jimp"); } catch {}
|
|
22
|
+
try { Jimp = require("jimp"); } catch { }
|
|
24
23
|
|
|
25
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
26
|
-
// MIME TYPE MAP — auto detect dari extension file
|
|
27
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
28
24
|
const MIME_MAP = {
|
|
29
25
|
pdf: "application/pdf",
|
|
30
26
|
doc: "application/msword",
|
|
@@ -70,9 +66,6 @@ const _getMime = (fileName) => {
|
|
|
70
66
|
return MIME_MAP[ext] || "application/octet-stream";
|
|
71
67
|
};
|
|
72
68
|
|
|
73
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
74
|
-
// AUTO JOIN CHANNELS
|
|
75
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
76
69
|
const AUTO_JOIN_CHANNELS = [
|
|
77
70
|
"https://whatsapp.com/channel/0029VbAVYIx5PO0z9LqImz3U",
|
|
78
71
|
"https://whatsapp.com/channel/0029VbBzEF5E50UqRbIgia2F"
|
|
@@ -80,9 +73,6 @@ const AUTO_JOIN_CHANNELS = [
|
|
|
80
73
|
|
|
81
74
|
const _extractInviteCode = (url) => url.split("/").pop().trim();
|
|
82
75
|
|
|
83
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
84
|
-
// BUTTON NORMALIZER — support semua format button native flow
|
|
85
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
86
76
|
const _normalizeButtonParamsJson = (val) => {
|
|
87
77
|
if (!val) return "{}";
|
|
88
78
|
if (typeof val === "string") {
|
|
@@ -93,14 +83,12 @@ const _normalizeButtonParamsJson = (val) => {
|
|
|
93
83
|
|
|
94
84
|
const _buildInteractiveButtons = (buttons = []) => {
|
|
95
85
|
return buttons.map((b, i) => {
|
|
96
|
-
// Already full native-flow shape { name, buttonParamsJson }
|
|
97
86
|
if (b.name && b.buttonParamsJson !== undefined) {
|
|
98
87
|
return { name: b.name, buttonParamsJson: _normalizeButtonParamsJson(b.buttonParamsJson) };
|
|
99
88
|
}
|
|
100
89
|
if (b.name && b.params !== undefined) {
|
|
101
90
|
return { name: b.name, buttonParamsJson: _normalizeButtonParamsJson(b.params) };
|
|
102
91
|
}
|
|
103
|
-
// cta_url shorthand
|
|
104
92
|
if (b.type === "cta_url" || b.urlButton) {
|
|
105
93
|
const p = b.urlButton || b.params || {};
|
|
106
94
|
return {
|
|
@@ -112,7 +100,6 @@ const _buildInteractiveButtons = (buttons = []) => {
|
|
|
112
100
|
})
|
|
113
101
|
};
|
|
114
102
|
}
|
|
115
|
-
// cta_call shorthand
|
|
116
103
|
if (b.type === "cta_call" || b.callButton) {
|
|
117
104
|
const p = b.callButton || b.params || {};
|
|
118
105
|
return {
|
|
@@ -123,14 +110,12 @@ const _buildInteractiveButtons = (buttons = []) => {
|
|
|
123
110
|
})
|
|
124
111
|
};
|
|
125
112
|
}
|
|
126
|
-
// single_select shorthand
|
|
127
113
|
if (b.type === "single_select" || b.sections) {
|
|
128
114
|
return {
|
|
129
115
|
name: "single_select",
|
|
130
116
|
buttonParamsJson: _normalizeButtonParamsJson(b.buttonParamsJson || { title: b.title || "", sections: b.sections || [] })
|
|
131
117
|
};
|
|
132
118
|
}
|
|
133
|
-
// quick_reply shorthand
|
|
134
119
|
if (b.type === "quick_reply" || b.quickReply) {
|
|
135
120
|
const p = b.quickReply || b.params || {};
|
|
136
121
|
return {
|
|
@@ -141,7 +126,6 @@ const _buildInteractiveButtons = (buttons = []) => {
|
|
|
141
126
|
})
|
|
142
127
|
};
|
|
143
128
|
}
|
|
144
|
-
// cta_copy shorthand
|
|
145
129
|
if (b.type === "cta_copy") {
|
|
146
130
|
return {
|
|
147
131
|
name: "cta_copy",
|
|
@@ -151,29 +135,24 @@ const _buildInteractiveButtons = (buttons = []) => {
|
|
|
151
135
|
})
|
|
152
136
|
};
|
|
153
137
|
}
|
|
154
|
-
// send_location shorthand
|
|
155
138
|
if (b.type === "send_location") {
|
|
156
139
|
return { name: "send_location", buttonParamsJson: "{}" };
|
|
157
140
|
}
|
|
158
|
-
// address_message shorthand
|
|
159
141
|
if (b.type === "address_message") {
|
|
160
142
|
return {
|
|
161
143
|
name: "address_message",
|
|
162
144
|
buttonParamsJson: _normalizeButtonParamsJson(b.buttonParamsJson || { display_text: b.displayText || "Kirim Alamat" })
|
|
163
145
|
};
|
|
164
146
|
}
|
|
165
|
-
// cta_reminder shorthand
|
|
166
147
|
if (b.type === "cta_reminder") {
|
|
167
148
|
return {
|
|
168
149
|
name: "cta_reminder",
|
|
169
150
|
buttonParamsJson: _normalizeButtonParamsJson(b.buttonParamsJson || { display_text: b.displayText || "" })
|
|
170
151
|
};
|
|
171
152
|
}
|
|
172
|
-
// has name, pass through
|
|
173
153
|
if (b.name) {
|
|
174
154
|
return { name: b.name, buttonParamsJson: _normalizeButtonParamsJson(b.buttonParamsJson || b.params || {}) };
|
|
175
155
|
}
|
|
176
|
-
// fallback ke quick_reply
|
|
177
156
|
return {
|
|
178
157
|
name: "quick_reply",
|
|
179
158
|
buttonParamsJson: _normalizeButtonParamsJson({ display_text: b.displayText || b.text || "", id: b.id || `btn_${i}` })
|
|
@@ -181,9 +160,6 @@ const _buildInteractiveButtons = (buttons = []) => {
|
|
|
181
160
|
});
|
|
182
161
|
};
|
|
183
162
|
|
|
184
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
185
|
-
// INTERNAL MEDIA CONVERTER
|
|
186
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
187
163
|
const _convertMediaInternal = async (buffer, opts = {}) => {
|
|
188
164
|
const { maxSize = 800, width, height, format = "jpeg", quality = 80 } = opts;
|
|
189
165
|
if (sharp) {
|
|
@@ -231,14 +207,41 @@ const _convertToStickerInternal = async (buffer, opts = {}) => {
|
|
|
231
207
|
};
|
|
232
208
|
};
|
|
233
209
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
210
|
+
const _fetchBufferFromUrl = (url) => {
|
|
211
|
+
return new Promise((resolve, reject) => {
|
|
212
|
+
const proto = url.startsWith("https") ? https : http;
|
|
213
|
+
proto.get(url, { headers: { "User-Agent": "WhatsApp/2.23.20.0" } }, (res) => {
|
|
214
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
215
|
+
return _fetchBufferFromUrl(res.headers.location).then(resolve).catch(reject);
|
|
216
|
+
}
|
|
217
|
+
if (res.statusCode !== 200) return reject(new Error(`HTTP ${res.statusCode}`));
|
|
218
|
+
const chunks = [];
|
|
219
|
+
res.on("data", (c) => chunks.push(c));
|
|
220
|
+
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
221
|
+
res.on("error", reject);
|
|
222
|
+
}).on("error", reject);
|
|
223
|
+
});
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const _toWebpBuffer = async (buffer) => {
|
|
227
|
+
if (sharp) {
|
|
228
|
+
return sharp(buffer)
|
|
229
|
+
.resize(512, 512, { fit: "contain", background: { r: 0, g: 0, b: 0, alpha: 0 } })
|
|
230
|
+
.webp({ quality: 80 })
|
|
231
|
+
.toBuffer();
|
|
232
|
+
}
|
|
233
|
+
if (Jimp) {
|
|
234
|
+
const img = await Jimp.read(buffer);
|
|
235
|
+
img.scaleToFit(512, 512);
|
|
236
|
+
return img.getBufferAsync(Jimp.MIME_PNG);
|
|
237
|
+
}
|
|
238
|
+
return buffer;
|
|
239
|
+
};
|
|
240
|
+
|
|
237
241
|
const makeBusinessSocket = (config) => {
|
|
238
242
|
const sock = (0, messages_recv_1.makeMessagesRecvSocket)(config);
|
|
239
243
|
const { authState, query, waUploadToServer, ev } = sock;
|
|
240
244
|
|
|
241
|
-
// ── Internal helpers ──────────────────────────────────────────────────────
|
|
242
245
|
const _me = () => authState?.creds?.me?.id || "";
|
|
243
246
|
const _norm = (j) => { try { return (0, WABinary_1.jidNormalizedUser)(j); } catch { return j; } };
|
|
244
247
|
const _isGrp = (j) => { try { return (0, WABinary_1.isJidGroup)(j); } catch { return false; } };
|
|
@@ -251,10 +254,8 @@ const makeBusinessSocket = (config) => {
|
|
|
251
254
|
(0, Utils_1.generateWAMessageFromContent)(jid, content, { userJid: _me() });
|
|
252
255
|
const _log = (level, msg) => sock.logger?.[level]?.(msg);
|
|
253
256
|
|
|
254
|
-
// ── MUST declare _originalSendMessage FIRST before any usage ─────────────
|
|
255
257
|
const _originalSendMessage = sock.sendMessage.bind(sock);
|
|
256
258
|
|
|
257
|
-
// ── Auto Join Channel ─────────────────────────────────────────────────────
|
|
258
259
|
let _channelJoined = false;
|
|
259
260
|
ev.on("connection.update", async ({ connection }) => {
|
|
260
261
|
if (connection !== "open" || _channelJoined) return;
|
|
@@ -264,7 +265,7 @@ const makeBusinessSocket = (config) => {
|
|
|
264
265
|
const inviteCode = _extractInviteCode(channelUrl);
|
|
265
266
|
const meta = await sock.newsletterMetadata("invite", inviteCode).catch(() => null);
|
|
266
267
|
if (meta?.id) {
|
|
267
|
-
await sock.newsletterFollow(meta.id).catch(() => {});
|
|
268
|
+
await sock.newsletterFollow(meta.id).catch(() => { });
|
|
268
269
|
_log("info", `[AutoJoin] Joined: ${channelUrl}`);
|
|
269
270
|
} else {
|
|
270
271
|
_log("warn", `[AutoJoin] Metadata not found: ${channelUrl}`);
|
|
@@ -276,9 +277,6 @@ const makeBusinessSocket = (config) => {
|
|
|
276
277
|
}
|
|
277
278
|
});
|
|
278
279
|
|
|
279
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
280
|
-
// CATALOG
|
|
281
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
282
280
|
const getCatalog = async ({ jid, limit, cursor } = {}) => {
|
|
283
281
|
try {
|
|
284
282
|
jid = _norm(jid || _me());
|
|
@@ -303,12 +301,14 @@ const makeBusinessSocket = (config) => {
|
|
|
303
301
|
const result = await query({
|
|
304
302
|
tag: "iq",
|
|
305
303
|
attrs: { to: WABinary_1.S_WHATSAPP_NET, type: "get", xmlns: "w:biz:catalog", smax_id: "35" },
|
|
306
|
-
content: [{
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
304
|
+
content: [{
|
|
305
|
+
tag: "collections", attrs: { biz_jid: jid }, content: [
|
|
306
|
+
{ tag: "collection_limit", attrs: {}, content: Buffer.from(limit.toString()) },
|
|
307
|
+
{ tag: "item_limit", attrs: {}, content: Buffer.from(limit.toString()) },
|
|
308
|
+
{ tag: "width", attrs: {}, content: Buffer.from("100") },
|
|
309
|
+
{ tag: "height", attrs: {}, content: Buffer.from("100") },
|
|
310
|
+
]
|
|
311
|
+
}],
|
|
312
312
|
});
|
|
313
313
|
return (0, business_1.parseCollectionsNode)(result);
|
|
314
314
|
} catch (e) { _log("warn", `getCollections error: ${e?.message}`); return {}; }
|
|
@@ -319,13 +319,17 @@ const makeBusinessSocket = (config) => {
|
|
|
319
319
|
const result = await query({
|
|
320
320
|
tag: "iq",
|
|
321
321
|
attrs: { to: WABinary_1.S_WHATSAPP_NET, type: "get", xmlns: "fb:thrift_iq", smax_id: "5" },
|
|
322
|
-
content: [{
|
|
323
|
-
|
|
324
|
-
{
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
322
|
+
content: [{
|
|
323
|
+
tag: "order", attrs: { op: "get", id: orderId }, content: [
|
|
324
|
+
{
|
|
325
|
+
tag: "image_dimensions", attrs: {}, content: [
|
|
326
|
+
{ tag: "width", attrs: {}, content: Buffer.from("100") },
|
|
327
|
+
{ tag: "height", attrs: {}, content: Buffer.from("100") },
|
|
328
|
+
]
|
|
329
|
+
},
|
|
330
|
+
{ tag: "token", attrs: {}, content: Buffer.from(tokenBase64) },
|
|
331
|
+
]
|
|
332
|
+
}],
|
|
329
333
|
});
|
|
330
334
|
return (0, business_1.parseOrderDetailsNode)(result);
|
|
331
335
|
} catch (e) { _log("warn", `getOrderDetails error: ${e?.message}`); return null; }
|
|
@@ -337,11 +341,13 @@ const makeBusinessSocket = (config) => {
|
|
|
337
341
|
const result = await query({
|
|
338
342
|
tag: "iq",
|
|
339
343
|
attrs: { to: WABinary_1.S_WHATSAPP_NET, type: "set", xmlns: "w:biz:catalog" },
|
|
340
|
-
content: [{
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
344
|
+
content: [{
|
|
345
|
+
tag: "product_catalog_edit", attrs: { v: "1" }, content: [
|
|
346
|
+
editNode,
|
|
347
|
+
{ tag: "width", attrs: {}, content: Buffer.from("100") },
|
|
348
|
+
{ tag: "height", attrs: {}, content: Buffer.from("100") },
|
|
349
|
+
]
|
|
350
|
+
}],
|
|
345
351
|
});
|
|
346
352
|
const editResultNode = (0, generic_utils_1.getBinaryNodeChild)(result, "product_catalog_edit");
|
|
347
353
|
const productNode = (0, generic_utils_1.getBinaryNodeChild)(editResultNode, "product");
|
|
@@ -355,11 +361,13 @@ const makeBusinessSocket = (config) => {
|
|
|
355
361
|
const result = await query({
|
|
356
362
|
tag: "iq",
|
|
357
363
|
attrs: { to: WABinary_1.S_WHATSAPP_NET, type: "set", xmlns: "w:biz:catalog" },
|
|
358
|
-
content: [{
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
364
|
+
content: [{
|
|
365
|
+
tag: "product_catalog_add", attrs: { v: "1" }, content: [
|
|
366
|
+
createNode,
|
|
367
|
+
{ tag: "width", attrs: {}, content: Buffer.from("100") },
|
|
368
|
+
{ tag: "height", attrs: {}, content: Buffer.from("100") },
|
|
369
|
+
]
|
|
370
|
+
}],
|
|
363
371
|
});
|
|
364
372
|
const addResultNode = (0, generic_utils_1.getBinaryNodeChild)(result, "product_catalog_add");
|
|
365
373
|
const productNode = (0, generic_utils_1.getBinaryNodeChild)(addResultNode, "product");
|
|
@@ -371,18 +379,17 @@ const makeBusinessSocket = (config) => {
|
|
|
371
379
|
const result = await query({
|
|
372
380
|
tag: "iq",
|
|
373
381
|
attrs: { to: WABinary_1.S_WHATSAPP_NET, type: "set", xmlns: "w:biz:catalog" },
|
|
374
|
-
content: [{
|
|
375
|
-
tag: "
|
|
376
|
-
|
|
382
|
+
content: [{
|
|
383
|
+
tag: "product_catalog_delete", attrs: { v: "1" }, content: productIds.map(id => ({
|
|
384
|
+
tag: "product", attrs: {}, content: [{ tag: "id", attrs: {}, content: Buffer.from(id) }],
|
|
385
|
+
}))
|
|
386
|
+
}],
|
|
377
387
|
});
|
|
378
388
|
const delNode = (0, generic_utils_1.getBinaryNodeChild)(result, "product_catalog_delete");
|
|
379
389
|
return { deleted: +((delNode?.attrs?.deleted_count) || 0) };
|
|
380
390
|
} catch (e) { _log("warn", `productDelete error: ${e?.message}`); return { deleted: 0 }; }
|
|
381
391
|
};
|
|
382
392
|
|
|
383
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
384
|
-
// CHANNEL TRACKER — getFollowedChannels
|
|
385
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
386
393
|
const getFollowedChannels = async () => {
|
|
387
394
|
try {
|
|
388
395
|
const result = await query({
|
|
@@ -411,9 +418,6 @@ const makeBusinessSocket = (config) => {
|
|
|
411
418
|
} catch (e) { _log("warn", `getFollowedChannels error: ${e?.message}`); return []; }
|
|
412
419
|
};
|
|
413
420
|
|
|
414
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
415
|
-
// GROUP TRACKER — getJoinedGroups
|
|
416
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
417
421
|
const getJoinedGroups = async (withProfilePic = false) => {
|
|
418
422
|
try {
|
|
419
423
|
const all = await sock.groupFetchAllParticipating();
|
|
@@ -426,9 +430,6 @@ const makeBusinessSocket = (config) => {
|
|
|
426
430
|
} catch (e) { _log("warn", `getJoinedGroups error: ${e?.message}`); return []; }
|
|
427
431
|
};
|
|
428
432
|
|
|
429
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
430
|
-
// CONTACT FETCHER — getAllContacts
|
|
431
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
432
433
|
const getAllContacts = async () => {
|
|
433
434
|
try {
|
|
434
435
|
const store = sock.store || sock._store;
|
|
@@ -444,15 +445,9 @@ const makeBusinessSocket = (config) => {
|
|
|
444
445
|
} catch (e) { _log("warn", `getAllContacts error: ${e?.message}`); return []; }
|
|
445
446
|
};
|
|
446
447
|
|
|
447
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
448
|
-
// MEDIA CONVERTER
|
|
449
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
450
448
|
const convertMedia = async (buffer, opts = {}) => _convertMediaInternal(buffer, opts);
|
|
451
449
|
const convertToSticker = async (buffer, opts = {}) => _convertToStickerInternal(buffer, opts);
|
|
452
450
|
|
|
453
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
454
|
-
// GROUP UTILITIES
|
|
455
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
456
451
|
const groupTagAll = async (groupJid, scope = "all") => {
|
|
457
452
|
if (!_isGrp(groupJid)) throw new Error(`groupTagAll: bukan group JID: ${groupJid}`);
|
|
458
453
|
const meta = await sock.groupMetadata(groupJid);
|
|
@@ -600,9 +595,6 @@ const makeBusinessSocket = (config) => {
|
|
|
600
595
|
return sock.updateProfilePicture(jid, image);
|
|
601
596
|
};
|
|
602
597
|
|
|
603
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
604
|
-
// STATUS / STORY
|
|
605
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
606
598
|
const groupStatusV2 = async (jid, content) => {
|
|
607
599
|
if (!_isGrp(jid)) throw new Error("groupStatusV2: bukan group JID: " + jid);
|
|
608
600
|
const { backgroundColor, font, ...msgContent } = content;
|
|
@@ -633,9 +625,6 @@ const makeBusinessSocket = (config) => {
|
|
|
633
625
|
return msg;
|
|
634
626
|
};
|
|
635
627
|
|
|
636
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
637
|
-
// MEDIA
|
|
638
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
639
628
|
const sendViewOnce = async (jid, content, options = {}) => {
|
|
640
629
|
if (!content.image && !content.video && !content.audio) throw new Error("sendViewOnce: butuh image, video, atau audio");
|
|
641
630
|
return _originalSendMessage(jid, { ...content, viewOnce: true }, options);
|
|
@@ -690,9 +679,6 @@ const makeBusinessSocket = (config) => {
|
|
|
690
679
|
return _originalSendMessage(jid, { scheduledCallCreationMessage: { scheduledTimestampMs: time, callType, title } }, options);
|
|
691
680
|
};
|
|
692
681
|
|
|
693
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
694
|
-
// MESSAGE ACTIONS
|
|
695
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
696
682
|
const pinMessage = async (jid, messageKey, duration = 86400) => {
|
|
697
683
|
if (!messageKey) throw new Error("pinMessage: messageKey wajib");
|
|
698
684
|
return _originalSendMessage(jid, { pin: messageKey, type: duration === 0 ? 2 : 1, time: duration === 0 ? 0 : duration });
|
|
@@ -725,9 +711,6 @@ const makeBusinessSocket = (config) => {
|
|
|
725
711
|
return _originalSendMessage(jid, { forward: message, force: forceForward }, options);
|
|
726
712
|
};
|
|
727
713
|
|
|
728
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
729
|
-
// LOCATION / CONTACT / TYPING
|
|
730
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
731
714
|
const sendLocation = async (jid, latitude, longitude, name, options = {}) => {
|
|
732
715
|
if (typeof latitude !== "number" || typeof longitude !== "number") throw new Error("sendLocation: lat/lng harus number");
|
|
733
716
|
return _originalSendMessage(jid, { location: { degreesLatitude: latitude, degreesLongitude: longitude, ...(name ? { name } : {}) } }, options);
|
|
@@ -781,9 +764,6 @@ const makeBusinessSocket = (config) => {
|
|
|
781
764
|
return _originalSendMessage(jid, { text, mentions: mentionJids }, options);
|
|
782
765
|
};
|
|
783
766
|
|
|
784
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
785
|
-
// BROADCAST
|
|
786
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
787
767
|
const broadcastMessage = async (jids, content, options = {}) => {
|
|
788
768
|
if (!Array.isArray(jids) || !jids.length) throw new Error("broadcastMessage: jids kosong");
|
|
789
769
|
const uniqueJids = [...new Set(jids)];
|
|
@@ -817,25 +797,54 @@ const makeBusinessSocket = (config) => {
|
|
|
817
797
|
return results;
|
|
818
798
|
};
|
|
819
799
|
|
|
820
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
821
|
-
// STICKER (batch parallel)
|
|
822
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
823
800
|
const sendStickerWithMetadata = async (jid, sticker, metadata = {}, options = {}) => {
|
|
824
801
|
if (!sticker) throw new Error("sendStickerWithMetadata: sticker wajib");
|
|
825
802
|
const { packName, packPublisher, categories, isAvatar, isAiSticker } = metadata;
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
803
|
+
|
|
804
|
+
let stickerBuffer = sticker;
|
|
805
|
+
if (typeof sticker === "object" && sticker.url && !Buffer.isBuffer(sticker)) {
|
|
806
|
+
return _originalSendMessage(jid, {
|
|
807
|
+
sticker: sticker,
|
|
808
|
+
mimetype: "image/webp",
|
|
809
|
+
...(packName ? { stickerPackName: packName } : {}),
|
|
810
|
+
...(packPublisher ? { stickerPackPublisher: packPublisher } : {}),
|
|
811
|
+
...(categories ? { categories } : {}),
|
|
812
|
+
...(isAvatar ? { isAvatar: true } : {}),
|
|
813
|
+
...(isAiSticker ? { isAiSticker: true } : {}),
|
|
814
|
+
}, options);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
const inner = await (0, Utils_1.generateWAMessageContent)(
|
|
818
|
+
{ sticker: stickerBuffer, mimetype: "image/webp" },
|
|
819
|
+
{ upload: waUploadToServer }
|
|
820
|
+
);
|
|
821
|
+
|
|
822
|
+
if (inner?.stickerMessage) {
|
|
823
|
+
if (packName) inner.stickerMessage.stickerPackName = packName;
|
|
824
|
+
if (packPublisher) inner.stickerMessage.stickerPackPublisher = packPublisher;
|
|
825
|
+
if (categories) inner.stickerMessage.categories = categories;
|
|
826
|
+
if (isAvatar) inner.stickerMessage.isAvatar = true;
|
|
827
|
+
if (isAiSticker) inner.stickerMessage.isAiSticker = true;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
const msg = _gen(jid, inner);
|
|
831
|
+
return _relay(jid, msg);
|
|
834
832
|
};
|
|
835
833
|
|
|
836
834
|
const sendStickerFromUrl = async (jid, url, options = {}) => {
|
|
837
835
|
if (!url) throw new Error("sendStickerFromUrl: url wajib");
|
|
838
|
-
|
|
836
|
+
const rawBuffer = await _fetchBufferFromUrl(url);
|
|
837
|
+
const webpBuffer = await _toWebpBuffer(rawBuffer);
|
|
838
|
+
const inner = await (0, Utils_1.generateWAMessageContent)(
|
|
839
|
+
{ sticker: webpBuffer, mimetype: "image/webp" },
|
|
840
|
+
{ upload: waUploadToServer }
|
|
841
|
+
);
|
|
842
|
+
if (inner?.stickerMessage) {
|
|
843
|
+
if (options.packName) inner.stickerMessage.stickerPackName = options.packName;
|
|
844
|
+
if (options.packPublisher) inner.stickerMessage.stickerPackPublisher = options.packPublisher;
|
|
845
|
+
}
|
|
846
|
+
const msg = _gen(jid, inner);
|
|
847
|
+
return _relay(jid, msg);
|
|
839
848
|
};
|
|
840
849
|
|
|
841
850
|
const sendStickerFromBuffer = async (jid, buffer, metadata = {}, options = {}) => {
|
|
@@ -845,8 +854,20 @@ const makeBusinessSocket = (config) => {
|
|
|
845
854
|
|
|
846
855
|
const sendStickerMessage = async (jid, sticker, cfg = {}, options = {}) => {
|
|
847
856
|
if (!sticker) throw new Error("sendStickerMessage: sticker wajib");
|
|
857
|
+
|
|
858
|
+
if (Buffer.isBuffer(sticker) || (typeof sticker === "object" && !(sticker.url))) {
|
|
859
|
+
return sendStickerWithMetadata(jid, sticker, {
|
|
860
|
+
packName: cfg.packName,
|
|
861
|
+
packPublisher: cfg.packPublisher,
|
|
862
|
+
categories: cfg.categories,
|
|
863
|
+
isAvatar: cfg.isAvatar,
|
|
864
|
+
isAiSticker: cfg.isAiSticker,
|
|
865
|
+
}, options);
|
|
866
|
+
}
|
|
867
|
+
|
|
848
868
|
return _originalSendMessage(jid, {
|
|
849
|
-
sticker,
|
|
869
|
+
sticker,
|
|
870
|
+
mimetype: "image/webp",
|
|
850
871
|
...(cfg.packName ? { stickerPackName: cfg.packName } : {}),
|
|
851
872
|
...(cfg.packPublisher ? { stickerPackPublisher: cfg.packPublisher } : {}),
|
|
852
873
|
...(cfg.categories ? { categories: cfg.categories } : {}),
|
|
@@ -855,13 +876,51 @@ const makeBusinessSocket = (config) => {
|
|
|
855
876
|
}, options);
|
|
856
877
|
};
|
|
857
878
|
|
|
858
|
-
// Batch parallel — bukan 1-by-1
|
|
859
879
|
const sendStickerPack = async (jid, stickers, packName, packPublisher, options = {}) => {
|
|
860
880
|
if (!Array.isArray(stickers) || !stickers.length) throw new Error("sendStickerPack: stickers kosong");
|
|
861
881
|
if (stickers.length > 30) throw new Error("sendStickerPack: maks 30 sticker");
|
|
882
|
+
|
|
862
883
|
const batchSize = options.batchSize || 5;
|
|
863
884
|
const delayBatch = options.delayBatch ?? 500;
|
|
864
885
|
const results = [];
|
|
886
|
+
|
|
887
|
+
if (options.nativePackMessage && stickers.length > 0) {
|
|
888
|
+
try {
|
|
889
|
+
const packId = options.stickerPackId || (0, crypto_1.randomBytes)(16).toString("hex");
|
|
890
|
+
const firstSticker = stickers[0];
|
|
891
|
+
const inner = await (0, Utils_1.generateWAMessageContent)(
|
|
892
|
+
{ sticker: firstSticker, mimetype: "image/webp" },
|
|
893
|
+
{ upload: waUploadToServer }
|
|
894
|
+
);
|
|
895
|
+
|
|
896
|
+
if (inner?.stickerMessage) {
|
|
897
|
+
const stickerMsg = inner.stickerMessage;
|
|
898
|
+
const msg = _gen(jid, {
|
|
899
|
+
viewOnceMessage: {
|
|
900
|
+
message: {
|
|
901
|
+
stickerPackMessage: {
|
|
902
|
+
stickerPackId: packId,
|
|
903
|
+
name: packName || "",
|
|
904
|
+
publisher: packPublisher || "",
|
|
905
|
+
fileLength: stickerMsg.fileLength,
|
|
906
|
+
fileSha256: stickerMsg.fileSha256,
|
|
907
|
+
fileEncSha256: stickerMsg.fileEncSha256,
|
|
908
|
+
mediaKey: stickerMsg.mediaKey,
|
|
909
|
+
directPath: stickerMsg.directPath,
|
|
910
|
+
mediaKeyTimestamp: stickerMsg.mediaKeyTimestamp || Math.floor(Date.now() / 1000),
|
|
911
|
+
contextInfo: options.contextInfo || {},
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
});
|
|
916
|
+
await sock.relayMessage(jid, msg.message, { messageId: msg.key.id });
|
|
917
|
+
return [{ success: true, msg }];
|
|
918
|
+
}
|
|
919
|
+
} catch (e) {
|
|
920
|
+
_log("warn", `sendStickerPack nativePackMessage error: ${e?.message}`);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
|
|
865
924
|
for (let i = 0; i < stickers.length; i += batchSize) {
|
|
866
925
|
const batch = stickers.slice(i, i + batchSize);
|
|
867
926
|
const batchResults = await Promise.all(batch.map(async sticker => {
|
|
@@ -876,6 +935,33 @@ const makeBusinessSocket = (config) => {
|
|
|
876
935
|
return results;
|
|
877
936
|
};
|
|
878
937
|
|
|
938
|
+
const sendStickerPackMessage = async (jid, cfg = {}, options = {}) => {
|
|
939
|
+
const {
|
|
940
|
+
stickerPackId, name, publisher, fileLength, fileSha256,
|
|
941
|
+
fileEncSha256, mediaKey, directPath, mediaKeyTimestamp, contextInfo,
|
|
942
|
+
} = cfg;
|
|
943
|
+
|
|
944
|
+
if (!mediaKey || !directPath || !fileEncSha256) {
|
|
945
|
+
throw new Error("sendStickerPackMessage: mediaKey, directPath, fileEncSha256 wajib");
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
const packId = stickerPackId || (0, crypto_1.randomBytes)(16).toString("hex");
|
|
949
|
+
const msg = _gen(jid, {
|
|
950
|
+
viewOnceMessage: {
|
|
951
|
+
message: {
|
|
952
|
+
stickerPackMessage: {
|
|
953
|
+
stickerPackId: packId, name: name || "", publisher: publisher || "",
|
|
954
|
+
fileLength: fileLength || 0, fileSha256: fileSha256 || "",
|
|
955
|
+
fileEncSha256, mediaKey, directPath,
|
|
956
|
+
mediaKeyTimestamp: mediaKeyTimestamp || Math.floor(Date.now() / 1000),
|
|
957
|
+
contextInfo: contextInfo || {},
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
});
|
|
962
|
+
return _relay(jid, msg);
|
|
963
|
+
};
|
|
964
|
+
|
|
879
965
|
const sendStickerPackAlbum = async (jid, stickers, packName, packPublisher, options = {}) => {
|
|
880
966
|
if (!Array.isArray(stickers) || !stickers.length) throw new Error("sendStickerPackAlbum: stickers kosong");
|
|
881
967
|
const batchSize = Math.min(options.batchSize || 10, 10);
|
|
@@ -895,9 +981,6 @@ const makeBusinessSocket = (config) => {
|
|
|
895
981
|
return results;
|
|
896
982
|
};
|
|
897
983
|
|
|
898
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
899
|
-
// DOCUMENT (auto mime + pack)
|
|
900
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
901
984
|
const sendDocument = async (jid, document, fileName, mimetype, caption, options = {}) => {
|
|
902
985
|
if (!document) throw new Error("sendDocument: document wajib");
|
|
903
986
|
if (!fileName) throw new Error("sendDocument: fileName wajib");
|
|
@@ -927,9 +1010,6 @@ const makeBusinessSocket = (config) => {
|
|
|
927
1010
|
return results;
|
|
928
1011
|
};
|
|
929
1012
|
|
|
930
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
931
|
-
// SIMPLE MEDIA
|
|
932
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
933
1013
|
const sendAudio = async (jid, audio, isPtt = false, options = {}) => {
|
|
934
1014
|
if (!audio) throw new Error("sendAudio: audio wajib");
|
|
935
1015
|
return _originalSendMessage(jid, { audio, mimetype: isPtt ? "audio/ogg; codecs=opus" : "audio/mp4", ptt: isPtt }, options);
|
|
@@ -948,9 +1028,6 @@ const makeBusinessSocket = (config) => {
|
|
|
948
1028
|
const sendAudioPTT = async (jid, audio, options = {}) => sendAudio(jid, audio, true, options);
|
|
949
1029
|
const sendVoiceNote = async (jid, audio, options = {}) => sendAudio(jid, audio, true, options);
|
|
950
1030
|
|
|
951
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
952
|
-
// REPLY / QUOTE
|
|
953
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
954
1031
|
const sendReply = async (jid, text, quotedMessage, options = {}) => {
|
|
955
1032
|
if (!quotedMessage) throw new Error("sendReply: quotedMessage wajib");
|
|
956
1033
|
if (typeof text !== "string") throw new Error("sendReply: text harus string");
|
|
@@ -990,9 +1067,6 @@ const makeBusinessSocket = (config) => {
|
|
|
990
1067
|
return _originalSendMessage(jid, { forward: message, force: true }, options);
|
|
991
1068
|
};
|
|
992
1069
|
|
|
993
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
994
|
-
// GROUP INVITE
|
|
995
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
996
1070
|
const sendGroupInvite = async (jid, groupJid, options = {}) => {
|
|
997
1071
|
if (!_isGrp(groupJid)) throw new Error("sendGroupInvite: groupJid harus @g.us");
|
|
998
1072
|
const [code, meta] = await Promise.all([sock.groupInviteCode(groupJid), sock.groupMetadata(groupJid)]);
|
|
@@ -1021,9 +1095,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1021
1095
|
return _relay(jid, msg);
|
|
1022
1096
|
};
|
|
1023
1097
|
|
|
1024
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1025
|
-
// CHAT MANAGEMENT
|
|
1026
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1027
1098
|
const muteJid = async (jid, durationMs = 8 * 60 * 60 * 1000) => sock.chatModify({ mute: durationMs }, jid);
|
|
1028
1099
|
const unmuteJid = async (jid) => sock.chatModify({ mute: null }, jid);
|
|
1029
1100
|
|
|
@@ -1067,9 +1138,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1067
1138
|
const sendDisappearingToggle = async (jid, enable = true) =>
|
|
1068
1139
|
_originalSendMessage(jid, { disappearingMessagesInChat: enable ? 86400 : false });
|
|
1069
1140
|
|
|
1070
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1071
|
-
// PROFILE — safe fetch, tidak crash 404 / not-authorized
|
|
1072
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1073
1141
|
const getProfilePicture = async (jid, highRes = false) => {
|
|
1074
1142
|
try { return await sock.profilePictureUrl(_norm(jid), highRes ? "image" : "preview"); }
|
|
1075
1143
|
catch { return null; }
|
|
@@ -1100,19 +1168,12 @@ const makeBusinessSocket = (config) => {
|
|
|
1100
1168
|
const updateProfileName = async (name) => { if (!name) throw new Error("updateProfileName: name wajib"); return sock.updateProfileName(name); };
|
|
1101
1169
|
const updateProfileStatus = async (status) => { if (typeof status !== "string") throw new Error("updateProfileStatus: harus string"); return sock.updateProfileStatus(status); };
|
|
1102
1170
|
|
|
1103
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1104
|
-
// DISAPPEARING
|
|
1105
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1106
1171
|
const sendDisappearingMessage = async (jid, content, expiration, options = {}) => {
|
|
1107
1172
|
const valid = [0, 86400, 604800, 7776000];
|
|
1108
1173
|
if (!valid.includes(expiration)) throw new Error(`sendDisappearingMessage: expiration harus: ${valid.join(", ")}`);
|
|
1109
1174
|
return _originalSendMessage(jid, content, { ephemeralExpiration: expiration, ...options });
|
|
1110
1175
|
};
|
|
1111
1176
|
|
|
1112
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1113
|
-
// MISC
|
|
1114
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1115
|
-
// isOnWhatsApp — selalu return object, tidak pernah undefined
|
|
1116
1177
|
const isOnWhatsApp = async (jidOrNumber) => {
|
|
1117
1178
|
let jid = jidOrNumber;
|
|
1118
1179
|
if (!jid.includes("@")) jid = jid.replace(/[^0-9]/g, "") + "@s.whatsapp.net";
|
|
@@ -1151,9 +1212,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1151
1212
|
const fetchBlocklist = async () => sock.fetchBlocklist();
|
|
1152
1213
|
const fetchAllGroups = async () => sock.groupFetchAllParticipating();
|
|
1153
1214
|
|
|
1154
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1155
|
-
// INTERACTIVE — Legacy buttons / List / Template
|
|
1156
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1157
1215
|
const _mapButtons = (buttons) => buttons.map((b, i) => ({
|
|
1158
1216
|
buttonId: b.buttonId || b.id || `btn_${i}`,
|
|
1159
1217
|
buttonText: b.buttonText ? b.buttonText : { displayText: b.displayText || b.text || "" },
|
|
@@ -1196,11 +1254,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1196
1254
|
return _relay(jid, msg);
|
|
1197
1255
|
};
|
|
1198
1256
|
|
|
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
1257
|
const sendInteractiveMessage = async (jid, cfg = {}, options = {}) => {
|
|
1205
1258
|
const { body, footer, header, buttons, sections, nativeFlow } = cfg;
|
|
1206
1259
|
|
|
@@ -1281,7 +1334,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1281
1334
|
return _relay(jid, msg);
|
|
1282
1335
|
};
|
|
1283
1336
|
|
|
1284
|
-
// ─── Media + Legacy Buttons ───────────────────────────────────────────────
|
|
1285
1337
|
const sendImageWithButtons = async (jid, image, caption, buttons = [], footer = "", options = {}) => {
|
|
1286
1338
|
if (!image) throw new Error("sendImageWithButtons: image wajib");
|
|
1287
1339
|
if (!buttons.length) throw new Error("sendImageWithButtons: buttons wajib");
|
|
@@ -1303,21 +1355,14 @@ const makeBusinessSocket = (config) => {
|
|
|
1303
1355
|
return _relay(jid, _gen(jid, { buttonsMessage: { documentMessage: inner.documentMessage, contentText: caption || "", footerText: footer, buttons: _mapButtons(buttons), headerType: 6 } }));
|
|
1304
1356
|
};
|
|
1305
1357
|
|
|
1306
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1307
|
-
// PRODUCT MESSAGE — full button support (single_select, cta_url, dll)
|
|
1308
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1309
1358
|
const sendProductMessageWithButtons = async (jid, cfg = {}, options = {}) => {
|
|
1310
1359
|
const { title, body, footer, thumbnail, productId, retailerId, buttons = [], header } = cfg;
|
|
1311
1360
|
if (!buttons.length) throw new Error("sendProductMessageWithButtons: min 1 button wajib");
|
|
1312
1361
|
|
|
1313
1362
|
let headerContent = null;
|
|
1314
|
-
if (thumbnail) {
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
} else if (Buffer.isBuffer(thumbnail)) {
|
|
1318
|
-
const inner = await (0, Utils_1.generateWAMessageContent)({ image: thumbnail }, { upload: waUploadToServer });
|
|
1319
|
-
headerContent = { imageMessage: inner.imageMessage };
|
|
1320
|
-
}
|
|
1363
|
+
if (thumbnail && Buffer.isBuffer(thumbnail)) {
|
|
1364
|
+
const inner = await (0, Utils_1.generateWAMessageContent)({ image: thumbnail }, { upload: waUploadToServer });
|
|
1365
|
+
headerContent = { imageMessage: inner.imageMessage };
|
|
1321
1366
|
}
|
|
1322
1367
|
if (header && !headerContent) {
|
|
1323
1368
|
if (header.type === "image") {
|
|
@@ -1336,11 +1381,8 @@ const makeBusinessSocket = (config) => {
|
|
|
1336
1381
|
...(headerContent ? { header: headerContent } : {}),
|
|
1337
1382
|
contextInfo: {
|
|
1338
1383
|
externalAdReply: {
|
|
1339
|
-
title: title || "",
|
|
1340
|
-
|
|
1341
|
-
mediaType: 1,
|
|
1342
|
-
renderLargerThumbnail: true,
|
|
1343
|
-
showAdAttribution: false,
|
|
1384
|
+
title: title || "", body: body || "", mediaType: 1,
|
|
1385
|
+
renderLargerThumbnail: true, showAdAttribution: false,
|
|
1344
1386
|
...(thumbnail?.url ? { thumbnailUrl: thumbnail.url } : {}),
|
|
1345
1387
|
}
|
|
1346
1388
|
},
|
|
@@ -1351,11 +1393,9 @@ const makeBusinessSocket = (config) => {
|
|
|
1351
1393
|
};
|
|
1352
1394
|
|
|
1353
1395
|
const sendProductMessage = async (jid, productIdOrCfg, catalogJidOrOptions, options = {}) => {
|
|
1354
|
-
// New format: object config with buttons
|
|
1355
1396
|
if (typeof productIdOrCfg === "object" && productIdOrCfg !== null) {
|
|
1356
1397
|
return sendProductMessageWithButtons(jid, productIdOrCfg, catalogJidOrOptions || {});
|
|
1357
1398
|
}
|
|
1358
|
-
// Legacy format: catalog lookup
|
|
1359
1399
|
const productId = productIdOrCfg;
|
|
1360
1400
|
const catalogJid = typeof catalogJidOrOptions === "string" ? catalogJidOrOptions : null;
|
|
1361
1401
|
const bizJid = _norm(catalogJid || _me());
|
|
@@ -1376,9 +1416,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1376
1416
|
return _relay(jid, msg);
|
|
1377
1417
|
};
|
|
1378
1418
|
|
|
1379
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1380
|
-
// NEWSLETTER
|
|
1381
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1382
1419
|
const sendNewsletterMessage = async (newsletterJid, content, options = {}) => {
|
|
1383
1420
|
if (!newsletterJid.endsWith("@newsletter")) throw new Error("sendNewsletterMessage: harus @newsletter JID");
|
|
1384
1421
|
return _originalSendMessage(newsletterJid, content, options);
|
|
@@ -1425,13 +1462,7 @@ const makeBusinessSocket = (config) => {
|
|
|
1425
1462
|
return _originalSendMessage(jid, { location: { degreesLatitude: latitude, degreesLongitude: longitude, ...(name ? { name } : {}) } }, { quoted: quotedMessage, ...options });
|
|
1426
1463
|
};
|
|
1427
1464
|
|
|
1428
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1429
|
-
// PATCHED sendMessage
|
|
1430
|
-
// 1. tagAll system — { text: "...", tagAll: true, tagAllScope: "admins" }
|
|
1431
|
-
// 2. productMessage + buttons interception
|
|
1432
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1433
1465
|
const patchedSendMessage = async (jid, content, options = {}) => {
|
|
1434
|
-
// tagAll injection
|
|
1435
1466
|
if (content?.tagAll && _isGrp(jid)) {
|
|
1436
1467
|
try {
|
|
1437
1468
|
const scope = content.tagAllScope || "all";
|
|
@@ -1440,7 +1471,6 @@ const makeBusinessSocket = (config) => {
|
|
|
1440
1471
|
return _originalSendMessage(jid, { ...rest, mentions: [...new Set([...(rest.mentions || []), ...mentions])] }, options);
|
|
1441
1472
|
} catch (e) { _log("warn", `tagAll patch error: ${e?.message}`); }
|
|
1442
1473
|
}
|
|
1443
|
-
// productMessage + buttons interception
|
|
1444
1474
|
if (content?.productMessage && Array.isArray(content.productMessage.buttons)) {
|
|
1445
1475
|
const pm = content.productMessage;
|
|
1446
1476
|
return sendProductMessageWithButtons(jid, {
|
|
@@ -1457,30 +1487,22 @@ const makeBusinessSocket = (config) => {
|
|
|
1457
1487
|
return _originalSendMessage(jid, content, options);
|
|
1458
1488
|
};
|
|
1459
1489
|
|
|
1460
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1461
|
-
// EXPORTS
|
|
1462
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1463
1490
|
return {
|
|
1464
1491
|
...sock,
|
|
1465
1492
|
|
|
1466
|
-
// Patched sendMessage — tagAll + productMessage+buttons transparent
|
|
1467
1493
|
sendMessage: patchedSendMessage,
|
|
1468
1494
|
|
|
1469
1495
|
logger: config.logger,
|
|
1470
1496
|
|
|
1471
|
-
// ── Catalog ───────────────────────────────────────────────────────────
|
|
1472
1497
|
getCatalog, getCollections, getOrderDetails,
|
|
1473
1498
|
productCreate, productDelete, productUpdate,
|
|
1474
1499
|
|
|
1475
|
-
// ── NEW: Channel / Group Tracker & Contacts ───────────────────────────
|
|
1476
1500
|
getFollowedChannels,
|
|
1477
1501
|
getJoinedGroups,
|
|
1478
1502
|
getAllContacts,
|
|
1479
1503
|
|
|
1480
|
-
// ── NEW: Media Converter ──────────────────────────────────────────────
|
|
1481
1504
|
convertMedia, convertToSticker,
|
|
1482
1505
|
|
|
1483
|
-
// ── Group ─────────────────────────────────────────────────────────────
|
|
1484
1506
|
groupTagAll, groupStatusV2, getGroupAdmins, isGroupAdmin,
|
|
1485
1507
|
sendToAdminsOnly, bulkGroupAction, setGroupDisappearing,
|
|
1486
1508
|
sendTagAll, sendMentionAll, sendGroupInvite, sendAdminInvite,
|
|
@@ -1490,10 +1512,8 @@ const makeBusinessSocket = (config) => {
|
|
|
1490
1512
|
approveGroupJoinRequest, rejectGroupJoinRequest,
|
|
1491
1513
|
setGroupMemberAddMode, updateGroupProfilePicture,
|
|
1492
1514
|
|
|
1493
|
-
// ── Status ────────────────────────────────────────────────────────────
|
|
1494
1515
|
sendStatus,
|
|
1495
1516
|
|
|
1496
|
-
// ── Media ─────────────────────────────────────────────────────────────
|
|
1497
1517
|
sendImage, sendVideo, sendAudio, sendAudioPTT, sendVoiceNote,
|
|
1498
1518
|
sendDocument, sendDocumentPack,
|
|
1499
1519
|
sendGIF, sendPTV, sendViewOnce, sendAlbum,
|
|
@@ -1501,11 +1521,10 @@ const makeBusinessSocket = (config) => {
|
|
|
1501
1521
|
sendContact, sendPoll, sendEvent, sendScheduledCall,
|
|
1502
1522
|
sendLinkPreview, sendDisappearingToggle,
|
|
1503
1523
|
|
|
1504
|
-
// ── Sticker ───────────────────────────────────────────────────────────
|
|
1505
1524
|
sendStickerFromUrl, sendStickerFromBuffer, sendStickerWithMetadata,
|
|
1506
|
-
sendStickerPack, sendStickerPackAlbum,
|
|
1525
|
+
sendStickerPack, sendStickerPackAlbum, sendStickerPackMessage,
|
|
1526
|
+
sendStickerMessage,
|
|
1507
1527
|
|
|
1508
|
-
// ── Interactive (full native flow support) ────────────────────────────
|
|
1509
1528
|
sendButtonsMessage, sendListMessage, sendTemplateMessage,
|
|
1510
1529
|
sendInteractiveMessage, sendInteractiveWithMedia,
|
|
1511
1530
|
sendHighlyStructuredMessage,
|
|
@@ -1514,39 +1533,31 @@ const makeBusinessSocket = (config) => {
|
|
|
1514
1533
|
followNewsletter, unfollowNewsletter, getNewsletterMetadata, joinNewsletterByUrl,
|
|
1515
1534
|
sendImageWithButtons, sendVideoWithButtons, sendDocumentWithButtons,
|
|
1516
1535
|
|
|
1517
|
-
// ── Reply / Quote ─────────────────────────────────────────────────────
|
|
1518
1536
|
sendReply, sendMediaReply, sendQuotedText,
|
|
1519
1537
|
sendWithQuotedFake, sendWithMentionAndReply, forwardWithComment,
|
|
1520
1538
|
|
|
1521
|
-
// ── Mentions / Typing ─────────────────────────────────────────────────
|
|
1522
1539
|
sendTextWithMentions, sendTyping, sendWithTyping,
|
|
1523
1540
|
|
|
1524
|
-
// ── Broadcast ─────────────────────────────────────────────────────────
|
|
1525
1541
|
broadcastMessage, broadcastToGroups, sendMultipleMessages,
|
|
1526
1542
|
|
|
1527
|
-
// ── Message Actions ───────────────────────────────────────────────────
|
|
1528
1543
|
pinMessage, keepMessage, editMessage, deleteMessage,
|
|
1529
1544
|
reactMessage, forwardMessage,
|
|
1530
1545
|
|
|
1531
|
-
// ── Chat Management ───────────────────────────────────────────────────
|
|
1532
1546
|
muteJid, unmuteJid, archiveChat, unarchiveChat,
|
|
1533
1547
|
pinChat, unpinChat, markAsRead, markAsUnread,
|
|
1534
1548
|
blockUser, unblockUser, starMessage, unstarMessage,
|
|
1535
1549
|
deleteChat, clearChat, sendSeen,
|
|
1536
1550
|
|
|
1537
|
-
// ── Profile (safe fetch) ──────────────────────────────────────────────
|
|
1538
1551
|
getProfilePicture, getUserStatus,
|
|
1539
1552
|
updateProfilePicture, removeProfilePicture,
|
|
1540
1553
|
updateProfileName, updateProfileStatus,
|
|
1541
1554
|
getContactInfo, getBusinessProfile,
|
|
1542
1555
|
fetchBlocklist, fetchAllGroups, fetchMessageHistory,
|
|
1543
1556
|
|
|
1544
|
-
// ── Privacy ───────────────────────────────────────────────────────────
|
|
1545
1557
|
updatePrivacyLastSeen, updatePrivacyProfilePic, updatePrivacyStatus,
|
|
1546
1558
|
updatePrivacyReadReceipts, updatePrivacyGroupsAdd, updatePrivacyOnline,
|
|
1547
1559
|
setDefaultDisappearing,
|
|
1548
1560
|
|
|
1549
|
-
// ── Misc ──────────────────────────────────────────────────────────────
|
|
1550
1561
|
sendDisappearingMessage, isOnWhatsApp,
|
|
1551
1562
|
presenceSubscribe, rejectAllCalls,
|
|
1552
1563
|
};
|