whatsapp-web-sj.js 1.26.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.
Files changed (52) hide show
  1. package/.env.example +3 -0
  2. package/CODE_OF_CONDUCT.md +133 -0
  3. package/LICENSE +201 -0
  4. package/README.md +185 -0
  5. package/example.js +634 -0
  6. package/index.d.ts +1842 -0
  7. package/index.js +32 -0
  8. package/package.json +55 -0
  9. package/shell.js +36 -0
  10. package/src/Client.js +1747 -0
  11. package/src/authStrategies/BaseAuthStrategy.js +27 -0
  12. package/src/authStrategies/LocalAuth.js +56 -0
  13. package/src/authStrategies/NoAuth.js +12 -0
  14. package/src/authStrategies/RemoteAuth.js +204 -0
  15. package/src/factories/ChatFactory.js +16 -0
  16. package/src/factories/ContactFactory.js +16 -0
  17. package/src/structures/Base.js +22 -0
  18. package/src/structures/BusinessContact.js +21 -0
  19. package/src/structures/Buttons.js +82 -0
  20. package/src/structures/Call.js +76 -0
  21. package/src/structures/Chat.js +275 -0
  22. package/src/structures/ClientInfo.js +71 -0
  23. package/src/structures/Contact.js +208 -0
  24. package/src/structures/GroupChat.js +475 -0
  25. package/src/structures/GroupNotification.js +104 -0
  26. package/src/structures/Label.js +50 -0
  27. package/src/structures/List.js +79 -0
  28. package/src/structures/Location.js +61 -0
  29. package/src/structures/Message.js +711 -0
  30. package/src/structures/MessageMedia.js +111 -0
  31. package/src/structures/Order.js +52 -0
  32. package/src/structures/Payment.js +79 -0
  33. package/src/structures/Poll.js +44 -0
  34. package/src/structures/PollVote.js +61 -0
  35. package/src/structures/PrivateChat.js +13 -0
  36. package/src/structures/PrivateContact.js +13 -0
  37. package/src/structures/Product.js +68 -0
  38. package/src/structures/ProductMetadata.js +25 -0
  39. package/src/structures/Reaction.js +69 -0
  40. package/src/structures/index.js +24 -0
  41. package/src/util/Constants.js +176 -0
  42. package/src/util/Injected/AuthStore/AuthStore.js +17 -0
  43. package/src/util/Injected/AuthStore/LegacyAuthStore.js +22 -0
  44. package/src/util/Injected/LegacyStore.js +146 -0
  45. package/src/util/Injected/Store.js +167 -0
  46. package/src/util/Injected/Utils.js +1017 -0
  47. package/src/util/InterfaceController.js +127 -0
  48. package/src/util/Util.js +186 -0
  49. package/src/webCache/LocalWebCache.js +40 -0
  50. package/src/webCache/RemoteWebCache.js +40 -0
  51. package/src/webCache/WebCache.js +14 -0
  52. package/src/webCache/WebCacheFactory.js +20 -0
@@ -0,0 +1,275 @@
1
+ 'use strict';
2
+
3
+ const Base = require('./Base');
4
+ const Message = require('./Message');
5
+
6
+ /**
7
+ * Represents a Chat on WhatsApp
8
+ * @extends {Base}
9
+ */
10
+ class Chat extends Base {
11
+ constructor(client, data) {
12
+ super(client);
13
+
14
+ if (data) this._patch(data);
15
+ }
16
+
17
+ _patch(data) {
18
+ /**
19
+ * ID that represents the chat
20
+ * @type {object}
21
+ */
22
+ this.id = data.id;
23
+
24
+ /**
25
+ * Title of the chat
26
+ * @type {string}
27
+ */
28
+ this.name = data.formattedTitle;
29
+
30
+ /**
31
+ * Indicates if the Chat is a Group Chat
32
+ * @type {boolean}
33
+ */
34
+ this.isGroup = data.isGroup;
35
+
36
+ /**
37
+ * Indicates if the Chat is readonly
38
+ * @type {boolean}
39
+ */
40
+ this.isReadOnly = data.isReadOnly;
41
+
42
+ /**
43
+ * Amount of messages unread
44
+ * @type {number}
45
+ */
46
+ this.unreadCount = data.unreadCount;
47
+
48
+ /**
49
+ * Unix timestamp for when the last activity occurred
50
+ * @type {number}
51
+ */
52
+ this.timestamp = data.t;
53
+
54
+ /**
55
+ * Indicates if the Chat is archived
56
+ * @type {boolean}
57
+ */
58
+ this.archived = data.archive;
59
+
60
+ /**
61
+ * Indicates if the Chat is pinned
62
+ * @type {boolean}
63
+ */
64
+ this.pinned = !!data.pin;
65
+
66
+ /**
67
+ * Indicates if the chat is muted or not
68
+ * @type {boolean}
69
+ */
70
+ this.isMuted = data.isMuted;
71
+
72
+ /**
73
+ * Unix timestamp for when the mute expires
74
+ * @type {number}
75
+ */
76
+ this.muteExpiration = data.muteExpiration;
77
+
78
+ /**
79
+ * Last message fo chat
80
+ * @type {Message}
81
+ */
82
+ this.lastMessage = data.lastMessage ? new Message(super.client, data.lastMessage) : undefined;
83
+
84
+ return super._patch(data);
85
+ }
86
+
87
+ /**
88
+ * Send a message to this chat
89
+ * @param {string|MessageMedia|Location} content
90
+ * @param {MessageSendOptions} [options]
91
+ * @returns {Promise<Message>} Message that was just sent
92
+ */
93
+ async sendMessage(content, options) {
94
+ return this.client.sendMessage(this.id._serialized, content, options);
95
+ }
96
+
97
+ /**
98
+ * Set the message as seen
99
+ * @returns {Promise<Boolean>} result
100
+ */
101
+ async sendSeen() {
102
+ return this.client.sendSeen(this.id._serialized);
103
+ }
104
+
105
+ /**
106
+ * Clears all messages from the chat
107
+ * @returns {Promise<Boolean>} result
108
+ */
109
+ async clearMessages() {
110
+ return this.client.pupPage.evaluate(chatId => {
111
+ return window.WWebJS.sendClearChat(chatId);
112
+ }, this.id._serialized);
113
+ }
114
+
115
+ /**
116
+ * Deletes the chat
117
+ * @returns {Promise<Boolean>} result
118
+ */
119
+ async delete() {
120
+ return this.client.pupPage.evaluate(chatId => {
121
+ return window.WWebJS.sendDeleteChat(chatId);
122
+ }, this.id._serialized);
123
+ }
124
+
125
+ /**
126
+ * Archives this chat
127
+ */
128
+ async archive() {
129
+ return this.client.archiveChat(this.id._serialized);
130
+ }
131
+
132
+ /**
133
+ * un-archives this chat
134
+ */
135
+ async unarchive() {
136
+ return this.client.unarchiveChat(this.id._serialized);
137
+ }
138
+
139
+ /**
140
+ * Pins this chat
141
+ * @returns {Promise<boolean>} New pin state. Could be false if the max number of pinned chats was reached.
142
+ */
143
+ async pin() {
144
+ return this.client.pinChat(this.id._serialized);
145
+ }
146
+
147
+ /**
148
+ * Unpins this chat
149
+ * @returns {Promise<boolean>} New pin state
150
+ */
151
+ async unpin() {
152
+ return this.client.unpinChat(this.id._serialized);
153
+ }
154
+
155
+ /**
156
+ * Mutes this chat forever, unless a date is specified
157
+ * @param {?Date} unmuteDate Date at which the Chat will be unmuted, leave as is to mute forever
158
+ */
159
+ async mute(unmuteDate) {
160
+ return this.client.muteChat(this.id._serialized, unmuteDate);
161
+ }
162
+
163
+ /**
164
+ * Unmutes this chat
165
+ */
166
+ async unmute() {
167
+ return this.client.unmuteChat(this.id._serialized);
168
+ }
169
+
170
+ /**
171
+ * Mark this chat as unread
172
+ */
173
+ async markUnread(){
174
+ return this.client.markChatUnread(this.id._serialized);
175
+ }
176
+
177
+ /**
178
+ * Loads chat messages, sorted from earliest to latest.
179
+ * @param {Object} searchOptions Options for searching messages. Right now only limit and fromMe is supported.
180
+ * @param {Number} [searchOptions.limit] The amount of messages to return. If no limit is specified, the available messages will be returned. Note that the actual number of returned messages may be smaller if there aren't enough messages in the conversation. Set this to Infinity to load all messages.
181
+ * @param {Boolean} [searchOptions.fromMe] Return only messages from the bot number or vise versa. To get all messages, leave the option undefined.
182
+ * @returns {Promise<Array<Message>>}
183
+ */
184
+ async fetchMessages(searchOptions) {
185
+ let messages = await this.client.pupPage.evaluate(async (chatId, searchOptions) => {
186
+ const msgFilter = (m) => {
187
+ if (m.isNotification) {
188
+ return false; // dont include notification messages
189
+ }
190
+ if (searchOptions && searchOptions.fromMe !== undefined && m.id.fromMe !== searchOptions.fromMe) {
191
+ return false;
192
+ }
193
+ return true;
194
+ };
195
+
196
+ const chat = window.Store.Chat.get(chatId);
197
+ let msgs = chat.msgs.getModelsArray().filter(msgFilter);
198
+
199
+ if (searchOptions && searchOptions.limit > 0) {
200
+ while (msgs.length < searchOptions.limit) {
201
+ const loadedMessages = await window.Store.ConversationMsgs.loadEarlierMsgs(chat);
202
+ if (!loadedMessages || !loadedMessages.length) break;
203
+ msgs = [...loadedMessages.filter(msgFilter), ...msgs];
204
+ }
205
+
206
+ if (msgs.length > searchOptions.limit) {
207
+ msgs.sort((a, b) => (a.t > b.t) ? 1 : -1);
208
+ msgs = msgs.splice(msgs.length - searchOptions.limit);
209
+ }
210
+ }
211
+
212
+ return msgs.map(m => window.WWebJS.getMessageModel(m));
213
+
214
+ }, this.id._serialized, searchOptions);
215
+
216
+ return messages.map(m => new Message(this.client, m));
217
+ }
218
+
219
+ /**
220
+ * Simulate typing in chat. This will last for 25 seconds.
221
+ */
222
+ async sendStateTyping() {
223
+ return this.client.pupPage.evaluate(chatId => {
224
+ window.WWebJS.sendChatstate('typing', chatId);
225
+ return true;
226
+ }, this.id._serialized);
227
+ }
228
+
229
+ /**
230
+ * Simulate recording audio in chat. This will last for 25 seconds.
231
+ */
232
+ async sendStateRecording() {
233
+ return this.client.pupPage.evaluate(chatId => {
234
+ window.WWebJS.sendChatstate('recording', chatId);
235
+ return true;
236
+ }, this.id._serialized);
237
+ }
238
+
239
+ /**
240
+ * Stops typing or recording in chat immediately.
241
+ */
242
+ async clearState() {
243
+ return this.client.pupPage.evaluate(chatId => {
244
+ window.WWebJS.sendChatstate('stop', chatId);
245
+ return true;
246
+ }, this.id._serialized);
247
+ }
248
+
249
+ /**
250
+ * Returns the Contact that corresponds to this Chat.
251
+ * @returns {Promise<Contact>}
252
+ */
253
+ async getContact() {
254
+ return await this.client.getContactById(this.id._serialized);
255
+ }
256
+
257
+ /**
258
+ * Returns array of all Labels assigned to this Chat
259
+ * @returns {Promise<Array<Label>>}
260
+ */
261
+ async getLabels() {
262
+ return this.client.getChatLabels(this.id._serialized);
263
+ }
264
+
265
+ /**
266
+ * Add or remove labels to this Chat
267
+ * @param {Array<number|string>} labelIds
268
+ * @returns {Promise<void>}
269
+ */
270
+ async changeLabels(labelIds) {
271
+ return this.client.addOrRemoveLabels(labelIds, [this.id._serialized]);
272
+ }
273
+ }
274
+
275
+ module.exports = Chat;
@@ -0,0 +1,71 @@
1
+ 'use strict';
2
+
3
+ const Base = require('./Base');
4
+
5
+ /**
6
+ * Current connection information
7
+ * @extends {Base}
8
+ */
9
+ class ClientInfo extends Base {
10
+ constructor(client, data) {
11
+ super(client);
12
+
13
+ if (data) this._patch(data);
14
+ }
15
+
16
+ _patch(data) {
17
+ /**
18
+ * Name configured to be shown in push notifications
19
+ * @type {string}
20
+ */
21
+ this.pushname = data.pushname;
22
+
23
+ /**
24
+ * Current user ID
25
+ * @type {object}
26
+ */
27
+ this.wid = data.wid;
28
+
29
+ /**
30
+ * @type {object}
31
+ * @deprecated Use .wid instead
32
+ */
33
+ this.me = data.wid;
34
+
35
+ /**
36
+ * Information about the phone this client is connected to. Not available in multi-device.
37
+ * @type {object}
38
+ * @property {string} wa_version WhatsApp Version running on the phone
39
+ * @property {string} os_version OS Version running on the phone (iOS or Android version)
40
+ * @property {string} device_manufacturer Device manufacturer
41
+ * @property {string} device_model Device model
42
+ * @property {string} os_build_number OS build number
43
+ * @deprecated
44
+ */
45
+ this.phone = data.phone;
46
+
47
+ /**
48
+ * Platform WhatsApp is running on
49
+ * @type {string}
50
+ */
51
+ this.platform = data.platform;
52
+
53
+ return super._patch(data);
54
+ }
55
+
56
+ /**
57
+ * Get current battery percentage and charging status for the attached device
58
+ * @returns {object} batteryStatus
59
+ * @returns {number} batteryStatus.battery - The current battery percentage
60
+ * @returns {boolean} batteryStatus.plugged - Indicates if the phone is plugged in (true) or not (false)
61
+ * @deprecated
62
+ */
63
+ async getBatteryStatus() {
64
+ return await this.client.pupPage.evaluate(() => {
65
+ const { battery, plugged } = window.Store.Conn;
66
+ return { battery, plugged };
67
+ });
68
+ }
69
+ }
70
+
71
+ module.exports = ClientInfo;
@@ -0,0 +1,208 @@
1
+ 'use strict';
2
+
3
+ const Base = require('./Base');
4
+
5
+ /**
6
+ * ID that represents a contact
7
+ * @typedef {Object} ContactId
8
+ * @property {string} server
9
+ * @property {string} user
10
+ * @property {string} _serialized
11
+ */
12
+
13
+ /**
14
+ * Represents a Contact on WhatsApp
15
+ * @extends {Base}
16
+ */
17
+ class Contact extends Base {
18
+ constructor(client, data) {
19
+ super(client);
20
+
21
+ if(data) this._patch(data);
22
+ }
23
+
24
+ _patch(data) {
25
+ /**
26
+ * ID that represents the contact
27
+ * @type {ContactId}
28
+ */
29
+ this.id = data.id;
30
+
31
+ /**
32
+ * Contact's phone number
33
+ * @type {string}
34
+ */
35
+ this.number = data.userid;
36
+
37
+ /**
38
+ * Indicates if the contact is a business contact
39
+ * @type {boolean}
40
+ */
41
+ this.isBusiness = data.isBusiness;
42
+
43
+ /**
44
+ * Indicates if the contact is an enterprise contact
45
+ * @type {boolean}
46
+ */
47
+ this.isEnterprise = data.isEnterprise;
48
+
49
+ this.labels = data.labels;
50
+
51
+ /**
52
+ * The contact's name, as saved by the current user
53
+ * @type {?string}
54
+ */
55
+ this.name = data.name;
56
+
57
+ /**
58
+ * The name that the contact has configured to be shown publically
59
+ * @type {string}
60
+ */
61
+ this.pushname = data.pushname;
62
+
63
+ this.sectionHeader = data.sectionHeader;
64
+
65
+ /**
66
+ * A shortened version of name
67
+ * @type {?string}
68
+ */
69
+ this.shortName = data.shortName;
70
+
71
+ this.statusMute = data.statusMute;
72
+ this.type = data.type;
73
+ this.verifiedLevel = data.verifiedLevel;
74
+ this.verifiedName = data.verifiedName;
75
+
76
+ /**
77
+ * Indicates if the contact is the current user's contact
78
+ * @type {boolean}
79
+ */
80
+ this.isMe = data.isMe;
81
+
82
+ /**
83
+ * Indicates if the contact is a user contact
84
+ * @type {boolean}
85
+ */
86
+ this.isUser = data.isUser;
87
+
88
+ /**
89
+ * Indicates if the contact is a group contact
90
+ * @type {boolean}
91
+ */
92
+ this.isGroup = data.isGroup;
93
+
94
+ /**
95
+ * Indicates if the number is registered on WhatsApp
96
+ * @type {boolean}
97
+ */
98
+ this.isWAContact = data.isWAContact;
99
+
100
+ /**
101
+ * Indicates if the number is saved in the current phone's contacts
102
+ * @type {boolean}
103
+ */
104
+ this.isMyContact = data.isMyContact;
105
+
106
+ /**
107
+ * Indicates if you have blocked this contact
108
+ * @type {boolean}
109
+ */
110
+ this.isBlocked = data.isBlocked;
111
+
112
+ return super._patch(data);
113
+ }
114
+
115
+ /**
116
+ * Returns the contact's profile picture URL, if privacy settings allow it
117
+ * @returns {Promise<string>}
118
+ */
119
+ async getProfilePicUrl() {
120
+ return await this.client.getProfilePicUrl(this.id._serialized);
121
+ }
122
+
123
+ /**
124
+ * Returns the contact's formatted phone number, (12345678901@c.us) => (+1 (234) 5678-901)
125
+ * @returns {Promise<string>}
126
+ */
127
+ async getFormattedNumber() {
128
+ return await this.client.getFormattedNumber(this.id._serialized);
129
+ }
130
+
131
+ /**
132
+ * Returns the contact's countrycode, (1541859685@c.us) => (1)
133
+ * @returns {Promise<string>}
134
+ */
135
+ async getCountryCode() {
136
+ return await this.client.getCountryCode(this.id._serialized);
137
+ }
138
+
139
+ /**
140
+ * Returns the Chat that corresponds to this Contact.
141
+ * Will return null when getting chat for currently logged in user.
142
+ * @returns {Promise<Chat>}
143
+ */
144
+ async getChat() {
145
+ if(this.isMe) return null;
146
+
147
+ return await this.client.getChatById(this.id._serialized);
148
+ }
149
+
150
+ /**
151
+ * Blocks this contact from WhatsApp
152
+ * @returns {Promise<boolean>}
153
+ */
154
+ async block() {
155
+ if(this.isGroup) return false;
156
+
157
+ await this.client.pupPage.evaluate(async (contactId) => {
158
+ const contact = window.Store.Contact.get(contactId);
159
+ await window.Store.BlockContact.blockContact({contact});
160
+ }, this.id._serialized);
161
+
162
+ this.isBlocked = true;
163
+ return true;
164
+ }
165
+
166
+ /**
167
+ * Unblocks this contact from WhatsApp
168
+ * @returns {Promise<boolean>}
169
+ */
170
+ async unblock() {
171
+ if(this.isGroup) return false;
172
+
173
+ await this.client.pupPage.evaluate(async (contactId) => {
174
+ const contact = window.Store.Contact.get(contactId);
175
+ await window.Store.BlockContact.unblockContact(contact);
176
+ }, this.id._serialized);
177
+
178
+ this.isBlocked = false;
179
+ return true;
180
+ }
181
+
182
+ /**
183
+ * Gets the Contact's current "about" info. Returns null if you don't have permission to read their status.
184
+ * @returns {Promise<?string>}
185
+ */
186
+ async getAbout() {
187
+ const about = await this.client.pupPage.evaluate(async (contactId) => {
188
+ const wid = window.Store.WidFactory.createWid(contactId);
189
+ return window.Store.StatusUtils.getStatus(wid);
190
+ }, this.id._serialized);
191
+
192
+ if (typeof about.status !== 'string')
193
+ return null;
194
+
195
+ return about.status;
196
+ }
197
+
198
+ /**
199
+ * Gets the Contact's common groups with you. Returns empty array if you don't have any common group.
200
+ * @returns {Promise<WAWebJS.ChatId[]>}
201
+ */
202
+ async getCommonGroups() {
203
+ return await this.client.getCommonGroups(this.id._serialized);
204
+ }
205
+
206
+ }
207
+
208
+ module.exports = Contact;