whatsapp-web.js 1.23.0 → 1.23.1-alpha.1

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/README.md CHANGED
@@ -63,8 +63,8 @@ For more information on saving and restoring sessions, check out the available [
63
63
  | Receive media (images/audio/video/documents) | ✅ |
64
64
  | Send contact cards | ✅ |
65
65
  | Send location | ✅ |
66
- | Send buttons | |
67
- | Send lists | (business accounts not supported) |
66
+ | Send buttons | |
67
+ | Send lists | ❌ [(DEPRECATED)](https://www.youtube.com/watch?v=hv1R1rLeVVE) |
68
68
  | Receive location | ✅ |
69
69
  | Message replies | ✅ |
70
70
  | Join groups by invite | ✅ |
@@ -81,6 +81,8 @@ For more information on saving and restoring sessions, check out the available [
81
81
  | Get profile pictures | ✅ |
82
82
  | Set user status message | ✅ |
83
83
  | React to messages | ✅ |
84
+ | Vote in polls | 🔜 |
85
+ | Create polls | ✅ |
84
86
 
85
87
  Something missing? Make an issue and let us know!
86
88
 
package/index.d.ts CHANGED
@@ -143,6 +143,27 @@ declare namespace WAWebJS {
143
143
  * @param displayName New display name
144
144
  */
145
145
  setDisplayName(displayName: string): Promise<boolean>
146
+
147
+ /**
148
+ * Changes the autoload Audio
149
+ * @param flag true/false on or off
150
+ */
151
+ setAutoDownloadAudio(flag: boolean): Promise<void>
152
+ /**
153
+ * Changes the autoload Documents
154
+ * @param flag true/false on or off
155
+ */
156
+ setAutoDownloadDocuments(flag: boolean): Promise<void>
157
+ /**
158
+ * Changes the autoload Photos
159
+ * @param flag true/false on or off
160
+ */
161
+ setAutoDownloadPhotos(flag: boolean): Promise<void>
162
+ /**
163
+ * Changes the autoload Videos
164
+ * @param flag true/false on or off
165
+ */
166
+ setAutoDownloadVideos(flag: boolean): Promise<void>
146
167
 
147
168
  /** Changes and returns the archive state of the Chat */
148
169
  unarchiveChat(chatId: string): Promise<boolean>
@@ -960,17 +981,19 @@ declare namespace WAWebJS {
960
981
  * The custom message secret, can be used as a poll ID
961
982
  * @note It has to be a unique vector with a length of 32
962
983
  */
963
- messageSecret: ?Array<number>
984
+ messageSecret: Array<number>|undefined
964
985
  }
965
986
 
966
987
  /** Represents a Poll on WhatsApp */
967
- export interface Poll {
968
- pollName: string,
988
+ export class Poll {
989
+ pollName: string
969
990
  pollOptions: Array<{
970
991
  name: string,
971
992
  localId: number
972
- }>,
993
+ }>
973
994
  options: PollSendOptions
995
+
996
+ constructor(pollName: string, pollOptions: Array<string>, options?: PollSendOptions)
974
997
  }
975
998
 
976
999
  export interface Label {
@@ -1168,13 +1191,84 @@ declare namespace WAWebJS {
1168
1191
  user: string,
1169
1192
  _serialized: string,
1170
1193
  }
1194
+
1195
+ export interface BusinessCategory {
1196
+ id: string,
1197
+ localized_display_name: string,
1198
+ }
1199
+
1200
+ export interface BusinessHoursOfDay {
1201
+ mode: string,
1202
+ hours: number[]
1203
+ }
1204
+
1205
+ export interface BusinessHours {
1206
+ config: {
1207
+ sun: BusinessHoursOfDay,
1208
+ mon: BusinessHoursOfDay,
1209
+ tue: BusinessHoursOfDay,
1210
+ wed: BusinessHoursOfDay,
1211
+ thu: BusinessHoursOfDay,
1212
+ fri: BusinessHoursOfDay,
1213
+ }
1214
+ timezone: string,
1215
+ }
1216
+
1217
+
1171
1218
 
1172
1219
  export interface BusinessContact extends Contact {
1173
1220
  /**
1174
1221
  * The contact's business profile
1175
- * @todo add a more specific type for the object
1176
1222
  */
1177
- businessProfile: object
1223
+ businessProfile: {
1224
+ /** The contact's business profile id */
1225
+ id: ContactId,
1226
+
1227
+ /** The contact's business profile tag */
1228
+ tag: string,
1229
+
1230
+ /** The contact's business profile description */
1231
+ description: string,
1232
+
1233
+ /** The contact's business profile categories */
1234
+ categories: BusinessCategory[],
1235
+
1236
+ /** The contact's business profile options */
1237
+ profileOptions: {
1238
+ /** The contact's business profile commerce experience*/
1239
+ commerceExperience: string,
1240
+
1241
+ /** The contact's business profile cart options */
1242
+ cartEnabled: boolean,
1243
+ }
1244
+
1245
+ /** The contact's business profile email */
1246
+ email: string,
1247
+
1248
+ /** The contact's business profile websites */
1249
+ website: string[],
1250
+
1251
+ /** The contact's business profile latitude */
1252
+ latitude: number,
1253
+
1254
+ /** The contact's business profile longitude */
1255
+ longitude: number,
1256
+
1257
+ /** The contact's business profile work hours*/
1258
+ businessHours: BusinessHours
1259
+
1260
+ /** The contact's business profile address */
1261
+ address: string,
1262
+
1263
+ /** The contact's business profile facebook page */
1264
+ fbPage: object,
1265
+
1266
+ /** Indicate if the contact's business profile linked */
1267
+ ifProfileLinked: boolean
1268
+
1269
+ /** The contact's business profile coverPhoto */
1270
+ coverPhoto: null | any,
1271
+ }
1178
1272
  }
1179
1273
 
1180
1274
  export interface PrivateContact extends Contact {
@@ -1320,7 +1414,7 @@ declare namespace WAWebJS {
1320
1414
  code: number;
1321
1415
  message: string;
1322
1416
  isInviteV4Sent: boolean,
1323
- };
1417
+ }
1324
1418
  };
1325
1419
 
1326
1420
  /** An object that handles options for adding participants */
@@ -1389,7 +1483,7 @@ declare namespace WAWebJS {
1389
1483
  /** Group participants */
1390
1484
  participants: Array<GroupParticipant>;
1391
1485
  /** Adds a list of participants by ID to the group */
1392
- addParticipants: (participantIds: string|string[], options?: AddParticipantsOptions) => Promise<Object.<string, AddParticipantsResult>|string>;
1486
+ addParticipants: (participantIds: string | string[], options?: AddParticipantsOptions) => Promise<{ [key: string]: AddParticipantsResult } | string>;
1393
1487
  /** Removes a list of participants by ID to the group */
1394
1488
  removeParticipants: (participantIds: string[]) => Promise<{ status: number }>;
1395
1489
  /** Promotes participants by IDs to admins */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whatsapp-web.js",
3
- "version": "1.23.0",
3
+ "version": "1.23.1-alpha.1",
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
@@ -43,6 +43,7 @@ const NoAuth = require('./authStrategies/NoAuth');
43
43
  * @fires Client#message_create
44
44
  * @fires Client#message_revoke_me
45
45
  * @fires Client#message_revoke_everyone
46
+ * @fires Client#message_edit
46
47
  * @fires Client#media_uploaded
47
48
  * @fires Client#group_join
48
49
  * @fires Client#group_leave
@@ -665,7 +666,7 @@ class Client extends EventEmitter {
665
666
  window.Store.Msg.on('change:ack', (msg, ack) => { window.onMessageAckEvent(window.WWebJS.getMessageModel(msg), ack); });
666
667
  window.Store.Msg.on('change:isUnsentMedia', (msg, unsent) => { if (msg.id.fromMe && !unsent) window.onMessageMediaUploadedEvent(window.WWebJS.getMessageModel(msg)); });
667
668
  window.Store.Msg.on('remove', (msg) => { if (msg.isNewMsg) window.onRemoveMessageEvent(window.WWebJS.getMessageModel(msg)); });
668
- window.Store.Msg.on('change:body', (msg, newBody, prevBody) => { window.onEditMessageEvent(window.WWebJS.getMessageModel(msg), newBody, prevBody); });
669
+ window.Store.Msg.on('change:body change:caption', (msg, newBody, prevBody) => { window.onEditMessageEvent(window.WWebJS.getMessageModel(msg), newBody, prevBody); });
669
670
  window.Store.AppState.on('change:state', (_AppState, state) => { window.onAppStateChangedEvent(state); });
670
671
  window.Store.Conn.on('change:battery', (state) => { window.onBatteryStateChangedEvent(state); });
671
672
  window.Store.Call.on('add', (call) => { window.onIncomingCall(call); });
@@ -1047,8 +1048,8 @@ class Client extends EventEmitter {
1047
1048
  if(!window.Store.Conn.canSetMyPushname()) return false;
1048
1049
 
1049
1050
  if(window.Store.MDBackend) {
1050
- // TODO
1051
- return false;
1051
+ await window.Store.Settings.setPushname(displayName);
1052
+ return true;
1052
1053
  } else {
1053
1054
  const res = await window.Store.Wap.setPushname(displayName);
1054
1055
  return !res.status || res.status === 200;
@@ -1597,6 +1598,67 @@ class Client extends EventEmitter {
1597
1598
  return await window.WWebJS.membershipRequestAction(groupId, 'Reject', requesterIds, sleep);
1598
1599
  }, groupId, options);
1599
1600
  }
1601
+
1602
+
1603
+ /**
1604
+ * Setting autoload download audio
1605
+ * @param {boolean} flag true/false
1606
+ */
1607
+ async setAutoDownloadAudio(flag) {
1608
+ await this.pupPage.evaluate(async flag => {
1609
+ const autoDownload = window.Store.Settings.getAutoDownloadAudio();
1610
+ if (autoDownload === flag) {
1611
+ return flag;
1612
+ }
1613
+ await window.Store.Settings.setAutoDownloadAudio(flag);
1614
+ return flag;
1615
+ }, flag);
1616
+ }
1617
+
1618
+ /**
1619
+ * Setting autoload download documents
1620
+ * @param {boolean} flag true/false
1621
+ */
1622
+ async setAutoDownloadDocuments(flag) {
1623
+ await this.pupPage.evaluate(async flag => {
1624
+ const autoDownload = window.Store.Settings.getAutoDownloadDocuments();
1625
+ if (autoDownload === flag) {
1626
+ return flag;
1627
+ }
1628
+ await window.Store.Settings.setAutoDownloadDocuments(flag);
1629
+ return flag;
1630
+ }, flag);
1631
+ }
1632
+
1633
+ /**
1634
+ * Setting autoload download photos
1635
+ * @param {boolean} flag true/false
1636
+ */
1637
+ async setAutoDownloadPhotos(flag) {
1638
+ await this.pupPage.evaluate(async flag => {
1639
+ const autoDownload = window.Store.Settings.getAutoDownloadPhotos();
1640
+ if (autoDownload === flag) {
1641
+ return flag;
1642
+ }
1643
+ await window.Store.Settings.setAutoDownloadPhotos(flag);
1644
+ return flag;
1645
+ }, flag);
1646
+ }
1647
+
1648
+ /**
1649
+ * Setting autoload download videos
1650
+ * @param {boolean} flag true/false
1651
+ */
1652
+ async setAutoDownloadVideos(flag) {
1653
+ await this.pupPage.evaluate(async flag => {
1654
+ const autoDownload = window.Store.Settings.getAutoDownloadVideos();
1655
+ if (autoDownload === flag) {
1656
+ return flag;
1657
+ }
1658
+ await window.Store.Settings.setAutoDownloadVideos(flag);
1659
+ return flag;
1660
+ }, flag);
1661
+ }
1600
1662
  }
1601
1663
 
1602
1664
  module.exports = Client;
@@ -431,7 +431,7 @@ class Message extends Base {
431
431
 
432
432
  const result = await this.client.pupPage.evaluate(async (msgId) => {
433
433
  const msg = window.Store.Msg.get(msgId);
434
- if (!msg) {
434
+ if (!msg || !msg.mediaData) {
435
435
  return undefined;
436
436
  }
437
437
  if (msg.mediaData.mediaStage != 'RESOLVED') {
@@ -534,15 +534,20 @@ class Message extends Base {
534
534
  */
535
535
 
536
536
  /**
537
- * Get information about message delivery status. May return null if the message does not exist or is not sent by you.
537
+ * Get information about message delivery status.
538
+ * May return null if the message does not exist or is not sent by you.
538
539
  * @returns {Promise<?MessageInfo>}
539
540
  */
540
541
  async getInfo() {
541
542
  const info = await this.client.pupPage.evaluate(async (msgId) => {
542
543
  const msg = window.Store.Msg.get(msgId);
543
- if (!msg) return null;
544
+ if (!msg || !msg.id.fromMe) return null;
544
545
 
545
- return await window.Store.MessageInfo.sendQueryMsgInfo(msg.id);
546
+ return new Promise((resolve) => {
547
+ setTimeout(async () => {
548
+ resolve(await window.Store.getMsgInfo(msg.id));
549
+ }, (Date.now() - msg.t * 1000 < 1250) && Math.floor(Math.random() * (1200 - 1100 + 1)) + 1100 || 0);
550
+ });
546
551
  }, this.id._serialized);
547
552
 
548
553
  return info;
@@ -639,7 +644,7 @@ class Message extends Base {
639
644
  let msg = window.Store.Msg.get(msgId);
640
645
  if (!msg) return null;
641
646
 
642
- let catEdit = (msg.type === 'chat' && window.Store.MsgActionChecks.canEditText(msg));
647
+ let catEdit = window.Store.MsgActionChecks.canEditText(msg) || window.Store.MsgActionChecks.canEditCaption(msg);
643
648
  if (catEdit) {
644
649
  const msgEdit = await window.WWebJS.editMessage(msg, message, options);
645
650
  return msgEdit.serialize();
@@ -23,7 +23,6 @@ exports.ExposeStore = (moduleRaidStr) => {
23
23
  window.Store.MediaTypes = window.mR.findModule('msgToMediaType')[0];
24
24
  window.Store.MediaUpload = window.mR.findModule('uploadMedia')[0];
25
25
  window.Store.MsgKey = window.mR.findModule((module) => module.default && module.default.fromString)[0].default;
26
- window.Store.MessageInfo = window.mR.findModule('sendQueryMsgInfo')[0];
27
26
  window.Store.OpaqueData = window.mR.findModule(module => module.default && module.default.createFromData)[0].default;
28
27
  window.Store.QueryProduct = window.mR.findModule('queryProduct')[0];
29
28
  window.Store.QueryOrder = window.mR.findModule('queryOrder')[0];
@@ -62,8 +61,13 @@ exports.ExposeStore = (moduleRaidStr) => {
62
61
  /* eslint-disable no-undef, no-cond-assign */
63
62
  window.Store.QueryExist = ((m = window.mR.findModule('queryExists')[0]) ? m.queryExists : window.mR.findModule('queryExist')[0].queryWidExists);
64
63
  window.Store.ReplyUtils = (m = window.mR.findModule('canReplyMsg')).length > 0 && m[0];
64
+ window.Store.getMsgInfo = (window.mR.findModule('sendQueryMsgInfo')[0] || {}).sendQueryMsgInfo || window.mR.findModule('queryMsgInfo')[0].queryMsgInfo;
65
65
  /* eslint-enable no-undef, no-cond-assign */
66
66
 
67
+ window.Store.Settings = {
68
+ ...window.mR.findModule('ChatlistPanelState')[0],
69
+ setPushname: window.mR.findModule((m) => m.setPushname && !m.ChatlistPanelState)[0].setPushname
70
+ };
67
71
  window.Store.StickerTools = {
68
72
  ...window.mR.findModule('toWebpSticker')[0],
69
73
  ...window.mR.findModule('addWebpMetadata')[0]
@@ -124,9 +128,9 @@ exports.ExposeStore = (moduleRaidStr) => {
124
128
  /**
125
129
  * Target options object description
126
130
  * @typedef {Object} TargetOptions
127
- * @property {string|number} moduleId The name or a key of the target module to search
131
+ * @property {string|number} module The name or a key of the target module to search
128
132
  * @property {number} index The index value of the target module
129
- * @property {string} property The function name to get from a module
133
+ * @property {string} function The function name to get from a module
130
134
  */
131
135
 
132
136
  /**
@@ -135,17 +139,17 @@ exports.ExposeStore = (moduleRaidStr) => {
135
139
  * @param {Function} callback Modified function
136
140
  */
137
141
  window.injectToFunction = (target, callback) => {
138
- const module = typeof target.moduleId === 'string'
139
- ? window.mR.findModule(target.moduleId)
140
- : window.mR.modules[target.moduleId];
141
- const originalFunction = module[target.index][target.property];
142
+ const module = typeof target.module === 'string'
143
+ ? window.mR.findModule(target.module)
144
+ : window.mR.modules[target.module];
145
+ const originalFunction = module[target.index][target.function];
142
146
  const modifiedFunction = (...args) => callback(originalFunction, ...args);
143
- module[target.index][target.property] = modifiedFunction;
147
+ module[target.index][target.function] = modifiedFunction;
144
148
  };
145
149
 
146
- window.injectToFunction({ moduleId: 'mediaTypeFromProtobuf', index: 0, property: 'mediaTypeFromProtobuf' }, (func, ...args) => { const [proto] = args; return proto.locationMessage ? null : func(...args); });
150
+ window.injectToFunction({ module: 'mediaTypeFromProtobuf', index: 0, function: 'mediaTypeFromProtobuf' }, (func, ...args) => { const [proto] = args; return proto.locationMessage ? null : func(...args); });
147
151
 
148
- window.injectToFunction({ moduleId: 'typeAttributeFromProtobuf', index: 0, property: 'typeAttributeFromProtobuf' }, (func, ...args) => { const [proto] = args; return proto.locationMessage || proto.groupInviteMessage ? 'text' : func(...args); });
152
+ window.injectToFunction({ module: 'typeAttributeFromProtobuf', index: 0, function: 'typeAttributeFromProtobuf' }, (func, ...args) => { const [proto] = args; return proto.locationMessage || proto.groupInviteMessage ? 'text' : func(...args); });
149
153
  };
150
154
 
151
155
  exports.LoadUtils = () => {