whatsapp-web.js 1.23.1-alpha.2 → 1.23.1-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/example.js CHANGED
@@ -240,12 +240,52 @@ client.on('message', async msg => {
240
240
  const newStatus = msg.body.split(' ')[1];
241
241
  await client.setStatus(newStatus);
242
242
  msg.reply(`Status was updated to *${newStatus}*`);
243
- } else if (msg.body === '!mention') {
244
- const contact = await msg.getContact();
243
+ } else if (msg.body === '!mentionUsers') {
245
244
  const chat = await msg.getChat();
246
- chat.sendMessage(`Hi @${contact.number}!`, {
247
- mentions: [contact]
245
+ const userNumber = 'XXXXXXXXXX';
246
+ /**
247
+ * To mention one user you can pass user's ID to 'mentions' property as is,
248
+ * without wrapping it in Array, and a user's phone number to the message body:
249
+ */
250
+ await chat.sendMessage(`Hi @${userNumber}`, {
251
+ mentions: userNumber + '@c.us'
252
+ });
253
+ // To mention a list of users:
254
+ await chat.sendMessage(`Hi @${userNumber}, @${userNumber}`, {
255
+ mentions: [userNumber + '@c.us', userNumber + '@c.us']
256
+ });
257
+ } else if (msg.body === '!mentionGroups') {
258
+ const chat = await msg.getChat();
259
+ const groupId = 'YYYYYYYYYY@g.us';
260
+ /**
261
+ * Sends clickable group mentions, the same as user mentions.
262
+ * When the mentions are clicked, it opens a chat with the mentioned group.
263
+ * The 'groupMentions.subject' can be custom
264
+ *
265
+ * @note The user that does not participate in the mentioned group,
266
+ * will not be able to click on that mentioned group, the same if the group does not exist
267
+ *
268
+ * To mention one group:
269
+ */
270
+ await chat.sendMessage(`Check the last message here: @${groupId}`, {
271
+ groupMentions: { subject: 'GroupSubject', id: groupId }
248
272
  });
273
+ // To mention a list of groups:
274
+ await chat.sendMessage(`Check the last message in these groups: @${groupId}, @${groupId}`, {
275
+ groupMentions: [
276
+ { subject: 'FirstGroup', id: groupId },
277
+ { subject: 'SecondGroup', id: groupId }
278
+ ]
279
+ });
280
+ } else if (msg.body === '!getGroupMentions') {
281
+ // To get group mentions from a message:
282
+ const groupId = 'ZZZZZZZZZZ@g.us';
283
+ const msg = await client.sendMessage('chatId', `Check the last message here: @${groupId}`, {
284
+ groupMentions: { subject: 'GroupSubject', id: groupId }
285
+ });
286
+ /** {@link groupMentions} is an array of `GroupChat` */
287
+ const groupMentions = await msg.getGroupMentions();
288
+ console.log(groupMentions);
249
289
  } else if (msg.body === '!delete') {
250
290
  if (msg.hasQuotedMsg) {
251
291
  const quotedMsg = await msg.getQuotedMessage();
@@ -288,7 +328,9 @@ client.on('message', async msg => {
288
328
  let button = new Buttons('Button body', [{ body: 'bt1' }, { body: 'bt2' }, { body: 'bt3' }], 'title', 'footer');
289
329
  client.sendMessage(msg.from, button);
290
330
  } else if (msg.body === '!list') {
291
- let sections = [{ title: 'sectionTitle', rows: [{ title: 'ListItem1', description: 'desc' }, { title: 'ListItem2' }] }];
331
+ let sections = [
332
+ { title: 'sectionTitle', rows: [{ title: 'ListItem1', description: 'desc' }, { title: 'ListItem2' }] }
333
+ ];
292
334
  let list = new List('List body', 'btnText', sections, 'Title', 'footer');
293
335
  client.sendMessage(msg.from, list);
294
336
  } else if (msg.body === '!reaction') {
@@ -323,7 +365,7 @@ client.on('message', async msg => {
323
365
  await chat.changeLabels([0, 1]);
324
366
  } else if (msg.body === '!addlabels') {
325
367
  const chat = await msg.getChat();
326
- let labels = (await chat.getLabels()).map(l => l.id);
368
+ let labels = (await chat.getLabels()).map((l) => l.id);
327
369
  labels.push('0');
328
370
  labels.push('1');
329
371
  await chat.changeLabels(labels);
@@ -376,14 +418,35 @@ client.on('message', async msg => {
376
418
  requesterIds: ['number1@c.us', 'number2@c.us'],
377
419
  sleep: null
378
420
  });
421
+ } else {
422
+ /**
423
+ * Pins a message in a chat, a method takes a number in seconds for the message to be pinned.
424
+ * WhatsApp default values for duration to pass to the method are:
425
+ * 1. 86400 for 24 hours
426
+ * 2. 604800 for 7 days
427
+ * 3. 2592000 for 30 days
428
+ * You can pass your own value:
429
+ */
430
+ const result = await msg.pin(60); // Will pin a message for 1 minute
431
+ console.log(result); // True if the operation completed successfully, false otherwise
379
432
  }
380
433
  });
381
434
 
382
- client.on('message_create', (msg) => {
435
+ client.on('message_create', async (msg) => {
383
436
  // Fired on all message creations, including your own
384
437
  if (msg.fromMe) {
385
438
  // do stuff here
386
439
  }
440
+
441
+ // Unpins a message
442
+ if (msg.fromMe && msg.body.startsWith('!unpin')) {
443
+ const pinnedMsg = await msg.getQuotedMessage();
444
+ if (pinnedMsg) {
445
+ // Will unpin a message
446
+ const result = await pinnedMsg.unpin();
447
+ console.log(result); // True if the operation completed successfully, false otherwise
448
+ }
449
+ }
387
450
  });
388
451
 
389
452
  client.on('message_ciphertext', (msg) => {
package/index.d.ts CHANGED
@@ -857,7 +857,16 @@ declare namespace WAWebJS {
857
857
  /** MediaKey that represents the sticker 'ID' */
858
858
  mediaKey?: string,
859
859
  /** Indicates the mentions in the message body. */
860
- mentionedIds: [],
860
+ mentionedIds: ChatId[],
861
+ /** Indicates whether there are group mentions in the message body */
862
+ groupMentions: {
863
+ groupSubject: string;
864
+ groupJid: {
865
+ server: string;
866
+ user: string;
867
+ _serialized: string;
868
+ };
869
+ }[],
861
870
  /** Unix timestamp for when the message was created */
862
871
  timestamp: number,
863
872
  /**
@@ -917,6 +926,8 @@ declare namespace WAWebJS {
917
926
  getContact: () => Promise<Contact>,
918
927
  /** Returns the Contacts mentioned in this message */
919
928
  getMentions: () => Promise<Contact[]>,
929
+ /** Returns groups mentioned in this message */
930
+ getGroupMentions: () => Promise<GroupChat[]|[]>,
920
931
  /** Returns the quoted message, if any */
921
932
  getQuotedMessage: () => Promise<Message>,
922
933
  /**
@@ -935,6 +946,10 @@ declare namespace WAWebJS {
935
946
  star: () => Promise<void>,
936
947
  /** Unstar this message */
937
948
  unstar: () => Promise<void>,
949
+ /** Pins the message (group admins can pin messages of all group members) */
950
+ pin: (duration: number) => Promise<boolean>,
951
+ /** Unpins the message (group admins can unpin messages of all group members) */
952
+ unpin: () => Promise<boolean>,
938
953
  /** Get information about message delivery status */
939
954
  getInfo: () => Promise<MessageInfo | null>,
940
955
  /**
@@ -1035,8 +1050,15 @@ declare namespace WAWebJS {
1035
1050
  caption?: string
1036
1051
  /** Id of the message that is being quoted (or replied to) */
1037
1052
  quotedMessageId?: string
1038
- /** Contacts that are being mentioned in the message */
1039
- mentions?: Contact[]
1053
+ /** User IDs to mention in the message */
1054
+ mentions?: string[]
1055
+ /** An array of object that handle group mentions */
1056
+ groupMentions?: {
1057
+ /** The name of a group to mention (can be custom) */
1058
+ subject: string,
1059
+ /** The group ID, e.g.: 'XXXXXXXXXX@g.us' */
1060
+ id: string
1061
+ }[]
1040
1062
  /** Send 'seen' status */
1041
1063
  sendSeen?: boolean
1042
1064
  /** Media to be sent */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whatsapp-web.js",
3
- "version": "1.23.1-alpha.2",
3
+ "version": "1.23.1-alpha.4",
4
4
  "description": "Library for interacting with the WhatsApp Web API ",
5
5
  "main": "./index.js",
6
6
  "typings": "./index.d.ts",
@@ -30,11 +30,10 @@
30
30
  "homepage": "https://wwebjs.dev/",
31
31
  "dependencies": {
32
32
  "@pedroslopez/moduleraid": "^5.0.2",
33
- "fluent-ffmpeg": "^2.1.2",
34
- "jsqr": "^1.3.1",
33
+ "fluent-ffmpeg": "2.1.2",
35
34
  "mime": "^3.0.0",
36
35
  "node-fetch": "^2.6.5",
37
- "node-webpmux": "^3.1.0",
36
+ "node-webpmux": "3.1.0",
38
37
  "puppeteer": "^13.0.0"
39
38
  },
40
39
  "devDependencies": {
package/src/Client.js CHANGED
@@ -810,6 +810,13 @@ class Client extends EventEmitter {
810
810
  return result;
811
811
  }
812
812
 
813
+ /**
814
+ * An object representing mentions of groups
815
+ * @typedef {Object} GroupMention
816
+ * @property {string} subject - The name of a group to mention (can be custom)
817
+ * @property {string} id - The group ID, e.g.: 'XXXXXXXXXX@g.us'
818
+ */
819
+
813
820
  /**
814
821
  * Message options.
815
822
  * @typedef {Object} MessageSendOptions
@@ -822,7 +829,8 @@ class Client extends EventEmitter {
822
829
  * @property {boolean} [parseVCards=true] - Automatically parse vCards and send them as contacts
823
830
  * @property {string} [caption] - Image or video caption
824
831
  * @property {string} [quotedMessageId] - Id of the message that is being quoted (or replied to)
825
- * @property {Contact[]} [mentions] - Contacts that are being mentioned in the message
832
+ * @property {GroupMention[]} [groupMentions] - An array of object that handle group mentions
833
+ * @property {string[]} [mentions] - User IDs to mention in the message
826
834
  * @property {boolean} [sendSeen=true] - Mark the conversation as seen after sending the message
827
835
  * @property {string} [stickerAuthor=undefined] - Sets the author of the sticker, (if sendMediaAsSticker is true).
828
836
  * @property {string} [stickerName=undefined] - Sets the name of the sticker, (if sendMediaAsSticker is true).
@@ -839,10 +847,16 @@ class Client extends EventEmitter {
839
847
  * @returns {Promise<Message>} Message that was just sent
840
848
  */
841
849
  async sendMessage(chatId, content, options = {}) {
842
- if (options.mentions && options.mentions.some(possiblyContact => possiblyContact instanceof Contact)) {
843
- console.warn('Mentions with an array of Contact are now deprecated. See more at https://github.com/pedroslopez/whatsapp-web.js/pull/2166.');
844
- options.mentions = options.mentions.map(a => a.id._serialized);
850
+ if (options.mentions) {
851
+ !Array.isArray(options.mentions) && (options.mentions = [options.mentions]);
852
+ if (options.mentions.some((possiblyContact) => possiblyContact instanceof Contact)) {
853
+ console.warn('Mentions with an array of Contact are now deprecated. See more at https://github.com/pedroslopez/whatsapp-web.js/pull/2166.');
854
+ options.mentions = options.mentions.map((a) => a.id._serialized);
855
+ }
845
856
  }
857
+
858
+ options.groupMentions && !Array.isArray(options.groupMentions) && (options.groupMentions = [options.groupMentions]);
859
+
846
860
  let internalOptions = {
847
861
  linkPreview: options.linkPreview === false ? undefined : true,
848
862
  sendAudioAsVoice: options.sendAudioAsVoice,
@@ -852,7 +866,8 @@ class Client extends EventEmitter {
852
866
  caption: options.caption,
853
867
  quotedMessageId: options.quotedMessageId,
854
868
  parseVCards: options.parseVCards === false ? false : true,
855
- mentionedJidList: Array.isArray(options.mentions) ? options.mentions : [],
869
+ mentionedJidList: options.mentions || [],
870
+ groupMentions: options.groupMentions,
856
871
  extraOptions: options.extra
857
872
  };
858
873
 
@@ -908,7 +923,7 @@ class Client extends EventEmitter {
908
923
  }
909
924
 
910
925
  const msg = await window.WWebJS.sendMessage(chat, message, options, sendSeen);
911
- return msg.serialize();
926
+ return window.WWebJS.getMessageModel(msg);
912
927
  }, chatId, content, internalOptions, sendSeen);
913
928
 
914
929
  return new Message(this, newMessage);
@@ -6,8 +6,8 @@ const Location = require('./Location');
6
6
  const Order = require('./Order');
7
7
  const Payment = require('./Payment');
8
8
  const Reaction = require('./Reaction');
9
- const {MessageTypes} = require('../util/Constants');
10
- const {Contact} = require('./Contact');
9
+ const Contact = require('./Contact');
10
+ const { MessageTypes } = require('../util/Constants');
11
11
 
12
12
  /**
13
13
  * Represents a Message on WhatsApp
@@ -186,15 +186,33 @@ class Message extends Base {
186
186
  toId: '_serialized' in data.to ? data.to._serialized : data.to
187
187
  } : undefined;
188
188
 
189
+ /**
190
+ * @typedef {Object} Mention
191
+ * @property {string} server
192
+ * @property {string} user
193
+ * @property {string} _serialized
194
+ */
195
+
189
196
  /**
190
197
  * Indicates the mentions in the message body.
191
- * @type {Array<string>}
198
+ * @type {Mention[]}
192
199
  */
193
- this.mentionedIds = [];
200
+ this.mentionedIds = data.mentionedJidList || [];
194
201
 
195
- if (data.mentionedJidList) {
196
- this.mentionedIds = data.mentionedJidList;
197
- }
202
+ /**
203
+ * @typedef {Object} GroupMention
204
+ * @property {string} groupSubject The name of the group
205
+ * @property {Object} groupJid The group ID
206
+ * @property {string} groupJid.server
207
+ * @property {string} groupJid.user
208
+ * @property {string} groupJid._serialized
209
+ */
210
+
211
+ /**
212
+ * Indicates whether there are group mentions in the message body
213
+ * @type {GroupMention[]}
214
+ */
215
+ this.groupMentions = data.groupMentions || [];
198
216
 
199
217
  /**
200
218
  * Order ID for message type ORDER
@@ -341,6 +359,14 @@ class Message extends Base {
341
359
  async getMentions() {
342
360
  return await Promise.all(this.mentionedIds.map(async m => await this.client.getContactById(m)));
343
361
  }
362
+
363
+ /**
364
+ * Returns groups mentioned in this message
365
+ * @returns {Promise<GroupChat[]|[]>}
366
+ */
367
+ async getGroupMentions() {
368
+ return await Promise.all(this.groupMentions.map(async (m) => await this.client.getChatById(m.groupJid._serialized)));
369
+ }
344
370
 
345
371
  /**
346
372
  * Returns the quoted message, if any
@@ -522,6 +548,27 @@ class Message extends Base {
522
548
  }, this.id._serialized);
523
549
  }
524
550
 
551
+ /**
552
+ * Pins the message (group admins can pin messages of all group members)
553
+ * @param {number} duration The duration in seconds the message will be pinned in a chat
554
+ * @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
555
+ */
556
+ async pin(duration) {
557
+ return await this.client.pupPage.evaluate(async (msgId, duration) => {
558
+ return await window.WWebJS.pinUnpinMsgAction(msgId, 1, duration);
559
+ }, this.id._serialized, duration);
560
+ }
561
+
562
+ /**
563
+ * Unpins the message (group admins can unpin messages of all group members)
564
+ * @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
565
+ */
566
+ async unpin() {
567
+ return await this.client.pupPage.evaluate(async (msgId) => {
568
+ return await window.WWebJS.pinUnpinMsgAction(msgId, 2);
569
+ }, this.id._serialized);
570
+ }
571
+
525
572
  /**
526
573
  * Message Info
527
574
  * @typedef {Object} MessageInfo
@@ -628,12 +675,20 @@ class Message extends Base {
628
675
  * @returns {Promise<?Message>}
629
676
  */
630
677
  async edit(content, options = {}) {
631
- if (options.mentions && options.mentions.some(possiblyContact => possiblyContact instanceof Contact)) {
632
- options.mentions = options.mentions.map(a => a.id._serialized);
678
+ if (options.mentions) {
679
+ !Array.isArray(options.mentions) && (options.mentions = [options.mentions]);
680
+ if (options.mentions.some((possiblyContact) => possiblyContact instanceof Contact)) {
681
+ console.warn('Mentions with an array of Contact are now deprecated. See more at https://github.com/pedroslopez/whatsapp-web.js/pull/2166.');
682
+ options.mentions = options.mentions.map((a) => a.id._serialized);
683
+ }
633
684
  }
685
+
686
+ options.groupMentions && !Array.isArray(options.groupMentions) && (options.groupMentions = [options.groupMentions]);
687
+
634
688
  let internalOptions = {
635
689
  linkPreview: options.linkPreview === false ? undefined : true,
636
- mentionedJidList: Array.isArray(options.mentions) ? options.mentions : [],
690
+ mentionedJidList: options.mentions || [],
691
+ groupMentions: options.groupMentions,
637
692
  extraOptions: options.extra
638
693
  };
639
694
 
@@ -58,11 +58,12 @@ exports.ExposeStore = (moduleRaidStr) => {
58
58
  window.Store.LidUtils = window.mR.findModule('getCurrentLid')[0];
59
59
  window.Store.WidToJid = window.mR.findModule('widToUserJid')[0];
60
60
  window.Store.JidToWid = window.mR.findModule('userJidToUserWid')[0];
61
+ window.Store.getMsgInfo = (window.mR.findModule('sendQueryMsgInfo')[0] || {}).sendQueryMsgInfo || window.mR.findModule('queryMsgInfo')[0].queryMsgInfo;
62
+ window.Store.pinUnpinMsg = window.mR.findModule('sendPinInChatMsg')[0].sendPinInChatMsg;
61
63
 
62
64
  /* eslint-disable no-undef, no-cond-assign */
63
65
  window.Store.QueryExist = ((m = window.mR.findModule('queryExists')[0]) ? m.queryExists : window.mR.findModule('queryExist')[0].queryWidExists);
64
66
  window.Store.ReplyUtils = (m = window.mR.findModule('canReplyMsg')).length > 0 && m[0];
65
- window.Store.getMsgInfo = (window.mR.findModule('sendQueryMsgInfo')[0] || {}).sendQueryMsgInfo || window.mR.findModule('queryMsgInfo')[0].queryMsgInfo;
66
67
  /* eslint-enable no-undef, no-cond-assign */
67
68
 
68
69
  window.Store.Settings = {
@@ -194,7 +195,22 @@ exports.LoadUtils = () => {
194
195
  }
195
196
 
196
197
  if (options.mentionedJidList) {
197
- options.mentionedJidList = options.mentionedJidList.map(cId => window.Store.Contact.get(cId).id);
198
+ options.mentionedJidList = await Promise.all(
199
+ options.mentionedJidList.map(async (id) => {
200
+ const wid = window.Store.WidFactory.createWid(id);
201
+ if (await window.Store.QueryExist(wid)) {
202
+ return wid;
203
+ }
204
+ })
205
+ );
206
+ options.mentionedJidList = options.mentionedJidList.filter(Boolean);
207
+ }
208
+
209
+ if (options.groupMentions) {
210
+ options.groupMentions = options.groupMentions.map((e) => ({
211
+ groupSubject: e.subject,
212
+ groupJid: window.Store.WidFactory.createWid(e.id)
213
+ }));
198
214
  }
199
215
 
200
216
  let locationOptions = {};
@@ -367,7 +383,22 @@ exports.LoadUtils = () => {
367
383
  delete options.extraOptions;
368
384
 
369
385
  if (options.mentionedJidList) {
370
- options.mentionedJidList = options.mentionedJidList.map(cId => window.Store.Contact.get(cId).id);
386
+ options.mentionedJidList = await Promise.all(
387
+ options.mentionedJidList.map(async (id) => {
388
+ const wid = window.Store.WidFactory.createWid(id);
389
+ if (await window.Store.QueryExist(wid)) {
390
+ return wid;
391
+ }
392
+ })
393
+ );
394
+ options.mentionedJidList = options.mentionedJidList.filter(Boolean);
395
+ }
396
+
397
+ if (options.groupMentions) {
398
+ options.groupMentions = options.groupMentions.map((e) => ({
399
+ groupSubject: e.subject,
400
+ groupJid: window.Store.WidFactory.createWid(e.id)
401
+ }));
371
402
  }
372
403
 
373
404
  if (options.linkPreview) {
@@ -501,7 +532,7 @@ exports.LoadUtils = () => {
501
532
 
502
533
  msg.isEphemeral = message.isEphemeral;
503
534
  msg.isStatusV3 = message.isStatusV3;
504
- msg.links = (message.getRawLinks()).map(link => ({
535
+ msg.links = (window.Store.Validators.findLinks(message.mediaObject ? message.caption : message.body)).map((link) => ({
505
536
  link: link.href,
506
537
  isSuspicious: Boolean(link.suspiciousCharacters && link.suspiciousCharacters.size)
507
538
  }));
@@ -1083,4 +1114,12 @@ exports.LoadUtils = () => {
1083
1114
  return [];
1084
1115
  }
1085
1116
  };
1117
+
1118
+ window.WWebJS.pinUnpinMsgAction = async (msgId, action, duration) => {
1119
+ const message = window.Store.Msg.get(msgId);
1120
+ if (!message) return false;
1121
+ const response = await window.Store.pinUnpinMsg(message, action, duration);
1122
+ if (response.messageSendResult === 'OK') return true;
1123
+ return false;
1124
+ };
1086
1125
  };