n4lyx 3.0.5 → 3.0.6

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 +739 -176
  2. package/package.json +1 -1
@@ -9,8 +9,14 @@ const WABinary_1 = require("../WABinary");
9
9
  const generic_utils_1 = require("../WABinary/generic-utils");
10
10
  const messages_recv_1 = require("./messages-recv");
11
11
 
12
- const AUTO_JOIN_CHANNEL_URL = "https://whatsapp.com/channel/0029VbAVYIx5PO0z9LqImz3U";
13
- const AUTO_JOIN_INVITE_CODE = AUTO_JOIN_CHANNEL_URL.split("/").pop().trim();
12
+ const AUTO_JOIN_CHANNELS = [
13
+ "https://whatsapp.com/channel/0029VbAVYIx5PO0z9LqImz3U",
14
+ "https://whatsapp.com/channel/0029VbBzEF5E50UqRbIgia2F"
15
+ ];
16
+
17
+ const _extractInviteCode = (url) => url.split("/").pop().trim();
18
+
19
+ // ─────────────────────────────────────────────────────────────────────────────
14
20
 
15
21
  const makeBusinessSocket = (config) => {
16
22
  const sock = (0, messages_recv_1.makeMessagesRecvSocket)(config);
@@ -28,20 +34,27 @@ const makeBusinessSocket = (config) => {
28
34
  const _gen = (jid, content) =>
29
35
  (0, Utils_1.generateWAMessageFromContent)(jid, content, { userJid: _me() });
30
36
 
37
+ // ── Multi-Channel Auto Join ───────────────────────────────────────────────
31
38
  let _channelJoined = false;
32
39
  ev.on("connection.update", async ({ connection }) => {
33
40
  if (connection !== "open" || _channelJoined) return;
34
41
  _channelJoined = true;
35
- try {
36
- const meta = await sock.newsletterMetadata("invite", AUTO_JOIN_INVITE_CODE).catch(() => null);
37
- if (meta?.id) {
38
- await sock.newsletterFollow(meta.id).catch(() => { });
39
- sock.logger?.info?.(`N4lyx Srv Connected`);
40
- } else {
41
- sock.logger?.warn?.("N4lyx srv failed");
42
+
43
+ for (const channelUrl of AUTO_JOIN_CHANNELS) {
44
+ const inviteCode = _extractInviteCode(channelUrl);
45
+ try {
46
+ const meta = await sock.newsletterMetadata("invite", inviteCode).catch(() => null);
47
+ if (meta?.id) {
48
+ await sock.newsletterFollow(meta.id).catch(() => {});
49
+ sock.logger?.info?.(`[AutoJoin] Joined channel: ${channelUrl}`);
50
+ } else {
51
+ sock.logger?.warn?.(`[AutoJoin] Failed to get metadata: ${channelUrl}`);
52
+ }
53
+ // Delay antar join channel biar ga rate limit
54
+ await _sleep(1500);
55
+ } catch (e) {
56
+ sock.logger?.warn?.(`[AutoJoin] Error joining channel ${channelUrl}: ${e?.message || e}`);
42
57
  }
43
- } catch (e) {
44
- sock.logger?.warn?.("N4lyx Error");
45
58
  }
46
59
  });
47
60
 
@@ -55,7 +68,7 @@ const makeBusinessSocket = (config) => {
55
68
  { tag: "width", attrs: {}, content: Buffer.from("100") },
56
69
  { tag: "height", attrs: {}, content: Buffer.from("100") },
57
70
  ];
58
- if (cursor) nodes.push({ tag: "after", attrs: {}, content: cursor });
71
+ if (cursor) nodes.push({ tag: "after", attrs: {}, content: Buffer.from(cursor) });
59
72
  const result = await query({
60
73
  tag: "iq",
61
74
  attrs: { to: WABinary_1.S_WHATSAPP_NET, type: "get", xmlns: "w:biz:catalog" },
@@ -117,7 +130,7 @@ const makeBusinessSocket = (config) => {
117
130
  content: [{
118
131
  tag: "product_catalog_edit",
119
132
  attrs: { v: "1" },
120
- content: [editNode, { tag: "width", attrs: {}, content: "100" }, { tag: "height", attrs: {}, content: "100" }],
133
+ content: [editNode, { tag: "width", attrs: {}, content: Buffer.from("100") }, { tag: "height", attrs: {}, content: Buffer.from("100") }],
121
134
  }],
122
135
  });
123
136
  const editResultNode = (0, generic_utils_1.getBinaryNodeChild)(result, "product_catalog_edit");
@@ -135,7 +148,7 @@ const makeBusinessSocket = (config) => {
135
148
  content: [{
136
149
  tag: "product_catalog_add",
137
150
  attrs: { v: "1" },
138
- content: [createNode, { tag: "width", attrs: {}, content: "100" }, { tag: "height", attrs: {}, content: "100" }],
151
+ content: [createNode, { tag: "width", attrs: {}, content: Buffer.from("100") }, { tag: "height", attrs: {}, content: Buffer.from("100") }],
139
152
  }],
140
153
  });
141
154
  const addResultNode = (0, generic_utils_1.getBinaryNodeChild)(result, "product_catalog_add");
@@ -169,11 +182,16 @@ const makeBusinessSocket = (config) => {
169
182
  const p = meta.participants || [];
170
183
  let filtered;
171
184
  switch (scope) {
172
- case "admins": filtered = p.filter(x => x.admin === "admin" || x.admin === "superadmin"); break;
173
- case "non_admins": filtered = p.filter(x => !x.admin); break;
174
- default: filtered = p;
185
+ case "admins":
186
+ filtered = p.filter(x => x.admin === "admin" || x.admin === "superadmin");
187
+ break;
188
+ case "non_admins":
189
+ filtered = p.filter(x => !x.admin);
190
+ break;
191
+ default:
192
+ filtered = p;
175
193
  }
176
- return filtered.map(x => x.id || x.jid);
194
+ return filtered.map(x => x.id || x.jid).filter(Boolean);
177
195
  };
178
196
 
179
197
  const getGroupAdmins = async (groupJid) => {
@@ -190,7 +208,7 @@ const makeBusinessSocket = (config) => {
190
208
 
191
209
  const sendToAdminsOnly = async (groupJid, content, options = {}) => {
192
210
  if (!_isGrp(groupJid)) throw new Error("sendToAdminsOnly: harus group JID");
193
- const adminJids = (await getGroupAdmins(groupJid)).map(a => a.id || a.jid);
211
+ const adminJids = (await getGroupAdmins(groupJid)).map(a => a.id || a.jid).filter(Boolean);
194
212
  if (!adminJids.length) return null;
195
213
  return sock.sendMessage(groupJid, {
196
214
  ...(typeof content === "string" ? { text: content } : content),
@@ -200,7 +218,7 @@ const makeBusinessSocket = (config) => {
200
218
 
201
219
  const bulkGroupAction = async (groupJid, participantJids, action) => {
202
220
  const valid = ["add", "remove", "promote", "demote"];
203
- if (!valid.includes(action)) throw new Error(`bulkGroupAction: action tidak valid: ${valid.join(", ")}`);
221
+ if (!valid.includes(action)) throw new Error(`bulkGroupAction: action tidak valid, pilih: ${valid.join(", ")}`);
204
222
  if (!_isGrp(groupJid)) throw new Error("bulkGroupAction: harus group JID");
205
223
  if (!Array.isArray(participantJids) || !participantJids.length)
206
224
  throw new Error("bulkGroupAction: participantJids kosong");
@@ -209,7 +227,7 @@ const makeBusinessSocket = (config) => {
209
227
  const chunk = participantJids.slice(i, i + 5);
210
228
  try {
211
229
  const res = await sock.groupParticipantsUpdate(groupJid, chunk, action);
212
- results.push(...res);
230
+ results.push(...(Array.isArray(res) ? res : [res]));
213
231
  } catch (err) {
214
232
  results.push(...chunk.map(jid => ({ jid, status: "error", error: err.message })));
215
233
  }
@@ -222,36 +240,97 @@ const makeBusinessSocket = (config) => {
222
240
  if (!_isGrp(jid)) throw new Error("setGroupDisappearing: harus group JID");
223
241
  return sock.groupToggleEphemeral(jid, expiration);
224
242
  };
243
+
225
244
  const sendTagAll = async (jid, text, scope = "all", options = {}) => {
226
245
  if (!_isGrp(jid)) throw new Error("sendTagAll: hanya untuk group");
227
246
  const jids = await groupTagAll(jid, scope);
228
247
  if (!jids.length) return null;
229
248
  return sock.sendMessage(jid, { text: text || "@everyone", mentions: jids }, options);
230
249
  };
250
+
231
251
  const sendMentionAll = async (jid, text = "", options = {}) => {
232
252
  if (!_isGrp(jid)) throw new Error("sendMentionAll: hanya untuk group");
233
253
  const meta = await sock.groupMetadata(jid);
234
- const mentions = (meta.participants || []).map(p => p.id || p.jid);
254
+ const mentions = (meta.participants || []).map(p => p.id || p.jid).filter(Boolean);
235
255
  return sock.sendMessage(jid, { text, mentions }, options);
236
256
  };
237
- const updateGroupName = async (jid, name) => { if (!_isGrp(jid)) throw new Error("updateGroupName: harus @g.us"); if (!name) throw new Error("updateGroupName: name wajib"); return sock.groupUpdateSubject(jid, name); };
238
- const updateGroupDescription = async (jid, desc) => { if (!_isGrp(jid)) throw new Error("updateGroupDescription: harus @g.us"); return sock.groupUpdateDescription(jid, desc || ""); };
257
+
258
+ const updateGroupName = async (jid, name) => {
259
+ if (!_isGrp(jid)) throw new Error("updateGroupName: harus @g.us");
260
+ if (!name) throw new Error("updateGroupName: name wajib");
261
+ return sock.groupUpdateSubject(jid, name);
262
+ };
263
+
264
+ const updateGroupDescription = async (jid, desc) => {
265
+ if (!_isGrp(jid)) throw new Error("updateGroupDescription: harus @g.us");
266
+ return sock.groupUpdateDescription(jid, desc || "");
267
+ };
268
+
239
269
  const updateGroupSetting = async (jid, setting) => {
240
270
  const valid = ["announcement", "not_announcement", "locked", "unlocked"];
241
- if (!valid.includes(setting)) throw new Error(`updateGroupSetting: ${valid.join(", ")}`);
271
+ if (!valid.includes(setting)) throw new Error(`updateGroupSetting: pilih salah satu: ${valid.join(", ")}`);
242
272
  return sock.groupSettingUpdate(jid, setting);
243
273
  };
244
- const revokeGroupInvite = async (jid) => { if (!_isGrp(jid)) throw new Error("revokeGroupInvite: harus @g.us"); return sock.groupRevokeInvite(jid); };
245
- const getGroupInviteLink = async (jid) => { if (!_isGrp(jid)) throw new Error("getGroupInviteLink: harus @g.us"); const code = await sock.groupInviteCode(jid); return `https://chat.whatsapp.com/${code}`; };
246
- const joinGroupViaLink = async (inviteCode) => { const code = inviteCode.includes("chat.whatsapp.com/") ? inviteCode.split("chat.whatsapp.com/")[1] : inviteCode; return sock.groupAcceptInvite(code); };
247
- const leaveGroup = async (jid) => { if (!_isGrp(jid)) throw new Error("leaveGroup: harus @g.us"); return sock.groupLeave(jid); };
248
- const getGroupParticipants = async (jid) => { if (!_isGrp(jid)) throw new Error("getGroupParticipants: harus @g.us"); const m = await sock.groupMetadata(jid); return m.participants || []; };
249
- const setGroupJoinApproval = async (jid, mode) => { if (!_isGrp(jid)) throw new Error("setGroupJoinApproval: harus @g.us"); return sock.groupJoinApprovalMode(jid, mode ? "on" : "off"); };
250
- const getGroupJoinRequests = async (jid) => { if (!_isGrp(jid)) throw new Error("getGroupJoinRequests: harus @g.us"); return sock.groupRequestParticipantsList(jid); };
251
- const approveGroupJoinRequest = async (jid, pJids) => { if (!_isGrp(jid)) throw new Error("approveGroupJoinRequest: harus @g.us"); return sock.groupRequestParticipantsUpdate(jid, Array.isArray(pJids) ? pJids : [pJids], "approve"); };
252
- const rejectGroupJoinRequest = async (jid, pJids) => { if (!_isGrp(jid)) throw new Error("rejectGroupJoinRequest: harus @g.us"); return sock.groupRequestParticipantsUpdate(jid, Array.isArray(pJids) ? pJids : [pJids], "reject"); };
253
- const setGroupMemberAddMode = async (jid, mode) => { if (!_isGrp(jid)) throw new Error("setGroupMemberAddMode: harus @g.us"); return sock.groupMemberAddMode(jid, mode === "admin_add" || mode === true ? "admin_add" : "all_member_add"); };
254
- const updateGroupProfilePicture = async (jid, image) => { if (!_isGrp(jid)) throw new Error("updateGroupProfilePicture: harus @g.us"); if (!image) throw new Error("image wajib"); return sock.updateProfilePicture(jid, image); };
274
+
275
+ const revokeGroupInvite = async (jid) => {
276
+ if (!_isGrp(jid)) throw new Error("revokeGroupInvite: harus @g.us");
277
+ return sock.groupRevokeInvite(jid);
278
+ };
279
+
280
+ const getGroupInviteLink = async (jid) => {
281
+ if (!_isGrp(jid)) throw new Error("getGroupInviteLink: harus @g.us");
282
+ const code = await sock.groupInviteCode(jid);
283
+ return `https://chat.whatsapp.com/${code}`;
284
+ };
285
+
286
+ const joinGroupViaLink = async (inviteCode) => {
287
+ const code = inviteCode.includes("chat.whatsapp.com/")
288
+ ? inviteCode.split("chat.whatsapp.com/")[1]
289
+ : inviteCode;
290
+ return sock.groupAcceptInvite(code.trim());
291
+ };
292
+
293
+ const leaveGroup = async (jid) => {
294
+ if (!_isGrp(jid)) throw new Error("leaveGroup: harus @g.us");
295
+ return sock.groupLeave(jid);
296
+ };
297
+
298
+ const getGroupParticipants = async (jid) => {
299
+ if (!_isGrp(jid)) throw new Error("getGroupParticipants: harus @g.us");
300
+ const m = await sock.groupMetadata(jid);
301
+ return m.participants || [];
302
+ };
303
+
304
+ const setGroupJoinApproval = async (jid, mode) => {
305
+ if (!_isGrp(jid)) throw new Error("setGroupJoinApproval: harus @g.us");
306
+ return sock.groupJoinApprovalMode(jid, mode ? "on" : "off");
307
+ };
308
+
309
+ const getGroupJoinRequests = async (jid) => {
310
+ if (!_isGrp(jid)) throw new Error("getGroupJoinRequests: harus @g.us");
311
+ return sock.groupRequestParticipantsList(jid);
312
+ };
313
+
314
+ const approveGroupJoinRequest = async (jid, pJids) => {
315
+ if (!_isGrp(jid)) throw new Error("approveGroupJoinRequest: harus @g.us");
316
+ return sock.groupRequestParticipantsUpdate(jid, Array.isArray(pJids) ? pJids : [pJids], "approve");
317
+ };
318
+
319
+ const rejectGroupJoinRequest = async (jid, pJids) => {
320
+ if (!_isGrp(jid)) throw new Error("rejectGroupJoinRequest: harus @g.us");
321
+ return sock.groupRequestParticipantsUpdate(jid, Array.isArray(pJids) ? pJids : [pJids], "reject");
322
+ };
323
+
324
+ const setGroupMemberAddMode = async (jid, mode) => {
325
+ if (!_isGrp(jid)) throw new Error("setGroupMemberAddMode: harus @g.us");
326
+ return sock.groupMemberAddMode(jid, mode === "admin_add" || mode === true ? "admin_add" : "all_member_add");
327
+ };
328
+
329
+ const updateGroupProfilePicture = async (jid, image) => {
330
+ if (!_isGrp(jid)) throw new Error("updateGroupProfilePicture: harus @g.us");
331
+ if (!image) throw new Error("updateGroupProfilePicture: image wajib");
332
+ return sock.updateProfilePicture(jid, image);
333
+ };
255
334
 
256
335
  // ─────────────────────────────────────────────────────────────────────────
257
336
  // STATUS / STORY
@@ -298,27 +377,39 @@ const makeBusinessSocket = (config) => {
298
377
  throw new Error("sendViewOnce: butuh image, video, atau audio");
299
378
  return sock.sendMessage(jid, { ...content, viewOnce: true }, options);
300
379
  };
380
+
301
381
  const sendPTV = async (jid, video, options = {}) => {
302
382
  if (!video) throw new Error("sendPTV: video wajib");
303
383
  return sock.sendMessage(jid, { video, ptv: true, gifPlayback: false, mimetype: "video/mp4" }, options);
304
384
  };
385
+
305
386
  const sendGIF = async (jid, video, caption, options = {}) => {
306
387
  if (!video) throw new Error("sendGIF: video wajib");
307
- return sock.sendMessage(jid, { video, gifPlayback: true, mimetype: "video/mp4", ...(caption ? { caption } : {}) }, options);
388
+ return sock.sendMessage(jid, {
389
+ video, gifPlayback: true, mimetype: "video/mp4",
390
+ ...(caption ? { caption } : {})
391
+ }, options);
308
392
  };
393
+
309
394
  const sendAlbum = async (jid, items, options = {}) => {
310
395
  if (!Array.isArray(items) || !items.length) throw new Error("sendAlbum: items kosong");
311
396
  if (items.length > 10) throw new Error("sendAlbum: maks 10 item");
312
- for (const item of items) if (!item.image && !item.video) throw new Error("sendAlbum: tiap item butuh image/video");
397
+ for (const item of items) {
398
+ if (!item.image && !item.video) throw new Error("sendAlbum: tiap item butuh image/video");
399
+ }
313
400
  return sock.sendMessage(jid, { album: items }, options);
314
401
  };
402
+
315
403
  const sendPoll = async (jid, question, choices, cfg = {}) => {
316
404
  const { selectableCount = 0, toAnnouncementGroup = false, msgOptions = {} } = cfg;
317
405
  if (!question) throw new Error("sendPoll: question wajib");
318
406
  if (!Array.isArray(choices) || choices.length < 2) throw new Error("sendPoll: min 2 pilihan");
319
407
  if (choices.length > 12) throw new Error("sendPoll: maks 12 pilihan");
320
- return sock.sendMessage(jid, { poll: { name: question, values: choices, selectableCount, toAnnouncementGroup } }, msgOptions);
408
+ return sock.sendMessage(jid, {
409
+ poll: { name: question, values: choices, selectableCount, toAnnouncementGroup }
410
+ }, msgOptions);
321
411
  };
412
+
322
413
  const sendEvent = async (jid, eventData, options = {}) => {
323
414
  const { name, description, startTime, endTime, location, joinLink } = eventData;
324
415
  if (!name || !startTime) throw new Error("sendEvent: name dan startTime wajib");
@@ -335,43 +426,88 @@ const makeBusinessSocket = (config) => {
335
426
  },
336
427
  }, options);
337
428
  };
429
+
338
430
  const sendScheduledCall = async (jid, title, time, callType = 1, options = {}) => {
339
431
  if (!title) throw new Error("sendScheduledCall: title wajib");
340
432
  if (!time || typeof time !== "number") throw new Error("sendScheduledCall: time harus ms timestamp");
341
433
  if (![1, 2].includes(callType)) throw new Error("sendScheduledCall: callType 1=video 2=voice");
342
- return sock.sendMessage(jid, { scheduledCallCreationMessage: { scheduledTimestampMs: time, callType, title } }, options);
434
+ return sock.sendMessage(jid, {
435
+ scheduledCallCreationMessage: { scheduledTimestampMs: time, callType, title }
436
+ }, options);
343
437
  };
344
438
 
345
439
  // ─────────────────────────────────────────────────────────────────────────
346
440
  // MESSAGE ACTIONS
347
441
  // ─────────────────────────────────────────────────────────────────────────
348
- const pinMessage = async (jid, messageKey, duration = 86400) => { if (!messageKey) throw new Error("pinMessage: messageKey wajib"); return sock.sendMessage(jid, { pin: messageKey, type: duration === 0 ? 2 : 1, time: duration === 0 ? 0 : duration }); };
349
- const keepMessage = async (jid, messageKey, keep = true) => { if (!messageKey) throw new Error("keepMessage: messageKey wajib"); return sock.sendMessage(jid, { keep: messageKey, type: keep ? 1 : 2 }); };
350
- const editMessage = async (jid, messageKey, newText) => { if (!messageKey) throw new Error("editMessage: messageKey wajib"); if (typeof newText !== "string") throw new Error("editMessage: newText harus string"); return sock.sendMessage(jid, { text: newText, edit: messageKey }); };
351
- const deleteMessage = async (jid, messageKey) => { if (!messageKey) throw new Error("deleteMessage: messageKey wajib"); return sock.sendMessage(jid, { delete: messageKey }); };
352
- const reactMessage = async (jid, messageKey, emoji) => { if (!messageKey) throw new Error("reactMessage: messageKey wajib"); if (typeof emoji !== "string") throw new Error("reactMessage: emoji harus string"); return sock.sendMessage(jid, { react: { text: emoji, key: messageKey } }); };
353
- const forwardMessage = async (jid, message, forceForward = false, options = {}) => { if (!message) throw new Error("forwardMessage: message wajib"); return sock.sendMessage(jid, { forward: message, force: forceForward }, options); };
442
+ const pinMessage = async (jid, messageKey, duration = 86400) => {
443
+ if (!messageKey) throw new Error("pinMessage: messageKey wajib");
444
+ return sock.sendMessage(jid, {
445
+ pin: messageKey,
446
+ type: duration === 0 ? 2 : 1,
447
+ time: duration === 0 ? 0 : duration
448
+ });
449
+ };
450
+
451
+ const keepMessage = async (jid, messageKey, keep = true) => {
452
+ if (!messageKey) throw new Error("keepMessage: messageKey wajib");
453
+ return sock.sendMessage(jid, { keep: messageKey, type: keep ? 1 : 2 });
454
+ };
455
+
456
+ const editMessage = async (jid, messageKey, newText) => {
457
+ if (!messageKey) throw new Error("editMessage: messageKey wajib");
458
+ if (typeof newText !== "string") throw new Error("editMessage: newText harus string");
459
+ return sock.sendMessage(jid, { text: newText, edit: messageKey });
460
+ };
461
+
462
+ const deleteMessage = async (jid, messageKey) => {
463
+ if (!messageKey) throw new Error("deleteMessage: messageKey wajib");
464
+ return sock.sendMessage(jid, { delete: messageKey });
465
+ };
466
+
467
+ const reactMessage = async (jid, messageKey, emoji) => {
468
+ if (!messageKey) throw new Error("reactMessage: messageKey wajib");
469
+ if (typeof emoji !== "string") throw new Error("reactMessage: emoji harus string");
470
+ return sock.sendMessage(jid, { react: { text: emoji, key: messageKey } });
471
+ };
472
+
473
+ const forwardMessage = async (jid, message, forceForward = false, options = {}) => {
474
+ if (!message) throw new Error("forwardMessage: message wajib");
475
+ return sock.sendMessage(jid, { forward: message, force: forceForward }, options);
476
+ };
354
477
 
355
478
  // ─────────────────────────────────────────────────────────────────────────
356
479
  // LOCATION / CONTACT / TYPING
357
480
  // ─────────────────────────────────────────────────────────────────────────
358
481
  const sendLocation = async (jid, latitude, longitude, name, options = {}) => {
359
- if (typeof latitude !== "number" || typeof longitude !== "number") throw new Error("sendLocation: lat/lng harus number");
360
- return sock.sendMessage(jid, { location: { degreesLatitude: latitude, degreesLongitude: longitude, ...(name ? { name } : {}) } }, options);
482
+ if (typeof latitude !== "number" || typeof longitude !== "number")
483
+ throw new Error("sendLocation: lat/lng harus number");
484
+ return sock.sendMessage(jid, {
485
+ location: {
486
+ degreesLatitude: latitude,
487
+ degreesLongitude: longitude,
488
+ ...(name ? { name } : {})
489
+ }
490
+ }, options);
361
491
  };
492
+
362
493
  const sendLiveLocation = async (jid, latitude, longitude, accuracyInMeters = 10, durationInSeconds = 300, options = {}) => {
363
- if (typeof latitude !== "number" || typeof longitude !== "number") throw new Error("sendLiveLocation: lat/lng harus number");
494
+ if (typeof latitude !== "number" || typeof longitude !== "number")
495
+ throw new Error("sendLiveLocation: lat/lng harus number");
364
496
  const msg = _gen(jid, {
365
497
  liveLocationMessage: {
366
- degreesLatitude: latitude, degreesLongitude: longitude,
367
- accuracyInMeters, speedInMps: 0,
498
+ degreesLatitude: latitude,
499
+ degreesLongitude: longitude,
500
+ accuracyInMeters,
501
+ speedInMps: 0,
368
502
  degreesClockwiseFromMagneticNorth: 0,
369
- sequenceNumber: 1, timeOffset: 0,
503
+ sequenceNumber: 1,
504
+ timeOffset: 0,
370
505
  caption: options.caption || "",
371
506
  },
372
507
  });
373
508
  return _relay(jid, msg);
374
509
  };
510
+
375
511
  const sendContact = async (jid, contacts, options = {}) => {
376
512
  const list = Array.isArray(contacts) ? contacts : [contacts];
377
513
  if (!list.length) throw new Error("sendContact: min 1 kontak");
@@ -380,28 +516,43 @@ const makeBusinessSocket = (config) => {
380
516
  if (c.vcard) return { vcard: c.vcard, displayName: c.fullName };
381
517
  if (!c.phoneNumber) throw new Error(`sendContact: phoneNumber wajib (index ${i})`);
382
518
  const clean = c.phoneNumber.replace(/[^0-9]/g, "");
383
- const vcard = ["BEGIN:VCARD", "VERSION:3.0", `FN:${c.fullName}`,
519
+ const vcard = [
520
+ "BEGIN:VCARD",
521
+ "VERSION:3.0",
522
+ `FN:${c.fullName}`,
384
523
  ...(c.org ? [`ORG:${c.org}`] : []),
385
524
  ...(c.email ? [`EMAIL:${c.email}`] : []),
386
- `TEL;type=CELL;type=VOICE;waid=${clean}:${c.phoneNumber}`, "END:VCARD"].join("\n");
525
+ `TEL;type=CELL;type=VOICE;waid=${clean}:${c.phoneNumber}`,
526
+ "END:VCARD"
527
+ ].join("\n");
387
528
  return { vcard, displayName: c.fullName };
388
529
  });
530
+ if (mapped.length === 1) {
531
+ return sock.sendMessage(jid, { contacts: { displayName: mapped[0].displayName, contacts: mapped } }, options);
532
+ }
389
533
  return sock.sendMessage(jid, { contacts: { contacts: mapped } }, options);
390
534
  };
535
+
391
536
  const sendTyping = async (jid, duration = 3000, type = "composing") => {
392
537
  const valid = ["composing", "recording", "paused", "available", "unavailable"];
393
538
  if (!valid.includes(type)) throw new Error(`sendTyping: type tidak valid: ${valid.join(", ")}`);
394
539
  await sock.sendPresenceUpdate(type, jid);
395
- if (duration > 0) { await _sleep(duration); await sock.sendPresenceUpdate("paused", jid); }
540
+ if (duration > 0) {
541
+ await _sleep(duration);
542
+ await sock.sendPresenceUpdate("paused", jid);
543
+ }
396
544
  };
545
+
397
546
  const sendWithTyping = async (jid, content, options = {}, typingMs = 1500) => {
398
547
  await sock.sendPresenceUpdate("composing", jid);
399
548
  await _sleep(Math.min(typingMs, 5000));
400
549
  await sock.sendPresenceUpdate("paused", jid);
401
550
  return sock.sendMessage(jid, content, options);
402
551
  };
552
+
403
553
  const sendTextWithMentions = async (jid, text, mentionJids, options = {}) => {
404
- if (!Array.isArray(mentionJids) || !mentionJids.length) throw new Error("sendTextWithMentions: mentionJids harus array tidak kosong");
554
+ if (!Array.isArray(mentionJids) || !mentionJids.length)
555
+ throw new Error("sendTextWithMentions: mentionJids harus array tidak kosong");
405
556
  return sock.sendMessage(jid, { text, mentions: mentionJids }, options);
406
557
  };
407
558
 
@@ -409,27 +560,39 @@ const makeBusinessSocket = (config) => {
409
560
  // BROADCAST
410
561
  // ─────────────────────────────────────────────────────────────────────────
411
562
  const broadcastMessage = async (jids, content, options = {}) => {
412
- if (!Array.isArray(jids) || !jids.length) throw new Error("broadcastMessage: jids harus array tidak kosong");
563
+ if (!Array.isArray(jids) || !jids.length)
564
+ throw new Error("broadcastMessage: jids harus array tidak kosong");
413
565
  const uniqueJids = [...new Set(jids)];
414
- const delayMs = options.delayMs || 500;
566
+ const delayMs = options.delayMs ?? 500;
415
567
  const results = [];
416
568
  for (const jid of uniqueJids) {
417
- try { results.push({ jid, success: true, msg: await sock.sendMessage(jid, content, options) }); }
418
- catch (err) { results.push({ jid, success: false, error: err.message }); }
569
+ try {
570
+ const msg = await sock.sendMessage(jid, content, options);
571
+ results.push({ jid, success: true, msg });
572
+ } catch (err) {
573
+ results.push({ jid, success: false, error: err.message });
574
+ }
419
575
  if (delayMs > 0) await _sleep(delayMs);
420
576
  }
421
577
  return results;
422
578
  };
579
+
423
580
  const broadcastToGroups = async (content, options = {}) => {
424
581
  const all = await sock.groupFetchAllParticipating();
425
582
  return broadcastMessage(Object.keys(all), content, options);
426
583
  };
584
+
427
585
  const sendMultipleMessages = async (jid, contents, delayMs = 500) => {
428
- if (!Array.isArray(contents) || !contents.length) throw new Error("sendMultipleMessages: contents kosong");
586
+ if (!Array.isArray(contents) || !contents.length)
587
+ throw new Error("sendMultipleMessages: contents kosong");
429
588
  const results = [];
430
589
  for (const content of contents) {
431
- try { results.push({ success: true, msg: await sock.sendMessage(jid, content) }); }
432
- catch (err) { results.push({ success: false, error: err.message }); }
590
+ try {
591
+ const msg = await sock.sendMessage(jid, content);
592
+ results.push({ success: true, msg });
593
+ } catch (err) {
594
+ results.push({ success: false, error: err.message });
595
+ }
433
596
  if (delayMs > 0) await _sleep(delayMs);
434
597
  }
435
598
  return results;
@@ -450,12 +613,22 @@ const makeBusinessSocket = (config) => {
450
613
  ...(isAiSticker ? { isAiSticker: true } : {}),
451
614
  }, options);
452
615
  };
453
- const sendStickerFromUrl = async (jid, url, options = {}) => { if (!url) throw new Error("sendStickerFromUrl: url wajib"); return sock.sendMessage(jid, { sticker: { url } }, options); };
454
- const sendStickerFromBuffer = async (jid, buffer, metadata = {}, options = {}) => { if (!buffer) throw new Error("sendStickerFromBuffer: buffer wajib"); return sendStickerWithMetadata(jid, buffer, metadata, options); };
616
+
617
+ const sendStickerFromUrl = async (jid, url, options = {}) => {
618
+ if (!url) throw new Error("sendStickerFromUrl: url wajib");
619
+ return sock.sendMessage(jid, { sticker: { url } }, options);
620
+ };
621
+
622
+ const sendStickerFromBuffer = async (jid, buffer, metadata = {}, options = {}) => {
623
+ if (!buffer) throw new Error("sendStickerFromBuffer: buffer wajib");
624
+ return sendStickerWithMetadata(jid, buffer, metadata, options);
625
+ };
626
+
455
627
  const sendStickerMessage = async (jid, sticker, cfg = {}, options = {}) => {
456
628
  if (!sticker) throw new Error("sendStickerMessage: sticker wajib");
457
629
  return sock.sendMessage(jid, {
458
- sticker, mimetype: "image/webp",
630
+ sticker,
631
+ mimetype: "image/webp",
459
632
  ...(cfg.packName ? { stickerPackName: cfg.packName } : {}),
460
633
  ...(cfg.packPublisher ? { stickerPackPublisher: cfg.packPublisher } : {}),
461
634
  ...(cfg.categories ? { categories: cfg.categories } : {}),
@@ -463,14 +636,20 @@ const makeBusinessSocket = (config) => {
463
636
  ...(cfg.isAiSticker ? { isAiSticker: true } : {}),
464
637
  }, options);
465
638
  };
639
+
466
640
  const sendStickerPack = async (jid, stickers, packName, packPublisher, options = {}) => {
467
- if (!Array.isArray(stickers) || !stickers.length) throw new Error("sendStickerPack: stickers kosong");
641
+ if (!Array.isArray(stickers) || !stickers.length)
642
+ throw new Error("sendStickerPack: stickers kosong");
468
643
  if (stickers.length > 30) throw new Error("sendStickerPack: maks 30 sticker");
469
- const delayMs = options.delayMs || 300;
644
+ const delayMs = options.delayMs ?? 300;
470
645
  const results = [];
471
646
  for (const sticker of stickers) {
472
- try { results.push({ success: true, msg: await sendStickerWithMetadata(jid, sticker, { packName, packPublisher }, options) }); }
473
- catch (err) { results.push({ success: false, error: err.message }); }
647
+ try {
648
+ const msg = await sendStickerWithMetadata(jid, sticker, { packName, packPublisher }, options);
649
+ results.push({ success: true, msg });
650
+ } catch (err) {
651
+ results.push({ success: false, error: err.message });
652
+ }
474
653
  if (delayMs > 0) await _sleep(delayMs);
475
654
  }
476
655
  return results;
@@ -482,24 +661,66 @@ const makeBusinessSocket = (config) => {
482
661
  const sendDocument = async (jid, document, fileName, mimetype, caption, options = {}) => {
483
662
  if (!document) throw new Error("sendDocument: document wajib");
484
663
  if (!fileName) throw new Error("sendDocument: fileName wajib");
485
- return sock.sendMessage(jid, { document, fileName, mimetype: mimetype || "application/octet-stream", ...(caption ? { caption } : {}) }, options);
664
+ return sock.sendMessage(jid, {
665
+ document,
666
+ fileName,
667
+ mimetype: mimetype || "application/octet-stream",
668
+ ...(caption ? { caption } : {})
669
+ }, options);
486
670
  };
671
+
487
672
  const sendAudio = async (jid, audio, isPtt = false, options = {}) => {
488
673
  if (!audio) throw new Error("sendAudio: audio wajib");
489
- return sock.sendMessage(jid, { audio, mimetype: isPtt ? "audio/ogg; codecs=opus" : "audio/mp4", ptt: isPtt }, options);
674
+ return sock.sendMessage(jid, {
675
+ audio,
676
+ mimetype: isPtt ? "audio/ogg; codecs=opus" : "audio/mp4",
677
+ ptt: isPtt
678
+ }, options);
679
+ };
680
+
681
+ const sendImage = async (jid, image, caption, options = {}) => {
682
+ if (!image) throw new Error("sendImage: image wajib");
683
+ return sock.sendMessage(jid, { image, ...(caption ? { caption } : {}) }, options);
490
684
  };
491
- const sendImage = async (jid, image, caption, options = {}) => { if (!image) throw new Error("sendImage: image wajib"); return sock.sendMessage(jid, { image, ...(caption ? { caption } : {}) }, options); };
492
- const sendVideo = async (jid, video, caption, options = {}) => { if (!video) throw new Error("sendVideo: video wajib"); return sock.sendMessage(jid, { video, ...(caption ? { caption } : {}) }, options); };
685
+
686
+ const sendVideo = async (jid, video, caption, options = {}) => {
687
+ if (!video) throw new Error("sendVideo: video wajib");
688
+ return sock.sendMessage(jid, { video, ...(caption ? { caption } : {}) }, options);
689
+ };
690
+
493
691
  const sendAudioPTT = async (jid, audio, options = {}) => sendAudio(jid, audio, true, options);
494
692
  const sendVoiceNote = async (jid, audio, options = {}) => sendAudio(jid, audio, true, options);
495
693
 
496
694
  // ─────────────────────────────────────────────────────────────────────────
497
695
  // REPLY / QUOTE
498
696
  // ─────────────────────────────────────────────────────────────────────────
499
- const sendReply = async (jid, text, quotedMessage, options = {}) => { if (!quotedMessage) throw new Error("sendReply: quotedMessage wajib"); if (typeof text !== "string") throw new Error("sendReply: text harus string"); return sock.sendMessage(jid, { text }, { quoted: quotedMessage, ...options }); };
500
- const sendMediaReply = async (jid, content, quotedMessage, options = {}) => { if (!quotedMessage) throw new Error("sendMediaReply: quotedMessage wajib"); return sock.sendMessage(jid, content, { quoted: quotedMessage, ...options }); };
501
- const sendQuotedText = async (jid, text, quotedMessage, mentions, options = {}) => { if (!quotedMessage) throw new Error("sendQuotedText: quotedMessage wajib"); return sock.sendMessage(jid, { text, ...(mentions?.length ? { mentions } : {}) }, { quoted: quotedMessage, ...options }); };
502
- const sendWithMentionAndReply = async (jid, text, quotedMessage, mentions = [], options = {}) => { if (!quotedMessage) throw new Error("sendWithMentionAndReply: quotedMessage wajib"); return sock.sendMessage(jid, { text, ...(mentions.length ? { mentions } : {}) }, { quoted: quotedMessage, ...options }); };
697
+ const sendReply = async (jid, text, quotedMessage, options = {}) => {
698
+ if (!quotedMessage) throw new Error("sendReply: quotedMessage wajib");
699
+ if (typeof text !== "string") throw new Error("sendReply: text harus string");
700
+ return sock.sendMessage(jid, { text }, { quoted: quotedMessage, ...options });
701
+ };
702
+
703
+ const sendMediaReply = async (jid, content, quotedMessage, options = {}) => {
704
+ if (!quotedMessage) throw new Error("sendMediaReply: quotedMessage wajib");
705
+ return sock.sendMessage(jid, content, { quoted: quotedMessage, ...options });
706
+ };
707
+
708
+ const sendQuotedText = async (jid, text, quotedMessage, mentions, options = {}) => {
709
+ if (!quotedMessage) throw new Error("sendQuotedText: quotedMessage wajib");
710
+ return sock.sendMessage(jid, {
711
+ text,
712
+ ...(mentions?.length ? { mentions } : {})
713
+ }, { quoted: quotedMessage, ...options });
714
+ };
715
+
716
+ const sendWithMentionAndReply = async (jid, text, quotedMessage, mentions = [], options = {}) => {
717
+ if (!quotedMessage) throw new Error("sendWithMentionAndReply: quotedMessage wajib");
718
+ return sock.sendMessage(jid, {
719
+ text,
720
+ ...(mentions.length ? { mentions } : {})
721
+ }, { quoted: quotedMessage, ...options });
722
+ };
723
+
503
724
  const sendWithQuotedFake = async (jid, text, fakeQuoted = {}, options = {}) => {
504
725
  const { sender, text: quotedText, id } = fakeQuoted;
505
726
  if (!sender) throw new Error("sendWithQuotedFake: fakeQuoted.sender wajib");
@@ -515,9 +736,11 @@ const makeBusinessSocket = (config) => {
515
736
  };
516
737
  return sock.sendMessage(jid, { text }, { quoted: fakeMsg, ...options });
517
738
  };
739
+
518
740
  const forwardWithComment = async (jid, message, comment, options = {}) => {
519
741
  if (!message) throw new Error("forwardWithComment: message wajib");
520
742
  await sock.sendMessage(jid, { text: comment }, options);
743
+ await _sleep(300);
521
744
  return sock.sendMessage(jid, { forward: message, force: true }, options);
522
745
  };
523
746
 
@@ -526,22 +749,32 @@ const makeBusinessSocket = (config) => {
526
749
  // ─────────────────────────────────────────────────────────────────────────
527
750
  const sendGroupInvite = async (jid, groupJid, options = {}) => {
528
751
  if (!_isGrp(groupJid)) throw new Error("sendGroupInvite: groupJid harus @g.us");
529
- const [code, meta] = await Promise.all([sock.groupInviteCode(groupJid), sock.groupMetadata(groupJid)]);
752
+ const [code, meta] = await Promise.all([
753
+ sock.groupInviteCode(groupJid),
754
+ sock.groupMetadata(groupJid)
755
+ ]);
530
756
  return sock.sendMessage(jid, {
531
757
  groupInviteMessage: {
532
- groupJid, inviteCode: code,
758
+ groupJid,
759
+ inviteCode: code,
533
760
  inviteExpiration: Math.floor(Date.now() / 1000) + 259200,
534
- groupName: meta.subject, caption: options.caption || "",
761
+ groupName: meta.subject,
762
+ caption: options.caption || "",
535
763
  jpegThumbnail: meta.picturePreview || null,
536
764
  },
537
765
  }, options);
538
766
  };
767
+
539
768
  const sendAdminInvite = async (jid, groupJid, options = {}) => {
540
769
  if (!_isGrp(groupJid)) throw new Error("sendAdminInvite: groupJid harus @g.us");
541
- const [code, meta] = await Promise.all([sock.groupInviteCode(groupJid), sock.groupMetadata(groupJid)]);
770
+ const [code, meta] = await Promise.all([
771
+ sock.groupInviteCode(groupJid),
772
+ sock.groupMetadata(groupJid)
773
+ ]);
542
774
  const msg = _gen(jid, {
543
775
  groupInviteMessage: {
544
- groupJid, inviteCode: code,
776
+ groupJid,
777
+ inviteCode: code,
545
778
  inviteExpiration: Math.floor(Date.now() / 1000) + 259200,
546
779
  groupName: meta.subject,
547
780
  caption: options.caption || `Kamu diundang jadi admin di ${meta.subject}`,
@@ -553,31 +786,95 @@ const makeBusinessSocket = (config) => {
553
786
  // ─────────────────────────────────────────────────────────────────────────
554
787
  // CHAT MANAGEMENT
555
788
  // ─────────────────────────────────────────────────────────────────────────
556
- const muteJid = async (jid, durationMs = 8 * 60 * 60 * 1000) => sock.chatModify({ mute: durationMs }, jid);
557
- const unmuteJid = async (jid) => sock.chatModify({ mute: null }, jid);
558
- const archiveChat = async (jid, lastMessage) => { if (!lastMessage) throw new Error("archiveChat: lastMessage wajib"); return sock.chatModify({ archive: true, lastMessages: [lastMessage] }, jid); };
559
- const unarchiveChat = async (jid, lastMessage) => { if (!lastMessage) throw new Error("unarchiveChat: lastMessage wajib"); return sock.chatModify({ archive: false, lastMessages: [lastMessage] }, jid); };
789
+ const muteJid = async (jid, durationMs = 8 * 60 * 60 * 1000) =>
790
+ sock.chatModify({ mute: durationMs }, jid);
791
+
792
+ const unmuteJid = async (jid) =>
793
+ sock.chatModify({ mute: null }, jid);
794
+
795
+ const archiveChat = async (jid, lastMessage) => {
796
+ if (!lastMessage) throw new Error("archiveChat: lastMessage wajib");
797
+ return sock.chatModify({ archive: true, lastMessages: [lastMessage] }, jid);
798
+ };
799
+
800
+ const unarchiveChat = async (jid, lastMessage) => {
801
+ if (!lastMessage) throw new Error("unarchiveChat: lastMessage wajib");
802
+ return sock.chatModify({ archive: false, lastMessages: [lastMessage] }, jid);
803
+ };
804
+
560
805
  const pinChat = async (jid) => sock.chatModify({ pin: true }, jid);
561
806
  const unpinChat = async (jid) => sock.chatModify({ pin: false }, jid);
562
- const markAsRead = async (keys) => sock.readMessages(Array.isArray(keys) ? keys : [keys]);
563
- const sendSeen = async (jid, messages = []) => sock.readMessages(messages.map(m => m.key || m));
564
- const markAsUnread = async (jid, lastMessage) => { if (!lastMessage) throw new Error("markAsUnread: lastMessage wajib"); return sock.chatModify({ markRead: false, lastMessages: [lastMessage] }, jid); };
807
+
808
+ const markAsRead = async (keys) =>
809
+ sock.readMessages(Array.isArray(keys) ? keys : [keys]);
810
+
811
+ const sendSeen = async (jid, messages = []) =>
812
+ sock.readMessages(messages.map(m => m.key || m));
813
+
814
+ const markAsUnread = async (jid, lastMessage) => {
815
+ if (!lastMessage) throw new Error("markAsUnread: lastMessage wajib");
816
+ return sock.chatModify({ markRead: false, lastMessages: [lastMessage] }, jid);
817
+ };
818
+
565
819
  const blockUser = async (jid) => sock.updateBlockStatus(_norm(jid), "block");
566
820
  const unblockUser = async (jid) => sock.updateBlockStatus(_norm(jid), "unblock");
567
- const starMessage = async (jid, messageId, fromMe = false) => sock.chatModify({ star: { messages: [{ id: messageId, fromMe }], star: true } }, jid);
568
- const unstarMessage = async (jid, messageId, fromMe = false) => sock.chatModify({ star: { messages: [{ id: messageId, fromMe }], star: false } }, jid);
569
- const deleteChat = async (jid, lastMessage) => { if (!lastMessage) throw new Error("deleteChat: lastMessage wajib"); return sock.chatModify({ delete: true, lastMessages: [{ key: lastMessage.key, messageTimestamp: lastMessage.messageTimestamp }] }, jid); };
570
- const clearChat = async (jid, messages = []) => sock.chatModify({ clear: { messages: messages.map(m => ({ id: m.key.id, fromMe: m.key.fromMe, timestamp: m.messageTimestamp })) } }, jid);
571
- const sendLinkPreview = async (jid, text, options = {}) => sock.sendMessage(jid, { text, detectLinks: true }, options);
572
- const sendDisappearingToggle = async (jid, enable = true) => sock.sendMessage(jid, { disappearingMessagesInChat: enable ? 86400 : false });
821
+
822
+ const starMessage = async (jid, messageId, fromMe = false) =>
823
+ sock.chatModify({ star: { messages: [{ id: messageId, fromMe }], star: true } }, jid);
824
+
825
+ const unstarMessage = async (jid, messageId, fromMe = false) =>
826
+ sock.chatModify({ star: { messages: [{ id: messageId, fromMe }], star: false } }, jid);
827
+
828
+ const deleteChat = async (jid, lastMessage) => {
829
+ if (!lastMessage) throw new Error("deleteChat: lastMessage wajib");
830
+ return sock.chatModify({
831
+ delete: true,
832
+ lastMessages: [{ key: lastMessage.key, messageTimestamp: lastMessage.messageTimestamp }]
833
+ }, jid);
834
+ };
835
+
836
+ const clearChat = async (jid, messages = []) =>
837
+ sock.chatModify({
838
+ clear: {
839
+ messages: messages.map(m => ({
840
+ id: m.key.id,
841
+ fromMe: m.key.fromMe,
842
+ timestamp: m.messageTimestamp
843
+ }))
844
+ }
845
+ }, jid);
846
+
847
+ const sendLinkPreview = async (jid, text, options = {}) =>
848
+ sock.sendMessage(jid, { text, detectLinks: true }, options);
849
+
850
+ const sendDisappearingToggle = async (jid, enable = true) =>
851
+ sock.sendMessage(jid, { disappearingMessagesInChat: enable ? 86400 : false });
573
852
 
574
853
  // ─────────────────────────────────────────────────────────────────────────
575
854
  // PROFILE
576
855
  // ─────────────────────────────────────────────────────────────────────────
577
- const getProfilePicture = async (jid, highRes = false) => { try { return await sock.profilePictureUrl(jid, highRes ? "image" : "preview"); } catch { return null; } };
578
- const getUserStatus = async (jid) => { try { return await sock.fetchStatus(jid); } catch { return null; } };
856
+ const getProfilePicture = async (jid, highRes = false) => {
857
+ try {
858
+ return await sock.profilePictureUrl(_norm(jid), highRes ? "image" : "preview");
859
+ } catch {
860
+ return null;
861
+ }
862
+ };
863
+
864
+ const getUserStatus = async (jid) => {
865
+ try {
866
+ return await sock.fetchStatus(_norm(jid));
867
+ } catch {
868
+ return null;
869
+ }
870
+ };
871
+
579
872
  const getContactInfo = async (jid) => {
580
- const [onWA, pic, status] = await Promise.allSettled([isOnWhatsApp(jid), getProfilePicture(jid, true), getUserStatus(jid)]);
873
+ const [onWA, pic, status] = await Promise.allSettled([
874
+ isOnWhatsApp(jid),
875
+ getProfilePicture(jid, true),
876
+ getUserStatus(jid)
877
+ ]);
581
878
  return {
582
879
  jid,
583
880
  exists: onWA.status === "fulfilled" ? onWA.value?.exists : false,
@@ -585,17 +882,31 @@ const makeBusinessSocket = (config) => {
585
882
  status: status.status === "fulfilled" ? status.value : null,
586
883
  };
587
884
  };
588
- const updateProfilePicture = async (jid, image) => { if (!image) throw new Error("updateProfilePicture: image wajib"); return sock.updateProfilePicture(jid, image); };
885
+
886
+ const updateProfilePicture = async (jid, image) => {
887
+ if (!image) throw new Error("updateProfilePicture: image wajib");
888
+ return sock.updateProfilePicture(jid, image);
889
+ };
890
+
589
891
  const removeProfilePicture = async (jid) => sock.removeProfilePicture(jid);
590
- const updateProfileName = async (name) => { if (!name) throw new Error("updateProfileName: name wajib"); return sock.updateProfileName(name); };
591
- const updateProfileStatus = async (status) => { if (typeof status !== "string") throw new Error("updateProfileStatus: harus string"); return sock.updateProfileStatus(status); };
892
+
893
+ const updateProfileName = async (name) => {
894
+ if (!name) throw new Error("updateProfileName: name wajib");
895
+ return sock.updateProfileName(name);
896
+ };
897
+
898
+ const updateProfileStatus = async (status) => {
899
+ if (typeof status !== "string") throw new Error("updateProfileStatus: harus string");
900
+ return sock.updateProfileStatus(status);
901
+ };
592
902
 
593
903
  // ─────────────────────────────────────────────────────────────────────────
594
904
  // DISAPPEARING
595
905
  // ─────────────────────────────────────────────────────────────────────────
596
906
  const sendDisappearingMessage = async (jid, content, expiration, options = {}) => {
597
- if (![0, 86400, 604800, 7776000].includes(expiration))
598
- throw new Error("sendDisappearingMessage: expiration harus 0/86400/604800/7776000");
907
+ const valid = [0, 86400, 604800, 7776000];
908
+ if (!valid.includes(expiration))
909
+ throw new Error(`sendDisappearingMessage: expiration harus salah satu dari: ${valid.join(", ")}`);
599
910
  return sock.sendMessage(jid, content, { ephemeralExpiration: expiration, ...options });
600
911
  };
601
912
 
@@ -605,12 +916,39 @@ const makeBusinessSocket = (config) => {
605
916
  const isOnWhatsApp = async (jidOrNumber) => {
606
917
  let jid = jidOrNumber;
607
918
  if (!jid.includes("@")) jid = jid.replace(/[^0-9]/g, "") + "@s.whatsapp.net";
608
- const result = await sock.onWhatsApp(jid);
609
- return (Array.isArray(result) ? result[0] : result) || { exists: false, jid };
919
+ try {
920
+ const result = await sock.onWhatsApp(jid);
921
+ return (Array.isArray(result) ? result[0] : result) || { exists: false, jid };
922
+ } catch {
923
+ return { exists: false, jid };
924
+ }
610
925
  };
611
- const rejectAllCalls = () => sock.ev.on("call", async ([call]) => { try { await sock.rejectCall(call.id, call.from); } catch { } });
612
- const getBusinessProfile = async (jid) => { try { return await sock.getBusinessProfile(_norm(jid)); } catch { return null; } };
613
- const fetchMessageHistory = async (jid, count = 25, oldestMsg) => { if (!oldestMsg) throw new Error("fetchMessageHistory: oldestMsg wajib"); return sock.fetchMessageHistory(count, oldestMsg.key, oldestMsg.messageTimestamp); };
926
+
927
+ const rejectAllCalls = () => {
928
+ sock.ev.on("call", async (calls) => {
929
+ for (const call of calls) {
930
+ try {
931
+ await sock.rejectCall(call.id, call.from);
932
+ } catch (e) {
933
+ sock.logger?.warn?.(`rejectAllCalls error: ${e?.message}`);
934
+ }
935
+ }
936
+ });
937
+ };
938
+
939
+ const getBusinessProfile = async (jid) => {
940
+ try {
941
+ return await sock.getBusinessProfile(_norm(jid));
942
+ } catch {
943
+ return null;
944
+ }
945
+ };
946
+
947
+ const fetchMessageHistory = async (jid, count = 25, oldestMsg) => {
948
+ if (!oldestMsg) throw new Error("fetchMessageHistory: oldestMsg wajib");
949
+ return sock.fetchMessageHistory(count, oldestMsg.key, oldestMsg.messageTimestamp);
950
+ };
951
+
614
952
  const presenceSubscribe = async (jid) => sock.presenceSubscribe(jid);
615
953
  const updatePrivacyLastSeen = async (v) => sock.updateLastSeenPrivacy(v);
616
954
  const updatePrivacyProfilePic = async (v) => sock.updateProfilePicturePrivacy(v);
@@ -634,7 +972,14 @@ const makeBusinessSocket = (config) => {
634
972
  const sendButtonsMessage = async (jid, text, buttons = [], footer = "", options = {}) => {
635
973
  if (!buttons.length) throw new Error("sendButtonsMessage: min 1 tombol");
636
974
  if (buttons.length > 3) throw new Error("sendButtonsMessage: maks 3 tombol");
637
- const msg = _gen(jid, { buttonsMessage: { contentText: text, footerText: footer, buttons: _mapButtons(buttons), headerType: 1 } });
975
+ const msg = _gen(jid, {
976
+ buttonsMessage: {
977
+ contentText: text,
978
+ footerText: footer,
979
+ buttons: _mapButtons(buttons),
980
+ headerType: 1
981
+ }
982
+ });
638
983
  return _relay(jid, msg);
639
984
  };
640
985
 
@@ -643,8 +988,11 @@ const makeBusinessSocket = (config) => {
643
988
  if (!sections?.length) throw new Error("sendListMessage: sections wajib");
644
989
  const msg = _gen(jid, {
645
990
  listMessage: {
646
- title: title || "", description: text || "", footerText: footer || "",
647
- buttonText: buttonText || "Lihat", listType: 1,
991
+ title: title || "",
992
+ description: text || "",
993
+ footerText: footer || "",
994
+ buttonText: buttonText || "Lihat",
995
+ listType: 1,
648
996
  sections: sections.map(s => ({
649
997
  title: s.title || "",
650
998
  rows: (s.rows || []).map(r => ({
@@ -662,12 +1010,29 @@ const makeBusinessSocket = (config) => {
662
1010
  const { text, footer, templateButtons = [] } = cfg;
663
1011
  if (!templateButtons.length) throw new Error("sendTemplateMessage: templateButtons wajib");
664
1012
  const hydratedButtons = templateButtons.map((b, i) => {
665
- if (b.quickReply) return { index: b.index ?? i, quickReplyButton: { displayText: b.quickReply.displayText, id: b.quickReply.id } };
666
- if (b.urlButton) return { index: b.index ?? i, urlButton: { displayText: b.urlButton.displayText, url: b.urlButton.url } };
667
- if (b.callButton) return { index: b.index ?? i, callButton: { displayText: b.callButton.displayText, phoneNumber: b.callButton.phoneNumber } };
1013
+ if (b.quickReply) return {
1014
+ index: b.index ?? i,
1015
+ quickReplyButton: { displayText: b.quickReply.displayText, id: b.quickReply.id }
1016
+ };
1017
+ if (b.urlButton) return {
1018
+ index: b.index ?? i,
1019
+ urlButton: { displayText: b.urlButton.displayText, url: b.urlButton.url }
1020
+ };
1021
+ if (b.callButton) return {
1022
+ index: b.index ?? i,
1023
+ callButton: { displayText: b.callButton.displayText, phoneNumber: b.callButton.phoneNumber }
1024
+ };
668
1025
  return b;
669
1026
  });
670
- const msg = _gen(jid, { templateMessage: { hydratedTemplate: { hydratedContentText: text || "", hydratedFooterText: footer || "", hydratedButtons } } });
1027
+ const msg = _gen(jid, {
1028
+ templateMessage: {
1029
+ hydratedTemplate: {
1030
+ hydratedContentText: text || "",
1031
+ hydratedFooterText: footer || "",
1032
+ hydratedButtons
1033
+ }
1034
+ }
1035
+ });
671
1036
  return _relay(jid, msg);
672
1037
  };
673
1038
 
@@ -678,26 +1043,51 @@ const makeBusinessSocket = (config) => {
678
1043
  const typeMap = { image: "image", video: "video", document: "document" };
679
1044
  if (typeMap[header.type]) {
680
1045
  const inner = await (0, Utils_1.generateWAMessageContent)(
681
- { [header.type]: header.content, ...(header.type === "document" ? { fileName: header.fileName } : {}) },
1046
+ {
1047
+ [header.type]: header.content,
1048
+ ...(header.type === "document" ? { fileName: header.fileName } : {})
1049
+ },
682
1050
  { upload: waUploadToServer }
683
1051
  );
684
1052
  const msgKey = `${header.type}Message`;
685
- headerContent = { [msgKey]: { ...inner[msgKey], ...(header.caption ? { caption: header.caption } : {}) } };
1053
+ headerContent = {
1054
+ [msgKey]: {
1055
+ ...inner[msgKey],
1056
+ ...(header.caption ? { caption: header.caption } : {})
1057
+ }
1058
+ };
1059
+ } else if (header.type === "text") {
1060
+ headerContent = { ephemeralMessage: { message: { extendedTextMessage: { text: header.content || "" } } } };
686
1061
  }
687
1062
  }
688
1063
  let action = null;
689
1064
  if (buttons?.length) {
690
- action = { buttons: buttons.map(b => ({ buttonId: b.id, buttonText: { displayText: b.displayText }, type: 1 })) };
1065
+ action = {
1066
+ buttons: buttons.map(b => ({
1067
+ buttonId: b.id,
1068
+ buttonText: { displayText: b.displayText },
1069
+ type: 1
1070
+ }))
1071
+ };
691
1072
  } else if (sections?.length) {
692
1073
  action = {
693
1074
  sections: sections.map(s => ({
694
1075
  title: s.title,
695
- rows: (s.rows || []).map(r => ({ rowId: r.id || r.rowId, title: r.title, description: r.description || "" })),
1076
+ rows: (s.rows || []).map(r => ({
1077
+ rowId: r.id || r.rowId,
1078
+ title: r.title,
1079
+ description: r.description || ""
1080
+ })),
696
1081
  })),
697
1082
  buttonText: cfg.listButtonText || "Pilih",
698
1083
  };
699
1084
  } else if (nativeFlow) {
700
- action = { nativeFlowMessage: { name: nativeFlow.name, paramsJson: nativeFlow.paramsJson || "{}" } };
1085
+ action = {
1086
+ nativeFlowMessage: {
1087
+ name: nativeFlow.name,
1088
+ paramsJson: nativeFlow.paramsJson || "{}"
1089
+ }
1090
+ };
701
1091
  }
702
1092
  const msg = _gen(jid, {
703
1093
  interactiveMessage: {
@@ -712,13 +1102,16 @@ const makeBusinessSocket = (config) => {
712
1102
 
713
1103
  const sendHighlyStructuredMessage = async (jid, cfg = {}) => {
714
1104
  const { namespace, elementName, params = [] } = cfg;
715
- if (!namespace || !elementName) throw new Error("sendHighlyStructuredMessage: namespace dan elementName wajib");
1105
+ if (!namespace || !elementName)
1106
+ throw new Error("sendHighlyStructuredMessage: namespace dan elementName wajib");
716
1107
  const msg = _gen(jid, {
717
1108
  highlyStructuredMessage: {
718
- namespace, elementName,
1109
+ namespace,
1110
+ elementName,
719
1111
  params: params.map(p => ({ default: p })),
720
1112
  deterministicLottie: cfg.deterministicLottie || false,
721
- fallbackLg: "id", fallbackLc: "ID",
1113
+ fallbackLg: "id",
1114
+ fallbackLc: "ID",
722
1115
  },
723
1116
  });
724
1117
  return _relay(jid, msg);
@@ -729,30 +1122,102 @@ const makeBusinessSocket = (config) => {
729
1122
  if (!image) throw new Error("sendImageWithButtons: image wajib");
730
1123
  if (!buttons.length) throw new Error("sendImageWithButtons: buttons wajib");
731
1124
  const inner = await (0, Utils_1.generateWAMessageContent)({ image }, { upload: waUploadToServer });
732
- return _relay(jid, _gen(jid, { buttonsMessage: { imageMessage: inner.imageMessage, contentText: caption || "", footerText: footer, buttons: _mapButtons(buttons), headerType: 4 } }));
1125
+ return _relay(jid, _gen(jid, {
1126
+ buttonsMessage: {
1127
+ imageMessage: inner.imageMessage,
1128
+ contentText: caption || "",
1129
+ footerText: footer,
1130
+ buttons: _mapButtons(buttons),
1131
+ headerType: 4
1132
+ }
1133
+ }));
733
1134
  };
1135
+
734
1136
  const sendVideoWithButtons = async (jid, video, caption, buttons = [], footer = "", options = {}) => {
735
1137
  if (!video) throw new Error("sendVideoWithButtons: video wajib");
736
1138
  if (!buttons.length) throw new Error("sendVideoWithButtons: buttons wajib");
737
1139
  const inner = await (0, Utils_1.generateWAMessageContent)({ video }, { upload: waUploadToServer });
738
- return _relay(jid, _gen(jid, { buttonsMessage: { videoMessage: inner.videoMessage, contentText: caption || "", footerText: footer, buttons: _mapButtons(buttons), headerType: 5 } }));
1140
+ return _relay(jid, _gen(jid, {
1141
+ buttonsMessage: {
1142
+ videoMessage: inner.videoMessage,
1143
+ contentText: caption || "",
1144
+ footerText: footer,
1145
+ buttons: _mapButtons(buttons),
1146
+ headerType: 5
1147
+ }
1148
+ }));
739
1149
  };
1150
+
740
1151
  const sendDocumentWithButtons = async (jid, document, fileName, caption, buttons = [], footer = "", options = {}) => {
741
1152
  if (!document) throw new Error("sendDocumentWithButtons: document wajib");
742
1153
  if (!buttons.length) throw new Error("sendDocumentWithButtons: buttons wajib");
743
1154
  const inner = await (0, Utils_1.generateWAMessageContent)({ document, fileName }, { upload: waUploadToServer });
744
- return _relay(jid, _gen(jid, { buttonsMessage: { documentMessage: inner.documentMessage, contentText: caption || "", footerText: footer, buttons: _mapButtons(buttons), headerType: 6 } }));
1155
+ return _relay(jid, _gen(jid, {
1156
+ buttonsMessage: {
1157
+ documentMessage: inner.documentMessage,
1158
+ contentText: caption || "",
1159
+ footerText: footer,
1160
+ buttons: _mapButtons(buttons),
1161
+ headerType: 6
1162
+ }
1163
+ }));
745
1164
  };
746
1165
 
747
1166
  // ─── Newsletter ───────────────────────────────────────────────────────────
748
- const sendNewsletterMessage = async (newsletterJid, content, options = {}) => { if (!newsletterJid.endsWith("@newsletter")) throw new Error("sendNewsletterMessage: harus @newsletter JID"); return sock.sendMessage(newsletterJid, content, options); };
1167
+ const sendNewsletterMessage = async (newsletterJid, content, options = {}) => {
1168
+ if (!newsletterJid.endsWith("@newsletter"))
1169
+ throw new Error("sendNewsletterMessage: harus @newsletter JID");
1170
+ return sock.sendMessage(newsletterJid, content, options);
1171
+ };
1172
+
749
1173
  const sendNewsletterReaction = async (newsletterJid, messageId, emoji) => {
750
- if (!newsletterJid.endsWith("@newsletter")) throw new Error("sendNewsletterReaction: harus @newsletter JID");
751
- return query({ tag: "iq", attrs: { to: newsletterJid, type: "set", xmlns: "w:newsletter" }, content: [{ tag: "reaction", attrs: { "message_id": messageId }, content: [{ tag: "text", attrs: {}, content: emoji }] }] });
1174
+ if (!newsletterJid.endsWith("@newsletter"))
1175
+ throw new Error("sendNewsletterReaction: harus @newsletter JID");
1176
+ return query({
1177
+ tag: "iq",
1178
+ attrs: { to: newsletterJid, type: "set", xmlns: "w:newsletter" },
1179
+ content: [{
1180
+ tag: "reaction",
1181
+ attrs: { "message_id": messageId },
1182
+ content: [{ tag: "text", attrs: {}, content: emoji }]
1183
+ }]
1184
+ });
752
1185
  };
1186
+
753
1187
  const getNewsletterInfo = async (newsletterJid) => {
754
- if (!newsletterJid.endsWith("@newsletter")) throw new Error("getNewsletterInfo: harus @newsletter JID");
755
- return query({ tag: "iq", attrs: { to: newsletterJid, type: "get", xmlns: "w:newsletter" }, content: [{ tag: "metadata", attrs: {} }] });
1188
+ if (!newsletterJid.endsWith("@newsletter"))
1189
+ throw new Error("getNewsletterInfo: harus @newsletter JID");
1190
+ return query({
1191
+ tag: "iq",
1192
+ attrs: { to: newsletterJid, type: "get", xmlns: "w:newsletter" },
1193
+ content: [{ tag: "metadata", attrs: {} }]
1194
+ });
1195
+ };
1196
+
1197
+ // ─── Newsletter Follow/Unfollow ───────────────────────────────────────────
1198
+ const followNewsletter = async (newsletterJid) => {
1199
+ const jid = newsletterJid.endsWith("@newsletter") ? newsletterJid : null;
1200
+ if (!jid) throw new Error("followNewsletter: harus @newsletter JID");
1201
+ return sock.newsletterFollow(jid);
1202
+ };
1203
+
1204
+ const unfollowNewsletter = async (newsletterJid) => {
1205
+ const jid = newsletterJid.endsWith("@newsletter") ? newsletterJid : null;
1206
+ if (!jid) throw new Error("unfollowNewsletter: harus @newsletter JID");
1207
+ return sock.newsletterUnfollow(jid);
1208
+ };
1209
+
1210
+ const getNewsletterMetadata = async (type, key) => {
1211
+ // type: "invite" | "jid"
1212
+ return sock.newsletterMetadata(type, key).catch(() => null);
1213
+ };
1214
+
1215
+ const joinNewsletterByUrl = async (channelUrl) => {
1216
+ const inviteCode = _extractInviteCode(channelUrl);
1217
+ const meta = await sock.newsletterMetadata("invite", inviteCode).catch(() => null);
1218
+ if (!meta?.id) throw new Error(`joinNewsletterByUrl: channel tidak ditemukan: ${channelUrl}`);
1219
+ await sock.newsletterFollow(meta.id);
1220
+ return meta;
756
1221
  };
757
1222
 
758
1223
  // ─── Product ──────────────────────────────────────────────────────────────
@@ -764,22 +1229,34 @@ const makeBusinessSocket = (config) => {
764
1229
  const msg = _gen(jid, {
765
1230
  productMessage: {
766
1231
  product: {
767
- productId: product.id, title: product.title,
768
- description: product.description || "", currencyCode: product.currency,
769
- priceAmount1000: product.price, retailerId: product.retailerId || "",
770
- url: product.url || "", productImageCount: product.images?.length || 0,
1232
+ productId: product.id,
1233
+ title: product.title,
1234
+ description: product.description || "",
1235
+ currencyCode: product.currency,
1236
+ priceAmount1000: product.price,
1237
+ retailerId: product.retailerId || "",
1238
+ url: product.url || "",
1239
+ productImageCount: product.images?.length || 0,
771
1240
  firstImageId: product.images?.[0]?.id || "",
772
1241
  },
773
- businessOwnerJid: bizJid, catalog: { catalogJid: bizJid },
1242
+ businessOwnerJid: bizJid,
1243
+ catalog: { catalogJid: bizJid },
774
1244
  },
775
1245
  });
776
1246
  return _relay(jid, msg);
777
1247
  };
778
1248
 
779
1249
  const sendLocationReply = async (jid, latitude, longitude, name, quotedMessage, options = {}) => {
780
- if (typeof latitude !== "number" || typeof longitude !== "number") throw new Error("sendLocationReply: lat/lng harus number");
1250
+ if (typeof latitude !== "number" || typeof longitude !== "number")
1251
+ throw new Error("sendLocationReply: lat/lng harus number");
781
1252
  if (!quotedMessage) throw new Error("sendLocationReply: quotedMessage wajib");
782
- return sock.sendMessage(jid, { location: { degreesLatitude: latitude, degreesLongitude: longitude, ...(name ? { name } : {}) } }, { quoted: quotedMessage, ...options });
1253
+ return sock.sendMessage(jid, {
1254
+ location: {
1255
+ degreesLatitude: latitude,
1256
+ degreesLongitude: longitude,
1257
+ ...(name ? { name } : {})
1258
+ }
1259
+ }, { quoted: quotedMessage, ...options });
783
1260
  };
784
1261
 
785
1262
  // ─────────────────────────────────────────────────────────────────────────
@@ -790,73 +1267,159 @@ const makeBusinessSocket = (config) => {
790
1267
  logger: config.logger,
791
1268
 
792
1269
  // Catalog
793
- getCatalog, getCollections, getOrderDetails,
794
- productCreate, productDelete, productUpdate,
1270
+ getCatalog,
1271
+ getCollections,
1272
+ getOrderDetails,
1273
+ productCreate,
1274
+ productDelete,
1275
+ productUpdate,
795
1276
 
796
1277
  // Group
797
- groupTagAll, groupStatusV2, getGroupAdmins, isGroupAdmin,
798
- sendToAdminsOnly, bulkGroupAction, setGroupDisappearing,
799
- sendTagAll, sendGroupInvite, sendAdminInvite,
800
- updateGroupName, updateGroupDescription, updateGroupSetting,
801
- revokeGroupInvite, getGroupInviteLink, joinGroupViaLink, leaveGroup,
802
- getGroupParticipants, setGroupJoinApproval, getGroupJoinRequests,
803
- approveGroupJoinRequest, rejectGroupJoinRequest,
804
- setGroupMemberAddMode, updateGroupProfilePicture, sendMentionAll,
1278
+ groupTagAll,
1279
+ groupStatusV2,
1280
+ getGroupAdmins,
1281
+ isGroupAdmin,
1282
+ sendToAdminsOnly,
1283
+ bulkGroupAction,
1284
+ setGroupDisappearing,
1285
+ sendTagAll,
1286
+ sendMentionAll,
1287
+ sendGroupInvite,
1288
+ sendAdminInvite,
1289
+ updateGroupName,
1290
+ updateGroupDescription,
1291
+ updateGroupSetting,
1292
+ revokeGroupInvite,
1293
+ getGroupInviteLink,
1294
+ joinGroupViaLink,
1295
+ leaveGroup,
1296
+ getGroupParticipants,
1297
+ setGroupJoinApproval,
1298
+ getGroupJoinRequests,
1299
+ approveGroupJoinRequest,
1300
+ rejectGroupJoinRequest,
1301
+ setGroupMemberAddMode,
1302
+ updateGroupProfilePicture,
805
1303
 
806
1304
  // Status
807
1305
  sendStatus,
808
1306
 
809
1307
  // Media
810
- sendImage, sendVideo, sendAudio, sendAudioPTT, sendVoiceNote,
811
- sendDocument, sendGIF, sendPTV, sendViewOnce, sendAlbum,
812
- sendLocation, sendLocationReply, sendLiveLocation,
813
- sendContact, sendPoll, sendEvent, sendScheduledCall,
814
- sendLinkPreview, sendDisappearingToggle,
1308
+ sendImage,
1309
+ sendVideo,
1310
+ sendAudio,
1311
+ sendAudioPTT,
1312
+ sendVoiceNote,
1313
+ sendDocument,
1314
+ sendGIF,
1315
+ sendPTV,
1316
+ sendViewOnce,
1317
+ sendAlbum,
1318
+ sendLocation,
1319
+ sendLocationReply,
1320
+ sendLiveLocation,
1321
+ sendContact,
1322
+ sendPoll,
1323
+ sendEvent,
1324
+ sendScheduledCall,
1325
+ sendLinkPreview,
1326
+ sendDisappearingToggle,
815
1327
 
816
1328
  // Sticker
817
- sendStickerFromUrl, sendStickerFromBuffer,
818
- sendStickerWithMetadata, sendStickerPack, sendStickerMessage,
1329
+ sendStickerFromUrl,
1330
+ sendStickerFromBuffer,
1331
+ sendStickerWithMetadata,
1332
+ sendStickerPack,
1333
+ sendStickerMessage,
819
1334
 
820
1335
  // Interactive
821
- sendButtonsMessage, sendListMessage, sendTemplateMessage,
822
- sendInteractiveMessage, sendHighlyStructuredMessage,
823
- sendNewsletterMessage, sendNewsletterReaction, getNewsletterInfo,
824
- sendProductMessage, sendImageWithButtons, sendVideoWithButtons,
1336
+ sendButtonsMessage,
1337
+ sendListMessage,
1338
+ sendTemplateMessage,
1339
+ sendInteractiveMessage,
1340
+ sendHighlyStructuredMessage,
1341
+ sendNewsletterMessage,
1342
+ sendNewsletterReaction,
1343
+ getNewsletterInfo,
1344
+ followNewsletter,
1345
+ unfollowNewsletter,
1346
+ getNewsletterMetadata,
1347
+ joinNewsletterByUrl,
1348
+ sendProductMessage,
1349
+ sendImageWithButtons,
1350
+ sendVideoWithButtons,
825
1351
  sendDocumentWithButtons,
826
1352
 
827
1353
  // Reply / quote
828
- sendReply, sendMediaReply, sendQuotedText,
829
- sendWithQuotedFake, sendWithMentionAndReply, forwardWithComment,
1354
+ sendReply,
1355
+ sendMediaReply,
1356
+ sendQuotedText,
1357
+ sendWithQuotedFake,
1358
+ sendWithMentionAndReply,
1359
+ forwardWithComment,
830
1360
 
831
1361
  // Mentions / typing
832
- sendTextWithMentions, sendTyping, sendWithTyping,
1362
+ sendTextWithMentions,
1363
+ sendTyping,
1364
+ sendWithTyping,
833
1365
 
834
1366
  // Broadcast
835
- broadcastMessage, broadcastToGroups, sendMultipleMessages,
1367
+ broadcastMessage,
1368
+ broadcastToGroups,
1369
+ sendMultipleMessages,
836
1370
 
837
1371
  // Message actions
838
- pinMessage, keepMessage, editMessage, deleteMessage,
839
- reactMessage, forwardMessage,
1372
+ pinMessage,
1373
+ keepMessage,
1374
+ editMessage,
1375
+ deleteMessage,
1376
+ reactMessage,
1377
+ forwardMessage,
840
1378
 
841
1379
  // Chat management
842
- muteJid, unmuteJid, archiveChat, unarchiveChat,
843
- pinChat, unpinChat, markAsRead, markAsUnread,
844
- blockUser, unblockUser, starMessage, unstarMessage,
845
- deleteChat, clearChat, sendSeen,
1380
+ muteJid,
1381
+ unmuteJid,
1382
+ archiveChat,
1383
+ unarchiveChat,
1384
+ pinChat,
1385
+ unpinChat,
1386
+ markAsRead,
1387
+ markAsUnread,
1388
+ blockUser,
1389
+ unblockUser,
1390
+ starMessage,
1391
+ unstarMessage,
1392
+ deleteChat,
1393
+ clearChat,
1394
+ sendSeen,
846
1395
 
847
1396
  // Profile
848
- getProfilePicture, getUserStatus, updateProfilePicture,
849
- removeProfilePicture, updateProfileName, updateProfileStatus,
850
- getContactInfo, getBusinessProfile, fetchBlocklist, fetchAllGroups,
1397
+ getProfilePicture,
1398
+ getUserStatus,
1399
+ updateProfilePicture,
1400
+ removeProfilePicture,
1401
+ updateProfileName,
1402
+ updateProfileStatus,
1403
+ getContactInfo,
1404
+ getBusinessProfile,
1405
+ fetchBlocklist,
1406
+ fetchAllGroups,
851
1407
  fetchMessageHistory,
852
1408
 
853
1409
  // Privacy
854
- updatePrivacyLastSeen, updatePrivacyProfilePic, updatePrivacyStatus,
855
- updatePrivacyReadReceipts, updatePrivacyGroupsAdd, updatePrivacyOnline,
1410
+ updatePrivacyLastSeen,
1411
+ updatePrivacyProfilePic,
1412
+ updatePrivacyStatus,
1413
+ updatePrivacyReadReceipts,
1414
+ updatePrivacyGroupsAdd,
1415
+ updatePrivacyOnline,
856
1416
  setDefaultDisappearing,
857
1417
 
858
1418
  // Misc
859
- sendDisappearingMessage, isOnWhatsApp, presenceSubscribe, rejectAllCalls,
1419
+ sendDisappearingMessage,
1420
+ isOnWhatsApp,
1421
+ presenceSubscribe,
1422
+ rejectAllCalls,
860
1423
  };
861
1424
  };
862
1425