whatsapp-web.js 1.32.0 → 1.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1086,6 +1086,11 @@ declare namespace WAWebJS {
1086
1086
  latestEditSenderTimestampMs?: number,
1087
1087
  /** Last edit message author */
1088
1088
  latestEditMsgKey?: MessageId,
1089
+ /**
1090
+ * Protocol message key.
1091
+ * Can be used to retrieve the ID of an original message that was revoked.
1092
+ */
1093
+ protocolMessageKey?: MessageId,
1089
1094
  /** Message buttons */
1090
1095
  dynamicReplyButtons?: object,
1091
1096
  /** Selected button ID */
@@ -1382,6 +1387,11 @@ declare namespace WAWebJS {
1382
1387
  /** Should the bot send a quoted message without the quoted message if it fails to get the quote?
1383
1388
  * @default true (enabled) */
1384
1389
  ignoreQuoteErrors?: boolean
1390
+ /**
1391
+ * Should the bot wait for the message send result?
1392
+ * @default false
1393
+ */
1394
+ waitUntilMsgSent?: boolean
1385
1395
  }
1386
1396
 
1387
1397
  /** Options for editing a message */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whatsapp-web.js",
3
- "version": "1.32.0",
3
+ "version": "1.33.0",
4
4
  "description": "Library for interacting with the WhatsApp Web API ",
5
5
  "main": "./index.js",
6
6
  "typings": "./index.d.ts",
package/src/Client.js CHANGED
@@ -468,6 +468,9 @@ class Client extends EventEmitter {
468
468
  let revoked_msg;
469
469
  if (last_message && msg.id.id === last_message.id.id) {
470
470
  revoked_msg = new Message(this, last_message);
471
+
472
+ if (message.protocolMessageKey)
473
+ revoked_msg.id = { ...message.protocolMessageKey };
471
474
  }
472
475
 
473
476
  /**
@@ -706,14 +709,15 @@ class Client extends EventEmitter {
706
709
  this.emit(Events.MESSAGE_CIPHERTEXT, new Message(this, msg));
707
710
  });
708
711
 
709
- await exposeFunctionIfAbsent(this.pupPage, 'onPollVoteEvent', (vote) => {
710
- const _vote = new PollVote(this, vote);
711
- /**
712
- * Emitted when some poll option is selected or deselected,
713
- * shows a user's current selected option(s) on the poll
714
- * @event Client#vote_update
715
- */
716
- this.emit(Events.VOTE_UPDATE, _vote);
712
+ await exposeFunctionIfAbsent(this.pupPage, 'onPollVoteEvent', (votes) => {
713
+ for (const vote of votes) {
714
+ /**
715
+ * Emitted when some poll option is selected or deselected,
716
+ * shows a user's current selected option(s) on the poll
717
+ * @event Client#vote_update
718
+ */
719
+ this.emit(Events.VOTE_UPDATE, new PollVote(this, vote));
720
+ }
717
721
  });
718
722
 
719
723
  await this.pupPage.evaluate(() => {
@@ -740,10 +744,6 @@ class Client extends EventEmitter {
740
744
  }
741
745
  });
742
746
  window.Store.Chat.on('change:unreadCount', (chat) => {window.onChatUnreadCountEvent(chat);});
743
- window.Store.PollVote.on('add', async (vote) => {
744
- const pollVoteModel = await window.WWebJS.getPollVoteModel(vote);
745
- pollVoteModel && window.onPollVoteEvent(pollVoteModel);
746
- });
747
747
 
748
748
  if (window.compareWwebVersions(window.Debug.VERSION, '>=', '2.3000.1014111620')) {
749
749
  const module = window.Store.AddonReactionTable;
@@ -761,6 +761,39 @@ class Client extends EventEmitter {
761
761
 
762
762
  return ogMethod(...args);
763
763
  }).bind(module);
764
+
765
+ const pollVoteModule = window.Store.AddonPollVoteTable;
766
+ const ogPollVoteMethod = pollVoteModule.bulkUpsert;
767
+
768
+ pollVoteModule.bulkUpsert = (async (...args) => {
769
+ const votes = await Promise.all(args[0].map(async vote => {
770
+ const msgKey = vote.id;
771
+ const parentMsgKey = vote.pollUpdateParentKey;
772
+ const timestamp = vote.t / 1000;
773
+ const sender = vote.author ?? vote.from;
774
+ const senderUserJid = sender._serialized;
775
+
776
+ let parentMessage = window.Store.Msg.get(parentMsgKey._serialized);
777
+ if (!parentMessage) {
778
+ const fetched = await window.Store.Msg.getMessagesById([parentMsgKey._serialized]);
779
+ parentMessage = fetched?.messages?.[0] || null;
780
+ }
781
+
782
+ return {
783
+ ...vote,
784
+ msgKey,
785
+ sender,
786
+ parentMsgKey,
787
+ senderUserJid,
788
+ timestamp,
789
+ parentMessage
790
+ };
791
+ }));
792
+
793
+ window.onPollVoteEvent(votes);
794
+
795
+ return ogPollVoteMethod.apply(pollVoteModule, args);
796
+ }).bind(pollVoteModule);
764
797
  } else {
765
798
  const module = window.Store.createOrUpdateReactionsModule;
766
799
  const ogMethod = module.createOrUpdateReactions;
@@ -900,6 +933,7 @@ class Client extends EventEmitter {
900
933
  * @property {string} [stickerName=undefined] - Sets the name of the sticker, (if sendMediaAsSticker is true).
901
934
  * @property {string[]} [stickerCategories=undefined] - Sets the categories of the sticker, (if sendMediaAsSticker is true). Provide emoji char array, can be null.
902
935
  * @property {boolean} [ignoreQuoteErrors = true] - Should the bot send a quoted message without the quoted message if it fails to get the quote?
936
+ * @property {boolean} [waitUntilMsgSent = false] - Should the bot wait for the message send result?
903
937
  * @property {MessageMedia} [media] - Media to be sent
904
938
  * @property {any} [extra] - Extra options
905
939
  */
@@ -950,6 +984,7 @@ class Client extends EventEmitter {
950
984
  groupMentions: options.groupMentions,
951
985
  invokedBotWid: options.invokedBotWid,
952
986
  ignoreQuoteErrors: options.ignoreQuoteErrors !== false,
987
+ waitUntilMsgSent: options.waitUntilMsgSent || false,
953
988
  extraOptions: options.extra
954
989
  };
955
990
 
@@ -258,6 +258,14 @@ class Message extends Base {
258
258
  this.latestEditMsgKey = data.latestEditMsgKey;
259
259
  }
260
260
 
261
+ /**
262
+ * Protocol message key.
263
+ * Can be used to retrieve the ID of an original message that was revoked.
264
+ */
265
+ if (data.protocolMessageKey) {
266
+ this.protocolMessageKey = data.protocolMessageKey;
267
+ }
268
+
261
269
  /**
262
270
  * Links included in the message.
263
271
  * @type {Array<{link: string, isSuspicious: boolean}>}
@@ -34,14 +34,22 @@ class PollVote extends Base {
34
34
  * may occur when they deselected all poll options
35
35
  * @type {SelectedPollOption[]}
36
36
  */
37
- this.selectedOptions =
38
- data.selectedOptionLocalIds.length > 0
39
- ? data.selectedOptionLocalIds.map((e) => ({
37
+ if (data.selectedOptionLocalIds.length > 0) {
38
+ if(data.parentMessage) { // temporary failsafe
39
+ this.selectedOptions = data.selectedOptionLocalIds.map((e) => ({
40
40
  name: data.parentMessage.pollOptions.find((x) => x.localId === e).name,
41
41
  localId: e
42
- }))
43
- : [];
44
-
42
+ }));
43
+ } else {
44
+ this.selectedOptions = data.selectedOptionLocalIds.map((e) => ({
45
+ name: undefined,
46
+ localId: e
47
+ }));
48
+ }
49
+ } else {
50
+ this.selectedOptions = [];
51
+ }
52
+
45
53
  /**
46
54
  * Timestamp the option was selected or deselected at
47
55
  * @type {number}
@@ -54,6 +62,12 @@ class PollVote extends Base {
54
62
  */
55
63
  this.parentMessage = new Message(this.client, data.parentMessage);
56
64
 
65
+ /**
66
+ * The poll creation message id
67
+ * @type {Object}
68
+ */
69
+ this.parentMsgKey = data.parentMsgKey;
70
+
57
71
  return super._patch(data);
58
72
  }
59
73
  }
@@ -96,6 +96,7 @@ exports.ExposeStore = () => {
96
96
  window.Store.DeviceList = window.require('WAWebApiDeviceList');
97
97
  window.Store.HistorySync = window.require('WAWebSendNonMessageDataRequest');
98
98
  window.Store.AddonReactionTable = window.require('WAWebAddonReactionTableMode').reactionTableMode;
99
+ window.Store.AddonPollVoteTable = window.require('WAWebAddonPollVoteTableMode').pollVoteTableMode;
99
100
  window.Store.PinnedMsgUtils = window.require('WAWebPinInChatSchema');
100
101
  window.Store.ChatGetters = window.require('WAWebChatGetters');
101
102
  window.Store.PinnedMsgUtils = window.require('WAWebSendPinMessageAction');
@@ -247,9 +247,9 @@ exports.LoadUtils = () => {
247
247
  let from = chat.id.isLid() ? lidUser : meUser;
248
248
  let participant;
249
249
 
250
- if (chat.isGroup) {
250
+ if (typeof chat.id?.isGroup === 'function' && chat.id.isGroup()) {
251
251
  from = chat.groupMetadata && chat.groupMetadata.isLidAddressingMode ? lidUser : meUser;
252
- participant = window.Store.WidFactory.toUserWid(from);
252
+ participant = window.Store.WidFactory.toUserWidOrThrow(from);
253
253
  }
254
254
 
255
255
  const newMsgKey = new window.Store.MsgKey({
@@ -326,10 +326,11 @@ exports.LoadUtils = () => {
326
326
  return msg;
327
327
  }
328
328
 
329
- await window.Store.SendMessage.addAndSendMsgToChat(chat, message);
330
- await window.Store.HistorySync.sendPeerDataOperationRequest(3, {
331
- chatId: chat.id
332
- });
329
+ const [msgPromise, sendMsgResultPromise] = window.Store.SendMessage.addAndSendMsgToChat(chat, message);
330
+ await msgPromise;
331
+
332
+ if (options.waitUntilMsgSent) await sendMsgResultPromise;
333
+
333
334
  return window.Store.Msg.get(newMsgKey._serialized);
334
335
  };
335
336
 
@@ -522,15 +523,6 @@ exports.LoadUtils = () => {
522
523
  return msg;
523
524
  };
524
525
 
525
- window.WWebJS.getPollVoteModel = async (vote) => {
526
- const _vote = vote.serialize();
527
- if (!vote.parentMsgKey) return null;
528
- const msg =
529
- window.Store.Msg.get(vote.parentMsgKey) || (await window.Store.Msg.getMessagesById([vote.parentMsgKey]))?.messages?.[0];
530
- msg && (_vote.parentMessage = window.WWebJS.getMessageModel(msg));
531
- return _vote;
532
- };
533
-
534
526
  window.WWebJS.getChat = async (chatId, { getAsModel = true } = {}) => {
535
527
  const isChannel = /@\w*newsletter\b/.test(chatId);
536
528
  const chatWid = window.Store.WidFactory.createWid(chatId);