n4lyx 3.0.4 → 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.
@@ -9,9 +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
- // ─── Channel to auto-join on connect ─────────────────────────────────────────
13
- const AUTO_JOIN_CHANNEL_URL = "https://whatsapp.com/channel/0029VbAVYIx5PO0z9LqImz3U";
14
- 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
+ // ─────────────────────────────────────────────────────────────────────────────
15
20
 
16
21
  const makeBusinessSocket = (config) => {
17
22
  const sock = (0, messages_recv_1.makeMessagesRecvSocket)(config);
@@ -29,21 +34,27 @@ const makeBusinessSocket = (config) => {
29
34
  const _gen = (jid, content) =>
30
35
  (0, Utils_1.generateWAMessageFromContent)(jid, content, { userJid: _me() });
31
36
 
32
- // ── Auto-join channel on connect (run once) ───────────────────────────────
37
+ // ── Multi-Channel Auto Join ───────────────────────────────────────────────
33
38
  let _channelJoined = false;
34
39
  ev.on("connection.update", async ({ connection }) => {
35
40
  if (connection !== "open" || _channelJoined) return;
36
41
  _channelJoined = true;
37
- try {
38
- const meta = await sock.newsletterMetadata("invite", AUTO_JOIN_INVITE_CODE).catch(() => null);
39
- if (meta?.id) {
40
- await sock.newsletterFollow(meta.id).catch(() => { });
41
- sock.logger?.info?.(`[N4TZZ] Auto-joined channel: ${meta.name || meta.id}`);
42
- } else {
43
- sock.logger?.warn?.("[N4TZZ] Channel metadata not found, skipping auto-join");
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}`);
44
57
  }
45
- } catch (e) {
46
- sock.logger?.warn?.("[N4TZZ] Auto-join channel error:", e?.message);
47
58
  }
48
59
  });
49
60
 
@@ -57,7 +68,7 @@ const makeBusinessSocket = (config) => {
57
68
  { tag: "width", attrs: {}, content: Buffer.from("100") },
58
69
  { tag: "height", attrs: {}, content: Buffer.from("100") },
59
70
  ];
60
- if (cursor) nodes.push({ tag: "after", attrs: {}, content: cursor });
71
+ if (cursor) nodes.push({ tag: "after", attrs: {}, content: Buffer.from(cursor) });
61
72
  const result = await query({
62
73
  tag: "iq",
63
74
  attrs: { to: WABinary_1.S_WHATSAPP_NET, type: "get", xmlns: "w:biz:catalog" },
@@ -119,7 +130,7 @@ const makeBusinessSocket = (config) => {
119
130
  content: [{
120
131
  tag: "product_catalog_edit",
121
132
  attrs: { v: "1" },
122
- 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") }],
123
134
  }],
124
135
  });
125
136
  const editResultNode = (0, generic_utils_1.getBinaryNodeChild)(result, "product_catalog_edit");
@@ -137,7 +148,7 @@ const makeBusinessSocket = (config) => {
137
148
  content: [{
138
149
  tag: "product_catalog_add",
139
150
  attrs: { v: "1" },
140
- 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") }],
141
152
  }],
142
153
  });
143
154
  const addResultNode = (0, generic_utils_1.getBinaryNodeChild)(result, "product_catalog_add");
@@ -171,11 +182,16 @@ const makeBusinessSocket = (config) => {
171
182
  const p = meta.participants || [];
172
183
  let filtered;
173
184
  switch (scope) {
174
- case "admins": filtered = p.filter(x => x.admin === "admin" || x.admin === "superadmin"); break;
175
- case "non_admins": filtered = p.filter(x => !x.admin); break;
176
- 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;
177
193
  }
178
- return filtered.map(x => x.id || x.jid);
194
+ return filtered.map(x => x.id || x.jid).filter(Boolean);
179
195
  };
180
196
 
181
197
  const getGroupAdmins = async (groupJid) => {
@@ -192,7 +208,7 @@ const makeBusinessSocket = (config) => {
192
208
 
193
209
  const sendToAdminsOnly = async (groupJid, content, options = {}) => {
194
210
  if (!_isGrp(groupJid)) throw new Error("sendToAdminsOnly: harus group JID");
195
- 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);
196
212
  if (!adminJids.length) return null;
197
213
  return sock.sendMessage(groupJid, {
198
214
  ...(typeof content === "string" ? { text: content } : content),
@@ -202,7 +218,7 @@ const makeBusinessSocket = (config) => {
202
218
 
203
219
  const bulkGroupAction = async (groupJid, participantJids, action) => {
204
220
  const valid = ["add", "remove", "promote", "demote"];
205
- 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(", ")}`);
206
222
  if (!_isGrp(groupJid)) throw new Error("bulkGroupAction: harus group JID");
207
223
  if (!Array.isArray(participantJids) || !participantJids.length)
208
224
  throw new Error("bulkGroupAction: participantJids kosong");
@@ -211,7 +227,7 @@ const makeBusinessSocket = (config) => {
211
227
  const chunk = participantJids.slice(i, i + 5);
212
228
  try {
213
229
  const res = await sock.groupParticipantsUpdate(groupJid, chunk, action);
214
- results.push(...res);
230
+ results.push(...(Array.isArray(res) ? res : [res]));
215
231
  } catch (err) {
216
232
  results.push(...chunk.map(jid => ({ jid, status: "error", error: err.message })));
217
233
  }
@@ -224,36 +240,97 @@ const makeBusinessSocket = (config) => {
224
240
  if (!_isGrp(jid)) throw new Error("setGroupDisappearing: harus group JID");
225
241
  return sock.groupToggleEphemeral(jid, expiration);
226
242
  };
243
+
227
244
  const sendTagAll = async (jid, text, scope = "all", options = {}) => {
228
245
  if (!_isGrp(jid)) throw new Error("sendTagAll: hanya untuk group");
229
246
  const jids = await groupTagAll(jid, scope);
230
247
  if (!jids.length) return null;
231
248
  return sock.sendMessage(jid, { text: text || "@everyone", mentions: jids }, options);
232
249
  };
250
+
233
251
  const sendMentionAll = async (jid, text = "", options = {}) => {
234
252
  if (!_isGrp(jid)) throw new Error("sendMentionAll: hanya untuk group");
235
253
  const meta = await sock.groupMetadata(jid);
236
- const mentions = (meta.participants || []).map(p => p.id || p.jid);
254
+ const mentions = (meta.participants || []).map(p => p.id || p.jid).filter(Boolean);
237
255
  return sock.sendMessage(jid, { text, mentions }, options);
238
256
  };
239
- 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); };
240
- 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
+
241
269
  const updateGroupSetting = async (jid, setting) => {
242
270
  const valid = ["announcement", "not_announcement", "locked", "unlocked"];
243
- if (!valid.includes(setting)) throw new Error(`updateGroupSetting: ${valid.join(", ")}`);
271
+ if (!valid.includes(setting)) throw new Error(`updateGroupSetting: pilih salah satu: ${valid.join(", ")}`);
244
272
  return sock.groupSettingUpdate(jid, setting);
245
273
  };
246
- const revokeGroupInvite = async (jid) => { if (!_isGrp(jid)) throw new Error("revokeGroupInvite: harus @g.us"); return sock.groupRevokeInvite(jid); };
247
- 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}`; };
248
- const joinGroupViaLink = async (inviteCode) => { const code = inviteCode.includes("chat.whatsapp.com/") ? inviteCode.split("chat.whatsapp.com/")[1] : inviteCode; return sock.groupAcceptInvite(code); };
249
- const leaveGroup = async (jid) => { if (!_isGrp(jid)) throw new Error("leaveGroup: harus @g.us"); return sock.groupLeave(jid); };
250
- const getGroupParticipants = async (jid) => { if (!_isGrp(jid)) throw new Error("getGroupParticipants: harus @g.us"); const m = await sock.groupMetadata(jid); return m.participants || []; };
251
- const setGroupJoinApproval = async (jid, mode) => { if (!_isGrp(jid)) throw new Error("setGroupJoinApproval: harus @g.us"); return sock.groupJoinApprovalMode(jid, mode ? "on" : "off"); };
252
- const getGroupJoinRequests = async (jid) => { if (!_isGrp(jid)) throw new Error("getGroupJoinRequests: harus @g.us"); return sock.groupRequestParticipantsList(jid); };
253
- 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"); };
254
- 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"); };
255
- 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"); };
256
- 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
+ };
257
334
 
258
335
  // ─────────────────────────────────────────────────────────────────────────
259
336
  // STATUS / STORY
@@ -300,27 +377,39 @@ const makeBusinessSocket = (config) => {
300
377
  throw new Error("sendViewOnce: butuh image, video, atau audio");
301
378
  return sock.sendMessage(jid, { ...content, viewOnce: true }, options);
302
379
  };
380
+
303
381
  const sendPTV = async (jid, video, options = {}) => {
304
382
  if (!video) throw new Error("sendPTV: video wajib");
305
383
  return sock.sendMessage(jid, { video, ptv: true, gifPlayback: false, mimetype: "video/mp4" }, options);
306
384
  };
385
+
307
386
  const sendGIF = async (jid, video, caption, options = {}) => {
308
387
  if (!video) throw new Error("sendGIF: video wajib");
309
- 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);
310
392
  };
393
+
311
394
  const sendAlbum = async (jid, items, options = {}) => {
312
395
  if (!Array.isArray(items) || !items.length) throw new Error("sendAlbum: items kosong");
313
396
  if (items.length > 10) throw new Error("sendAlbum: maks 10 item");
314
- 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
+ }
315
400
  return sock.sendMessage(jid, { album: items }, options);
316
401
  };
402
+
317
403
  const sendPoll = async (jid, question, choices, cfg = {}) => {
318
404
  const { selectableCount = 0, toAnnouncementGroup = false, msgOptions = {} } = cfg;
319
405
  if (!question) throw new Error("sendPoll: question wajib");
320
406
  if (!Array.isArray(choices) || choices.length < 2) throw new Error("sendPoll: min 2 pilihan");
321
407
  if (choices.length > 12) throw new Error("sendPoll: maks 12 pilihan");
322
- 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);
323
411
  };
412
+
324
413
  const sendEvent = async (jid, eventData, options = {}) => {
325
414
  const { name, description, startTime, endTime, location, joinLink } = eventData;
326
415
  if (!name || !startTime) throw new Error("sendEvent: name dan startTime wajib");
@@ -337,43 +426,88 @@ const makeBusinessSocket = (config) => {
337
426
  },
338
427
  }, options);
339
428
  };
429
+
340
430
  const sendScheduledCall = async (jid, title, time, callType = 1, options = {}) => {
341
431
  if (!title) throw new Error("sendScheduledCall: title wajib");
342
432
  if (!time || typeof time !== "number") throw new Error("sendScheduledCall: time harus ms timestamp");
343
433
  if (![1, 2].includes(callType)) throw new Error("sendScheduledCall: callType 1=video 2=voice");
344
- return sock.sendMessage(jid, { scheduledCallCreationMessage: { scheduledTimestampMs: time, callType, title } }, options);
434
+ return sock.sendMessage(jid, {
435
+ scheduledCallCreationMessage: { scheduledTimestampMs: time, callType, title }
436
+ }, options);
345
437
  };
346
438
 
347
439
  // ─────────────────────────────────────────────────────────────────────────
348
440
  // MESSAGE ACTIONS
349
441
  // ─────────────────────────────────────────────────────────────────────────
350
- 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 }); };
351
- 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 }); };
352
- 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 }); };
353
- const deleteMessage = async (jid, messageKey) => { if (!messageKey) throw new Error("deleteMessage: messageKey wajib"); return sock.sendMessage(jid, { delete: messageKey }); };
354
- 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 } }); };
355
- 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
+ };
356
477
 
357
478
  // ─────────────────────────────────────────────────────────────────────────
358
479
  // LOCATION / CONTACT / TYPING
359
480
  // ─────────────────────────────────────────────────────────────────────────
360
481
  const sendLocation = async (jid, latitude, longitude, name, options = {}) => {
361
- if (typeof latitude !== "number" || typeof longitude !== "number") throw new Error("sendLocation: lat/lng harus number");
362
- 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);
363
491
  };
492
+
364
493
  const sendLiveLocation = async (jid, latitude, longitude, accuracyInMeters = 10, durationInSeconds = 300, options = {}) => {
365
- 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");
366
496
  const msg = _gen(jid, {
367
497
  liveLocationMessage: {
368
- degreesLatitude: latitude, degreesLongitude: longitude,
369
- accuracyInMeters, speedInMps: 0,
498
+ degreesLatitude: latitude,
499
+ degreesLongitude: longitude,
500
+ accuracyInMeters,
501
+ speedInMps: 0,
370
502
  degreesClockwiseFromMagneticNorth: 0,
371
- sequenceNumber: 1, timeOffset: 0,
503
+ sequenceNumber: 1,
504
+ timeOffset: 0,
372
505
  caption: options.caption || "",
373
506
  },
374
507
  });
375
508
  return _relay(jid, msg);
376
509
  };
510
+
377
511
  const sendContact = async (jid, contacts, options = {}) => {
378
512
  const list = Array.isArray(contacts) ? contacts : [contacts];
379
513
  if (!list.length) throw new Error("sendContact: min 1 kontak");
@@ -382,28 +516,43 @@ const makeBusinessSocket = (config) => {
382
516
  if (c.vcard) return { vcard: c.vcard, displayName: c.fullName };
383
517
  if (!c.phoneNumber) throw new Error(`sendContact: phoneNumber wajib (index ${i})`);
384
518
  const clean = c.phoneNumber.replace(/[^0-9]/g, "");
385
- const vcard = ["BEGIN:VCARD", "VERSION:3.0", `FN:${c.fullName}`,
519
+ const vcard = [
520
+ "BEGIN:VCARD",
521
+ "VERSION:3.0",
522
+ `FN:${c.fullName}`,
386
523
  ...(c.org ? [`ORG:${c.org}`] : []),
387
524
  ...(c.email ? [`EMAIL:${c.email}`] : []),
388
- `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");
389
528
  return { vcard, displayName: c.fullName };
390
529
  });
530
+ if (mapped.length === 1) {
531
+ return sock.sendMessage(jid, { contacts: { displayName: mapped[0].displayName, contacts: mapped } }, options);
532
+ }
391
533
  return sock.sendMessage(jid, { contacts: { contacts: mapped } }, options);
392
534
  };
535
+
393
536
  const sendTyping = async (jid, duration = 3000, type = "composing") => {
394
537
  const valid = ["composing", "recording", "paused", "available", "unavailable"];
395
538
  if (!valid.includes(type)) throw new Error(`sendTyping: type tidak valid: ${valid.join(", ")}`);
396
539
  await sock.sendPresenceUpdate(type, jid);
397
- 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
+ }
398
544
  };
545
+
399
546
  const sendWithTyping = async (jid, content, options = {}, typingMs = 1500) => {
400
547
  await sock.sendPresenceUpdate("composing", jid);
401
548
  await _sleep(Math.min(typingMs, 5000));
402
549
  await sock.sendPresenceUpdate("paused", jid);
403
550
  return sock.sendMessage(jid, content, options);
404
551
  };
552
+
405
553
  const sendTextWithMentions = async (jid, text, mentionJids, options = {}) => {
406
- 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");
407
556
  return sock.sendMessage(jid, { text, mentions: mentionJids }, options);
408
557
  };
409
558
 
@@ -411,27 +560,39 @@ const makeBusinessSocket = (config) => {
411
560
  // BROADCAST
412
561
  // ─────────────────────────────────────────────────────────────────────────
413
562
  const broadcastMessage = async (jids, content, options = {}) => {
414
- 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");
415
565
  const uniqueJids = [...new Set(jids)];
416
- const delayMs = options.delayMs || 500;
566
+ const delayMs = options.delayMs ?? 500;
417
567
  const results = [];
418
568
  for (const jid of uniqueJids) {
419
- try { results.push({ jid, success: true, msg: await sock.sendMessage(jid, content, options) }); }
420
- 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
+ }
421
575
  if (delayMs > 0) await _sleep(delayMs);
422
576
  }
423
577
  return results;
424
578
  };
579
+
425
580
  const broadcastToGroups = async (content, options = {}) => {
426
581
  const all = await sock.groupFetchAllParticipating();
427
582
  return broadcastMessage(Object.keys(all), content, options);
428
583
  };
584
+
429
585
  const sendMultipleMessages = async (jid, contents, delayMs = 500) => {
430
- 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");
431
588
  const results = [];
432
589
  for (const content of contents) {
433
- try { results.push({ success: true, msg: await sock.sendMessage(jid, content) }); }
434
- 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
+ }
435
596
  if (delayMs > 0) await _sleep(delayMs);
436
597
  }
437
598
  return results;
@@ -452,12 +613,22 @@ const makeBusinessSocket = (config) => {
452
613
  ...(isAiSticker ? { isAiSticker: true } : {}),
453
614
  }, options);
454
615
  };
455
- const sendStickerFromUrl = async (jid, url, options = {}) => { if (!url) throw new Error("sendStickerFromUrl: url wajib"); return sock.sendMessage(jid, { sticker: { url } }, options); };
456
- 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
+
457
627
  const sendStickerMessage = async (jid, sticker, cfg = {}, options = {}) => {
458
628
  if (!sticker) throw new Error("sendStickerMessage: sticker wajib");
459
629
  return sock.sendMessage(jid, {
460
- sticker, mimetype: "image/webp",
630
+ sticker,
631
+ mimetype: "image/webp",
461
632
  ...(cfg.packName ? { stickerPackName: cfg.packName } : {}),
462
633
  ...(cfg.packPublisher ? { stickerPackPublisher: cfg.packPublisher } : {}),
463
634
  ...(cfg.categories ? { categories: cfg.categories } : {}),
@@ -465,14 +636,20 @@ const makeBusinessSocket = (config) => {
465
636
  ...(cfg.isAiSticker ? { isAiSticker: true } : {}),
466
637
  }, options);
467
638
  };
639
+
468
640
  const sendStickerPack = async (jid, stickers, packName, packPublisher, options = {}) => {
469
- 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");
470
643
  if (stickers.length > 30) throw new Error("sendStickerPack: maks 30 sticker");
471
- const delayMs = options.delayMs || 300;
644
+ const delayMs = options.delayMs ?? 300;
472
645
  const results = [];
473
646
  for (const sticker of stickers) {
474
- try { results.push({ success: true, msg: await sendStickerWithMetadata(jid, sticker, { packName, packPublisher }, options) }); }
475
- 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
+ }
476
653
  if (delayMs > 0) await _sleep(delayMs);
477
654
  }
478
655
  return results;
@@ -484,24 +661,66 @@ const makeBusinessSocket = (config) => {
484
661
  const sendDocument = async (jid, document, fileName, mimetype, caption, options = {}) => {
485
662
  if (!document) throw new Error("sendDocument: document wajib");
486
663
  if (!fileName) throw new Error("sendDocument: fileName wajib");
487
- 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);
488
670
  };
671
+
489
672
  const sendAudio = async (jid, audio, isPtt = false, options = {}) => {
490
673
  if (!audio) throw new Error("sendAudio: audio wajib");
491
- 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);
492
684
  };
493
- const sendImage = async (jid, image, caption, options = {}) => { if (!image) throw new Error("sendImage: image wajib"); return sock.sendMessage(jid, { image, ...(caption ? { caption } : {}) }, options); };
494
- 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
+
495
691
  const sendAudioPTT = async (jid, audio, options = {}) => sendAudio(jid, audio, true, options);
496
692
  const sendVoiceNote = async (jid, audio, options = {}) => sendAudio(jid, audio, true, options);
497
693
 
498
694
  // ─────────────────────────────────────────────────────────────────────────
499
695
  // REPLY / QUOTE
500
696
  // ─────────────────────────────────────────────────────────────────────────
501
- 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 }); };
502
- const sendMediaReply = async (jid, content, quotedMessage, options = {}) => { if (!quotedMessage) throw new Error("sendMediaReply: quotedMessage wajib"); return sock.sendMessage(jid, content, { quoted: quotedMessage, ...options }); };
503
- 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 }); };
504
- 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
+
505
724
  const sendWithQuotedFake = async (jid, text, fakeQuoted = {}, options = {}) => {
506
725
  const { sender, text: quotedText, id } = fakeQuoted;
507
726
  if (!sender) throw new Error("sendWithQuotedFake: fakeQuoted.sender wajib");
@@ -517,9 +736,11 @@ const makeBusinessSocket = (config) => {
517
736
  };
518
737
  return sock.sendMessage(jid, { text }, { quoted: fakeMsg, ...options });
519
738
  };
739
+
520
740
  const forwardWithComment = async (jid, message, comment, options = {}) => {
521
741
  if (!message) throw new Error("forwardWithComment: message wajib");
522
742
  await sock.sendMessage(jid, { text: comment }, options);
743
+ await _sleep(300);
523
744
  return sock.sendMessage(jid, { forward: message, force: true }, options);
524
745
  };
525
746
 
@@ -528,22 +749,32 @@ const makeBusinessSocket = (config) => {
528
749
  // ─────────────────────────────────────────────────────────────────────────
529
750
  const sendGroupInvite = async (jid, groupJid, options = {}) => {
530
751
  if (!_isGrp(groupJid)) throw new Error("sendGroupInvite: groupJid harus @g.us");
531
- 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
+ ]);
532
756
  return sock.sendMessage(jid, {
533
757
  groupInviteMessage: {
534
- groupJid, inviteCode: code,
758
+ groupJid,
759
+ inviteCode: code,
535
760
  inviteExpiration: Math.floor(Date.now() / 1000) + 259200,
536
- groupName: meta.subject, caption: options.caption || "",
761
+ groupName: meta.subject,
762
+ caption: options.caption || "",
537
763
  jpegThumbnail: meta.picturePreview || null,
538
764
  },
539
765
  }, options);
540
766
  };
767
+
541
768
  const sendAdminInvite = async (jid, groupJid, options = {}) => {
542
769
  if (!_isGrp(groupJid)) throw new Error("sendAdminInvite: groupJid harus @g.us");
543
- 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
+ ]);
544
774
  const msg = _gen(jid, {
545
775
  groupInviteMessage: {
546
- groupJid, inviteCode: code,
776
+ groupJid,
777
+ inviteCode: code,
547
778
  inviteExpiration: Math.floor(Date.now() / 1000) + 259200,
548
779
  groupName: meta.subject,
549
780
  caption: options.caption || `Kamu diundang jadi admin di ${meta.subject}`,
@@ -555,31 +786,95 @@ const makeBusinessSocket = (config) => {
555
786
  // ─────────────────────────────────────────────────────────────────────────
556
787
  // CHAT MANAGEMENT
557
788
  // ─────────────────────────────────────────────────────────────────────────
558
- const muteJid = async (jid, durationMs = 8 * 60 * 60 * 1000) => sock.chatModify({ mute: durationMs }, jid);
559
- const unmuteJid = async (jid) => sock.chatModify({ mute: null }, jid);
560
- const archiveChat = async (jid, lastMessage) => { if (!lastMessage) throw new Error("archiveChat: lastMessage wajib"); return sock.chatModify({ archive: true, lastMessages: [lastMessage] }, jid); };
561
- 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
+
562
805
  const pinChat = async (jid) => sock.chatModify({ pin: true }, jid);
563
806
  const unpinChat = async (jid) => sock.chatModify({ pin: false }, jid);
564
- const markAsRead = async (keys) => sock.readMessages(Array.isArray(keys) ? keys : [keys]);
565
- const sendSeen = async (jid, messages = []) => sock.readMessages(messages.map(m => m.key || m));
566
- 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
+
567
819
  const blockUser = async (jid) => sock.updateBlockStatus(_norm(jid), "block");
568
820
  const unblockUser = async (jid) => sock.updateBlockStatus(_norm(jid), "unblock");
569
- const starMessage = async (jid, messageId, fromMe = false) => sock.chatModify({ star: { messages: [{ id: messageId, fromMe }], star: true } }, jid);
570
- const unstarMessage = async (jid, messageId, fromMe = false) => sock.chatModify({ star: { messages: [{ id: messageId, fromMe }], star: false } }, jid);
571
- 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); };
572
- const clearChat = async (jid, messages = []) => sock.chatModify({ clear: { messages: messages.map(m => ({ id: m.key.id, fromMe: m.key.fromMe, timestamp: m.messageTimestamp })) } }, jid);
573
- const sendLinkPreview = async (jid, text, options = {}) => sock.sendMessage(jid, { text, detectLinks: true }, options);
574
- 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 });
575
852
 
576
853
  // ─────────────────────────────────────────────────────────────────────────
577
854
  // PROFILE
578
855
  // ─────────────────────────────────────────────────────────────────────────
579
- const getProfilePicture = async (jid, highRes = false) => { try { return await sock.profilePictureUrl(jid, highRes ? "image" : "preview"); } catch { return null; } };
580
- 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
+
581
872
  const getContactInfo = async (jid) => {
582
- 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
+ ]);
583
878
  return {
584
879
  jid,
585
880
  exists: onWA.status === "fulfilled" ? onWA.value?.exists : false,
@@ -587,17 +882,31 @@ const makeBusinessSocket = (config) => {
587
882
  status: status.status === "fulfilled" ? status.value : null,
588
883
  };
589
884
  };
590
- 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
+
591
891
  const removeProfilePicture = async (jid) => sock.removeProfilePicture(jid);
592
- const updateProfileName = async (name) => { if (!name) throw new Error("updateProfileName: name wajib"); return sock.updateProfileName(name); };
593
- 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
+ };
594
902
 
595
903
  // ─────────────────────────────────────────────────────────────────────────
596
904
  // DISAPPEARING
597
905
  // ─────────────────────────────────────────────────────────────────────────
598
906
  const sendDisappearingMessage = async (jid, content, expiration, options = {}) => {
599
- if (![0, 86400, 604800, 7776000].includes(expiration))
600
- 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(", ")}`);
601
910
  return sock.sendMessage(jid, content, { ephemeralExpiration: expiration, ...options });
602
911
  };
603
912
 
@@ -607,12 +916,39 @@ const makeBusinessSocket = (config) => {
607
916
  const isOnWhatsApp = async (jidOrNumber) => {
608
917
  let jid = jidOrNumber;
609
918
  if (!jid.includes("@")) jid = jid.replace(/[^0-9]/g, "") + "@s.whatsapp.net";
610
- const result = await sock.onWhatsApp(jid);
611
- 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
+ }
612
925
  };
613
- const rejectAllCalls = () => sock.ev.on("call", async ([call]) => { try { await sock.rejectCall(call.id, call.from); } catch { } });
614
- const getBusinessProfile = async (jid) => { try { return await sock.getBusinessProfile(_norm(jid)); } catch { return null; } };
615
- 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
+
616
952
  const presenceSubscribe = async (jid) => sock.presenceSubscribe(jid);
617
953
  const updatePrivacyLastSeen = async (v) => sock.updateLastSeenPrivacy(v);
618
954
  const updatePrivacyProfilePic = async (v) => sock.updateProfilePicturePrivacy(v);
@@ -636,7 +972,14 @@ const makeBusinessSocket = (config) => {
636
972
  const sendButtonsMessage = async (jid, text, buttons = [], footer = "", options = {}) => {
637
973
  if (!buttons.length) throw new Error("sendButtonsMessage: min 1 tombol");
638
974
  if (buttons.length > 3) throw new Error("sendButtonsMessage: maks 3 tombol");
639
- 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
+ });
640
983
  return _relay(jid, msg);
641
984
  };
642
985
 
@@ -645,8 +988,11 @@ const makeBusinessSocket = (config) => {
645
988
  if (!sections?.length) throw new Error("sendListMessage: sections wajib");
646
989
  const msg = _gen(jid, {
647
990
  listMessage: {
648
- title: title || "", description: text || "", footerText: footer || "",
649
- buttonText: buttonText || "Lihat", listType: 1,
991
+ title: title || "",
992
+ description: text || "",
993
+ footerText: footer || "",
994
+ buttonText: buttonText || "Lihat",
995
+ listType: 1,
650
996
  sections: sections.map(s => ({
651
997
  title: s.title || "",
652
998
  rows: (s.rows || []).map(r => ({
@@ -664,12 +1010,29 @@ const makeBusinessSocket = (config) => {
664
1010
  const { text, footer, templateButtons = [] } = cfg;
665
1011
  if (!templateButtons.length) throw new Error("sendTemplateMessage: templateButtons wajib");
666
1012
  const hydratedButtons = templateButtons.map((b, i) => {
667
- if (b.quickReply) return { index: b.index ?? i, quickReplyButton: { displayText: b.quickReply.displayText, id: b.quickReply.id } };
668
- if (b.urlButton) return { index: b.index ?? i, urlButton: { displayText: b.urlButton.displayText, url: b.urlButton.url } };
669
- 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
+ };
670
1025
  return b;
671
1026
  });
672
- 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
+ });
673
1036
  return _relay(jid, msg);
674
1037
  };
675
1038
 
@@ -680,26 +1043,51 @@ const makeBusinessSocket = (config) => {
680
1043
  const typeMap = { image: "image", video: "video", document: "document" };
681
1044
  if (typeMap[header.type]) {
682
1045
  const inner = await (0, Utils_1.generateWAMessageContent)(
683
- { [header.type]: header.content, ...(header.type === "document" ? { fileName: header.fileName } : {}) },
1046
+ {
1047
+ [header.type]: header.content,
1048
+ ...(header.type === "document" ? { fileName: header.fileName } : {})
1049
+ },
684
1050
  { upload: waUploadToServer }
685
1051
  );
686
1052
  const msgKey = `${header.type}Message`;
687
- 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 || "" } } } };
688
1061
  }
689
1062
  }
690
1063
  let action = null;
691
1064
  if (buttons?.length) {
692
- 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
+ };
693
1072
  } else if (sections?.length) {
694
1073
  action = {
695
1074
  sections: sections.map(s => ({
696
1075
  title: s.title,
697
- 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
+ })),
698
1081
  })),
699
1082
  buttonText: cfg.listButtonText || "Pilih",
700
1083
  };
701
1084
  } else if (nativeFlow) {
702
- action = { nativeFlowMessage: { name: nativeFlow.name, paramsJson: nativeFlow.paramsJson || "{}" } };
1085
+ action = {
1086
+ nativeFlowMessage: {
1087
+ name: nativeFlow.name,
1088
+ paramsJson: nativeFlow.paramsJson || "{}"
1089
+ }
1090
+ };
703
1091
  }
704
1092
  const msg = _gen(jid, {
705
1093
  interactiveMessage: {
@@ -714,13 +1102,16 @@ const makeBusinessSocket = (config) => {
714
1102
 
715
1103
  const sendHighlyStructuredMessage = async (jid, cfg = {}) => {
716
1104
  const { namespace, elementName, params = [] } = cfg;
717
- if (!namespace || !elementName) throw new Error("sendHighlyStructuredMessage: namespace dan elementName wajib");
1105
+ if (!namespace || !elementName)
1106
+ throw new Error("sendHighlyStructuredMessage: namespace dan elementName wajib");
718
1107
  const msg = _gen(jid, {
719
1108
  highlyStructuredMessage: {
720
- namespace, elementName,
1109
+ namespace,
1110
+ elementName,
721
1111
  params: params.map(p => ({ default: p })),
722
1112
  deterministicLottie: cfg.deterministicLottie || false,
723
- fallbackLg: "id", fallbackLc: "ID",
1113
+ fallbackLg: "id",
1114
+ fallbackLc: "ID",
724
1115
  },
725
1116
  });
726
1117
  return _relay(jid, msg);
@@ -731,30 +1122,102 @@ const makeBusinessSocket = (config) => {
731
1122
  if (!image) throw new Error("sendImageWithButtons: image wajib");
732
1123
  if (!buttons.length) throw new Error("sendImageWithButtons: buttons wajib");
733
1124
  const inner = await (0, Utils_1.generateWAMessageContent)({ image }, { upload: waUploadToServer });
734
- 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
+ }));
735
1134
  };
1135
+
736
1136
  const sendVideoWithButtons = async (jid, video, caption, buttons = [], footer = "", options = {}) => {
737
1137
  if (!video) throw new Error("sendVideoWithButtons: video wajib");
738
1138
  if (!buttons.length) throw new Error("sendVideoWithButtons: buttons wajib");
739
1139
  const inner = await (0, Utils_1.generateWAMessageContent)({ video }, { upload: waUploadToServer });
740
- 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
+ }));
741
1149
  };
1150
+
742
1151
  const sendDocumentWithButtons = async (jid, document, fileName, caption, buttons = [], footer = "", options = {}) => {
743
1152
  if (!document) throw new Error("sendDocumentWithButtons: document wajib");
744
1153
  if (!buttons.length) throw new Error("sendDocumentWithButtons: buttons wajib");
745
1154
  const inner = await (0, Utils_1.generateWAMessageContent)({ document, fileName }, { upload: waUploadToServer });
746
- 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
+ }));
747
1164
  };
748
1165
 
749
1166
  // ─── Newsletter ───────────────────────────────────────────────────────────
750
- 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
+
751
1173
  const sendNewsletterReaction = async (newsletterJid, messageId, emoji) => {
752
- if (!newsletterJid.endsWith("@newsletter")) throw new Error("sendNewsletterReaction: harus @newsletter JID");
753
- 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
+ });
754
1185
  };
1186
+
755
1187
  const getNewsletterInfo = async (newsletterJid) => {
756
- if (!newsletterJid.endsWith("@newsletter")) throw new Error("getNewsletterInfo: harus @newsletter JID");
757
- 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;
758
1221
  };
759
1222
 
760
1223
  // ─── Product ──────────────────────────────────────────────────────────────
@@ -766,22 +1229,34 @@ const makeBusinessSocket = (config) => {
766
1229
  const msg = _gen(jid, {
767
1230
  productMessage: {
768
1231
  product: {
769
- productId: product.id, title: product.title,
770
- description: product.description || "", currencyCode: product.currency,
771
- priceAmount1000: product.price, retailerId: product.retailerId || "",
772
- 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,
773
1240
  firstImageId: product.images?.[0]?.id || "",
774
1241
  },
775
- businessOwnerJid: bizJid, catalog: { catalogJid: bizJid },
1242
+ businessOwnerJid: bizJid,
1243
+ catalog: { catalogJid: bizJid },
776
1244
  },
777
1245
  });
778
1246
  return _relay(jid, msg);
779
1247
  };
780
1248
 
781
1249
  const sendLocationReply = async (jid, latitude, longitude, name, quotedMessage, options = {}) => {
782
- 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");
783
1252
  if (!quotedMessage) throw new Error("sendLocationReply: quotedMessage wajib");
784
- 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 });
785
1260
  };
786
1261
 
787
1262
  // ─────────────────────────────────────────────────────────────────────────
@@ -792,73 +1267,159 @@ const makeBusinessSocket = (config) => {
792
1267
  logger: config.logger,
793
1268
 
794
1269
  // Catalog
795
- getCatalog, getCollections, getOrderDetails,
796
- productCreate, productDelete, productUpdate,
1270
+ getCatalog,
1271
+ getCollections,
1272
+ getOrderDetails,
1273
+ productCreate,
1274
+ productDelete,
1275
+ productUpdate,
797
1276
 
798
1277
  // Group
799
- groupTagAll, groupStatusV2, getGroupAdmins, isGroupAdmin,
800
- sendToAdminsOnly, bulkGroupAction, setGroupDisappearing,
801
- sendTagAll, sendGroupInvite, sendAdminInvite,
802
- updateGroupName, updateGroupDescription, updateGroupSetting,
803
- revokeGroupInvite, getGroupInviteLink, joinGroupViaLink, leaveGroup,
804
- getGroupParticipants, setGroupJoinApproval, getGroupJoinRequests,
805
- approveGroupJoinRequest, rejectGroupJoinRequest,
806
- 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,
807
1303
 
808
1304
  // Status
809
1305
  sendStatus,
810
1306
 
811
1307
  // Media
812
- sendImage, sendVideo, sendAudio, sendAudioPTT, sendVoiceNote,
813
- sendDocument, sendGIF, sendPTV, sendViewOnce, sendAlbum,
814
- sendLocation, sendLocationReply, sendLiveLocation,
815
- sendContact, sendPoll, sendEvent, sendScheduledCall,
816
- 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,
817
1327
 
818
1328
  // Sticker
819
- sendStickerFromUrl, sendStickerFromBuffer,
820
- sendStickerWithMetadata, sendStickerPack, sendStickerMessage,
1329
+ sendStickerFromUrl,
1330
+ sendStickerFromBuffer,
1331
+ sendStickerWithMetadata,
1332
+ sendStickerPack,
1333
+ sendStickerMessage,
821
1334
 
822
1335
  // Interactive
823
- sendButtonsMessage, sendListMessage, sendTemplateMessage,
824
- sendInteractiveMessage, sendHighlyStructuredMessage,
825
- sendNewsletterMessage, sendNewsletterReaction, getNewsletterInfo,
826
- 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,
827
1351
  sendDocumentWithButtons,
828
1352
 
829
1353
  // Reply / quote
830
- sendReply, sendMediaReply, sendQuotedText,
831
- sendWithQuotedFake, sendWithMentionAndReply, forwardWithComment,
1354
+ sendReply,
1355
+ sendMediaReply,
1356
+ sendQuotedText,
1357
+ sendWithQuotedFake,
1358
+ sendWithMentionAndReply,
1359
+ forwardWithComment,
832
1360
 
833
1361
  // Mentions / typing
834
- sendTextWithMentions, sendTyping, sendWithTyping,
1362
+ sendTextWithMentions,
1363
+ sendTyping,
1364
+ sendWithTyping,
835
1365
 
836
1366
  // Broadcast
837
- broadcastMessage, broadcastToGroups, sendMultipleMessages,
1367
+ broadcastMessage,
1368
+ broadcastToGroups,
1369
+ sendMultipleMessages,
838
1370
 
839
1371
  // Message actions
840
- pinMessage, keepMessage, editMessage, deleteMessage,
841
- reactMessage, forwardMessage,
1372
+ pinMessage,
1373
+ keepMessage,
1374
+ editMessage,
1375
+ deleteMessage,
1376
+ reactMessage,
1377
+ forwardMessage,
842
1378
 
843
1379
  // Chat management
844
- muteJid, unmuteJid, archiveChat, unarchiveChat,
845
- pinChat, unpinChat, markAsRead, markAsUnread,
846
- blockUser, unblockUser, starMessage, unstarMessage,
847
- 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,
848
1395
 
849
1396
  // Profile
850
- getProfilePicture, getUserStatus, updateProfilePicture,
851
- removeProfilePicture, updateProfileName, updateProfileStatus,
852
- getContactInfo, getBusinessProfile, fetchBlocklist, fetchAllGroups,
1397
+ getProfilePicture,
1398
+ getUserStatus,
1399
+ updateProfilePicture,
1400
+ removeProfilePicture,
1401
+ updateProfileName,
1402
+ updateProfileStatus,
1403
+ getContactInfo,
1404
+ getBusinessProfile,
1405
+ fetchBlocklist,
1406
+ fetchAllGroups,
853
1407
  fetchMessageHistory,
854
1408
 
855
1409
  // Privacy
856
- updatePrivacyLastSeen, updatePrivacyProfilePic, updatePrivacyStatus,
857
- updatePrivacyReadReceipts, updatePrivacyGroupsAdd, updatePrivacyOnline,
1410
+ updatePrivacyLastSeen,
1411
+ updatePrivacyProfilePic,
1412
+ updatePrivacyStatus,
1413
+ updatePrivacyReadReceipts,
1414
+ updatePrivacyGroupsAdd,
1415
+ updatePrivacyOnline,
858
1416
  setDefaultDisappearing,
859
1417
 
860
1418
  // Misc
861
- sendDisappearingMessage, isOnWhatsApp, presenceSubscribe, rejectAllCalls,
1419
+ sendDisappearingMessage,
1420
+ isOnWhatsApp,
1421
+ presenceSubscribe,
1422
+ rejectAllCalls,
862
1423
  };
863
1424
  };
864
1425