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
package/example.js ADDED
@@ -0,0 +1,634 @@
1
+ const { Client, Location, Poll, List, Buttons, LocalAuth } = require('./index');
2
+
3
+ const client = new Client({
4
+ authStrategy: new LocalAuth(),
5
+ // proxyAuthentication: { username: 'username', password: 'password' },
6
+ puppeteer: {
7
+ // args: ['--proxy-server=proxy-server-that-requires-authentication.example.com'],
8
+ headless: false,
9
+ }
10
+ });
11
+
12
+ // client initialize does not finish at ready now.
13
+ client.initialize();
14
+
15
+ client.on('loading_screen', (percent, message) => {
16
+ console.log('LOADING SCREEN', percent, message);
17
+ });
18
+
19
+ // Pairing code only needs to be requested once
20
+ let pairingCodeRequested = false;
21
+ client.on('qr', async (qr) => {
22
+ // NOTE: This event will not be fired if a session is specified.
23
+ console.log('QR RECEIVED', qr);
24
+
25
+ // paiuting code example
26
+ const pairingCodeEnabled = false;
27
+ if (pairingCodeEnabled && !pairingCodeRequested) {
28
+ const pairingCode = await client.requestPairingCode('96170100100'); // enter the target phone number
29
+ console.log('Pairing code enabled, code: '+ pairingCode);
30
+ pairingCodeRequested = true;
31
+ }
32
+ });
33
+
34
+ client.on('authenticated', () => {
35
+ console.log('AUTHENTICATED');
36
+ });
37
+
38
+ client.on('auth_failure', msg => {
39
+ // Fired if session restore was unsuccessful
40
+ console.error('AUTHENTICATION FAILURE', msg);
41
+ });
42
+
43
+ client.on('ready', async () => {
44
+ console.log('READY');
45
+ const debugWWebVersion = await client.getWWebVersion();
46
+ console.log(`WWebVersion = ${debugWWebVersion}`);
47
+
48
+ client.pupPage.on('pageerror', function(err) {
49
+ console.log('Page error: ' + err.toString());
50
+ });
51
+ client.pupPage.on('error', function(err) {
52
+ console.log('Page error: ' + err.toString());
53
+ });
54
+
55
+ });
56
+
57
+ client.on('message', async msg => {
58
+ console.log('MESSAGE RECEIVED', msg);
59
+
60
+ if (msg.body === '!ping reply') {
61
+ // Send a new message as a reply to the current one
62
+ msg.reply('pong');
63
+
64
+ } else if (msg.body === '!ping') {
65
+ // Send a new message to the same chat
66
+ client.sendMessage(msg.from, 'pong');
67
+
68
+ } else if (msg.body.startsWith('!sendto ')) {
69
+ // Direct send a new message to specific id
70
+ let number = msg.body.split(' ')[1];
71
+ let messageIndex = msg.body.indexOf(number) + number.length;
72
+ let message = msg.body.slice(messageIndex, msg.body.length);
73
+ number = number.includes('@c.us') ? number : `${number}@c.us`;
74
+ let chat = await msg.getChat();
75
+ chat.sendSeen();
76
+ client.sendMessage(number, message);
77
+
78
+ } else if (msg.body.startsWith('!subject ')) {
79
+ // Change the group subject
80
+ let chat = await msg.getChat();
81
+ if (chat.isGroup) {
82
+ let newSubject = msg.body.slice(9);
83
+ chat.setSubject(newSubject);
84
+ } else {
85
+ msg.reply('This command can only be used in a group!');
86
+ }
87
+ } else if (msg.body.startsWith('!echo ')) {
88
+ // Replies with the same message
89
+ msg.reply(msg.body.slice(6));
90
+ } else if (msg.body.startsWith('!preview ')) {
91
+ const text = msg.body.slice(9);
92
+ msg.reply(text, null, { linkPreview: true });
93
+ } else if (msg.body.startsWith('!desc ')) {
94
+ // Change the group description
95
+ let chat = await msg.getChat();
96
+ if (chat.isGroup) {
97
+ let newDescription = msg.body.slice(6);
98
+ chat.setDescription(newDescription);
99
+ } else {
100
+ msg.reply('This command can only be used in a group!');
101
+ }
102
+ } else if (msg.body === '!leave') {
103
+ // Leave the group
104
+ let chat = await msg.getChat();
105
+ if (chat.isGroup) {
106
+ chat.leave();
107
+ } else {
108
+ msg.reply('This command can only be used in a group!');
109
+ }
110
+ } else if (msg.body.startsWith('!join ')) {
111
+ const inviteCode = msg.body.split(' ')[1];
112
+ try {
113
+ await client.acceptInvite(inviteCode);
114
+ msg.reply('Joined the group!');
115
+ } catch (e) {
116
+ msg.reply('That invite code seems to be invalid.');
117
+ }
118
+ } else if (msg.body.startsWith('!addmembers')) {
119
+ const group = await msg.getChat();
120
+ const result = await group.addParticipants(['number1@c.us', 'number2@c.us', 'number3@c.us']);
121
+ /**
122
+ * The example of the {@link result} output:
123
+ *
124
+ * {
125
+ * 'number1@c.us': {
126
+ * code: 200,
127
+ * message: 'The participant was added successfully',
128
+ * isInviteV4Sent: false
129
+ * },
130
+ * 'number2@c.us': {
131
+ * code: 403,
132
+ * message: 'The participant can be added by sending private invitation only',
133
+ * isInviteV4Sent: true
134
+ * },
135
+ * 'number3@c.us': {
136
+ * code: 404,
137
+ * message: 'The phone number is not registered on WhatsApp',
138
+ * isInviteV4Sent: false
139
+ * }
140
+ * }
141
+ *
142
+ * For more usage examples:
143
+ * @see https://github.com/pedroslopez/whatsapp-web.js/pull/2344#usage-example1
144
+ */
145
+ console.log(result);
146
+ } else if (msg.body === '!creategroup') {
147
+ const partitipantsToAdd = ['number1@c.us', 'number2@c.us', 'number3@c.us'];
148
+ const result = await client.createGroup('Group Title', partitipantsToAdd);
149
+ /**
150
+ * The example of the {@link result} output:
151
+ * {
152
+ * title: 'Group Title',
153
+ * gid: {
154
+ * server: 'g.us',
155
+ * user: '1111111111',
156
+ * _serialized: '1111111111@g.us'
157
+ * },
158
+ * participants: {
159
+ * 'botNumber@c.us': {
160
+ * statusCode: 200,
161
+ * message: 'The participant was added successfully',
162
+ * isGroupCreator: true,
163
+ * isInviteV4Sent: false
164
+ * },
165
+ * 'number1@c.us': {
166
+ * statusCode: 200,
167
+ * message: 'The participant was added successfully',
168
+ * isGroupCreator: false,
169
+ * isInviteV4Sent: false
170
+ * },
171
+ * 'number2@c.us': {
172
+ * statusCode: 403,
173
+ * message: 'The participant can be added by sending private invitation only',
174
+ * isGroupCreator: false,
175
+ * isInviteV4Sent: true
176
+ * },
177
+ * 'number3@c.us': {
178
+ * statusCode: 404,
179
+ * message: 'The phone number is not registered on WhatsApp',
180
+ * isGroupCreator: false,
181
+ * isInviteV4Sent: false
182
+ * }
183
+ * }
184
+ * }
185
+ *
186
+ * For more usage examples:
187
+ * @see https://github.com/pedroslopez/whatsapp-web.js/pull/2344#usage-example2
188
+ */
189
+ console.log(result);
190
+ } else if (msg.body === '!groupinfo') {
191
+ let chat = await msg.getChat();
192
+ if (chat.isGroup) {
193
+ msg.reply(`
194
+ *Group Details*
195
+ Name: ${chat.name}
196
+ Description: ${chat.description}
197
+ Created At: ${chat.createdAt.toString()}
198
+ Created By: ${chat.owner.user}
199
+ Participant count: ${chat.participants.length}
200
+ `);
201
+ } else {
202
+ msg.reply('This command can only be used in a group!');
203
+ }
204
+ } else if (msg.body === '!chats') {
205
+ const chats = await client.getChats();
206
+ client.sendMessage(msg.from, `The bot has ${chats.length} chats open.`);
207
+ } else if (msg.body === '!info') {
208
+ let info = client.info;
209
+ client.sendMessage(msg.from, `
210
+ *Connection info*
211
+ User name: ${info.pushname}
212
+ My number: ${info.wid.user}
213
+ Platform: ${info.platform}
214
+ `);
215
+ } else if (msg.body === '!mediainfo' && msg.hasMedia) {
216
+ const attachmentData = await msg.downloadMedia();
217
+ msg.reply(`
218
+ *Media info*
219
+ MimeType: ${attachmentData.mimetype}
220
+ Filename: ${attachmentData.filename}
221
+ Data (length): ${attachmentData.data.length}
222
+ `);
223
+ } else if (msg.body === '!quoteinfo' && msg.hasQuotedMsg) {
224
+ const quotedMsg = await msg.getQuotedMessage();
225
+
226
+ quotedMsg.reply(`
227
+ ID: ${quotedMsg.id._serialized}
228
+ Type: ${quotedMsg.type}
229
+ Author: ${quotedMsg.author || quotedMsg.from}
230
+ Timestamp: ${quotedMsg.timestamp}
231
+ Has Media? ${quotedMsg.hasMedia}
232
+ `);
233
+ } else if (msg.body === '!resendmedia' && msg.hasQuotedMsg) {
234
+ const quotedMsg = await msg.getQuotedMessage();
235
+ if (quotedMsg.hasMedia) {
236
+ const attachmentData = await quotedMsg.downloadMedia();
237
+ client.sendMessage(msg.from, attachmentData, { caption: 'Here\'s your requested media.' });
238
+ }
239
+ if (quotedMsg.hasMedia && quotedMsg.type === 'audio') {
240
+ const audio = await quotedMsg.downloadMedia();
241
+ await client.sendMessage(msg.from, audio, { sendAudioAsVoice: true });
242
+ }
243
+ } else if (msg.body === '!isviewonce' && msg.hasQuotedMsg) {
244
+ const quotedMsg = await msg.getQuotedMessage();
245
+ if (quotedMsg.hasMedia) {
246
+ const media = await quotedMsg.downloadMedia();
247
+ await client.sendMessage(msg.from, media, { isViewOnce: true });
248
+ }
249
+ } else if (msg.body === '!location') {
250
+ // only latitude and longitude
251
+ await msg.reply(new Location(37.422, -122.084));
252
+ // location with name only
253
+ await msg.reply(new Location(37.422, -122.084, { name: 'Googleplex' }));
254
+ // location with address only
255
+ await msg.reply(new Location(37.422, -122.084, { address: '1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA' }));
256
+ // location with name, address and url
257
+ await msg.reply(new Location(37.422, -122.084, { name: 'Googleplex', address: '1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA', url: 'https://google.com' }));
258
+ } else if (msg.location) {
259
+ msg.reply(msg.location);
260
+ } else if (msg.body.startsWith('!status ')) {
261
+ const newStatus = msg.body.split(' ')[1];
262
+ await client.setStatus(newStatus);
263
+ msg.reply(`Status was updated to *${newStatus}*`);
264
+ } else if (msg.body === '!mentionUsers') {
265
+ const chat = await msg.getChat();
266
+ const userNumber = 'XXXXXXXXXX';
267
+ /**
268
+ * To mention one user you can pass user's ID to 'mentions' property as is,
269
+ * without wrapping it in Array, and a user's phone number to the message body:
270
+ */
271
+ await chat.sendMessage(`Hi @${userNumber}`, {
272
+ mentions: userNumber + '@c.us'
273
+ });
274
+ // To mention a list of users:
275
+ await chat.sendMessage(`Hi @${userNumber}, @${userNumber}`, {
276
+ mentions: [userNumber + '@c.us', userNumber + '@c.us']
277
+ });
278
+ } else if (msg.body === '!mentionGroups') {
279
+ const chat = await msg.getChat();
280
+ const groupId = 'YYYYYYYYYY@g.us';
281
+ /**
282
+ * Sends clickable group mentions, the same as user mentions.
283
+ * When the mentions are clicked, it opens a chat with the mentioned group.
284
+ * The 'groupMentions.subject' can be custom
285
+ *
286
+ * @note The user that does not participate in the mentioned group,
287
+ * will not be able to click on that mentioned group, the same if the group does not exist
288
+ *
289
+ * To mention one group:
290
+ */
291
+ await chat.sendMessage(`Check the last message here: @${groupId}`, {
292
+ groupMentions: { subject: 'GroupSubject', id: groupId }
293
+ });
294
+ // To mention a list of groups:
295
+ await chat.sendMessage(`Check the last message in these groups: @${groupId}, @${groupId}`, {
296
+ groupMentions: [
297
+ { subject: 'FirstGroup', id: groupId },
298
+ { subject: 'SecondGroup', id: groupId }
299
+ ]
300
+ });
301
+ } else if (msg.body === '!getGroupMentions') {
302
+ // To get group mentions from a message:
303
+ const groupId = 'ZZZZZZZZZZ@g.us';
304
+ const msg = await client.sendMessage('chatId', `Check the last message here: @${groupId}`, {
305
+ groupMentions: { subject: 'GroupSubject', id: groupId }
306
+ });
307
+ /** {@link groupMentions} is an array of `GroupChat` */
308
+ const groupMentions = await msg.getGroupMentions();
309
+ console.log(groupMentions);
310
+ } else if (msg.body === '!delete') {
311
+ if (msg.hasQuotedMsg) {
312
+ const quotedMsg = await msg.getQuotedMessage();
313
+ if (quotedMsg.fromMe) {
314
+ quotedMsg.delete(true);
315
+ } else {
316
+ msg.reply('I can only delete my own messages');
317
+ }
318
+ }
319
+ } else if (msg.body === '!pin') {
320
+ const chat = await msg.getChat();
321
+ await chat.pin();
322
+ } else if (msg.body === '!archive') {
323
+ const chat = await msg.getChat();
324
+ await chat.archive();
325
+ } else if (msg.body === '!mute') {
326
+ const chat = await msg.getChat();
327
+ // mute the chat for 20 seconds
328
+ const unmuteDate = new Date();
329
+ unmuteDate.setSeconds(unmuteDate.getSeconds() + 20);
330
+ await chat.mute(unmuteDate);
331
+ } else if (msg.body === '!typing') {
332
+ const chat = await msg.getChat();
333
+ // simulates typing in the chat
334
+ chat.sendStateTyping();
335
+ } else if (msg.body === '!recording') {
336
+ const chat = await msg.getChat();
337
+ // simulates recording audio in the chat
338
+ chat.sendStateRecording();
339
+ } else if (msg.body === '!clearstate') {
340
+ const chat = await msg.getChat();
341
+ // stops typing or recording in the chat
342
+ chat.clearState();
343
+ } else if (msg.body === '!jumpto') {
344
+ if (msg.hasQuotedMsg) {
345
+ const quotedMsg = await msg.getQuotedMessage();
346
+ client.interface.openChatWindowAt(quotedMsg.id._serialized);
347
+ }
348
+ } else if (msg.body === '!buttons') {
349
+ let button = new Buttons('Button body', [{ body: 'bt1' }, { body: 'bt2' }, { body: 'bt3' }], 'title', 'footer');
350
+ client.sendMessage(msg.from, button);
351
+ } else if (msg.body === '!list') {
352
+ let sections = [
353
+ { title: 'sectionTitle', rows: [{ title: 'ListItem1', description: 'desc' }, { title: 'ListItem2' }] }
354
+ ];
355
+ let list = new List('List body', 'btnText', sections, 'Title', 'footer');
356
+ client.sendMessage(msg.from, list);
357
+ } else if (msg.body === '!reaction') {
358
+ msg.react('👍');
359
+ } else if (msg.body === '!sendpoll') {
360
+ /** By default the poll is created as a single choice poll: */
361
+ await msg.reply(new Poll('Winter or Summer?', ['Winter', 'Summer']));
362
+ /** If you want to provide a multiple choice poll, add allowMultipleAnswers as true: */
363
+ await msg.reply(new Poll('Cats or Dogs?', ['Cats', 'Dogs'], { allowMultipleAnswers: true }));
364
+ /**
365
+ * You can provide a custom message secret, it can be used as a poll ID:
366
+ * @note It has to be a unique vector with a length of 32
367
+ */
368
+ await msg.reply(
369
+ new Poll('Cats or Dogs?', ['Cats', 'Dogs'], {
370
+ messageSecret: [
371
+ 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
372
+ ]
373
+ })
374
+ );
375
+ } else if (msg.body === '!edit') {
376
+ if (msg.hasQuotedMsg) {
377
+ const quotedMsg = await msg.getQuotedMessage();
378
+ if (quotedMsg.fromMe) {
379
+ quotedMsg.edit(msg.body.replace('!edit', ''));
380
+ } else {
381
+ msg.reply('I can only edit my own messages');
382
+ }
383
+ }
384
+ } else if (msg.body === '!updatelabels') {
385
+ const chat = await msg.getChat();
386
+ await chat.changeLabels([0, 1]);
387
+ } else if (msg.body === '!addlabels') {
388
+ const chat = await msg.getChat();
389
+ let labels = (await chat.getLabels()).map((l) => l.id);
390
+ labels.push('0');
391
+ labels.push('1');
392
+ await chat.changeLabels(labels);
393
+ } else if (msg.body === '!removelabels') {
394
+ const chat = await msg.getChat();
395
+ await chat.changeLabels([]);
396
+ } else if (msg.body === '!approverequest') {
397
+ /**
398
+ * Presented an example for membership request approvals, the same examples are for the request rejections.
399
+ * To approve the membership request from a specific user:
400
+ */
401
+ await client.approveGroupMembershipRequests(msg.from, { requesterIds: 'number@c.us' });
402
+ /** The same for execution on group object (no need to provide the group ID): */
403
+ const group = await msg.getChat();
404
+ await group.approveGroupMembershipRequests({ requesterIds: 'number@c.us' });
405
+ /** To approve several membership requests: */
406
+ const approval = await client.approveGroupMembershipRequests(msg.from, {
407
+ requesterIds: ['number1@c.us', 'number2@c.us']
408
+ });
409
+ /**
410
+ * The example of the {@link approval} output:
411
+ * [
412
+ * {
413
+ * requesterId: 'number1@c.us',
414
+ * message: 'Rejected successfully'
415
+ * },
416
+ * {
417
+ * requesterId: 'number2@c.us',
418
+ * error: 404,
419
+ * message: 'ParticipantRequestNotFoundError'
420
+ * }
421
+ * ]
422
+ *
423
+ */
424
+ console.log(approval);
425
+ /** To approve all the existing membership requests (simply don't provide any user IDs): */
426
+ await client.approveGroupMembershipRequests(msg.from);
427
+ /** To change the sleep value to 300 ms: */
428
+ await client.approveGroupMembershipRequests(msg.from, {
429
+ requesterIds: ['number1@c.us', 'number2@c.us'],
430
+ sleep: 300
431
+ });
432
+ /** To change the sleep value to random value between 100 and 300 ms: */
433
+ await client.approveGroupMembershipRequests(msg.from, {
434
+ requesterIds: ['number1@c.us', 'number2@c.us'],
435
+ sleep: [100, 300]
436
+ });
437
+ /** To explicitly disable the sleep: */
438
+ await client.approveGroupMembershipRequests(msg.from, {
439
+ requesterIds: ['number1@c.us', 'number2@c.us'],
440
+ sleep: null
441
+ });
442
+ } else if (msg.body === '!pinmsg') {
443
+ /**
444
+ * Pins a message in a chat, a method takes a number in seconds for the message to be pinned.
445
+ * WhatsApp default values for duration to pass to the method are:
446
+ * 1. 86400 for 24 hours
447
+ * 2. 604800 for 7 days
448
+ * 3. 2592000 for 30 days
449
+ * You can pass your own value:
450
+ */
451
+ const result = await msg.pin(60); // Will pin a message for 1 minute
452
+ console.log(result); // True if the operation completed successfully, false otherwise
453
+ }else if (msg.body === '!howManyConnections'){
454
+ /**
455
+ * Get user device count by ID
456
+ * Each WaWeb Connection counts as one device, and the phone (if exists) counts as one
457
+ * So for a non-enterprise user with one WaWeb connection it should return "2"
458
+ */
459
+ let deviceCount = await client.getContactDeviceCount(msg.from);
460
+ await msg.reply(`You have *${deviceCount}* devices connected`);
461
+ }
462
+ });
463
+
464
+ client.on('message_create', async (msg) => {
465
+ // Fired on all message creations, including your own
466
+ if (msg.fromMe) {
467
+ // do stuff here
468
+ }
469
+
470
+ // Unpins a message
471
+ if (msg.fromMe && msg.body.startsWith('!unpin')) {
472
+ const pinnedMsg = await msg.getQuotedMessage();
473
+ if (pinnedMsg) {
474
+ // Will unpin a message
475
+ const result = await pinnedMsg.unpin();
476
+ console.log(result); // True if the operation completed successfully, false otherwise
477
+ }
478
+ }
479
+ });
480
+
481
+ client.on('message_ciphertext', (msg) => {
482
+ // Receiving new incoming messages that have been encrypted
483
+ // msg.type === 'ciphertext'
484
+ msg.body = 'Waiting for this message. Check your phone.';
485
+
486
+ // do stuff here
487
+ });
488
+
489
+ client.on('message_revoke_everyone', async (after, before) => {
490
+ // Fired whenever a message is deleted by anyone (including you)
491
+ console.log(after); // message after it was deleted.
492
+ if (before) {
493
+ console.log(before); // message before it was deleted.
494
+ }
495
+ });
496
+
497
+ client.on('message_revoke_me', async (msg) => {
498
+ // Fired whenever a message is only deleted in your own view.
499
+ console.log(msg.body); // message before it was deleted.
500
+ });
501
+
502
+ client.on('message_ack', (msg, ack) => {
503
+ /*
504
+ == ACK VALUES ==
505
+ ACK_ERROR: -1
506
+ ACK_PENDING: 0
507
+ ACK_SERVER: 1
508
+ ACK_DEVICE: 2
509
+ ACK_READ: 3
510
+ ACK_PLAYED: 4
511
+ */
512
+
513
+ if (ack == 3) {
514
+ // The message was read
515
+ }
516
+ });
517
+
518
+ client.on('group_join', (notification) => {
519
+ // User has joined or been added to the group.
520
+ console.log('join', notification);
521
+ notification.reply('User joined.');
522
+ });
523
+
524
+ client.on('group_leave', (notification) => {
525
+ // User has left or been kicked from the group.
526
+ console.log('leave', notification);
527
+ notification.reply('User left.');
528
+ });
529
+
530
+ client.on('group_update', (notification) => {
531
+ // Group picture, subject or description has been updated.
532
+ console.log('update', notification);
533
+ });
534
+
535
+ client.on('change_state', state => {
536
+ console.log('CHANGE STATE', state);
537
+ });
538
+
539
+ // Change to false if you don't want to reject incoming calls
540
+ let rejectCalls = true;
541
+
542
+ client.on('call', async (call) => {
543
+ console.log('Call received, rejecting. GOTO Line 261 to disable', call);
544
+ if (rejectCalls) await call.reject();
545
+ await client.sendMessage(call.from, `[${call.fromMe ? 'Outgoing' : 'Incoming'}] Phone call from ${call.from}, type ${call.isGroup ? 'group' : ''} ${call.isVideo ? 'video' : 'audio'} call. ${rejectCalls ? 'This call was automatically rejected by the script.' : ''}`);
546
+ });
547
+
548
+ client.on('disconnected', (reason) => {
549
+ console.log('Client was logged out', reason);
550
+ });
551
+
552
+ client.on('contact_changed', async (message, oldId, newId, isContact) => {
553
+ /** The time the event occurred. */
554
+ const eventTime = (new Date(message.timestamp * 1000)).toLocaleString();
555
+
556
+ console.log(
557
+ `The contact ${oldId.slice(0, -5)}` +
558
+ `${!isContact ? ' that participates in group ' +
559
+ `${(await client.getChatById(message.to ?? message.from)).name} ` : ' '}` +
560
+ `changed their phone number\nat ${eventTime}.\n` +
561
+ `Their new phone number is ${newId.slice(0, -5)}.\n`);
562
+
563
+ /**
564
+ * Information about the @param {message}:
565
+ *
566
+ * 1. If a notification was emitted due to a group participant changing their phone number:
567
+ * @param {message.author} is a participant's id before the change.
568
+ * @param {message.recipients[0]} is a participant's id after the change (a new one).
569
+ *
570
+ * 1.1 If the contact who changed their number WAS in the current user's contact list at the time of the change:
571
+ * @param {message.to} is a group chat id the event was emitted in.
572
+ * @param {message.from} is a current user's id that got an notification message in the group.
573
+ * Also the @param {message.fromMe} is TRUE.
574
+ *
575
+ * 1.2 Otherwise:
576
+ * @param {message.from} is a group chat id the event was emitted in.
577
+ * @param {message.to} is @type {undefined}.
578
+ * Also @param {message.fromMe} is FALSE.
579
+ *
580
+ * 2. If a notification was emitted due to a contact changing their phone number:
581
+ * @param {message.templateParams} is an array of two user's ids:
582
+ * the old (before the change) and a new one, stored in alphabetical order.
583
+ * @param {message.from} is a current user's id that has a chat with a user,
584
+ * whos phone number was changed.
585
+ * @param {message.to} is a user's id (after the change), the current user has a chat with.
586
+ */
587
+ });
588
+
589
+ client.on('group_admin_changed', (notification) => {
590
+ if (notification.type === 'promote') {
591
+ /**
592
+ * Emitted when a current user is promoted to an admin.
593
+ * {@link notification.author} is a user who performs the action of promoting/demoting the current user.
594
+ */
595
+ console.log(`You were promoted by ${notification.author}`);
596
+ } else if (notification.type === 'demote')
597
+ /** Emitted when a current user is demoted to a regular user. */
598
+ console.log(`You were demoted by ${notification.author}`);
599
+ });
600
+
601
+ client.on('group_membership_request', async (notification) => {
602
+ /**
603
+ * The example of the {@link notification} output:
604
+ * {
605
+ * id: {
606
+ * fromMe: false,
607
+ * remote: 'groupId@g.us',
608
+ * id: '123123123132132132',
609
+ * participant: 'number@c.us',
610
+ * _serialized: 'false_groupId@g.us_123123123132132132_number@c.us'
611
+ * },
612
+ * body: '',
613
+ * type: 'created_membership_requests',
614
+ * timestamp: 1694456538,
615
+ * chatId: 'groupId@g.us',
616
+ * author: 'number@c.us',
617
+ * recipientIds: []
618
+ * }
619
+ *
620
+ */
621
+ console.log(notification);
622
+ /** You can approve or reject the newly appeared membership request: */
623
+ await client.approveGroupMembershipRequestss(notification.chatId, notification.author);
624
+ await client.rejectGroupMembershipRequests(notification.chatId, notification.author);
625
+ });
626
+
627
+ client.on('message_reaction', async (reaction) => {
628
+ console.log('REACTION RECEIVED', reaction);
629
+ });
630
+
631
+ client.on('vote_update', (vote) => {
632
+ /** The vote that was affected: */
633
+ console.log(vote);
634
+ });