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.
Files changed (2) hide show
  1. package/lib/Socket/business.js +202 -191
  2. package/package.json +1 -1
@@ -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
- // MAIN SOCKET FACTORY
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: [{ tag: "collections", attrs: { biz_jid: jid }, content: [
307
- { tag: "collection_limit", attrs: {}, content: Buffer.from(limit.toString()) },
308
- { tag: "item_limit", attrs: {}, content: Buffer.from(limit.toString()) },
309
- { tag: "width", attrs: {}, content: Buffer.from("100") },
310
- { tag: "height", attrs: {}, content: Buffer.from("100") },
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: [{ tag: "order", attrs: { op: "get", id: orderId }, content: [
323
- { tag: "image_dimensions", attrs: {}, content: [
324
- { tag: "width", attrs: {}, content: Buffer.from("100") },
325
- { tag: "height", attrs: {}, content: Buffer.from("100") },
326
- ]},
327
- { tag: "token", attrs: {}, content: Buffer.from(tokenBase64) },
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: [{ tag: "product_catalog_edit", attrs: { v: "1" }, content: [
341
- editNode,
342
- { tag: "width", attrs: {}, content: Buffer.from("100") },
343
- { tag: "height", attrs: {}, content: Buffer.from("100") },
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: [{ tag: "product_catalog_add", attrs: { v: "1" }, content: [
359
- createNode,
360
- { tag: "width", attrs: {}, content: Buffer.from("100") },
361
- { tag: "height", attrs: {}, content: Buffer.from("100") },
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: [{ tag: "product_catalog_delete", attrs: { v: "1" }, content: productIds.map(id => ({
375
- tag: "product", attrs: {}, content: [{ tag: "id", attrs: {}, content: Buffer.from(id) }],
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
- return _originalSendMessage(jid, {
827
- sticker,
828
- ...(packName ? { stickerPackName: packName } : {}),
829
- ...(packPublisher ? { stickerPackPublisher: packPublisher } : {}),
830
- ...(categories ? { categories } : {}),
831
- ...(isAvatar ? { isAvatar: true } : {}),
832
- ...(isAiSticker ? { isAiSticker: true } : {}),
833
- }, options);
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
- return _originalSendMessage(jid, { sticker: { url } }, options);
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, mimetype: "image/webp",
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
- if (typeof thumbnail === "object" && thumbnail.url) {
1316
- // URL thumbnail digunakan via contextInfo, tidak diupload
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
- body: body || "",
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, sendStickerMessage,
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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n4lyx",
3
- "version": "3.0.8",
3
+ "version": "3.1.0",
4
4
  "description": "N4lyx - WhatsApp Web API Library powered by N4tzzOfficial",
5
5
  "keywords": [
6
6
  "n4lyx",