whatsapp-web.js 1.25.0 → 1.26.1-alpha.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/README.md +1 -1
- package/example.js +15 -0
- package/index.d.ts +14 -1
- package/package.json +1 -1
- package/src/Client.js +248 -225
- package/src/structures/Chat.js +8 -0
- package/src/structures/Message.js +21 -22
- package/src/util/Constants.js +1 -1
- package/src/util/Injected/Store.js +2 -0
- package/src/util/Injected/Utils.js +19 -13
- package/src/util/InterfaceController.js +5 -5
- package/src/util/Puppeteer.js +23 -0
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<p>
|
|
8
8
|
<a href="https://www.npmjs.com/package/whatsapp-web.js"><img src="https://img.shields.io/npm/v/whatsapp-web.js.svg" alt="npm" /></a>
|
|
9
9
|
<a href="https://depfu.com/github/pedroslopez/whatsapp-web.js?project_id=9765"><img src="https://badges.depfu.com/badges/4a65a0de96ece65fdf39e294e0c8dcba/overview.svg" alt="Depfu" /></a>
|
|
10
|
-
<img src="https://img.shields.io/badge/WhatsApp_Web-2.
|
|
10
|
+
<img src="https://img.shields.io/badge/WhatsApp_Web-2.3000.1016590837-brightgreen.svg" alt="WhatsApp_Web 2.2346.52" />
|
|
11
11
|
<a href="https://discord.gg/H7DqQs4"><img src="https://img.shields.io/discord/698610475432411196.svg?logo=discord" alt="Discord server" /></a>
|
|
12
12
|
</p>
|
|
13
13
|
<br />
|
package/example.js
CHANGED
|
@@ -450,6 +450,21 @@ client.on('message', async msg => {
|
|
|
450
450
|
*/
|
|
451
451
|
const result = await msg.pin(60); // Will pin a message for 1 minute
|
|
452
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
|
+
} else if (msg.body === '!syncHistory') {
|
|
462
|
+
const isSynced = await client.syncHistory(msg.from);
|
|
463
|
+
// Or through the Chat object:
|
|
464
|
+
// const chat = await client.getChatById(msg.from);
|
|
465
|
+
// const isSynced = await chat.syncHistory();
|
|
466
|
+
|
|
467
|
+
await msg.reply(isSynced ? 'Historical chat is syncing..' : 'There is no historical chat to sync.');
|
|
453
468
|
}
|
|
454
469
|
});
|
|
455
470
|
|
package/index.d.ts
CHANGED
|
@@ -176,7 +176,18 @@ declare namespace WAWebJS {
|
|
|
176
176
|
* @param flag true/false on or off
|
|
177
177
|
*/
|
|
178
178
|
setAutoDownloadVideos(flag: boolean): Promise<void>
|
|
179
|
-
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Get user device count by ID
|
|
182
|
+
* Each WaWeb Connection counts as one device, and the phone (if exists) counts as one
|
|
183
|
+
* So for a non-enterprise user with one WaWeb connection it should return "2"
|
|
184
|
+
* @param {string} contactId
|
|
185
|
+
*/
|
|
186
|
+
getContactDeviceCount(userId: string): Promise<number>
|
|
187
|
+
|
|
188
|
+
/** Sync history conversation of the Chat */
|
|
189
|
+
syncHistory(chatId: string): Promise<boolean>
|
|
190
|
+
|
|
180
191
|
/** Changes and returns the archive state of the Chat */
|
|
181
192
|
unarchiveChat(chatId: string): Promise<boolean>
|
|
182
193
|
|
|
@@ -1432,6 +1443,8 @@ declare namespace WAWebJS {
|
|
|
1432
1443
|
getLabels: () => Promise<Label[]>,
|
|
1433
1444
|
/** Add or remove labels to this Chat */
|
|
1434
1445
|
changeLabels: (labelIds: Array<string | number>) => Promise<void>
|
|
1446
|
+
/** Sync history conversation of the Chat */
|
|
1447
|
+
syncHistory: () => Promise<boolean>
|
|
1435
1448
|
}
|
|
1436
1449
|
|
|
1437
1450
|
export interface MessageSearchOptions {
|
package/package.json
CHANGED
package/src/Client.js
CHANGED
|
@@ -17,6 +17,7 @@ const ContactFactory = require('./factories/ContactFactory');
|
|
|
17
17
|
const WebCacheFactory = require('./webCache/WebCacheFactory');
|
|
18
18
|
const { ClientInfo, Message, MessageMedia, Contact, Location, Poll, PollVote, GroupNotification, Label, Call, Buttons, List, Reaction } = require('./structures');
|
|
19
19
|
const NoAuth = require('./authStrategies/NoAuth');
|
|
20
|
+
const {exposeFunctionIfAbsent} = require('./util/Puppeteer');
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* Starting point for interacting with the WhatsApp Web API
|
|
@@ -90,9 +91,8 @@ class Client extends EventEmitter {
|
|
|
90
91
|
/**
|
|
91
92
|
* Injection logic
|
|
92
93
|
* Private function
|
|
93
|
-
* @property {boolean} reinject is this a reinject?
|
|
94
94
|
*/
|
|
95
|
-
async inject(
|
|
95
|
+
async inject() {
|
|
96
96
|
await this.pupPage.waitForFunction('window.Debug?.VERSION != undefined', {timeout: this.options.authTimeoutMs});
|
|
97
97
|
|
|
98
98
|
const version = await this.getWWebVersion();
|
|
@@ -142,26 +142,21 @@ class Client extends EventEmitter {
|
|
|
142
142
|
|
|
143
143
|
// Register qr events
|
|
144
144
|
let qrRetries = 0;
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
qrRetries++;
|
|
158
|
-
if (qrRetries > this.options.qrMaxRetries) {
|
|
159
|
-
this.emit(Events.DISCONNECTED, 'Max qrcode retries reached');
|
|
160
|
-
await this.destroy();
|
|
161
|
-
}
|
|
145
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onQRChangedEvent', async (qr) => {
|
|
146
|
+
/**
|
|
147
|
+
* Emitted when a QR code is received
|
|
148
|
+
* @event Client#qr
|
|
149
|
+
* @param {string} qr QR Code
|
|
150
|
+
*/
|
|
151
|
+
this.emit(Events.QR_RECEIVED, qr);
|
|
152
|
+
if (this.options.qrMaxRetries > 0) {
|
|
153
|
+
qrRetries++;
|
|
154
|
+
if (qrRetries > this.options.qrMaxRetries) {
|
|
155
|
+
this.emit(Events.DISCONNECTED, 'Max qrcode retries reached');
|
|
156
|
+
await this.destroy();
|
|
162
157
|
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
158
|
+
}
|
|
159
|
+
});
|
|
165
160
|
|
|
166
161
|
|
|
167
162
|
await this.pupPage.evaluate(async () => {
|
|
@@ -178,86 +173,78 @@ class Client extends EventEmitter {
|
|
|
178
173
|
});
|
|
179
174
|
}
|
|
180
175
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
});
|
|
176
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onAuthAppStateChangedEvent', async (state) => {
|
|
177
|
+
if (state == 'UNPAIRED_IDLE') {
|
|
178
|
+
// refresh qr code
|
|
179
|
+
window.Store.Cmd.refreshQR();
|
|
180
|
+
}
|
|
181
|
+
});
|
|
188
182
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
183
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onAppStateHasSyncedEvent', async () => {
|
|
184
|
+
const authEventPayload = await this.authStrategy.getAuthEventPayload();
|
|
185
|
+
/**
|
|
192
186
|
* Emitted when authentication is successful
|
|
193
187
|
* @event Client#authenticated
|
|
194
188
|
*/
|
|
195
|
-
|
|
189
|
+
this.emit(Events.AUTHENTICATED, authEventPayload);
|
|
196
190
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
191
|
+
const injected = await this.pupPage.evaluate(async () => {
|
|
192
|
+
return typeof window.Store !== 'undefined' && typeof window.WWebJS !== 'undefined';
|
|
193
|
+
});
|
|
200
194
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
195
|
+
if (!injected) {
|
|
196
|
+
if (this.options.webVersionCache.type === 'local' && this.currentIndexHtml) {
|
|
197
|
+
const { type: webCacheType, ...webCacheOptions } = this.options.webVersionCache;
|
|
198
|
+
const webCache = WebCacheFactory.createWebCache(webCacheType, webCacheOptions);
|
|
205
199
|
|
|
206
|
-
|
|
207
|
-
|
|
200
|
+
await webCache.persist(this.currentIndexHtml, version);
|
|
201
|
+
}
|
|
208
202
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
203
|
+
if (isCometOrAbove) {
|
|
204
|
+
await this.pupPage.evaluate(ExposeStore);
|
|
205
|
+
} else {
|
|
206
|
+
// make sure all modules are ready before injection
|
|
207
|
+
// 2 second delay after authentication makes sense and does not need to be made dyanmic or removed
|
|
208
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
209
|
+
await this.pupPage.evaluate(ExposeLegacyStore);
|
|
210
|
+
}
|
|
217
211
|
|
|
218
|
-
|
|
219
|
-
|
|
212
|
+
// Check window.Store Injection
|
|
213
|
+
await this.pupPage.waitForFunction('window.Store != undefined');
|
|
220
214
|
|
|
221
|
-
|
|
215
|
+
/**
|
|
222
216
|
* Current connection information
|
|
223
217
|
* @type {ClientInfo}
|
|
224
218
|
*/
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
219
|
+
this.info = new ClientInfo(this, await this.pupPage.evaluate(() => {
|
|
220
|
+
return { ...window.Store.Conn.serialize(), wid: window.Store.User.getMeUser() };
|
|
221
|
+
}));
|
|
228
222
|
|
|
229
|
-
|
|
223
|
+
this.interface = new InterfaceController(this);
|
|
230
224
|
|
|
231
|
-
|
|
232
|
-
|
|
225
|
+
//Load util functions (serializers, helper functions)
|
|
226
|
+
await this.pupPage.evaluate(LoadUtils);
|
|
233
227
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
/**
|
|
228
|
+
await this.attachEventListeners();
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
238
231
|
* Emitted when the client has initialized and is ready to receive messages.
|
|
239
232
|
* @event Client#ready
|
|
240
233
|
*/
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
234
|
+
this.emit(Events.READY);
|
|
235
|
+
this.authStrategy.afterAuthReady();
|
|
236
|
+
});
|
|
237
|
+
let lastPercent = null;
|
|
238
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onOfflineProgressUpdateEvent', async (percent) => {
|
|
239
|
+
if (lastPercent !== percent) {
|
|
240
|
+
lastPercent = percent;
|
|
241
|
+
this.emit(Events.LOADING_SCREEN, percent, 'WhatsApp'); // Message is hardcoded as "WhatsApp" for now
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onLogoutEvent', async () => {
|
|
245
|
+
this.lastLoggedOut = true;
|
|
246
|
+
await this.pupPage.waitForNavigation({waitUntil: 'load', timeout: 5000}).catch((_) => _);
|
|
254
247
|
});
|
|
255
|
-
if (!logoutCatchInjected) {
|
|
256
|
-
await this.pupPage.exposeFunction('onLogoutEvent', async () => {
|
|
257
|
-
this.lastLoggedOut = true;
|
|
258
|
-
await this.pupPage.waitForNavigation({waitUntil: 'load', timeout: 5000}).catch((_) => _);
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
248
|
await this.pupPage.evaluate(() => {
|
|
262
249
|
window.AuthStore.AppState.on('change:state', (_AppState, state) => { window.onAuthAppStateChangedEvent(state); });
|
|
263
250
|
window.AuthStore.AppState.on('change:hasSynced', () => { window.onAppStateHasSyncedEvent(); });
|
|
@@ -323,6 +310,7 @@ class Client extends EventEmitter {
|
|
|
323
310
|
// remove after 2.3000.x hard release
|
|
324
311
|
await page.evaluateOnNewDocument(() => {
|
|
325
312
|
const originalError = Error;
|
|
313
|
+
window.originalError = originalError;
|
|
326
314
|
//eslint-disable-next-line no-global-assign
|
|
327
315
|
Error = function (message) {
|
|
328
316
|
const error = new originalError(message);
|
|
@@ -348,7 +336,7 @@ class Client extends EventEmitter {
|
|
|
348
336
|
await this.authStrategy.afterBrowserInitialized();
|
|
349
337
|
this.lastLoggedOut = false;
|
|
350
338
|
}
|
|
351
|
-
await this.inject(
|
|
339
|
+
await this.inject();
|
|
352
340
|
});
|
|
353
341
|
}
|
|
354
342
|
|
|
@@ -371,34 +359,33 @@ class Client extends EventEmitter {
|
|
|
371
359
|
* Private function
|
|
372
360
|
* @property {boolean} reinject is this a reinject?
|
|
373
361
|
*/
|
|
374
|
-
async attachEventListeners(
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
/**
|
|
362
|
+
async attachEventListeners() {
|
|
363
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onAddMessageEvent', msg => {
|
|
364
|
+
if (msg.type === 'gp2') {
|
|
365
|
+
const notification = new GroupNotification(this, msg);
|
|
366
|
+
if (['add', 'invite', 'linked_group_join'].includes(msg.subtype)) {
|
|
367
|
+
/**
|
|
381
368
|
* Emitted when a user joins the chat via invite link or is added by an admin.
|
|
382
369
|
* @event Client#group_join
|
|
383
370
|
* @param {GroupNotification} notification GroupNotification with more information about the action
|
|
384
371
|
*/
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
372
|
+
this.emit(Events.GROUP_JOIN, notification);
|
|
373
|
+
} else if (msg.subtype === 'remove' || msg.subtype === 'leave') {
|
|
374
|
+
/**
|
|
388
375
|
* Emitted when a user leaves the chat or is removed by an admin.
|
|
389
376
|
* @event Client#group_leave
|
|
390
377
|
* @param {GroupNotification} notification GroupNotification with more information about the action
|
|
391
378
|
*/
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
379
|
+
this.emit(Events.GROUP_LEAVE, notification);
|
|
380
|
+
} else if (msg.subtype === 'promote' || msg.subtype === 'demote') {
|
|
381
|
+
/**
|
|
395
382
|
* Emitted when a current user is promoted to an admin or demoted to a regular user.
|
|
396
383
|
* @event Client#group_admin_changed
|
|
397
384
|
* @param {GroupNotification} notification GroupNotification with more information about the action
|
|
398
385
|
*/
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
386
|
+
this.emit(Events.GROUP_ADMIN_CHANGED, notification);
|
|
387
|
+
} else if (msg.subtype === 'membership_approval_request') {
|
|
388
|
+
/**
|
|
402
389
|
* Emitted when some user requested to join the group
|
|
403
390
|
* that has the membership approval mode turned on
|
|
404
391
|
* @event Client#group_membership_request
|
|
@@ -407,86 +394,86 @@ class Client extends EventEmitter {
|
|
|
407
394
|
* @param {string} notification.author The user ID that made a request
|
|
408
395
|
* @param {number} notification.timestamp The timestamp the request was made at
|
|
409
396
|
*/
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
397
|
+
this.emit(Events.GROUP_MEMBERSHIP_REQUEST, notification);
|
|
398
|
+
} else {
|
|
399
|
+
/**
|
|
413
400
|
* Emitted when group settings are updated, such as subject, description or picture.
|
|
414
401
|
* @event Client#group_update
|
|
415
402
|
* @param {GroupNotification} notification GroupNotification with more information about the action
|
|
416
403
|
*/
|
|
417
|
-
|
|
418
|
-
}
|
|
419
|
-
return;
|
|
404
|
+
this.emit(Events.GROUP_UPDATE, notification);
|
|
420
405
|
}
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
421
408
|
|
|
422
|
-
|
|
409
|
+
const message = new Message(this, msg);
|
|
423
410
|
|
|
424
|
-
|
|
411
|
+
/**
|
|
425
412
|
* Emitted when a new message is created, which may include the current user's own messages.
|
|
426
413
|
* @event Client#message_create
|
|
427
414
|
* @param {Message} message The message that was created
|
|
428
415
|
*/
|
|
429
|
-
|
|
416
|
+
this.emit(Events.MESSAGE_CREATE, message);
|
|
430
417
|
|
|
431
|
-
|
|
418
|
+
if (msg.id.fromMe) return;
|
|
432
419
|
|
|
433
|
-
|
|
420
|
+
/**
|
|
434
421
|
* Emitted when a new message is received.
|
|
435
422
|
* @event Client#message
|
|
436
423
|
* @param {Message} message The message that was received
|
|
437
424
|
*/
|
|
438
|
-
|
|
439
|
-
|
|
425
|
+
this.emit(Events.MESSAGE_RECEIVED, message);
|
|
426
|
+
});
|
|
440
427
|
|
|
441
|
-
|
|
428
|
+
let last_message;
|
|
442
429
|
|
|
443
|
-
|
|
430
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onChangeMessageTypeEvent', (msg) => {
|
|
444
431
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
432
|
+
if (msg.type === 'revoked') {
|
|
433
|
+
const message = new Message(this, msg);
|
|
434
|
+
let revoked_msg;
|
|
435
|
+
if (last_message && msg.id.id === last_message.id.id) {
|
|
436
|
+
revoked_msg = new Message(this, last_message);
|
|
437
|
+
}
|
|
451
438
|
|
|
452
|
-
|
|
439
|
+
/**
|
|
453
440
|
* Emitted when a message is deleted for everyone in the chat.
|
|
454
441
|
* @event Client#message_revoke_everyone
|
|
455
442
|
* @param {Message} message The message that was revoked, in its current state. It will not contain the original message's data.
|
|
456
443
|
* @param {?Message} revoked_msg The message that was revoked, before it was revoked. It will contain the message's original data.
|
|
457
444
|
* Note that due to the way this data is captured, it may be possible that this param will be undefined.
|
|
458
445
|
*/
|
|
459
|
-
|
|
460
|
-
|
|
446
|
+
this.emit(Events.MESSAGE_REVOKED_EVERYONE, message, revoked_msg);
|
|
447
|
+
}
|
|
461
448
|
|
|
462
|
-
|
|
449
|
+
});
|
|
463
450
|
|
|
464
|
-
|
|
451
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onChangeMessageEvent', (msg) => {
|
|
465
452
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
453
|
+
if (msg.type !== 'revoked') {
|
|
454
|
+
last_message = msg;
|
|
455
|
+
}
|
|
469
456
|
|
|
470
|
-
|
|
457
|
+
/**
|
|
471
458
|
* The event notification that is received when one of
|
|
472
459
|
* the group participants changes their phone number.
|
|
473
460
|
*/
|
|
474
|
-
|
|
461
|
+
const isParticipant = msg.type === 'gp2' && msg.subtype === 'modify';
|
|
475
462
|
|
|
476
|
-
|
|
463
|
+
/**
|
|
477
464
|
* The event notification that is received when one of
|
|
478
465
|
* the contacts changes their phone number.
|
|
479
466
|
*/
|
|
480
|
-
|
|
467
|
+
const isContact = msg.type === 'notification_template' && msg.subtype === 'change_number';
|
|
481
468
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
469
|
+
if (isParticipant || isContact) {
|
|
470
|
+
/** @type {GroupNotification} object does not provide enough information about this event, so a @type {Message} object is used. */
|
|
471
|
+
const message = new Message(this, msg);
|
|
485
472
|
|
|
486
|
-
|
|
487
|
-
|
|
473
|
+
const newId = isParticipant ? msg.recipients[0] : msg.to;
|
|
474
|
+
const oldId = isParticipant ? msg.author : msg.templateParams.find(id => id !== newId);
|
|
488
475
|
|
|
489
|
-
|
|
476
|
+
/**
|
|
490
477
|
* Emitted when a contact or a group participant changes their phone number.
|
|
491
478
|
* @event Client#contact_changed
|
|
492
479
|
* @param {Message} message Message with more information about the event.
|
|
@@ -495,98 +482,98 @@ class Client extends EventEmitter {
|
|
|
495
482
|
* @param {String} newId The user's new id after the change.
|
|
496
483
|
* @param {Boolean} isContact Indicates if a contact or a group participant changed their phone number.
|
|
497
484
|
*/
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
485
|
+
this.emit(Events.CONTACT_CHANGED, message, oldId, newId, isContact);
|
|
486
|
+
}
|
|
487
|
+
});
|
|
501
488
|
|
|
502
|
-
|
|
489
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onRemoveMessageEvent', (msg) => {
|
|
503
490
|
|
|
504
|
-
|
|
491
|
+
if (!msg.isNewMsg) return;
|
|
505
492
|
|
|
506
|
-
|
|
493
|
+
const message = new Message(this, msg);
|
|
507
494
|
|
|
508
|
-
|
|
495
|
+
/**
|
|
509
496
|
* Emitted when a message is deleted by the current user.
|
|
510
497
|
* @event Client#message_revoke_me
|
|
511
498
|
* @param {Message} message The message that was revoked
|
|
512
499
|
*/
|
|
513
|
-
|
|
500
|
+
this.emit(Events.MESSAGE_REVOKED_ME, message);
|
|
514
501
|
|
|
515
|
-
|
|
502
|
+
});
|
|
516
503
|
|
|
517
|
-
|
|
504
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onMessageAckEvent', (msg, ack) => {
|
|
518
505
|
|
|
519
|
-
|
|
506
|
+
const message = new Message(this, msg);
|
|
520
507
|
|
|
521
|
-
|
|
508
|
+
/**
|
|
522
509
|
* Emitted when an ack event occurrs on message type.
|
|
523
510
|
* @event Client#message_ack
|
|
524
511
|
* @param {Message} message The message that was affected
|
|
525
512
|
* @param {MessageAck} ack The new ACK value
|
|
526
513
|
*/
|
|
527
|
-
|
|
514
|
+
this.emit(Events.MESSAGE_ACK, message, ack);
|
|
528
515
|
|
|
529
|
-
|
|
516
|
+
});
|
|
530
517
|
|
|
531
|
-
|
|
532
|
-
|
|
518
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onChatUnreadCountEvent', async (data) =>{
|
|
519
|
+
const chat = await this.getChatById(data.id);
|
|
533
520
|
|
|
534
|
-
|
|
521
|
+
/**
|
|
535
522
|
* Emitted when the chat unread count changes
|
|
536
523
|
*/
|
|
537
|
-
|
|
538
|
-
|
|
524
|
+
this.emit(Events.UNREAD_COUNT, chat);
|
|
525
|
+
});
|
|
539
526
|
|
|
540
|
-
|
|
527
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onMessageMediaUploadedEvent', (msg) => {
|
|
541
528
|
|
|
542
|
-
|
|
529
|
+
const message = new Message(this, msg);
|
|
543
530
|
|
|
544
|
-
|
|
531
|
+
/**
|
|
545
532
|
* Emitted when media has been uploaded for a message sent by the client.
|
|
546
533
|
* @event Client#media_uploaded
|
|
547
534
|
* @param {Message} message The message with media that was uploaded
|
|
548
535
|
*/
|
|
549
|
-
|
|
550
|
-
|
|
536
|
+
this.emit(Events.MEDIA_UPLOADED, message);
|
|
537
|
+
});
|
|
551
538
|
|
|
552
|
-
|
|
553
|
-
|
|
539
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onAppStateChangedEvent', async (state) => {
|
|
540
|
+
/**
|
|
554
541
|
* Emitted when the connection state changes
|
|
555
542
|
* @event Client#change_state
|
|
556
543
|
* @param {WAState} state the new connection state
|
|
557
544
|
*/
|
|
558
|
-
|
|
545
|
+
this.emit(Events.STATE_CHANGED, state);
|
|
559
546
|
|
|
560
|
-
|
|
547
|
+
const ACCEPTED_STATES = [WAState.CONNECTED, WAState.OPENING, WAState.PAIRING, WAState.TIMEOUT];
|
|
561
548
|
|
|
562
|
-
|
|
563
|
-
|
|
549
|
+
if (this.options.takeoverOnConflict) {
|
|
550
|
+
ACCEPTED_STATES.push(WAState.CONFLICT);
|
|
564
551
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
}
|
|
552
|
+
if (state === WAState.CONFLICT) {
|
|
553
|
+
setTimeout(() => {
|
|
554
|
+
this.pupPage.evaluate(() => window.Store.AppState.takeover());
|
|
555
|
+
}, this.options.takeoverTimeoutMs);
|
|
570
556
|
}
|
|
557
|
+
}
|
|
571
558
|
|
|
572
|
-
|
|
573
|
-
|
|
559
|
+
if (!ACCEPTED_STATES.includes(state)) {
|
|
560
|
+
/**
|
|
574
561
|
* Emitted when the client has been disconnected
|
|
575
562
|
* @event Client#disconnected
|
|
576
563
|
* @param {WAState|"LOGOUT"} reason reason that caused the disconnect
|
|
577
564
|
*/
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
565
|
+
await this.authStrategy.disconnect();
|
|
566
|
+
this.emit(Events.DISCONNECTED, state);
|
|
567
|
+
this.destroy();
|
|
568
|
+
}
|
|
569
|
+
});
|
|
583
570
|
|
|
584
|
-
|
|
585
|
-
|
|
571
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onBatteryStateChangedEvent', (state) => {
|
|
572
|
+
const { battery, plugged } = state;
|
|
586
573
|
|
|
587
|
-
|
|
574
|
+
if (battery === undefined) return;
|
|
588
575
|
|
|
589
|
-
|
|
576
|
+
/**
|
|
590
577
|
* Emitted when the battery percentage for the attached device changes. Will not be sent if using multi-device.
|
|
591
578
|
* @event Client#change_battery
|
|
592
579
|
* @param {object} batteryInfo
|
|
@@ -594,11 +581,11 @@ class Client extends EventEmitter {
|
|
|
594
581
|
* @param {boolean} batteryInfo.plugged - Indicates if the phone is plugged in (true) or not (false)
|
|
595
582
|
* @deprecated
|
|
596
583
|
*/
|
|
597
|
-
|
|
598
|
-
|
|
584
|
+
this.emit(Events.BATTERY_CHANGED, { battery, plugged });
|
|
585
|
+
});
|
|
599
586
|
|
|
600
|
-
|
|
601
|
-
|
|
587
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onIncomingCall', (call) => {
|
|
588
|
+
/**
|
|
602
589
|
* Emitted when a call is received
|
|
603
590
|
* @event Client#incoming_call
|
|
604
591
|
* @param {object} call
|
|
@@ -611,13 +598,13 @@ class Client extends EventEmitter {
|
|
|
611
598
|
* @param {boolean} call.webClientShouldHandle - If Waweb should handle
|
|
612
599
|
* @param {object} call.participants - Participants
|
|
613
600
|
*/
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
601
|
+
const cll = new Call(this, call);
|
|
602
|
+
this.emit(Events.INCOMING_CALL, cll);
|
|
603
|
+
});
|
|
617
604
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
605
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onReaction', (reactions) => {
|
|
606
|
+
for (const reaction of reactions) {
|
|
607
|
+
/**
|
|
621
608
|
* Emitted when a reaction is sent, received, updated or removed
|
|
622
609
|
* @event Client#message_reaction
|
|
623
610
|
* @param {object} reaction
|
|
@@ -632,61 +619,60 @@ class Client extends EventEmitter {
|
|
|
632
619
|
* @param {?number} reaction.ack - Ack
|
|
633
620
|
*/
|
|
634
621
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
622
|
+
this.emit(Events.MESSAGE_REACTION, new Reaction(this, reaction));
|
|
623
|
+
}
|
|
624
|
+
});
|
|
638
625
|
|
|
639
|
-
|
|
640
|
-
|
|
626
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onRemoveChatEvent', async (chat) => {
|
|
627
|
+
const _chat = await this.getChatById(chat.id);
|
|
641
628
|
|
|
642
|
-
|
|
629
|
+
/**
|
|
643
630
|
* Emitted when a chat is removed
|
|
644
631
|
* @event Client#chat_removed
|
|
645
632
|
* @param {Chat} chat
|
|
646
633
|
*/
|
|
647
|
-
|
|
648
|
-
|
|
634
|
+
this.emit(Events.CHAT_REMOVED, _chat);
|
|
635
|
+
});
|
|
649
636
|
|
|
650
|
-
|
|
651
|
-
|
|
637
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onArchiveChatEvent', async (chat, currState, prevState) => {
|
|
638
|
+
const _chat = await this.getChatById(chat.id);
|
|
652
639
|
|
|
653
|
-
|
|
640
|
+
/**
|
|
654
641
|
* Emitted when a chat is archived/unarchived
|
|
655
642
|
* @event Client#chat_archived
|
|
656
643
|
* @param {Chat} chat
|
|
657
644
|
* @param {boolean} currState
|
|
658
645
|
* @param {boolean} prevState
|
|
659
646
|
*/
|
|
660
|
-
|
|
661
|
-
|
|
647
|
+
this.emit(Events.CHAT_ARCHIVED, _chat, currState, prevState);
|
|
648
|
+
});
|
|
662
649
|
|
|
663
|
-
|
|
650
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onEditMessageEvent', (msg, newBody, prevBody) => {
|
|
664
651
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
652
|
+
if(msg.type === 'revoked'){
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
669
656
|
* Emitted when messages are edited
|
|
670
657
|
* @event Client#message_edit
|
|
671
658
|
* @param {Message} message
|
|
672
659
|
* @param {string} newBody
|
|
673
660
|
* @param {string} prevBody
|
|
674
661
|
*/
|
|
675
|
-
|
|
676
|
-
|
|
662
|
+
this.emit(Events.MESSAGE_EDIT, new Message(this, msg), newBody, prevBody);
|
|
663
|
+
});
|
|
677
664
|
|
|
678
|
-
|
|
665
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onAddMessageCiphertextEvent', msg => {
|
|
679
666
|
|
|
680
|
-
|
|
667
|
+
/**
|
|
681
668
|
* Emitted when messages are edited
|
|
682
669
|
* @event Client#message_ciphertext
|
|
683
670
|
* @param {Message} message
|
|
684
671
|
*/
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
}
|
|
672
|
+
this.emit(Events.MESSAGE_CIPHERTEXT, new Message(this, msg));
|
|
673
|
+
});
|
|
688
674
|
|
|
689
|
-
await this.pupPage
|
|
675
|
+
await exposeFunctionIfAbsent(this.pupPage, 'onPollVoteEvent', (vote) => {
|
|
690
676
|
const _vote = new PollVote(this, vote);
|
|
691
677
|
/**
|
|
692
678
|
* Emitted when some poll option is selected or deselected,
|
|
@@ -720,8 +706,8 @@ class Client extends EventEmitter {
|
|
|
720
706
|
}
|
|
721
707
|
});
|
|
722
708
|
window.Store.Chat.on('change:unreadCount', (chat) => {window.onChatUnreadCountEvent(chat);});
|
|
723
|
-
window.Store.PollVote.on('add', (vote) => {
|
|
724
|
-
const pollVoteModel = window.WWebJS.getPollVoteModel(vote);
|
|
709
|
+
window.Store.PollVote.on('add', async (vote) => {
|
|
710
|
+
const pollVoteModel = await window.WWebJS.getPollVoteModel(vote);
|
|
725
711
|
pollVoteModel && window.onPollVoteEvent(pollVoteModel);
|
|
726
712
|
});
|
|
727
713
|
|
|
@@ -802,7 +788,9 @@ class Client extends EventEmitter {
|
|
|
802
788
|
*/
|
|
803
789
|
async logout() {
|
|
804
790
|
await this.pupPage.evaluate(() => {
|
|
805
|
-
|
|
791
|
+
if (window.Store && window.Store.AppState && typeof window.Store.AppState.logout === 'function') {
|
|
792
|
+
return window.Store.AppState.logout();
|
|
793
|
+
}
|
|
806
794
|
});
|
|
807
795
|
await this.pupBrowser.close();
|
|
808
796
|
|
|
@@ -1034,7 +1022,7 @@ class Client extends EventEmitter {
|
|
|
1034
1022
|
if(msg) return window.WWebJS.getMessageModel(msg);
|
|
1035
1023
|
|
|
1036
1024
|
const params = messageId.split('_');
|
|
1037
|
-
if(params.length !== 3) throw new Error('Invalid serialized message id specified');
|
|
1025
|
+
if (params.length !== 3 && params.length !== 4) throw new Error('Invalid serialized message id specified');
|
|
1038
1026
|
|
|
1039
1027
|
let messagesObject = await window.Store.Msg.getMessagesById([messageId]);
|
|
1040
1028
|
if (messagesObject && messagesObject.messages.length) msg = messagesObject.messages[0];
|
|
@@ -1614,8 +1602,8 @@ class Client extends EventEmitter {
|
|
|
1614
1602
|
* @returns {Promise<Array<GroupMembershipRequest>>} An array of membership requests
|
|
1615
1603
|
*/
|
|
1616
1604
|
async getGroupMembershipRequests(groupId) {
|
|
1617
|
-
return await this.pupPage.evaluate(async (
|
|
1618
|
-
const groupWid = window.Store.WidFactory.createWid(
|
|
1605
|
+
return await this.pupPage.evaluate(async (groupId) => {
|
|
1606
|
+
const groupWid = window.Store.WidFactory.createWid(groupId);
|
|
1619
1607
|
return await window.Store.MembershipRequestUtils.getMembershipApprovalRequests(groupWid);
|
|
1620
1608
|
}, groupId);
|
|
1621
1609
|
}
|
|
@@ -1721,6 +1709,41 @@ class Client extends EventEmitter {
|
|
|
1721
1709
|
return flag;
|
|
1722
1710
|
}, flag);
|
|
1723
1711
|
}
|
|
1712
|
+
|
|
1713
|
+
/**
|
|
1714
|
+
* Get user device count by ID
|
|
1715
|
+
* Each WaWeb Connection counts as one device, and the phone (if exists) counts as one
|
|
1716
|
+
* So for a non-enterprise user with one WaWeb connection it should return "2"
|
|
1717
|
+
* @param {string} userId
|
|
1718
|
+
* @returns {Promise<number>}
|
|
1719
|
+
*/
|
|
1720
|
+
async getContactDeviceCount(userId) {
|
|
1721
|
+
return await this.pupPage.evaluate(async (userId) => {
|
|
1722
|
+
const devices = await window.Store.DeviceList.getDeviceIds([window.Store.WidFactory.createWid(userId)]);
|
|
1723
|
+
if (devices && devices.length && devices[0] != null && typeof devices[0].devices == 'object') {
|
|
1724
|
+
return devices[0].devices.length;
|
|
1725
|
+
}
|
|
1726
|
+
return 0;
|
|
1727
|
+
}, userId);
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
/**
|
|
1731
|
+
* Sync chat history conversation
|
|
1732
|
+
* @param {string} chatId
|
|
1733
|
+
* @return {Promise<boolean>} True if operation completed successfully, false otherwise.
|
|
1734
|
+
*/
|
|
1735
|
+
async syncHistory(chatId) {
|
|
1736
|
+
return await this.pupPage.evaluate(async (chatId) => {
|
|
1737
|
+
const chat = await window.WWebJS.getChat(chatId);
|
|
1738
|
+
if (chat.endOfHistoryTransferType === 0) {
|
|
1739
|
+
await window.Store.HistorySync.sendPeerDataOperationRequest(3, {
|
|
1740
|
+
chatId: chat.id
|
|
1741
|
+
});
|
|
1742
|
+
return true;
|
|
1743
|
+
}
|
|
1744
|
+
return false;
|
|
1745
|
+
}, chatId);
|
|
1746
|
+
}
|
|
1724
1747
|
}
|
|
1725
1748
|
|
|
1726
1749
|
module.exports = Client;
|
package/src/structures/Chat.js
CHANGED
|
@@ -270,6 +270,14 @@ class Chat extends Base {
|
|
|
270
270
|
async changeLabels(labelIds) {
|
|
271
271
|
return this.client.addOrRemoveLabels(labelIds, [this.id._serialized]);
|
|
272
272
|
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Sync chat history conversation
|
|
276
|
+
* @return {Promise<boolean>} True if operation completed successfully, false otherwise.
|
|
277
|
+
*/
|
|
278
|
+
async syncHistory() {
|
|
279
|
+
return this.client.syncHistory(this.id._serialized);
|
|
280
|
+
}
|
|
273
281
|
}
|
|
274
282
|
|
|
275
283
|
module.exports = Chat;
|
|
@@ -182,8 +182,8 @@ class Message extends Base {
|
|
|
182
182
|
inviteCodeExp: data.inviteCodeExp,
|
|
183
183
|
groupId: data.inviteGrp,
|
|
184
184
|
groupName: data.inviteGrpName,
|
|
185
|
-
fromId: '_serialized' in data.from ? data.from._serialized : data.from,
|
|
186
|
-
toId: '_serialized' in data.to ? data.to._serialized : data.to
|
|
185
|
+
fromId: typeof data.from === 'object' && '_serialized' in data.from ? data.from._serialized : data.from,
|
|
186
|
+
toId: typeof data.to === 'object' && '_serialized' in data.to ? data.to._serialized : data.to
|
|
187
187
|
} : undefined;
|
|
188
188
|
|
|
189
189
|
/**
|
|
@@ -311,9 +311,9 @@ class Message extends Base {
|
|
|
311
311
|
* @returns {Promise<Message>}
|
|
312
312
|
*/
|
|
313
313
|
async reload() {
|
|
314
|
-
const newData = await this.client.pupPage.evaluate((msgId) => {
|
|
315
|
-
const msg = window.Store.Msg.get(msgId);
|
|
316
|
-
if(!msg) return null;
|
|
314
|
+
const newData = await this.client.pupPage.evaluate(async (msgId) => {
|
|
315
|
+
const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
|
|
316
|
+
if (!msg) return null;
|
|
317
317
|
return window.WWebJS.getMessageModel(msg);
|
|
318
318
|
}, this.id._serialized);
|
|
319
319
|
|
|
@@ -370,8 +370,8 @@ class Message extends Base {
|
|
|
370
370
|
async getQuotedMessage() {
|
|
371
371
|
if (!this.hasQuotedMsg) return undefined;
|
|
372
372
|
|
|
373
|
-
const quotedMsg = await this.client.pupPage.evaluate((msgId) => {
|
|
374
|
-
const msg = window.Store.Msg.get(msgId);
|
|
373
|
+
const quotedMsg = await this.client.pupPage.evaluate(async (msgId) => {
|
|
374
|
+
const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
|
|
375
375
|
const quotedMsg = window.Store.QuotedMsg.getQuotedMsgObj(msg);
|
|
376
376
|
return window.WWebJS.getMessageModel(quotedMsg);
|
|
377
377
|
}, this.id._serialized);
|
|
@@ -409,9 +409,10 @@ class Message extends Base {
|
|
|
409
409
|
*/
|
|
410
410
|
async react(reaction){
|
|
411
411
|
await this.client.pupPage.evaluate(async (messageId, reaction) => {
|
|
412
|
-
if (!messageId)
|
|
413
|
-
|
|
414
|
-
|
|
412
|
+
if (!messageId) return null;
|
|
413
|
+
const msg =
|
|
414
|
+
window.Store.Msg.get(messageId) || (await window.Store.Msg.getMessagesById([messageId]))?.messages?.[0];
|
|
415
|
+
if(!msg) return null;
|
|
415
416
|
await window.Store.sendReactionToMsg(msg, reaction);
|
|
416
417
|
}, this.id._serialized, reaction);
|
|
417
418
|
}
|
|
@@ -448,9 +449,9 @@ class Message extends Base {
|
|
|
448
449
|
}
|
|
449
450
|
|
|
450
451
|
const result = await this.client.pupPage.evaluate(async (msgId) => {
|
|
451
|
-
const msg = window.Store.Msg.get(msgId);
|
|
452
|
+
const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
|
|
452
453
|
if (!msg || !msg.mediaData) {
|
|
453
|
-
return
|
|
454
|
+
return null;
|
|
454
455
|
}
|
|
455
456
|
if (msg.mediaData.mediaStage != 'RESOLVED') {
|
|
456
457
|
// try to resolve media
|
|
@@ -500,7 +501,7 @@ class Message extends Base {
|
|
|
500
501
|
*/
|
|
501
502
|
async delete(everyone) {
|
|
502
503
|
await this.client.pupPage.evaluate(async (msgId, everyone) => {
|
|
503
|
-
|
|
504
|
+
const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
|
|
504
505
|
let chat = await window.Store.Chat.find(msg.id.remote);
|
|
505
506
|
|
|
506
507
|
const canRevoke = window.Store.MsgActionChecks.canSenderRevokeMsg(msg) || window.Store.MsgActionChecks.canAdminRevokeMsg(msg);
|
|
@@ -521,8 +522,7 @@ class Message extends Base {
|
|
|
521
522
|
*/
|
|
522
523
|
async star() {
|
|
523
524
|
await this.client.pupPage.evaluate(async (msgId) => {
|
|
524
|
-
|
|
525
|
-
|
|
525
|
+
const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
|
|
526
526
|
if (window.Store.MsgActionChecks.canStarMsg(msg)) {
|
|
527
527
|
let chat = await window.Store.Chat.find(msg.id.remote);
|
|
528
528
|
return window.Store.Cmd.sendStarMsgs(chat, [msg], false);
|
|
@@ -535,8 +535,7 @@ class Message extends Base {
|
|
|
535
535
|
*/
|
|
536
536
|
async unstar() {
|
|
537
537
|
await this.client.pupPage.evaluate(async (msgId) => {
|
|
538
|
-
|
|
539
|
-
|
|
538
|
+
const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
|
|
540
539
|
if (window.Store.MsgActionChecks.canStarMsg(msg)) {
|
|
541
540
|
let chat = await window.Store.Chat.find(msg.id.remote);
|
|
542
541
|
return window.Store.Cmd.sendUnstarMsgs(chat, [msg], false);
|
|
@@ -583,7 +582,7 @@ class Message extends Base {
|
|
|
583
582
|
*/
|
|
584
583
|
async getInfo() {
|
|
585
584
|
const info = await this.client.pupPage.evaluate(async (msgId) => {
|
|
586
|
-
const msg = window.Store.Msg.get(msgId);
|
|
585
|
+
const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
|
|
587
586
|
if (!msg || !msg.id.fromMe) return null;
|
|
588
587
|
|
|
589
588
|
return new Promise((resolve) => {
|
|
@@ -617,7 +616,7 @@ class Message extends Base {
|
|
|
617
616
|
async getPayment() {
|
|
618
617
|
if (this.type === MessageTypes.PAYMENT) {
|
|
619
618
|
const msg = await this.client.pupPage.evaluate(async (msgId) => {
|
|
620
|
-
const msg = window.Store.Msg.get(msgId);
|
|
619
|
+
const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
|
|
621
620
|
if(!msg) return null;
|
|
622
621
|
return msg.serialize();
|
|
623
622
|
}, this.id._serialized);
|
|
@@ -692,11 +691,11 @@ class Message extends Base {
|
|
|
692
691
|
return null;
|
|
693
692
|
}
|
|
694
693
|
const messageEdit = await this.client.pupPage.evaluate(async (msgId, message, options) => {
|
|
695
|
-
|
|
694
|
+
const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
|
|
696
695
|
if (!msg) return null;
|
|
697
696
|
|
|
698
|
-
let
|
|
699
|
-
if (
|
|
697
|
+
let canEdit = window.Store.MsgActionChecks.canEditText(msg) || window.Store.MsgActionChecks.canEditCaption(msg);
|
|
698
|
+
if (canEdit) {
|
|
700
699
|
const msgEdit = await window.WWebJS.editMessage(msg, message, options);
|
|
701
700
|
return msgEdit.serialize();
|
|
702
701
|
}
|
package/src/util/Constants.js
CHANGED
|
@@ -97,6 +97,8 @@ exports.ExposeStore = () => {
|
|
|
97
97
|
window.Store.Settings = window.require('WAWebUserPrefsGeneral');
|
|
98
98
|
window.Store.BotSecret = window.require('WAWebBotMessageSecret');
|
|
99
99
|
window.Store.BotProfiles = window.require('WAWebBotProfileCollection');
|
|
100
|
+
window.Store.DeviceList = window.require('WAWebApiDeviceList');
|
|
101
|
+
window.Store.HistorySync = window.require('WAWebSendNonMessageDataRequest');
|
|
100
102
|
if (window.compareWwebVersions(window.Debug.VERSION, '>=', '2.3000.1014111620'))
|
|
101
103
|
window.Store.AddonReactionTable = window.require('WAWebAddonReactionTableMode').reactionTableMode;
|
|
102
104
|
|
|
@@ -4,7 +4,7 @@ exports.LoadUtils = () => {
|
|
|
4
4
|
window.WWebJS = {};
|
|
5
5
|
|
|
6
6
|
window.WWebJS.forwardMessage = async (chatId, msgId) => {
|
|
7
|
-
|
|
7
|
+
const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
|
|
8
8
|
let chat = window.Store.Chat.get(chatId);
|
|
9
9
|
|
|
10
10
|
if (window.compareWwebVersions(window.Debug.VERSION, '>', '2.3000.0')) {
|
|
@@ -44,7 +44,13 @@ exports.LoadUtils = () => {
|
|
|
44
44
|
}
|
|
45
45
|
let quotedMsgOptions = {};
|
|
46
46
|
if (options.quotedMessageId) {
|
|
47
|
-
let quotedMessage = window.Store.Msg.
|
|
47
|
+
let quotedMessage = await window.Store.Msg.getMessagesById([options.quotedMessageId]);
|
|
48
|
+
|
|
49
|
+
if (quotedMessage['messages'].length != 1) {
|
|
50
|
+
throw new Error('Could not get the quoted message.');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
quotedMessage = quotedMessage['messages'][0];
|
|
48
54
|
|
|
49
55
|
// TODO remove .canReply() once all clients are updated to >= v2.2241.6
|
|
50
56
|
const canReply = window.Store.ReplyUtils ?
|
|
@@ -433,14 +439,13 @@ exports.LoadUtils = () => {
|
|
|
433
439
|
return msg;
|
|
434
440
|
};
|
|
435
441
|
|
|
436
|
-
window.WWebJS.getPollVoteModel = (vote) => {
|
|
442
|
+
window.WWebJS.getPollVoteModel = async (vote) => {
|
|
437
443
|
const _vote = vote.serialize();
|
|
438
|
-
if (vote.parentMsgKey)
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
return null;
|
|
444
|
+
if (!vote.parentMsgKey) return null;
|
|
445
|
+
const msg =
|
|
446
|
+
window.Store.Msg.get(vote.parentMsgKey) || (await window.Store.Msg.getMessagesById([vote.parentMsgKey]))?.messages?.[0];
|
|
447
|
+
msg && (_vote.parentMessage = window.WWebJS.getMessageModel(msg));
|
|
448
|
+
return _vote;
|
|
444
449
|
};
|
|
445
450
|
|
|
446
451
|
window.WWebJS.getChatModel = async chat => {
|
|
@@ -458,7 +463,9 @@ exports.LoadUtils = () => {
|
|
|
458
463
|
|
|
459
464
|
res.lastMessage = null;
|
|
460
465
|
if (res.msgs && res.msgs.length) {
|
|
461
|
-
const lastMessage = chat.lastReceivedKey
|
|
466
|
+
const lastMessage = chat.lastReceivedKey
|
|
467
|
+
? window.Store.Msg.get(chat.lastReceivedKey._serialized) || (await window.Store.Msg.getMessagesById([chat.lastReceivedKey._serialized]))?.messages?.[0]
|
|
468
|
+
: null;
|
|
462
469
|
if (lastMessage) {
|
|
463
470
|
res.lastMessage = window.WWebJS.getMessageModel(lastMessage);
|
|
464
471
|
}
|
|
@@ -1001,11 +1008,10 @@ exports.LoadUtils = () => {
|
|
|
1001
1008
|
};
|
|
1002
1009
|
|
|
1003
1010
|
window.WWebJS.pinUnpinMsgAction = async (msgId, action, duration) => {
|
|
1004
|
-
const message = window.Store.Msg.get(msgId);
|
|
1011
|
+
const message = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
|
|
1005
1012
|
if (!message) return false;
|
|
1006
1013
|
const response = await window.Store.pinUnpinMsg(message, action, duration);
|
|
1007
|
-
|
|
1008
|
-
return false;
|
|
1014
|
+
return response.messageSendResult === 'OK';
|
|
1009
1015
|
};
|
|
1010
1016
|
|
|
1011
1017
|
};
|
|
@@ -15,9 +15,9 @@ class InterfaceController {
|
|
|
15
15
|
*/
|
|
16
16
|
async openChatWindow(chatId) {
|
|
17
17
|
await this.pupPage.evaluate(async chatId => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
await window.Store.Cmd.
|
|
18
|
+
const chatWid = window.Store.WidFactory.createWid(chatId);
|
|
19
|
+
const chat = window.Store.Chat.get(chat) || await window.Store.Chat.find(chatWid);
|
|
20
|
+
await window.Store.Cmd.openChatBottom(chat);
|
|
21
21
|
}, chatId);
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -49,7 +49,7 @@ class InterfaceController {
|
|
|
49
49
|
*/
|
|
50
50
|
async openChatWindowAt(msgId) {
|
|
51
51
|
await this.pupPage.evaluate(async msgId => {
|
|
52
|
-
|
|
52
|
+
const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
|
|
53
53
|
let chat = await window.Store.Chat.find(msg.id.remote);
|
|
54
54
|
let searchContext = await window.Store.SearchContext(chat,msg);
|
|
55
55
|
await window.Store.Cmd.openChatAt(chat, searchContext);
|
|
@@ -62,7 +62,7 @@ class InterfaceController {
|
|
|
62
62
|
*/
|
|
63
63
|
async openMessageDrawer(msgId) {
|
|
64
64
|
await this.pupPage.evaluate(async msgId => {
|
|
65
|
-
|
|
65
|
+
const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
|
|
66
66
|
await window.Store.Cmd.msgInfoDrawer(msg);
|
|
67
67
|
}, msgId);
|
|
68
68
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expose a function to the page if it does not exist
|
|
3
|
+
*
|
|
4
|
+
* NOTE:
|
|
5
|
+
* Rewrite it to 'upsertFunction' after updating Puppeteer to 20.6 or higher
|
|
6
|
+
* using page.removeExposedFunction
|
|
7
|
+
* https://pptr.dev/api/puppeteer.page.removeExposedFunction
|
|
8
|
+
*
|
|
9
|
+
* @param {import(puppeteer).Page} page
|
|
10
|
+
* @param {string} name
|
|
11
|
+
* @param {Function} fn
|
|
12
|
+
*/
|
|
13
|
+
async function exposeFunctionIfAbsent(page, name, fn) {
|
|
14
|
+
const exist = await page.evaluate((name) => {
|
|
15
|
+
return !!window[name];
|
|
16
|
+
}, name);
|
|
17
|
+
if (exist) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
await page.exposeFunction(name, fn);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = {exposeFunctionIfAbsent};
|