whatsapp-web.js 1.34.2 → 1.34.4
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 +18 -2
- package/index.d.ts +24 -4
- package/package.json +2 -2
- package/src/Client.js +99 -13
- package/src/structures/Contact.js +8 -1
- package/src/structures/GroupChat.js +9 -9
- package/src/structures/Message.js +36 -3
- package/src/structures/ScheduledEvent.js +3 -3
- package/src/util/Constants.js +3 -0
- package/src/util/Injected/Store.js +18 -5
- package/src/util/Injected/Utils.js +77 -12
- package/src/util/InterfaceController.js +2 -2
package/example.js
CHANGED
|
@@ -365,7 +365,7 @@ client.on('message', async msg => {
|
|
|
365
365
|
let list = new List('List body', 'btnText', sections, 'Title', 'footer');
|
|
366
366
|
client.sendMessage(msg.from, list);
|
|
367
367
|
} else if (msg.body === '!reaction') {
|
|
368
|
-
msg.react('👍');
|
|
368
|
+
await msg.react('👍');
|
|
369
369
|
} else if (msg.body === '!sendpoll') {
|
|
370
370
|
/** By default the poll is created as a single choice poll: */
|
|
371
371
|
await msg.reply(new Poll('Winter or Summer?', ['Winter', 'Summer']));
|
|
@@ -382,11 +382,20 @@ client.on('message', async msg => {
|
|
|
382
382
|
]
|
|
383
383
|
})
|
|
384
384
|
);
|
|
385
|
+
} else if (msg.body === '!vote') {
|
|
386
|
+
if (msg.hasQuotedMsg) {
|
|
387
|
+
const quotedMsg = await msg.getQuotedMessage();
|
|
388
|
+
if (quotedMsg.type === 'poll_creation') {
|
|
389
|
+
await quotedMsg.vote(msg.body.replace('!vote', ''));
|
|
390
|
+
} else {
|
|
391
|
+
msg.reply('Can only be used on poll messages');
|
|
392
|
+
}
|
|
393
|
+
}
|
|
385
394
|
} else if (msg.body === '!edit') {
|
|
386
395
|
if (msg.hasQuotedMsg) {
|
|
387
396
|
const quotedMsg = await msg.getQuotedMessage();
|
|
388
397
|
if (quotedMsg.fromMe) {
|
|
389
|
-
quotedMsg.edit(msg.body.replace('!edit', ''));
|
|
398
|
+
await quotedMsg.edit(msg.body.replace('!edit', ''));
|
|
390
399
|
} else {
|
|
391
400
|
msg.reply('I can only edit my own messages');
|
|
392
401
|
}
|
|
@@ -514,6 +523,13 @@ client.on('message', async msg => {
|
|
|
514
523
|
// NOTE: this action will take effect after you restart the client.
|
|
515
524
|
const backgroundSync = await client.setBackgroundSync(true);
|
|
516
525
|
console.log(backgroundSync);
|
|
526
|
+
} else if (msg.body === '!postStatus') {
|
|
527
|
+
await client.sendMessage('status@broadcast', 'Hello there!');
|
|
528
|
+
// send with a different style
|
|
529
|
+
await client.sendMessage('status@broadcast', 'Hello again! Looks different?', {
|
|
530
|
+
fontStyle: 1,
|
|
531
|
+
backgroundColor: '#0b3296'
|
|
532
|
+
});
|
|
517
533
|
}
|
|
518
534
|
});
|
|
519
535
|
|
package/index.d.ts
CHANGED
|
@@ -113,9 +113,15 @@ declare namespace WAWebJS {
|
|
|
113
113
|
|
|
114
114
|
/** Get all current Labels */
|
|
115
115
|
getLabels(): Promise<Label[]>
|
|
116
|
-
|
|
116
|
+
|
|
117
117
|
/** Get all current Broadcasts */
|
|
118
118
|
getBroadcasts(): Promise<Broadcast[]>
|
|
119
|
+
|
|
120
|
+
/** Get broadcast instance by current user ID */
|
|
121
|
+
getBroadcastById(contactId: string): Promise<Broadcast>
|
|
122
|
+
|
|
123
|
+
/** Revoke current own status messages */
|
|
124
|
+
revokeStatusMessage(messageId: string): Promise<void>
|
|
119
125
|
|
|
120
126
|
/** Change labels in chats */
|
|
121
127
|
addOrRemoveLabels(labelIds: Array<number|string>, chatIds: Array<string>): Promise<void>
|
|
@@ -556,6 +562,9 @@ declare namespace WAWebJS {
|
|
|
556
562
|
/** Timeout for authentication selector in puppeteer
|
|
557
563
|
* @default 0 */
|
|
558
564
|
authTimeoutMs?: number,
|
|
565
|
+
/** function to be evaluated On New Document
|
|
566
|
+
* @default undefined */
|
|
567
|
+
evalOnNewDoc?: Function,
|
|
559
568
|
/** Puppeteer launch options. View docs here: https://github.com/puppeteer/puppeteer/ */
|
|
560
569
|
puppeteer?: puppeteer.PuppeteerNodeLaunchOptions & puppeteer.ConnectOptions
|
|
561
570
|
/** Determines how to save and restore sessions. Will use LegacySessionAuth if options.session is set. Otherwise, NoAuth will be used. */
|
|
@@ -882,12 +891,14 @@ declare namespace WAWebJS {
|
|
|
882
891
|
GROUP_MEMBERSHIP_REQUEST = 'group_membership_request',
|
|
883
892
|
GROUP_UPDATE = 'group_update',
|
|
884
893
|
QR_RECEIVED = 'qr',
|
|
894
|
+
CODE_RECEIVED = 'code',
|
|
885
895
|
LOADING_SCREEN = 'loading_screen',
|
|
886
896
|
DISCONNECTED = 'disconnected',
|
|
887
897
|
STATE_CHANGED = 'change_state',
|
|
888
898
|
BATTERY_CHANGED = 'change_battery',
|
|
889
899
|
REMOTE_SESSION_SAVED = 'remote_session_saved',
|
|
890
|
-
|
|
900
|
+
INCOMING_CALL = 'call',
|
|
901
|
+
VOTE_UPDATE = 'vote_update',
|
|
891
902
|
}
|
|
892
903
|
|
|
893
904
|
/** Group notification types */
|
|
@@ -896,6 +907,8 @@ declare namespace WAWebJS {
|
|
|
896
907
|
INVITE = 'invite',
|
|
897
908
|
REMOVE = 'remove',
|
|
898
909
|
LEAVE = 'leave',
|
|
910
|
+
PROMOTE = 'promote',
|
|
911
|
+
DEMOTE = 'demote',
|
|
899
912
|
SUBJECT = 'subject',
|
|
900
913
|
DESCRIPTION = 'description',
|
|
901
914
|
PICTURE = 'picture',
|
|
@@ -919,6 +932,7 @@ declare namespace WAWebJS {
|
|
|
919
932
|
AUDIO = 'audio',
|
|
920
933
|
VOICE = 'ptt',
|
|
921
934
|
IMAGE = 'image',
|
|
935
|
+
ALBUM = 'album',
|
|
922
936
|
VIDEO = 'video',
|
|
923
937
|
DOCUMENT = 'document',
|
|
924
938
|
STICKER = 'sticker',
|
|
@@ -1210,6 +1224,10 @@ declare namespace WAWebJS {
|
|
|
1210
1224
|
* Once the event is canceled, it can not be edited.
|
|
1211
1225
|
*/
|
|
1212
1226
|
editScheduledEvent: (editedEventObject: Event) => Promise<Message | null>,
|
|
1227
|
+
/**
|
|
1228
|
+
* Send votes to the poll message
|
|
1229
|
+
*/
|
|
1230
|
+
vote: (selectedOptions: Array<string>) => Promise<void>,
|
|
1213
1231
|
}
|
|
1214
1232
|
|
|
1215
1233
|
/** ID that represents a message */
|
|
@@ -1273,7 +1291,7 @@ declare namespace WAWebJS {
|
|
|
1273
1291
|
endTime?: Date,
|
|
1274
1292
|
/** The location of the event */
|
|
1275
1293
|
location?: string,
|
|
1276
|
-
/** The type of a WhatsApp call link to generate, valid values are: `video` | `voice` */
|
|
1294
|
+
/** The type of a WhatsApp call link to generate, valid values are: `video` | `voice` | `none` */
|
|
1277
1295
|
callType?: string,
|
|
1278
1296
|
/**
|
|
1279
1297
|
* Indicates if a scheduled event should be sent as an already canceled
|
|
@@ -1300,7 +1318,7 @@ declare namespace WAWebJS {
|
|
|
1300
1318
|
messageSecret?: string;
|
|
1301
1319
|
};
|
|
1302
1320
|
|
|
1303
|
-
constructor(name: string, startTime: Date, options?:
|
|
1321
|
+
constructor(name: string, startTime: Date, options?: ScheduledEventSendOptions)
|
|
1304
1322
|
}
|
|
1305
1323
|
|
|
1306
1324
|
/** Represents a Poll Vote on WhatsApp */
|
|
@@ -1560,6 +1578,8 @@ declare namespace WAWebJS {
|
|
|
1560
1578
|
/** Gets the Contact's common groups with you. Returns empty array if you don't have any common group. */
|
|
1561
1579
|
getCommonGroups: () => Promise<ChatId[]>
|
|
1562
1580
|
|
|
1581
|
+
/** Gets the Contact's current status broadcast. */
|
|
1582
|
+
getBroadcast: () => Promise<Broadcast>
|
|
1563
1583
|
}
|
|
1564
1584
|
|
|
1565
1585
|
export interface ContactId {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "whatsapp-web.js",
|
|
3
|
-
"version": "1.34.
|
|
3
|
+
"version": "1.34.4",
|
|
4
4
|
"description": "Library for interacting with the WhatsApp Web API ",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"typings": "./index.d.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"mime": "^3.0.0",
|
|
35
35
|
"node-fetch": "^2.6.9",
|
|
36
36
|
"node-webpmux": "3.1.7",
|
|
37
|
-
"puppeteer": "^
|
|
37
|
+
"puppeteer": "^24.31.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node-fetch": "^2.5.12",
|
package/src/Client.js
CHANGED
|
@@ -6,7 +6,7 @@ const moduleRaid = require('@pedroslopez/moduleraid/moduleraid');
|
|
|
6
6
|
|
|
7
7
|
const Util = require('./util/Util');
|
|
8
8
|
const InterfaceController = require('./util/InterfaceController');
|
|
9
|
-
const { WhatsWebURL, DefaultOptions, Events, WAState } = require('./util/Constants');
|
|
9
|
+
const { WhatsWebURL, DefaultOptions, Events, WAState, MessageTypes } = require('./util/Constants');
|
|
10
10
|
const { ExposeAuthStore } = require('./util/Injected/AuthStore/AuthStore');
|
|
11
11
|
const { ExposeStore } = require('./util/Injected/Store');
|
|
12
12
|
const { ExposeLegacyAuthStore } = require('./util/Injected/AuthStore/LegacyAuthStore');
|
|
@@ -27,6 +27,7 @@ const {exposeFunctionIfAbsent} = require('./util/Puppeteer');
|
|
|
27
27
|
* @param {string} options.webVersion - The version of WhatsApp Web to use. Use options.webVersionCache to configure how the version is retrieved.
|
|
28
28
|
* @param {object} options.webVersionCache - Determines how to retrieve the WhatsApp Web version. Defaults to a local cache (LocalWebCache) that falls back to latest if the requested version is not found.
|
|
29
29
|
* @param {number} options.authTimeoutMs - Timeout for authentication selector in puppeteer
|
|
30
|
+
* @param {function} options.evalOnNewDoc - function to eval on new doc
|
|
30
31
|
* @param {object} options.puppeteer - Puppeteer launch options. View docs here: https://github.com/puppeteer/puppeteer/
|
|
31
32
|
* @param {number} options.qrMaxRetries - How many times should the qrcode be refreshed before giving up
|
|
32
33
|
* @param {string} options.restartOnAuthFail - @deprecated This option should be set directly on the LegacySessionAuth.
|
|
@@ -95,7 +96,20 @@ class Client extends EventEmitter {
|
|
|
95
96
|
* Private function
|
|
96
97
|
*/
|
|
97
98
|
async inject() {
|
|
98
|
-
|
|
99
|
+
if(this.options.authTimeoutMs === undefined || this.options.authTimeoutMs==0){
|
|
100
|
+
this.options.authTimeoutMs = 30000;
|
|
101
|
+
}
|
|
102
|
+
let start = Date.now();
|
|
103
|
+
let timeout = this.options.authTimeoutMs;
|
|
104
|
+
let res = false;
|
|
105
|
+
while(start > (Date.now() - timeout)){
|
|
106
|
+
res = await this.pupPage.evaluate('window.Debug?.VERSION != undefined');
|
|
107
|
+
if(res){break;}
|
|
108
|
+
await new Promise(r => setTimeout(r, 200));
|
|
109
|
+
}
|
|
110
|
+
if(!res){
|
|
111
|
+
throw 'auth timeout';
|
|
112
|
+
}
|
|
99
113
|
await this.setDeviceName(this.options.deviceName, this.options.browserName);
|
|
100
114
|
const pairWithPhoneNumber = this.options.pairWithPhoneNumber;
|
|
101
115
|
const version = await this.getWWebVersion();
|
|
@@ -225,9 +239,17 @@ class Client extends EventEmitter {
|
|
|
225
239
|
await new Promise(r => setTimeout(r, 2000));
|
|
226
240
|
await this.pupPage.evaluate(ExposeLegacyStore);
|
|
227
241
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
242
|
+
let start = Date.now();
|
|
243
|
+
let res = false;
|
|
244
|
+
while(start > (Date.now() - 30000)){
|
|
245
|
+
// Check window.Store Injection
|
|
246
|
+
res = await this.pupPage.evaluate('window.Store != undefined');
|
|
247
|
+
if(res){break;}
|
|
248
|
+
await new Promise(r => setTimeout(r, 200));
|
|
249
|
+
}
|
|
250
|
+
if(!res){
|
|
251
|
+
throw 'ready timeout';
|
|
252
|
+
}
|
|
231
253
|
|
|
232
254
|
/**
|
|
233
255
|
* Current connection information
|
|
@@ -300,7 +322,7 @@ class Client extends EventEmitter {
|
|
|
300
322
|
page = await browser.newPage();
|
|
301
323
|
} else {
|
|
302
324
|
const browserArgs = [...(puppeteerOpts.args || [])];
|
|
303
|
-
if(!browserArgs.find(arg => arg.includes('--user-agent'))) {
|
|
325
|
+
if(this.options.userAgent !== false && !browserArgs.find(arg => arg.includes('--user-agent'))) {
|
|
304
326
|
browserArgs.push(`--user-agent=${this.options.userAgent}`);
|
|
305
327
|
}
|
|
306
328
|
// navigator.webdriver fix
|
|
@@ -313,8 +335,9 @@ class Client extends EventEmitter {
|
|
|
313
335
|
if (this.options.proxyAuthentication !== undefined) {
|
|
314
336
|
await page.authenticate(this.options.proxyAuthentication);
|
|
315
337
|
}
|
|
316
|
-
|
|
317
|
-
|
|
338
|
+
if(this.options.userAgent !== false) {
|
|
339
|
+
await page.setUserAgent(this.options.userAgent);
|
|
340
|
+
}
|
|
318
341
|
if (this.options.bypassCSP) await page.setBypassCSP(true);
|
|
319
342
|
|
|
320
343
|
this.pupBrowser = browser;
|
|
@@ -322,7 +345,11 @@ class Client extends EventEmitter {
|
|
|
322
345
|
|
|
323
346
|
await this.authStrategy.afterBrowserInitialized();
|
|
324
347
|
await this.initWebVersionCache();
|
|
325
|
-
|
|
348
|
+
|
|
349
|
+
if (this.options.evalOnNewDoc !== undefined) {
|
|
350
|
+
await page.evaluateOnNewDocument(this.options.evalOnNewDoc);
|
|
351
|
+
}
|
|
352
|
+
|
|
326
353
|
// ocVersion (isOfficialClient patch)
|
|
327
354
|
// remove after 2.3000.x hard release
|
|
328
355
|
await page.evaluateOnNewDocument(() => {
|
|
@@ -948,9 +975,10 @@ class Client extends EventEmitter {
|
|
|
948
975
|
*/
|
|
949
976
|
async sendMessage(chatId, content, options = {}) {
|
|
950
977
|
const isChannel = /@\w*newsletter\b/.test(chatId);
|
|
978
|
+
const isStatus = /@\w*broadcast\b/.test(chatId);
|
|
951
979
|
|
|
952
980
|
if (isChannel && [
|
|
953
|
-
options.sendMediaAsDocument, options.quotedMessageId,
|
|
981
|
+
options.sendMediaAsDocument, options.quotedMessageId,
|
|
954
982
|
options.parseVCards, options.isViewOnce,
|
|
955
983
|
content instanceof Location, content instanceof Contact,
|
|
956
984
|
content instanceof Buttons, content instanceof List,
|
|
@@ -958,6 +986,16 @@ class Client extends EventEmitter {
|
|
|
958
986
|
].includes(true)) {
|
|
959
987
|
console.warn('The message type is currently not supported for sending in channels,\nthe supported message types are: text, image, sticker, gif, video, voice and poll.');
|
|
960
988
|
return null;
|
|
989
|
+
|
|
990
|
+
} else if (isStatus && [
|
|
991
|
+
options.sendMediaAsDocument, options.quotedMessageId,
|
|
992
|
+
options.parseVCards, options.isViewOnce, options.sendMediaAsSticker,
|
|
993
|
+
content instanceof Location, content instanceof Contact,
|
|
994
|
+
content instanceof Poll, content instanceof Buttons, content instanceof List,
|
|
995
|
+
Array.isArray(content) && content.length > 0 && content[0] instanceof Contact
|
|
996
|
+
].includes(true)) {
|
|
997
|
+
console.warn('The message type is currently not supported for sending in status broadcast,\nthe supported message types are: text, image, gif, audio and video.');
|
|
998
|
+
return null;
|
|
961
999
|
}
|
|
962
1000
|
|
|
963
1001
|
if (options.mentions) {
|
|
@@ -1193,7 +1231,12 @@ class Client extends EventEmitter {
|
|
|
1193
1231
|
|
|
1194
1232
|
return ContactFactory.create(this, contact);
|
|
1195
1233
|
}
|
|
1196
|
-
|
|
1234
|
+
|
|
1235
|
+
/**
|
|
1236
|
+
* Get message by ID
|
|
1237
|
+
* @param {string} messageId
|
|
1238
|
+
* @returns {Promise<Message>}
|
|
1239
|
+
*/
|
|
1197
1240
|
async getMessageById(messageId) {
|
|
1198
1241
|
const msg = await this.pupPage.evaluate(async messageId => {
|
|
1199
1242
|
let msg = window.Store.Msg.get(messageId);
|
|
@@ -1970,7 +2013,7 @@ class Client extends EventEmitter {
|
|
|
1970
2013
|
|
|
1971
2014
|
return labels.map(data => new Label(this, data));
|
|
1972
2015
|
}
|
|
1973
|
-
|
|
2016
|
+
|
|
1974
2017
|
/**
|
|
1975
2018
|
* Get all current Broadcast
|
|
1976
2019
|
* @returns {Promise<Array<Broadcast>>}
|
|
@@ -1982,6 +2025,49 @@ class Client extends EventEmitter {
|
|
|
1982
2025
|
return broadcasts.map(data => new Broadcast(this, data));
|
|
1983
2026
|
}
|
|
1984
2027
|
|
|
2028
|
+
/**
|
|
2029
|
+
* Get broadcast instance by current user ID
|
|
2030
|
+
* @param {string} contactId
|
|
2031
|
+
* @returns {Promise<Broadcast>}
|
|
2032
|
+
*/
|
|
2033
|
+
async getBroadcastById(contactId) {
|
|
2034
|
+
const broadcast = await this.pupPage.evaluate(async (userId) => {
|
|
2035
|
+
let status;
|
|
2036
|
+
try {
|
|
2037
|
+
status = window.Store.Status.get(userId);
|
|
2038
|
+
if (!status) {
|
|
2039
|
+
status = await window.Store.Status.find(userId);
|
|
2040
|
+
}
|
|
2041
|
+
} catch {
|
|
2042
|
+
status = null;
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
if (status) return window.WWebJS.getStatusModel(status);
|
|
2046
|
+
}, contactId);
|
|
2047
|
+
return new Broadcast(this, broadcast);
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
/**
|
|
2051
|
+
* Revoke current own status messages
|
|
2052
|
+
* @param {string} messageId
|
|
2053
|
+
* @returns {Promise<void>}
|
|
2054
|
+
*/
|
|
2055
|
+
async revokeStatusMessage(messageId) {
|
|
2056
|
+
return await this.pupPage.evaluate(async (msgId) => {
|
|
2057
|
+
const status = window.Store.Status.getMyStatus();
|
|
2058
|
+
if (!status) return;
|
|
2059
|
+
|
|
2060
|
+
const msg =
|
|
2061
|
+
window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
|
|
2062
|
+
if (!msg) return;
|
|
2063
|
+
|
|
2064
|
+
if (!msg.id.fromMe || !msg.id.remote.isStatus())
|
|
2065
|
+
throw 'Invalid usage! Can only revoke the message its from own status broadcast';
|
|
2066
|
+
|
|
2067
|
+
return await window.Store.StatusUtils.sendStatusRevokeMsgAction(status, msg);
|
|
2068
|
+
}, messageId);
|
|
2069
|
+
}
|
|
2070
|
+
|
|
1985
2071
|
/**
|
|
1986
2072
|
* Get Label instance by ID
|
|
1987
2073
|
* @param {string} labelId
|
|
@@ -2425,7 +2511,7 @@ class Client extends EventEmitter {
|
|
|
2425
2511
|
async getPollVotes(messageId) {
|
|
2426
2512
|
const msg = await this.getMessageById(messageId);
|
|
2427
2513
|
if (!msg) return [];
|
|
2428
|
-
if (msg.type !=
|
|
2514
|
+
if (msg.type != MessageTypes.POLL_CREATION) throw 'Invalid usage! Can only be used with a pollCreation message';
|
|
2429
2515
|
|
|
2430
2516
|
const pollVotes = await this.pupPage.evaluate( async (msg) => {
|
|
2431
2517
|
const msgKey = window.Store.MsgKey.fromString(msg.id._serialized);
|
|
@@ -202,7 +202,14 @@ class Contact extends Base {
|
|
|
202
202
|
async getCommonGroups() {
|
|
203
203
|
return await this.client.getCommonGroups(this.id._serialized);
|
|
204
204
|
}
|
|
205
|
-
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Gets the Contact's current status broadcast.
|
|
208
|
+
* @returns {Promise<Broadcast>}
|
|
209
|
+
*/
|
|
210
|
+
async getBroadcast() {
|
|
211
|
+
return await this.client.getBroadcastById(this.id._serialized);
|
|
212
|
+
}
|
|
206
213
|
}
|
|
207
214
|
|
|
208
215
|
module.exports = Contact;
|
|
@@ -297,12 +297,12 @@ class GroupChat extends Chat {
|
|
|
297
297
|
*/
|
|
298
298
|
async setAddMembersAdminsOnly(adminsOnly=true) {
|
|
299
299
|
const success = await this.client.pupPage.evaluate(async (groupId, adminsOnly) => {
|
|
300
|
-
const
|
|
300
|
+
const chat = await window.WWebJS.getChat(groupId, { getAsModel: false });
|
|
301
301
|
try {
|
|
302
|
-
|
|
303
|
-
return
|
|
302
|
+
await window.Store.GroupUtils.setGroupProperty(chat, 'member_add_mode', adminsOnly ? 0 : 1);
|
|
303
|
+
return true;
|
|
304
304
|
} catch (err) {
|
|
305
|
-
if(err.name === '
|
|
305
|
+
if(err.name === 'ServerStatusCodeError') return false;
|
|
306
306
|
throw err;
|
|
307
307
|
}
|
|
308
308
|
}, this.id._serialized, adminsOnly);
|
|
@@ -318,9 +318,9 @@ class GroupChat extends Chat {
|
|
|
318
318
|
*/
|
|
319
319
|
async setMessagesAdminsOnly(adminsOnly=true) {
|
|
320
320
|
const success = await this.client.pupPage.evaluate(async (chatId, adminsOnly) => {
|
|
321
|
-
const
|
|
321
|
+
const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
|
|
322
322
|
try {
|
|
323
|
-
await window.Store.GroupUtils.setGroupProperty(
|
|
323
|
+
await window.Store.GroupUtils.setGroupProperty(chat, 'announcement', adminsOnly ? 1 : 0);
|
|
324
324
|
return true;
|
|
325
325
|
} catch (err) {
|
|
326
326
|
if(err.name === 'ServerStatusCodeError') return false;
|
|
@@ -341,9 +341,9 @@ class GroupChat extends Chat {
|
|
|
341
341
|
*/
|
|
342
342
|
async setInfoAdminsOnly(adminsOnly=true) {
|
|
343
343
|
const success = await this.client.pupPage.evaluate(async (chatId, adminsOnly) => {
|
|
344
|
-
const
|
|
344
|
+
const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
|
|
345
345
|
try {
|
|
346
|
-
await window.Store.GroupUtils.setGroupProperty(
|
|
346
|
+
await window.Store.GroupUtils.setGroupProperty(chat, 'restrict', adminsOnly ? 1 : 0);
|
|
347
347
|
return true;
|
|
348
348
|
} catch (err) {
|
|
349
349
|
if(err.name === 'ServerStatusCodeError') return false;
|
|
@@ -356,7 +356,7 @@ class GroupChat extends Chat {
|
|
|
356
356
|
this.groupMetadata.restrict = adminsOnly;
|
|
357
357
|
return true;
|
|
358
358
|
}
|
|
359
|
-
|
|
359
|
+
|
|
360
360
|
/**
|
|
361
361
|
* Deletes the group's picture.
|
|
362
362
|
* @returns {Promise<boolean>} Returns true if the picture was properly deleted. This can return false if the user does not have the necessary permissions.
|
|
@@ -449,7 +449,9 @@ class Message extends Base {
|
|
|
449
449
|
|
|
450
450
|
const result = await this.client.pupPage.evaluate(async (msgId) => {
|
|
451
451
|
const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
|
|
452
|
-
|
|
452
|
+
|
|
453
|
+
// REUPLOADING mediaStage means the media is expired and the download button is spinning, cannot be downloaded now
|
|
454
|
+
if (!msg || !msg.mediaData || msg.mediaData.mediaStage === 'REUPLOADING') {
|
|
453
455
|
return null;
|
|
454
456
|
}
|
|
455
457
|
if (msg.mediaData.mediaStage != 'RESOLVED') {
|
|
@@ -466,6 +468,10 @@ class Message extends Base {
|
|
|
466
468
|
}
|
|
467
469
|
|
|
468
470
|
try {
|
|
471
|
+
const mockQpl = {
|
|
472
|
+
addAnnotations: function() { return this; },
|
|
473
|
+
addPoint: function() { return this; }
|
|
474
|
+
};
|
|
469
475
|
const decryptedMedia = await window.Store.DownloadManager.downloadAndMaybeDecrypt({
|
|
470
476
|
directPath: msg.directPath,
|
|
471
477
|
encFilehash: msg.encFilehash,
|
|
@@ -473,7 +479,8 @@ class Message extends Base {
|
|
|
473
479
|
mediaKey: msg.mediaKey,
|
|
474
480
|
mediaKeyTimestamp: msg.mediaKeyTimestamp,
|
|
475
481
|
type: msg.type,
|
|
476
|
-
signal: (new AbortController).signal
|
|
482
|
+
signal: (new AbortController).signal,
|
|
483
|
+
downloadQpl: mockQpl
|
|
477
484
|
});
|
|
478
485
|
|
|
479
486
|
const data = await window.WWebJS.arrayBufferToBase64Async(decryptedMedia);
|
|
@@ -562,7 +569,7 @@ class Message extends Base {
|
|
|
562
569
|
*/
|
|
563
570
|
async unpin() {
|
|
564
571
|
return await this.client.pupPage.evaluate(async (msgId) => {
|
|
565
|
-
return await window.WWebJS.pinUnpinMsgAction(msgId, 2);
|
|
572
|
+
return await window.WWebJS.pinUnpinMsgAction(msgId, 2, 0);
|
|
566
573
|
}, this.id._serialized);
|
|
567
574
|
}
|
|
568
575
|
|
|
@@ -749,6 +756,32 @@ class Message extends Base {
|
|
|
749
756
|
async getPollVotes() {
|
|
750
757
|
return await this.client.getPollVotes(this.id._serialized);
|
|
751
758
|
}
|
|
759
|
+
|
|
760
|
+
/**
|
|
761
|
+
* Send votes to the poll message
|
|
762
|
+
* @param {Array<string>} selectedOptions Array of options selected.
|
|
763
|
+
* @returns {Promise}
|
|
764
|
+
*/
|
|
765
|
+
async vote(selectedOptions) {
|
|
766
|
+
if (this.type != MessageTypes.POLL_CREATION) throw 'Invalid usage! Can only be used with a pollCreation message';
|
|
767
|
+
|
|
768
|
+
await this.client.pupPage.evaluate(async (messageId, votes) => {
|
|
769
|
+
if (!messageId) return null;
|
|
770
|
+
if (!Array.isArray(votes)) votes = [votes];
|
|
771
|
+
let localIdSet = new Set();
|
|
772
|
+
const msg =
|
|
773
|
+
window.Store.Msg.get(messageId) || (await window.Store.Msg.getMessagesById([messageId]))?.messages?.[0];
|
|
774
|
+
if (!msg) return null;
|
|
775
|
+
|
|
776
|
+
msg.pollOptions.forEach(a => {
|
|
777
|
+
for (const option of votes) {
|
|
778
|
+
if (a.name === option) localIdSet.add(a.localId);
|
|
779
|
+
}
|
|
780
|
+
});
|
|
781
|
+
|
|
782
|
+
await window.Store.PollsSendVote.sendVote(msg, localIdSet);
|
|
783
|
+
}, this.id._serialized, selectedOptions);
|
|
784
|
+
}
|
|
752
785
|
}
|
|
753
786
|
|
|
754
787
|
module.exports = Message;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @property {?string} description The scheduled event description
|
|
7
7
|
* @property {?Date} endTime The end time of the event
|
|
8
8
|
* @property {?string} location The location of the event
|
|
9
|
-
* @property {?string} callType The type of a WhatsApp call link to generate, valid values are: `video` | `voice`
|
|
9
|
+
* @property {?string} callType The type of a WhatsApp call link to generate, valid values are: `video` | `voice` | `none`
|
|
10
10
|
* @property {boolean} [isEventCanceled = false] Indicates if a scheduled event should be sent as an already canceled
|
|
11
11
|
* @property {?Array<number>} messageSecret The custom message secret, can be used as an event ID. NOTE: it has to be a unique vector with a length of 32
|
|
12
12
|
*/
|
|
@@ -58,10 +58,10 @@ class ScheduledEvent {
|
|
|
58
58
|
}(`Empty '${propName}' parameter value is provided.`);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
if (propName === 'callType' && propValue && !['video', 'voice'].includes(propValue)) {
|
|
61
|
+
if (propName === 'callType' && propValue && !['video', 'voice', 'none'].includes(propValue)) {
|
|
62
62
|
throw new class CreateScheduledEventError extends Error {
|
|
63
63
|
constructor(m) { super(m); }
|
|
64
|
-
}(`Invalid '${propName}' parameter value is provided. Valid values are: 'voice' | 'video'.`);
|
|
64
|
+
}(`Invalid '${propName}' parameter value is provided. Valid values are: 'voice' | 'video' | 'none'.`);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
return propValue;
|
package/src/util/Constants.js
CHANGED
|
@@ -85,6 +85,7 @@ exports.MessageTypes = {
|
|
|
85
85
|
AUDIO: 'audio',
|
|
86
86
|
VOICE: 'ptt',
|
|
87
87
|
IMAGE: 'image',
|
|
88
|
+
ALBUM: 'album',
|
|
88
89
|
VIDEO: 'video',
|
|
89
90
|
DOCUMENT: 'document',
|
|
90
91
|
STICKER: 'sticker',
|
|
@@ -130,6 +131,8 @@ exports.GroupNotificationTypes = {
|
|
|
130
131
|
INVITE: 'invite',
|
|
131
132
|
REMOVE: 'remove',
|
|
132
133
|
LEAVE: 'leave',
|
|
134
|
+
PROMOTE: 'promote',
|
|
135
|
+
DEMOTE: 'demote',
|
|
133
136
|
SUBJECT: 'subject',
|
|
134
137
|
DESCRIPTION: 'description',
|
|
135
138
|
PICTURE: 'picture',
|
|
@@ -54,6 +54,7 @@ exports.ExposeStore = () => {
|
|
|
54
54
|
window.Store.MediaObject = window.require('WAWebMediaStorage');
|
|
55
55
|
window.Store.MediaTypes = window.require('WAWebMmsMediaTypes');
|
|
56
56
|
window.Store.MediaUpload = window.require('WAWebMediaMmsV4Upload');
|
|
57
|
+
window.Store.MediaUpdate = window.require('WAWebMediaUpdateMsg');
|
|
57
58
|
window.Store.MsgKey = window.require('WAWebMsgKey');
|
|
58
59
|
window.Store.OpaqueData = window.require('WAWebMediaOpaqueData');
|
|
59
60
|
window.Store.QueryProduct = window.require('WAWebBizProductCatalogBridge');
|
|
@@ -62,9 +63,14 @@ exports.ExposeStore = () => {
|
|
|
62
63
|
window.Store.SendDelete = window.require('WAWebDeleteChatAction');
|
|
63
64
|
window.Store.SendMessage = window.require('WAWebSendMsgChatAction');
|
|
64
65
|
window.Store.EditMessage = window.require('WAWebSendMessageEditAction');
|
|
66
|
+
window.Store.MediaDataUtils = window.require('WAWebMediaDataUtils');
|
|
67
|
+
window.Store.BlobCache = window.require('WAWebMediaInMemoryBlobCache');
|
|
65
68
|
window.Store.SendSeen = window.require('WAWebUpdateUnreadChatAction');
|
|
66
69
|
window.Store.User = window.require('WAWebUserPrefsMeUser');
|
|
67
|
-
window.Store.ContactMethods =
|
|
70
|
+
window.Store.ContactMethods = {
|
|
71
|
+
...window.require('WAWebContactGetters'),
|
|
72
|
+
...window.require('WAWebFrontendContactGetters')
|
|
73
|
+
};
|
|
68
74
|
window.Store.UserConstructor = window.require('WAWebWid');
|
|
69
75
|
window.Store.Validators = window.require('WALinkify');
|
|
70
76
|
window.Store.WidFactory = window.require('WAWebWidFactory');
|
|
@@ -72,7 +78,6 @@ exports.ExposeStore = () => {
|
|
|
72
78
|
window.Store.PresenceUtils = window.require('WAWebPresenceChatAction');
|
|
73
79
|
window.Store.ChatState = window.require('WAWebChatStateBridge');
|
|
74
80
|
window.Store.findCommonGroups = window.require('WAWebFindCommonGroupsContactAction').findCommonGroups;
|
|
75
|
-
window.Store.StatusUtils = window.require('WAWebContactStatusBridge');
|
|
76
81
|
window.Store.ConversationMsgs = window.require('WAWebChatLoadMessages');
|
|
77
82
|
window.Store.sendReactionToMsg = window.require('WAWebSendReactionMsgAction').sendReactionToMsg;
|
|
78
83
|
window.Store.createOrUpdateReactionsModule = window.require('WAWebDBCreateOrUpdateReactions');
|
|
@@ -103,8 +108,9 @@ exports.ExposeStore = () => {
|
|
|
103
108
|
window.Store.FindOrCreateChat = window.require('WAWebFindChatAction');
|
|
104
109
|
window.Store.CustomerNoteUtils = window.require('WAWebNoteAction');
|
|
105
110
|
window.Store.BusinessGatingUtils = window.require('WAWebBizGatingUtils');
|
|
106
|
-
window.Store.PollsVotesSchema = require('WAWebPollsVotesSchema');
|
|
107
|
-
|
|
111
|
+
window.Store.PollsVotesSchema = window.require('WAWebPollsVotesSchema');
|
|
112
|
+
window.Store.PollsSendVote = window.require('WAWebPollsSendVoteMsgAction');
|
|
113
|
+
|
|
108
114
|
window.Store.Settings = {
|
|
109
115
|
...window.require('WAWebUserPrefsGeneral'),
|
|
110
116
|
...window.require('WAWebUserPrefsNotifications'),
|
|
@@ -139,7 +145,8 @@ exports.ExposeStore = () => {
|
|
|
139
145
|
...window.require('WAWebGroupCreateJob'),
|
|
140
146
|
...window.require('WAWebGroupModifyInfoJob'),
|
|
141
147
|
...window.require('WAWebExitGroupAction'),
|
|
142
|
-
...window.require('WAWebContactProfilePicThumbBridge')
|
|
148
|
+
...window.require('WAWebContactProfilePicThumbBridge'),
|
|
149
|
+
...window.require('WAWebSetPropertyGroupAction')
|
|
143
150
|
};
|
|
144
151
|
window.Store.GroupParticipants = {
|
|
145
152
|
...window.require('WAWebModifyParticipantsGroupAction'),
|
|
@@ -193,6 +200,12 @@ exports.ExposeStore = () => {
|
|
|
193
200
|
...window.require('WAWebSaveContactAction'),
|
|
194
201
|
...window.require('WAWebDeleteContactAction')
|
|
195
202
|
};
|
|
203
|
+
window.Store.StatusUtils = {
|
|
204
|
+
...window.require('WAWebContactStatusBridge'),
|
|
205
|
+
...window.require('WAWebSendStatusMsgAction'),
|
|
206
|
+
...window.require('WAWebRevokeStatusAction'),
|
|
207
|
+
...window.require('WAWebStatusGatingUtils')
|
|
208
|
+
};
|
|
196
209
|
|
|
197
210
|
if (!window.Store.Chat._find || !window.Store.Chat.findImpl) {
|
|
198
211
|
window.Store.Chat._find = e => {
|
|
@@ -22,10 +22,11 @@ exports.LoadUtils = () => {
|
|
|
22
22
|
|
|
23
23
|
window.WWebJS.sendMessage = async (chat, content, options = {}) => {
|
|
24
24
|
const isChannel = window.Store.ChatGetters.getIsNewsletter(chat);
|
|
25
|
+
const isStatus = window.Store.ChatGetters.getIsBroadcast(chat);
|
|
25
26
|
|
|
26
27
|
let mediaOptions = {};
|
|
27
28
|
if (options.media) {
|
|
28
|
-
mediaOptions = options.sendMediaAsSticker && !isChannel
|
|
29
|
+
mediaOptions = options.sendMediaAsSticker && !isChannel && !isStatus
|
|
29
30
|
? await window.WWebJS.processStickerData(options.media)
|
|
30
31
|
: await window.WWebJS.processMediaData(options.media, {
|
|
31
32
|
forceSticker: options.sendMediaAsSticker,
|
|
@@ -33,7 +34,8 @@ exports.LoadUtils = () => {
|
|
|
33
34
|
forceVoice: options.sendAudioAsVoice,
|
|
34
35
|
forceDocument: options.sendMediaAsDocument,
|
|
35
36
|
forceMediaHd: options.sendMediaAsHd,
|
|
36
|
-
sendToChannel: isChannel
|
|
37
|
+
sendToChannel: isChannel,
|
|
38
|
+
sendToStatus: isStatus
|
|
37
39
|
});
|
|
38
40
|
mediaOptions.caption = options.caption;
|
|
39
41
|
content = options.sendMediaAsSticker ? undefined : mediaOptions.preview;
|
|
@@ -92,15 +94,15 @@ exports.LoadUtils = () => {
|
|
|
92
94
|
delete options.location;
|
|
93
95
|
}
|
|
94
96
|
|
|
95
|
-
let
|
|
97
|
+
let pollOptions = {};
|
|
96
98
|
if (options.poll) {
|
|
97
|
-
const { pollName, pollOptions } = options.poll;
|
|
99
|
+
const { pollName, pollOptions: _pollOptions } = options.poll;
|
|
98
100
|
const { allowMultipleAnswers, messageSecret } = options.poll.options;
|
|
99
|
-
|
|
101
|
+
pollOptions = {
|
|
100
102
|
kind: 'pollCreation',
|
|
101
103
|
type: 'poll_creation',
|
|
102
104
|
pollName: pollName,
|
|
103
|
-
pollOptions:
|
|
105
|
+
pollOptions: _pollOptions,
|
|
104
106
|
pollSelectableOptionsCount: allowMultipleAnswers ? 0 : 1,
|
|
105
107
|
messageSecret:
|
|
106
108
|
Array.isArray(messageSecret) && messageSecret.length === 32
|
|
@@ -125,7 +127,7 @@ exports.LoadUtils = () => {
|
|
|
125
127
|
degreesLongitude: 0,
|
|
126
128
|
name: eventSendOptions.location
|
|
127
129
|
},
|
|
128
|
-
eventJoinLink: await window.Store.ScheduledEventMsgUtils.createEventCallLink(
|
|
130
|
+
eventJoinLink: eventSendOptions.callType === 'none' ? null : await window.Store.ScheduledEventMsgUtils.createEventCallLink(
|
|
129
131
|
startTimeTs,
|
|
130
132
|
eventSendOptions.callType
|
|
131
133
|
),
|
|
@@ -246,6 +248,10 @@ exports.LoadUtils = () => {
|
|
|
246
248
|
participant = window.Store.WidFactory.asUserWidOrThrow(from);
|
|
247
249
|
}
|
|
248
250
|
|
|
251
|
+
if (typeof chat.id?.isStatus === 'function' && chat.id.isStatus()) {
|
|
252
|
+
participant = window.Store.WidFactory.asUserWidOrThrow(from);
|
|
253
|
+
}
|
|
254
|
+
|
|
249
255
|
const newMsgKey = new window.Store.MsgKey({
|
|
250
256
|
from: from,
|
|
251
257
|
to: chat.id,
|
|
@@ -264,7 +270,7 @@ exports.LoadUtils = () => {
|
|
|
264
270
|
id: newMsgKey,
|
|
265
271
|
ack: 0,
|
|
266
272
|
body: content,
|
|
267
|
-
from:
|
|
273
|
+
from: from,
|
|
268
274
|
to: chat.id,
|
|
269
275
|
local: true,
|
|
270
276
|
self: 'out',
|
|
@@ -276,7 +282,7 @@ exports.LoadUtils = () => {
|
|
|
276
282
|
...(mediaOptions.toJSON ? mediaOptions.toJSON() : {}),
|
|
277
283
|
...quotedMsgOptions,
|
|
278
284
|
...locationOptions,
|
|
279
|
-
...
|
|
285
|
+
...pollOptions,
|
|
280
286
|
...eventOptions,
|
|
281
287
|
...vcardOptions,
|
|
282
288
|
...buttonOptions,
|
|
@@ -320,6 +326,37 @@ exports.LoadUtils = () => {
|
|
|
320
326
|
return msg;
|
|
321
327
|
}
|
|
322
328
|
|
|
329
|
+
if (isStatus) {
|
|
330
|
+
const { backgroundColor, fontStyle } = extraOptions;
|
|
331
|
+
const isMedia = Object.keys(mediaOptions).length > 0;
|
|
332
|
+
const mediaUpdate = data => window.Store.MediaUpdate(data, mediaOptions);
|
|
333
|
+
const msg = new window.Store.Msg.modelClass({
|
|
334
|
+
...message,
|
|
335
|
+
author: participant ? participant : null,
|
|
336
|
+
messageSecret: window.crypto.getRandomValues(new Uint8Array(32)),
|
|
337
|
+
cannotBeRanked: window.Store.StatusUtils.canCheckStatusRankingPosterGating()
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
// for text only
|
|
341
|
+
const statusOptions = {
|
|
342
|
+
color: backgroundColor && window.WWebJS.assertColor(backgroundColor) || 0xff7acca5,
|
|
343
|
+
font: fontStyle >= 0 && fontStyle <= 7 && fontStyle || 0,
|
|
344
|
+
text: msg.body
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
await window.Store.StatusUtils[
|
|
348
|
+
isMedia ?
|
|
349
|
+
'sendStatusMediaMsgAction' : 'sendStatusTextMsgAction'
|
|
350
|
+
](
|
|
351
|
+
...(
|
|
352
|
+
isMedia ?
|
|
353
|
+
[msg, mediaUpdate] : [statusOptions]
|
|
354
|
+
)
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
return msg;
|
|
358
|
+
}
|
|
359
|
+
|
|
323
360
|
const [msgPromise, sendMsgResultPromise] = window.Store.SendMessage.addAndSendMsgToChat(chat, message);
|
|
324
361
|
await msgPromise;
|
|
325
362
|
|
|
@@ -407,7 +444,7 @@ exports.LoadUtils = () => {
|
|
|
407
444
|
return stickerInfo;
|
|
408
445
|
};
|
|
409
446
|
|
|
410
|
-
window.WWebJS.processMediaData = async (mediaInfo, { forceSticker, forceGif, forceVoice, forceDocument, forceMediaHd, sendToChannel }) => {
|
|
447
|
+
window.WWebJS.processMediaData = async (mediaInfo, { forceSticker, forceGif, forceVoice, forceDocument, forceMediaHd, sendToChannel, sendToStatus }) => {
|
|
411
448
|
const file = window.WWebJS.mediaInfoToFile(mediaInfo);
|
|
412
449
|
const opaqueData = await window.Store.OpaqueData.createFromData(file, file.type);
|
|
413
450
|
const mediaParams = {
|
|
@@ -430,7 +467,11 @@ exports.LoadUtils = () => {
|
|
|
430
467
|
isNewsletter: sendToChannel,
|
|
431
468
|
});
|
|
432
469
|
|
|
433
|
-
if (
|
|
470
|
+
if (!mediaData.filehash) {
|
|
471
|
+
throw new Error('media-fault: sendToChat filehash undefined');
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if ((forceVoice && mediaData.type === 'ptt') || (sendToStatus && mediaData.type === 'audio')) {
|
|
434
475
|
const waveform = mediaObject.contentInfo.waveform;
|
|
435
476
|
mediaData.waveform =
|
|
436
477
|
waveform || await window.WWebJS.generateWaveform(file);
|
|
@@ -445,13 +486,21 @@ exports.LoadUtils = () => {
|
|
|
445
486
|
|
|
446
487
|
mediaData.renderableUrl = mediaData.mediaBlob.url();
|
|
447
488
|
mediaObject.consolidate(mediaData.toJSON());
|
|
489
|
+
|
|
448
490
|
mediaData.mediaBlob.autorelease();
|
|
491
|
+
const shouldUseMediaCache = window.Store.MediaDataUtils.shouldUseMediaCache(
|
|
492
|
+
window.Store.MediaTypes.castToV4(mediaObject.type)
|
|
493
|
+
);
|
|
494
|
+
if (shouldUseMediaCache && mediaData.mediaBlob instanceof window.Store.OpaqueData) {
|
|
495
|
+
const formData = mediaData.mediaBlob.formData();
|
|
496
|
+
window.Store.BlobCache.InMemoryMediaBlobCache.put(mediaObject.filehash, formData);
|
|
497
|
+
}
|
|
449
498
|
|
|
450
499
|
const dataToUpload = {
|
|
451
500
|
mimetype: mediaData.mimetype,
|
|
452
501
|
mediaObject,
|
|
453
502
|
mediaType,
|
|
454
|
-
...(sendToChannel ? { calculateToken: window.Store.SendChannelMessage.getRandomFilehash } : {})
|
|
503
|
+
...(sendToChannel ? { calculateToken: window.Store.SendChannelMessage.getRandomFilehash() } : {})
|
|
455
504
|
};
|
|
456
505
|
|
|
457
506
|
const uploadedMedia = !sendToChannel
|
|
@@ -1153,4 +1202,20 @@ exports.LoadUtils = () => {
|
|
|
1153
1202
|
|
|
1154
1203
|
return { lid, phone };
|
|
1155
1204
|
};
|
|
1205
|
+
|
|
1206
|
+
window.WWebJS.assertColor = (hex) => {
|
|
1207
|
+
let color;
|
|
1208
|
+
if (typeof hex === 'number') {
|
|
1209
|
+
color = hex > 0 ? hex : 0xffffffff + parseInt(hex) + 1;
|
|
1210
|
+
} else if (typeof hex === 'string') {
|
|
1211
|
+
let number = hex.trim().replace('#', '');
|
|
1212
|
+
if (number.length <= 6) {
|
|
1213
|
+
number = 'FF' + number.padStart(6, '0');
|
|
1214
|
+
}
|
|
1215
|
+
color = parseInt(number, 16);
|
|
1216
|
+
} else {
|
|
1217
|
+
throw 'Invalid hex color';
|
|
1218
|
+
}
|
|
1219
|
+
return color;
|
|
1220
|
+
};
|
|
1156
1221
|
};
|
|
@@ -14,9 +14,9 @@ class InterfaceController {
|
|
|
14
14
|
* @param {string} chatId ID of the chat window that will be opened
|
|
15
15
|
*/
|
|
16
16
|
async openChatWindow(chatId) {
|
|
17
|
-
await this.pupPage.evaluate(async (chatId) => {
|
|
17
|
+
return await this.pupPage.evaluate(async (chatId) => {
|
|
18
18
|
const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
|
|
19
|
-
await window.Store.Cmd.openChatBottom(chat);
|
|
19
|
+
return await window.Store.Cmd.openChatBottom({'chat':chat});
|
|
20
20
|
}, chatId);
|
|
21
21
|
}
|
|
22
22
|
|