whatsapp-web.js 1.19.5 → 1.20.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/example.js +59 -7
- package/index.d.ts +71 -1
- package/package.json +1 -1
- package/src/Client.js +103 -2
- package/src/structures/Chat.js +6 -0
- package/src/structures/GroupChat.js +25 -0
- package/src/structures/Message.js +60 -13
- package/src/util/Constants.js +7 -1
- package/src/util/Injected.js +87 -5
- package/src/util/InterfaceController.js +4 -2
package/example.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
const { Client, Location, List, Buttons, LocalAuth} = require('./index');
|
|
1
|
+
const { Client, Location, List, Buttons, LocalAuth } = require('./index');
|
|
2
2
|
|
|
3
3
|
const client = new Client({
|
|
4
4
|
authStrategy: new LocalAuth(),
|
|
5
|
-
|
|
5
|
+
// proxyAuthentication: { username: 'username', password: 'password' },
|
|
6
|
+
puppeteer: {
|
|
7
|
+
// args: ['--proxy-server=proxy-server-that-requires-authentication.example.com'],
|
|
8
|
+
headless: false
|
|
9
|
+
}
|
|
6
10
|
});
|
|
7
11
|
|
|
8
12
|
client.initialize();
|
|
@@ -189,11 +193,11 @@ client.on('message', async msg => {
|
|
|
189
193
|
client.interface.openChatWindowAt(quotedMsg.id._serialized);
|
|
190
194
|
}
|
|
191
195
|
} else if (msg.body === '!buttons') {
|
|
192
|
-
let button = new Buttons('Button body',[{body:'bt1'},{body:'bt2'},{body:'bt3'}],'title','footer');
|
|
196
|
+
let button = new Buttons('Button body', [{ body: 'bt1' }, { body: 'bt2' }, { body: 'bt3' }], 'title', 'footer');
|
|
193
197
|
client.sendMessage(msg.from, button);
|
|
194
198
|
} else if (msg.body === '!list') {
|
|
195
|
-
let sections = [{title:'sectionTitle',rows:[{title:'ListItem1', description: 'desc'},{title:'ListItem2'}]}];
|
|
196
|
-
let list = new List('List body','btnText',sections,'Title','footer');
|
|
199
|
+
let sections = [{ title: 'sectionTitle', rows: [{ title: 'ListItem1', description: 'desc' }, { title: 'ListItem2' }] }];
|
|
200
|
+
let list = new List('List body', 'btnText', sections, 'Title', 'footer');
|
|
197
201
|
client.sendMessage(msg.from, list);
|
|
198
202
|
} else if (msg.body === '!reaction') {
|
|
199
203
|
msg.react('👍');
|
|
@@ -231,7 +235,7 @@ client.on('message_ack', (msg, ack) => {
|
|
|
231
235
|
ACK_PLAYED: 4
|
|
232
236
|
*/
|
|
233
237
|
|
|
234
|
-
if(ack == 3) {
|
|
238
|
+
if (ack == 3) {
|
|
235
239
|
// The message was read
|
|
236
240
|
}
|
|
237
241
|
});
|
|
@@ -254,7 +258,7 @@ client.on('group_update', (notification) => {
|
|
|
254
258
|
});
|
|
255
259
|
|
|
256
260
|
client.on('change_state', state => {
|
|
257
|
-
console.log('CHANGE STATE', state
|
|
261
|
+
console.log('CHANGE STATE', state);
|
|
258
262
|
});
|
|
259
263
|
|
|
260
264
|
// Change to false if you don't want to reject incoming calls
|
|
@@ -270,3 +274,51 @@ client.on('disconnected', (reason) => {
|
|
|
270
274
|
console.log('Client was logged out', reason);
|
|
271
275
|
});
|
|
272
276
|
|
|
277
|
+
client.on('contact_changed', async (message, oldId, newId, isContact) => {
|
|
278
|
+
/** The time the event occurred. */
|
|
279
|
+
const eventTime = (new Date(message.timestamp * 1000)).toLocaleString();
|
|
280
|
+
|
|
281
|
+
console.log(
|
|
282
|
+
`The contact ${oldId.slice(0, -5)}` +
|
|
283
|
+
`${!isContact ? ' that participates in group ' +
|
|
284
|
+
`${(await client.getChatById(message.to ?? message.from)).name} ` : ' '}` +
|
|
285
|
+
`changed their phone number\nat ${eventTime}.\n` +
|
|
286
|
+
`Their new phone number is ${newId.slice(0, -5)}.\n`);
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Information about the {@name message}:
|
|
290
|
+
*
|
|
291
|
+
* 1. If a notification was emitted due to a group participant changing their phone number:
|
|
292
|
+
* {@name message.author} is a participant's id before the change.
|
|
293
|
+
* {@name message.recipients[0]} is a participant's id after the change (a new one).
|
|
294
|
+
*
|
|
295
|
+
* 1.1 If the contact who changed their number WAS in the current user's contact list at the time of the change:
|
|
296
|
+
* {@name message.to} is a group chat id the event was emitted in.
|
|
297
|
+
* {@name message.from} is a current user's id that got an notification message in the group.
|
|
298
|
+
* Also the {@name message.fromMe} is TRUE.
|
|
299
|
+
*
|
|
300
|
+
* 1.2 Otherwise:
|
|
301
|
+
* {@name message.from} is a group chat id the event was emitted in.
|
|
302
|
+
* {@name message.to} is @type {undefined}.
|
|
303
|
+
* Also {@name message.fromMe} is FALSE.
|
|
304
|
+
*
|
|
305
|
+
* 2. If a notification was emitted due to a contact changing their phone number:
|
|
306
|
+
* {@name message.templateParams} is an array of two user's ids:
|
|
307
|
+
* the old (before the change) and a new one, stored in alphabetical order.
|
|
308
|
+
* {@name message.from} is a current user's id that has a chat with a user,
|
|
309
|
+
* whos phone number was changed.
|
|
310
|
+
* {@name message.to} is a user's id (after the change), the current user has a chat with.
|
|
311
|
+
*/
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
client.on('group_admin_changed', (notification) => {
|
|
315
|
+
if (notification.type === 'promote') {
|
|
316
|
+
/**
|
|
317
|
+
* Emitted when a current user is promoted to an admin.
|
|
318
|
+
* {@link notification.author} is a user who performs the action of promoting/demoting the current user.
|
|
319
|
+
*/
|
|
320
|
+
console.log(`You were promoted by ${notification.author}`);
|
|
321
|
+
} else if (notification.type === 'demote')
|
|
322
|
+
/** Emitted when a current user is demoted to a regular user. */
|
|
323
|
+
console.log(`You were demoted by ${notification.author}`);
|
|
324
|
+
});
|
package/index.d.ts
CHANGED
|
@@ -148,6 +148,12 @@ declare namespace WAWebJS {
|
|
|
148
148
|
/** Unmutes the Chat */
|
|
149
149
|
unmuteChat(chatId: string): Promise<void>
|
|
150
150
|
|
|
151
|
+
/** Sets the current user's profile picture */
|
|
152
|
+
setProfilePicture(media: MessageMedia): Promise<boolean>
|
|
153
|
+
|
|
154
|
+
/** Deletes the current user's profile picture */
|
|
155
|
+
deleteProfilePicture(): Promise<boolean>
|
|
156
|
+
|
|
151
157
|
/** Generic event */
|
|
152
158
|
on(event: string, listener: (...args: any) => void): this
|
|
153
159
|
|
|
@@ -192,12 +198,30 @@ declare namespace WAWebJS {
|
|
|
192
198
|
notification: GroupNotification
|
|
193
199
|
) => void): this
|
|
194
200
|
|
|
201
|
+
/** Emitted when a current user is promoted to an admin or demoted to a regular user */
|
|
202
|
+
on(event: 'group_admin_changed', listener: (
|
|
203
|
+
/** GroupNotification with more information about the action */
|
|
204
|
+
notification: GroupNotification
|
|
205
|
+
) => void): this
|
|
206
|
+
|
|
195
207
|
/** Emitted when group settings are updated, such as subject, description or picture */
|
|
196
208
|
on(event: 'group_update', listener: (
|
|
197
209
|
/** GroupNotification with more information about the action */
|
|
198
210
|
notification: GroupNotification
|
|
199
211
|
) => void): this
|
|
200
212
|
|
|
213
|
+
/** Emitted when a contact or a group participant changed their phone number. */
|
|
214
|
+
on(event: 'contact_changed', listener: (
|
|
215
|
+
/** Message with more information about the event. */
|
|
216
|
+
message: Message,
|
|
217
|
+
/** Old user's id. */
|
|
218
|
+
oldId : String,
|
|
219
|
+
/** New user's id. */
|
|
220
|
+
newId : String,
|
|
221
|
+
/** Indicates if a contact or a group participant changed their phone number. */
|
|
222
|
+
isContact : Boolean
|
|
223
|
+
) => void): this
|
|
224
|
+
|
|
201
225
|
/** Emitted when media has been uploaded for a message sent by the client */
|
|
202
226
|
on(event: 'media_uploaded', listener: (
|
|
203
227
|
/** The message with media that was uploaded */
|
|
@@ -217,6 +241,12 @@ declare namespace WAWebJS {
|
|
|
217
241
|
/** The new ACK value */
|
|
218
242
|
ack: MessageAck
|
|
219
243
|
) => void): this
|
|
244
|
+
|
|
245
|
+
/** Emitted when a chat unread count changes */
|
|
246
|
+
on(event: 'unread_count', listener: (
|
|
247
|
+
/** The chat that was affected */
|
|
248
|
+
chat: Chat
|
|
249
|
+
) => void): this
|
|
220
250
|
|
|
221
251
|
/** Emitted when a new message is created, which may include the current user's own messages */
|
|
222
252
|
on(event: 'message_create', listener: (
|
|
@@ -247,6 +277,22 @@ declare namespace WAWebJS {
|
|
|
247
277
|
reaction: Reaction
|
|
248
278
|
) => void): this
|
|
249
279
|
|
|
280
|
+
/** Emitted when a chat is removed */
|
|
281
|
+
on(event: 'chat_removed', listener: (
|
|
282
|
+
/** The chat that was removed */
|
|
283
|
+
chat: Chat
|
|
284
|
+
) => void): this
|
|
285
|
+
|
|
286
|
+
/** Emitted when a chat is archived/unarchived */
|
|
287
|
+
on(event: 'chat_archived', listener: (
|
|
288
|
+
/** The chat that was archived/unarchived */
|
|
289
|
+
chat: Chat,
|
|
290
|
+
/** State the chat is currently in */
|
|
291
|
+
currState: boolean,
|
|
292
|
+
/** State the chat was previously in */
|
|
293
|
+
prevState: boolean
|
|
294
|
+
) => void): this
|
|
295
|
+
|
|
250
296
|
/** Emitted when loading screen is appearing */
|
|
251
297
|
on(event: 'loading_screen', listener: (percent: string, message: string) => void): this
|
|
252
298
|
|
|
@@ -341,7 +387,9 @@ declare namespace WAWebJS {
|
|
|
341
387
|
userAgent?: string
|
|
342
388
|
/** Ffmpeg path to use when formating videos to webp while sending stickers
|
|
343
389
|
* @default 'ffmpeg' */
|
|
344
|
-
ffmpegPath?: string
|
|
390
|
+
ffmpegPath?: string,
|
|
391
|
+
/** Object with proxy autentication requirements @default: undefined */
|
|
392
|
+
proxyAuthentication?: {username: string, password: string} | undefined
|
|
345
393
|
}
|
|
346
394
|
|
|
347
395
|
/**
|
|
@@ -498,8 +546,10 @@ declare namespace WAWebJS {
|
|
|
498
546
|
MESSAGE_REVOKED_ME = 'message_revoke_me',
|
|
499
547
|
MESSAGE_ACK = 'message_ack',
|
|
500
548
|
MEDIA_UPLOADED = 'media_uploaded',
|
|
549
|
+
CONTACT_CHANGED = 'contact_changed',
|
|
501
550
|
GROUP_JOIN = 'group_join',
|
|
502
551
|
GROUP_LEAVE = 'group_leave',
|
|
552
|
+
GROUP_ADMIN_CHANGED = 'group_admin_changed',
|
|
503
553
|
GROUP_UPDATE = 'group_update',
|
|
504
554
|
QR_RECEIVED = 'qr',
|
|
505
555
|
LOADING_SCREEN = 'loading_screen',
|
|
@@ -637,6 +687,7 @@ declare namespace WAWebJS {
|
|
|
637
687
|
* broadcast: false,
|
|
638
688
|
* fromMe: false,
|
|
639
689
|
* hasQuotedMsg: false,
|
|
690
|
+
* hasReaction: false,
|
|
640
691
|
* location: undefined,
|
|
641
692
|
* mentionedIds: []
|
|
642
693
|
* }
|
|
@@ -666,6 +717,8 @@ declare namespace WAWebJS {
|
|
|
666
717
|
hasMedia: boolean,
|
|
667
718
|
/** Indicates if the message was sent as a reply to another message */
|
|
668
719
|
hasQuotedMsg: boolean,
|
|
720
|
+
/** Indicates whether there are reactions to the message */
|
|
721
|
+
hasReaction: boolean,
|
|
669
722
|
/** Indicates the duration of the message in seconds */
|
|
670
723
|
duration: string,
|
|
671
724
|
/** ID that represents the message */
|
|
@@ -767,6 +820,10 @@ declare namespace WAWebJS {
|
|
|
767
820
|
* Gets the payment details associated with a given message
|
|
768
821
|
*/
|
|
769
822
|
getPayment: () => Promise<Payment>,
|
|
823
|
+
/**
|
|
824
|
+
* Gets the reactions associated with the given message
|
|
825
|
+
*/
|
|
826
|
+
getReactions: () => Promise<ReactionList[]>,
|
|
770
827
|
}
|
|
771
828
|
|
|
772
829
|
/** ID that represents a message */
|
|
@@ -1019,6 +1076,8 @@ declare namespace WAWebJS {
|
|
|
1019
1076
|
timestamp: number,
|
|
1020
1077
|
/** Amount of messages unread */
|
|
1021
1078
|
unreadCount: number,
|
|
1079
|
+
/** Last message fo chat */
|
|
1080
|
+
lastMessage: Message,
|
|
1022
1081
|
|
|
1023
1082
|
/** Archives this chat */
|
|
1024
1083
|
archive: () => Promise<void>,
|
|
@@ -1162,6 +1221,10 @@ declare namespace WAWebJS {
|
|
|
1162
1221
|
revokeInvite: () => Promise<void>;
|
|
1163
1222
|
/** Makes the bot leave the group */
|
|
1164
1223
|
leave: () => Promise<void>;
|
|
1224
|
+
/** Sets the group's picture.*/
|
|
1225
|
+
setPicture: (media: MessageMedia) => Promise<boolean>;
|
|
1226
|
+
/** Deletes the group's picture */
|
|
1227
|
+
deletePicture: () => Promise<boolean>;
|
|
1165
1228
|
}
|
|
1166
1229
|
|
|
1167
1230
|
/**
|
|
@@ -1365,6 +1428,13 @@ declare namespace WAWebJS {
|
|
|
1365
1428
|
senderId: string
|
|
1366
1429
|
ack?: number
|
|
1367
1430
|
}
|
|
1431
|
+
|
|
1432
|
+
export type ReactionList = {
|
|
1433
|
+
id: string,
|
|
1434
|
+
aggregateEmoji: string,
|
|
1435
|
+
hasReactionByMe: boolean,
|
|
1436
|
+
senders: Array<Reaction>
|
|
1437
|
+
}
|
|
1368
1438
|
}
|
|
1369
1439
|
|
|
1370
1440
|
export = WAWebJS
|
package/package.json
CHANGED
package/src/Client.js
CHANGED
|
@@ -10,7 +10,7 @@ const { WhatsWebURL, DefaultOptions, Events, WAState } = require('./util/Constan
|
|
|
10
10
|
const { ExposeStore, LoadUtils } = require('./util/Injected');
|
|
11
11
|
const ChatFactory = require('./factories/ChatFactory');
|
|
12
12
|
const ContactFactory = require('./factories/ContactFactory');
|
|
13
|
-
const { ClientInfo, Message, MessageMedia, Contact, Location, GroupNotification, Label, Call, Buttons, List, Reaction } = require('./structures');
|
|
13
|
+
const { ClientInfo, Message, MessageMedia, Contact, Location, GroupNotification, Label, Call, Buttons, List, Reaction, Chat } = require('./structures');
|
|
14
14
|
const LegacySessionAuth = require('./authStrategies/LegacySessionAuth');
|
|
15
15
|
const NoAuth = require('./authStrategies/NoAuth');
|
|
16
16
|
|
|
@@ -29,6 +29,7 @@ const NoAuth = require('./authStrategies/NoAuth');
|
|
|
29
29
|
* @param {string} options.userAgent - User agent to use in puppeteer
|
|
30
30
|
* @param {string} options.ffmpegPath - Ffmpeg path to use when formating videos to webp while sending stickers
|
|
31
31
|
* @param {boolean} options.bypassCSP - Sets bypassing of page's Content-Security-Policy.
|
|
32
|
+
* @param {object} options.proxyAuthentication - Proxy Authentication object.
|
|
32
33
|
*
|
|
33
34
|
* @fires Client#qr
|
|
34
35
|
* @fires Client#authenticated
|
|
@@ -45,6 +46,8 @@ const NoAuth = require('./authStrategies/NoAuth');
|
|
|
45
46
|
* @fires Client#group_update
|
|
46
47
|
* @fires Client#disconnected
|
|
47
48
|
* @fires Client#change_state
|
|
49
|
+
* @fires Client#contact_changed
|
|
50
|
+
* @fires Client#group_admin_changed
|
|
48
51
|
*/
|
|
49
52
|
class Client extends EventEmitter {
|
|
50
53
|
constructor(options = {}) {
|
|
@@ -100,6 +103,10 @@ class Client extends EventEmitter {
|
|
|
100
103
|
browser = await puppeteer.launch({...puppeteerOpts, args: browserArgs});
|
|
101
104
|
page = (await browser.pages())[0];
|
|
102
105
|
}
|
|
106
|
+
|
|
107
|
+
if (this.options.proxyAuthentication !== undefined) {
|
|
108
|
+
await page.authenticate(this.options.proxyAuthentication);
|
|
109
|
+
}
|
|
103
110
|
|
|
104
111
|
await page.setUserAgent(this.options.userAgent);
|
|
105
112
|
if (this.options.bypassCSP) await page.setBypassCSP(true);
|
|
@@ -317,6 +324,13 @@ class Client extends EventEmitter {
|
|
|
317
324
|
* @param {GroupNotification} notification GroupNotification with more information about the action
|
|
318
325
|
*/
|
|
319
326
|
this.emit(Events.GROUP_LEAVE, notification);
|
|
327
|
+
} else if (msg.subtype === 'promote' || msg.subtype === 'demote') {
|
|
328
|
+
/**
|
|
329
|
+
* Emitted when a current user is promoted to an admin or demoted to a regular user.
|
|
330
|
+
* @event Client#group_admin_changed
|
|
331
|
+
* @param {GroupNotification} notification GroupNotification with more information about the action
|
|
332
|
+
*/
|
|
333
|
+
this.emit(Events.GROUP_ADMIN_CHANGED, notification);
|
|
320
334
|
} else {
|
|
321
335
|
/**
|
|
322
336
|
* Emitted when group settings are updated, such as subject, description or picture.
|
|
@@ -376,6 +390,36 @@ class Client extends EventEmitter {
|
|
|
376
390
|
last_message = msg;
|
|
377
391
|
}
|
|
378
392
|
|
|
393
|
+
/**
|
|
394
|
+
* The event notification that is received when one of
|
|
395
|
+
* the group participants changes thier phone number.
|
|
396
|
+
*/
|
|
397
|
+
const isParticipant = msg.type === 'gp2' && msg.subtype === 'modify';
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* The event notification that is received when one of
|
|
401
|
+
* the contacts changes thier phone number.
|
|
402
|
+
*/
|
|
403
|
+
const isContact = msg.type === 'notification_template' && msg.subtype === 'change_number';
|
|
404
|
+
|
|
405
|
+
if (isParticipant || isContact) {
|
|
406
|
+
/** {@link GroupNotification} object does not provide enough information about this event, so a {@link Message} object is used. */
|
|
407
|
+
const message = new Message(this, msg);
|
|
408
|
+
|
|
409
|
+
const newId = isParticipant ? msg.recipients[0] : msg.to;
|
|
410
|
+
const oldId = isParticipant ? msg.author : msg.templateParams.find(id => id !== newId);
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Emitted when a contact or a group participant changes their phone number.
|
|
414
|
+
* @event Client#contact_changed
|
|
415
|
+
* @param {Message} message Message with more information about the event.
|
|
416
|
+
* @param {String} oldId The user's id (an old one) who changed their phone number
|
|
417
|
+
* and who triggered the notification.
|
|
418
|
+
* @param {String} newId The user's new id after the change.
|
|
419
|
+
* @param {Boolean} isContact Indicates if a contact or a group participant changed their phone number.
|
|
420
|
+
*/
|
|
421
|
+
this.emit(Events.CONTACT_CHANGED, message, oldId, newId, isContact);
|
|
422
|
+
}
|
|
379
423
|
});
|
|
380
424
|
|
|
381
425
|
await page.exposeFunction('onRemoveMessageEvent', (msg) => {
|
|
@@ -407,6 +451,15 @@ class Client extends EventEmitter {
|
|
|
407
451
|
|
|
408
452
|
});
|
|
409
453
|
|
|
454
|
+
await page.exposeFunction('onChatUnreadCountEvent', async (data) =>{
|
|
455
|
+
const chat = await this.getChatById(data.id);
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Emitted when the chat unread count changes
|
|
459
|
+
*/
|
|
460
|
+
this.emit(Events.UNREAD_COUNT, chat);
|
|
461
|
+
});
|
|
462
|
+
|
|
410
463
|
await page.exposeFunction('onMessageMediaUploadedEvent', (msg) => {
|
|
411
464
|
|
|
412
465
|
const message = new Message(this, msg);
|
|
@@ -507,6 +560,26 @@ class Client extends EventEmitter {
|
|
|
507
560
|
}
|
|
508
561
|
});
|
|
509
562
|
|
|
563
|
+
await page.exposeFunction('onRemoveChatEvent', (chat) => {
|
|
564
|
+
/**
|
|
565
|
+
* Emitted when a chat is removed
|
|
566
|
+
* @event Client#chat_removed
|
|
567
|
+
* @param {Chat} chat
|
|
568
|
+
*/
|
|
569
|
+
this.emit(Events.CHAT_REMOVED, new Chat(this, chat));
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
await page.exposeFunction('onArchiveChatEvent', (chat, currState, prevState) => {
|
|
573
|
+
/**
|
|
574
|
+
* Emitted when a chat is archived/unarchived
|
|
575
|
+
* @event Client#chat_archived
|
|
576
|
+
* @param {Chat} chat
|
|
577
|
+
* @param {boolean} currState
|
|
578
|
+
* @param {boolean} prevState
|
|
579
|
+
*/
|
|
580
|
+
this.emit(Events.CHAT_ARCHIVED, new Chat(this, chat), currState, prevState);
|
|
581
|
+
});
|
|
582
|
+
|
|
510
583
|
await page.evaluate(() => {
|
|
511
584
|
window.Store.Msg.on('change', (msg) => { window.onChangeMessageEvent(window.WWebJS.getMessageModel(msg)); });
|
|
512
585
|
window.Store.Msg.on('change:type', (msg) => { window.onChangeMessageTypeEvent(window.WWebJS.getMessageModel(msg)); });
|
|
@@ -516,6 +589,8 @@ class Client extends EventEmitter {
|
|
|
516
589
|
window.Store.AppState.on('change:state', (_AppState, state) => { window.onAppStateChangedEvent(state); });
|
|
517
590
|
window.Store.Conn.on('change:battery', (state) => { window.onBatteryStateChangedEvent(state); });
|
|
518
591
|
window.Store.Call.on('add', (call) => { window.onIncomingCall(call); });
|
|
592
|
+
window.Store.Chat.on('remove', async (chat) => { window.onRemoveChatEvent(await window.WWebJS.getChatModel(chat)); });
|
|
593
|
+
window.Store.Chat.on('change:archive', async (chat, currState, prevState) => { window.onArchiveChatEvent(await window.WWebJS.getChatModel(chat), currState, prevState); });
|
|
519
594
|
window.Store.Msg.on('add', (msg) => {
|
|
520
595
|
if (msg.isNewMsg) {
|
|
521
596
|
if(msg.type === 'ciphertext') {
|
|
@@ -526,7 +601,8 @@ class Client extends EventEmitter {
|
|
|
526
601
|
}
|
|
527
602
|
}
|
|
528
603
|
});
|
|
529
|
-
|
|
604
|
+
window.Store.Chat.on('change:unreadCount', (chat) => {window.onChatUnreadCountEvent(chat);});
|
|
605
|
+
|
|
530
606
|
{
|
|
531
607
|
const module = window.Store.createOrUpdateReactionsModule;
|
|
532
608
|
const ogMethod = module.createOrUpdateReactions;
|
|
@@ -1178,6 +1254,31 @@ class Client extends EventEmitter {
|
|
|
1178
1254
|
|
|
1179
1255
|
return blockedContacts.map(contact => ContactFactory.create(this.client, contact));
|
|
1180
1256
|
}
|
|
1257
|
+
|
|
1258
|
+
/**
|
|
1259
|
+
* Sets the current user's profile picture.
|
|
1260
|
+
* @param {MessageMedia} media
|
|
1261
|
+
* @returns {Promise<boolean>} Returns true if the picture was properly updated.
|
|
1262
|
+
*/
|
|
1263
|
+
async setProfilePicture(media) {
|
|
1264
|
+
const success = await this.pupPage.evaluate((chatid, media) => {
|
|
1265
|
+
return window.WWebJS.setPicture(chatid, media);
|
|
1266
|
+
}, this.info.wid._serialized, media);
|
|
1267
|
+
|
|
1268
|
+
return success;
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
/**
|
|
1272
|
+
* Deletes the current user's profile picture.
|
|
1273
|
+
* @returns {Promise<boolean>} Returns true if the picture was properly deleted.
|
|
1274
|
+
*/
|
|
1275
|
+
async deleteProfilePicture() {
|
|
1276
|
+
const success = await this.pupPage.evaluate((chatid) => {
|
|
1277
|
+
return window.WWebJS.deletePicture(chatid);
|
|
1278
|
+
}, this.info.wid._serialized);
|
|
1279
|
+
|
|
1280
|
+
return success;
|
|
1281
|
+
}
|
|
1181
1282
|
}
|
|
1182
1283
|
|
|
1183
1284
|
module.exports = Client;
|
package/src/structures/Chat.js
CHANGED
|
@@ -75,6 +75,12 @@ class Chat extends Base {
|
|
|
75
75
|
*/
|
|
76
76
|
this.muteExpiration = data.muteExpiration;
|
|
77
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Last message fo chat
|
|
80
|
+
* @type {Message}
|
|
81
|
+
*/
|
|
82
|
+
this.lastMessage = data.lastMessage ? new Message(super.client, data.lastMessage) : undefined;
|
|
83
|
+
|
|
78
84
|
return super._patch(data);
|
|
79
85
|
}
|
|
80
86
|
|
|
@@ -213,6 +213,31 @@ class GroupChat extends Chat {
|
|
|
213
213
|
return true;
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Deletes the group's picture.
|
|
218
|
+
* @returns {Promise<boolean>} Returns true if the picture was properly deleted. This can return false if the user does not have the necessary permissions.
|
|
219
|
+
*/
|
|
220
|
+
async deletePicture() {
|
|
221
|
+
const success = await this.client.pupPage.evaluate((chatid) => {
|
|
222
|
+
return window.WWebJS.deletePicture(chatid);
|
|
223
|
+
}, this.id._serialized);
|
|
224
|
+
|
|
225
|
+
return success;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Sets the group's picture.
|
|
230
|
+
* @param {MessageMedia} media
|
|
231
|
+
* @returns {Promise<boolean>} Returns true if the picture was properly updated. This can return false if the user does not have the necessary permissions.
|
|
232
|
+
*/
|
|
233
|
+
async setPicture(media) {
|
|
234
|
+
const success = await this.client.pupPage.evaluate((chatid, media) => {
|
|
235
|
+
return window.WWebJS.setPicture(chatid, media);
|
|
236
|
+
}, this.id._serialized, media);
|
|
237
|
+
|
|
238
|
+
return success;
|
|
239
|
+
}
|
|
240
|
+
|
|
216
241
|
/**
|
|
217
242
|
* Gets the invite code for a specific group
|
|
218
243
|
* @returns {Promise<string>} Group's invite code
|
|
@@ -5,7 +5,8 @@ const MessageMedia = require('./MessageMedia');
|
|
|
5
5
|
const Location = require('./Location');
|
|
6
6
|
const Order = require('./Order');
|
|
7
7
|
const Payment = require('./Payment');
|
|
8
|
-
const
|
|
8
|
+
const Reaction = require('./Reaction');
|
|
9
|
+
const {MessageTypes} = require('../util/Constants');
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Represents a Message on WhatsApp
|
|
@@ -88,8 +89,7 @@ class Message extends Base {
|
|
|
88
89
|
* String that represents from which device type the message was sent
|
|
89
90
|
* @type {string}
|
|
90
91
|
*/
|
|
91
|
-
this.deviceType = data.id.id.length > 21 ? 'android' : data.id.id.substring(0, 2)
|
|
92
|
-
|
|
92
|
+
this.deviceType = typeof data.id.id === 'string' && data.id.id.length > 21 ? 'android' : typeof data.id.id === 'string' && data.id.id.substring(0, 2) === '3A' ? 'ios' : 'web';
|
|
93
93
|
/**
|
|
94
94
|
* Indicates if the message was forwarded
|
|
95
95
|
* @type {boolean}
|
|
@@ -108,7 +108,7 @@ class Message extends Base {
|
|
|
108
108
|
* Indicates if the message is a status update
|
|
109
109
|
* @type {boolean}
|
|
110
110
|
*/
|
|
111
|
-
this.isStatus = data.isStatusV3;
|
|
111
|
+
this.isStatus = data.isStatusV3 || data.id.remote === 'status@broadcast';
|
|
112
112
|
|
|
113
113
|
/**
|
|
114
114
|
* Indicates if the message was starred
|
|
@@ -134,6 +134,12 @@ class Message extends Base {
|
|
|
134
134
|
*/
|
|
135
135
|
this.hasQuotedMsg = data.quotedMsg ? true : false;
|
|
136
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Indicates whether there are reactions to the message
|
|
139
|
+
* @type {boolean}
|
|
140
|
+
*/
|
|
141
|
+
this.hasReaction = data.hasReaction ? true : false;
|
|
142
|
+
|
|
137
143
|
/**
|
|
138
144
|
* Indicates the duration of the message in seconds
|
|
139
145
|
* @type {string}
|
|
@@ -436,15 +442,16 @@ class Message extends Base {
|
|
|
436
442
|
* @param {?boolean} everyone If true and the message is sent by the current user or the user is an admin, will delete it for everyone in the chat.
|
|
437
443
|
*/
|
|
438
444
|
async delete(everyone) {
|
|
439
|
-
await this.client.pupPage.evaluate((msgId, everyone) => {
|
|
445
|
+
await this.client.pupPage.evaluate(async (msgId, everyone) => {
|
|
440
446
|
let msg = window.Store.Msg.get(msgId);
|
|
441
|
-
|
|
447
|
+
let chat = await window.Store.Chat.find(msg.id.remote);
|
|
448
|
+
|
|
442
449
|
const canRevoke = window.Store.MsgActionChecks.canSenderRevokeMsg(msg) || window.Store.MsgActionChecks.canAdminRevokeMsg(msg);
|
|
443
450
|
if (everyone && canRevoke) {
|
|
444
|
-
return window.Store.Cmd.sendRevokeMsgs(
|
|
451
|
+
return window.Store.Cmd.sendRevokeMsgs(chat, [msg], { clearMedia: true, type: msg.id.fromMe ? 'Sender' : 'Admin' });
|
|
445
452
|
}
|
|
446
453
|
|
|
447
|
-
return window.Store.Cmd.sendDeleteMsgs(
|
|
454
|
+
return window.Store.Cmd.sendDeleteMsgs(chat, [msg], true);
|
|
448
455
|
}, this.id._serialized, everyone);
|
|
449
456
|
}
|
|
450
457
|
|
|
@@ -452,11 +459,12 @@ class Message extends Base {
|
|
|
452
459
|
* Stars this message
|
|
453
460
|
*/
|
|
454
461
|
async star() {
|
|
455
|
-
await this.client.pupPage.evaluate((msgId) => {
|
|
462
|
+
await this.client.pupPage.evaluate(async (msgId) => {
|
|
456
463
|
let msg = window.Store.Msg.get(msgId);
|
|
457
|
-
|
|
464
|
+
|
|
458
465
|
if (window.Store.MsgActionChecks.canStarMsg(msg)) {
|
|
459
|
-
|
|
466
|
+
let chat = await window.Store.Chat.find(msg.id.remote);
|
|
467
|
+
return window.Store.Cmd.sendStarMsgs(chat, [msg], false);
|
|
460
468
|
}
|
|
461
469
|
}, this.id._serialized);
|
|
462
470
|
}
|
|
@@ -465,11 +473,12 @@ class Message extends Base {
|
|
|
465
473
|
* Unstars this message
|
|
466
474
|
*/
|
|
467
475
|
async unstar() {
|
|
468
|
-
await this.client.pupPage.evaluate((msgId) => {
|
|
476
|
+
await this.client.pupPage.evaluate(async (msgId) => {
|
|
469
477
|
let msg = window.Store.Msg.get(msgId);
|
|
470
478
|
|
|
471
479
|
if (window.Store.MsgActionChecks.canStarMsg(msg)) {
|
|
472
|
-
|
|
480
|
+
let chat = await window.Store.Chat.find(msg.id.remote);
|
|
481
|
+
return window.Store.Cmd.sendUnstarMsgs(chat, [msg], false);
|
|
473
482
|
}
|
|
474
483
|
}, this.id._serialized);
|
|
475
484
|
}
|
|
@@ -529,6 +538,44 @@ class Message extends Base {
|
|
|
529
538
|
}
|
|
530
539
|
return undefined;
|
|
531
540
|
}
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Reaction List
|
|
545
|
+
* @typedef {Object} ReactionList
|
|
546
|
+
* @property {string} id Original emoji
|
|
547
|
+
* @property {string} aggregateEmoji aggregate emoji
|
|
548
|
+
* @property {boolean} hasReactionByMe Flag who sent the reaction
|
|
549
|
+
* @property {Array<Reaction>} senders Reaction senders, to this message
|
|
550
|
+
*/
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Gets the reactions associated with the given message
|
|
554
|
+
* @return {Promise<ReactionList[]>}
|
|
555
|
+
*/
|
|
556
|
+
async getReactions() {
|
|
557
|
+
if (!this.hasReaction) {
|
|
558
|
+
return undefined;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const reactions = await this.client.pupPage.evaluate(async (msgId) => {
|
|
562
|
+
const msgReactions = await window.Store.Reactions.find(msgId);
|
|
563
|
+
if (!msgReactions || !msgReactions.reactions.length) return null;
|
|
564
|
+
return msgReactions.reactions.serialize();
|
|
565
|
+
}, this.id._serialized);
|
|
566
|
+
|
|
567
|
+
if (!reactions) {
|
|
568
|
+
return undefined;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
return reactions.map(reaction => {
|
|
572
|
+
reaction.senders = reaction.senders.map(sender => {
|
|
573
|
+
sender.timestamp = Math.round(sender.timestamp / 1000);
|
|
574
|
+
return new Reaction(this.client, sender);
|
|
575
|
+
});
|
|
576
|
+
return reaction;
|
|
577
|
+
});
|
|
578
|
+
}
|
|
532
579
|
}
|
|
533
580
|
|
|
534
581
|
module.exports = Message;
|
package/src/util/Constants.js
CHANGED
|
@@ -13,7 +13,8 @@ exports.DefaultOptions = {
|
|
|
13
13
|
takeoverTimeoutMs: 0,
|
|
14
14
|
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36',
|
|
15
15
|
ffmpegPath: 'ffmpeg',
|
|
16
|
-
bypassCSP: false
|
|
16
|
+
bypassCSP: false,
|
|
17
|
+
proxyAuthentication: undefined
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
/**
|
|
@@ -36,15 +37,20 @@ exports.Events = {
|
|
|
36
37
|
AUTHENTICATED: 'authenticated',
|
|
37
38
|
AUTHENTICATION_FAILURE: 'auth_failure',
|
|
38
39
|
READY: 'ready',
|
|
40
|
+
CHAT_REMOVED: 'chat_removed',
|
|
41
|
+
CHAT_ARCHIVED: 'chat_archived',
|
|
39
42
|
MESSAGE_RECEIVED: 'message',
|
|
40
43
|
MESSAGE_CREATE: 'message_create',
|
|
41
44
|
MESSAGE_REVOKED_EVERYONE: 'message_revoke_everyone',
|
|
42
45
|
MESSAGE_REVOKED_ME: 'message_revoke_me',
|
|
43
46
|
MESSAGE_ACK: 'message_ack',
|
|
47
|
+
UNREAD_COUNT: 'unread_count',
|
|
44
48
|
MESSAGE_REACTION: 'message_reaction',
|
|
45
49
|
MEDIA_UPLOADED: 'media_uploaded',
|
|
50
|
+
CONTACT_CHANGED: 'contact_changed',
|
|
46
51
|
GROUP_JOIN: 'group_join',
|
|
47
52
|
GROUP_LEAVE: 'group_leave',
|
|
53
|
+
GROUP_ADMIN_CHANGED: 'group_admin_changed',
|
|
48
54
|
GROUP_UPDATE: 'group_update',
|
|
49
55
|
QR_RECEIVED: 'qr',
|
|
50
56
|
LOADING_SCREEN: 'loading_screen',
|
package/src/util/Injected.js
CHANGED
|
@@ -41,7 +41,7 @@ exports.ExposeStore = (moduleRaidStr) => {
|
|
|
41
41
|
window.Store.ProfilePic = window.mR.findModule('profilePicResync')[0];
|
|
42
42
|
window.Store.PresenceUtils = window.mR.findModule('sendPresenceAvailable')[0];
|
|
43
43
|
window.Store.ChatState = window.mR.findModule('sendChatStateComposing')[0];
|
|
44
|
-
window.Store.GroupParticipants = window.mR.findModule('promoteParticipants')[
|
|
44
|
+
window.Store.GroupParticipants = window.mR.findModule('promoteParticipants')[0];
|
|
45
45
|
window.Store.JoinInviteV4 = window.mR.findModule('sendJoinGroupViaInviteV4')[0];
|
|
46
46
|
window.Store.findCommonGroups = window.mR.findModule('findCommonGroups')[0].findCommonGroups;
|
|
47
47
|
window.Store.StatusUtils = window.mR.findModule('setMyStatus')[0];
|
|
@@ -54,6 +54,8 @@ exports.ExposeStore = (moduleRaidStr) => {
|
|
|
54
54
|
window.Store.QuotedMsg = window.mR.findModule('getQuotedMsgObj')[0];
|
|
55
55
|
window.Store.Socket = window.mR.findModule('deprecatedSendIq')[0];
|
|
56
56
|
window.Store.SocketWap = window.mR.findModule('wap')[0];
|
|
57
|
+
window.Store.SearchContext = window.mR.findModule('getSearchContext')[0].getSearchContext;
|
|
58
|
+
window.Store.DrawerManager = window.mR.findModule('DrawerManager')[0].DrawerManager;
|
|
57
59
|
window.Store.StickerTools = {
|
|
58
60
|
...window.mR.findModule('toWebpSticker')[0],
|
|
59
61
|
...window.mR.findModule('addWebpMetadata')[0]
|
|
@@ -62,7 +64,8 @@ exports.ExposeStore = (moduleRaidStr) => {
|
|
|
62
64
|
window.Store.GroupUtils = {
|
|
63
65
|
...window.mR.findModule('createGroup')[0],
|
|
64
66
|
...window.mR.findModule('setGroupDescription')[0],
|
|
65
|
-
...window.mR.findModule('sendExitGroup')[0]
|
|
67
|
+
...window.mR.findModule('sendExitGroup')[0],
|
|
68
|
+
...window.mR.findModule('sendSetPicture')[0]
|
|
66
69
|
};
|
|
67
70
|
|
|
68
71
|
if (!window.Store.Chat._find) {
|
|
@@ -242,11 +245,12 @@ exports.LoadUtils = () => {
|
|
|
242
245
|
|
|
243
246
|
const meUser = window.Store.User.getMaybeMeUser();
|
|
244
247
|
const isMD = window.Store.MDBackend;
|
|
245
|
-
|
|
248
|
+
const newId = await window.Store.MsgKey.newId();
|
|
249
|
+
|
|
246
250
|
const newMsgId = new window.Store.MsgKey({
|
|
247
251
|
from: meUser,
|
|
248
252
|
to: chat.id,
|
|
249
|
-
id:
|
|
253
|
+
id: newId,
|
|
250
254
|
participant: isMD && chat.id.isGroup() ? meUser : undefined,
|
|
251
255
|
selfDir: 'out',
|
|
252
256
|
});
|
|
@@ -271,6 +275,7 @@ exports.LoadUtils = () => {
|
|
|
271
275
|
...ephemeralFields,
|
|
272
276
|
...locationOptions,
|
|
273
277
|
...attOptions,
|
|
278
|
+
...(attOptions.toJSON ? attOptions.toJSON() : {}),
|
|
274
279
|
...quotedMsgOptions,
|
|
275
280
|
...vcardOptions,
|
|
276
281
|
...buttonOptions,
|
|
@@ -426,7 +431,15 @@ exports.LoadUtils = () => {
|
|
|
426
431
|
await window.Store.GroupMetadata.update(chatWid);
|
|
427
432
|
res.groupMetadata = chat.groupMetadata.serialize();
|
|
428
433
|
}
|
|
429
|
-
|
|
434
|
+
|
|
435
|
+
res.lastMessage = null;
|
|
436
|
+
if (res.msgs && res.msgs.length) {
|
|
437
|
+
const lastMessage = window.Store.Msg.get(chat.lastReceivedKey._serialized);
|
|
438
|
+
if (lastMessage) {
|
|
439
|
+
res.lastMessage = window.WWebJS.getMessageModel(lastMessage);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
430
443
|
delete res.msgs;
|
|
431
444
|
delete res.msgUnsyncedButtonReplyMsgs;
|
|
432
445
|
delete res.unsyncedButtonReplies;
|
|
@@ -625,4 +638,73 @@ exports.LoadUtils = () => {
|
|
|
625
638
|
]);
|
|
626
639
|
await window.Store.Socket.deprecatedCastStanza(stanza);
|
|
627
640
|
};
|
|
641
|
+
|
|
642
|
+
window.WWebJS.cropAndResizeImage = async (media, options = {}) => {
|
|
643
|
+
if (!media.mimetype.includes('image'))
|
|
644
|
+
throw new Error('Media is not an image');
|
|
645
|
+
|
|
646
|
+
if (options.mimetype && !options.mimetype.includes('image'))
|
|
647
|
+
delete options.mimetype;
|
|
648
|
+
|
|
649
|
+
options = Object.assign({ size: 640, mimetype: media.mimetype, quality: .75, asDataUrl: false }, options);
|
|
650
|
+
|
|
651
|
+
const img = await new Promise ((resolve, reject) => {
|
|
652
|
+
const img = new Image();
|
|
653
|
+
img.onload = () => resolve(img);
|
|
654
|
+
img.onerror = reject;
|
|
655
|
+
img.src = `data:${media.mimetype};base64,${media.data}`;
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
const sl = Math.min(img.width, img.height);
|
|
659
|
+
const sx = Math.floor((img.width - sl) / 2);
|
|
660
|
+
const sy = Math.floor((img.height - sl) / 2);
|
|
661
|
+
|
|
662
|
+
const canvas = document.createElement('canvas');
|
|
663
|
+
canvas.width = options.size;
|
|
664
|
+
canvas.height = options.size;
|
|
665
|
+
|
|
666
|
+
const ctx = canvas.getContext('2d');
|
|
667
|
+
ctx.drawImage(img, sx, sy, sl, sl, 0, 0, options.size, options.size);
|
|
668
|
+
|
|
669
|
+
const dataUrl = canvas.toDataURL(options.mimetype, options.quality);
|
|
670
|
+
|
|
671
|
+
if (options.asDataUrl)
|
|
672
|
+
return dataUrl;
|
|
673
|
+
|
|
674
|
+
return Object.assign(media, {
|
|
675
|
+
mimetype: options.mimeType,
|
|
676
|
+
data: dataUrl.replace(`data:${options.mimeType};base64,`, '')
|
|
677
|
+
});
|
|
678
|
+
};
|
|
679
|
+
|
|
680
|
+
window.WWebJS.setPicture = async (chatid, media) => {
|
|
681
|
+
const thumbnail = await window.WWebJS.cropAndResizeImage(media, { asDataUrl: true, mimetype: 'image/jpeg', size: 96 });
|
|
682
|
+
const profilePic = await window.WWebJS.cropAndResizeImage(media, { asDataUrl: true, mimetype: 'image/jpeg', size: 640 });
|
|
683
|
+
|
|
684
|
+
const chatWid = window.Store.WidFactory.createWid(chatid);
|
|
685
|
+
try {
|
|
686
|
+
const collection = window.Store.ProfilePicThumb.get(chatid);
|
|
687
|
+
if (!collection.canSet()) return;
|
|
688
|
+
|
|
689
|
+
const res = await window.Store.GroupUtils.sendSetPicture(chatWid, thumbnail, profilePic);
|
|
690
|
+
return res ? res.status === 200 : false;
|
|
691
|
+
} catch (err) {
|
|
692
|
+
if(err.name === 'ServerStatusCodeError') return false;
|
|
693
|
+
throw err;
|
|
694
|
+
}
|
|
695
|
+
};
|
|
696
|
+
|
|
697
|
+
window.WWebJS.deletePicture = async (chatid) => {
|
|
698
|
+
const chatWid = window.Store.WidFactory.createWid(chatid);
|
|
699
|
+
try {
|
|
700
|
+
const collection = window.Store.ProfilePicThumb.get(chatid);
|
|
701
|
+
if (!collection.canDelete()) return;
|
|
702
|
+
|
|
703
|
+
const res = await window.Store.GroupUtils.requestDeletePicture(chatWid);
|
|
704
|
+
return res ? res.status === 200 : false;
|
|
705
|
+
} catch (err) {
|
|
706
|
+
if(err.name === 'ServerStatusCodeError') return false;
|
|
707
|
+
throw err;
|
|
708
|
+
}
|
|
709
|
+
};
|
|
628
710
|
};
|
|
@@ -50,7 +50,9 @@ class InterfaceController {
|
|
|
50
50
|
async openChatWindowAt(msgId) {
|
|
51
51
|
await this.pupPage.evaluate(async msgId => {
|
|
52
52
|
let msg = await window.Store.Msg.get(msgId);
|
|
53
|
-
await window.Store.
|
|
53
|
+
let chat = await window.Store.Chat.find(msg.id.remote);
|
|
54
|
+
let searchContext = await window.Store.SearchContext(chat,msg);
|
|
55
|
+
await window.Store.Cmd.openChatAt(chat, searchContext);
|
|
54
56
|
}, msgId);
|
|
55
57
|
}
|
|
56
58
|
|
|
@@ -70,7 +72,7 @@ class InterfaceController {
|
|
|
70
72
|
*/
|
|
71
73
|
async closeRightDrawer() {
|
|
72
74
|
await this.pupPage.evaluate(async () => {
|
|
73
|
-
await window.Store.
|
|
75
|
+
await window.Store.DrawerManager.closeDrawerRight();
|
|
74
76
|
});
|
|
75
77
|
}
|
|
76
78
|
|