whatsapp-web.js 1.34.1 → 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/README.md +9 -39
- package/example.js +18 -2
- package/index.d.ts +62 -5
- package/package.json +2 -2
- package/src/Client.js +188 -16
- package/src/structures/Chat.js +30 -0
- package/src/structures/Contact.js +9 -2
- package/src/structures/GroupChat.js +9 -9
- package/src/structures/Message.js +43 -3
- package/src/structures/ScheduledEvent.js +3 -3
- package/src/util/Constants.js +3 -0
- package/src/util/Injected/Store.js +49 -19
- package/src/util/Injected/Utils.js +87 -35
- package/src/util/InterfaceController.js +2 -2
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<br />
|
|
3
3
|
<p>
|
|
4
|
-
<a href="https://wwebjs.dev"><img src="https://github.com/wwebjs/
|
|
4
|
+
<a href="https://wwebjs.dev"><img src="https://github.com/wwebjs/assets/blob/main/Collection/GitHub/wwebjs.png?raw=true" title="whatsapp-web.js" alt="WWebJS Website" width="500" /></a>
|
|
5
5
|
</p>
|
|
6
6
|
<br />
|
|
7
7
|
<p>
|
|
@@ -14,57 +14,28 @@
|
|
|
14
14
|
</div>
|
|
15
15
|
|
|
16
16
|
## About
|
|
17
|
-
**A WhatsApp API client that
|
|
17
|
+
**A WhatsApp API client that operates via the WhatsApp Web browser.**
|
|
18
18
|
|
|
19
|
-
The library
|
|
19
|
+
The library launches the WhatsApp Web browser app via Puppeteer, accessing its internal functions and creating a managed instance to reduce the risk of being blocked. This gives the API client nearly all WhatsApp Web features for dynamic use in a Node.js application.
|
|
20
20
|
|
|
21
21
|
> [!IMPORTANT]
|
|
22
22
|
> **It is not guaranteed you will not be blocked by using this method. WhatsApp does not allow bots or unofficial clients on their platform, so this shouldn't be considered totally safe.**
|
|
23
23
|
|
|
24
24
|
## Links
|
|
25
25
|
|
|
26
|
-
* [Website][website]
|
|
27
|
-
* [Guide][guide] ([source][guide-source]) _(work in progress)_
|
|
28
|
-
* [Documentation][documentation] ([source][documentation-source])
|
|
29
|
-
* [WWebJS Discord][discord]
|
|
30
26
|
* [GitHub][gitHub]
|
|
27
|
+
* [Guide][guide] ([source][guide-source])
|
|
28
|
+
* [Documentation][documentation] ([source][documentation-source])
|
|
29
|
+
* [Discord Server][discord]
|
|
31
30
|
* [npm][npm]
|
|
32
31
|
|
|
33
32
|
## Installation
|
|
34
33
|
|
|
35
|
-
The module is
|
|
34
|
+
The module is available on [npm][npm] via `npm i whatsapp-web.js`!
|
|
36
35
|
|
|
37
36
|
> [!NOTE]
|
|
38
|
-
> **Node ``v18
|
|
39
|
-
|
|
40
|
-
## QUICK STEPS TO UPGRADE NODE
|
|
41
|
-
|
|
42
|
-
### Windows
|
|
43
|
-
|
|
44
|
-
#### Manual
|
|
45
|
-
Just get the latest LTS from the [official node website][nodejs].
|
|
46
|
-
|
|
47
|
-
#### npm
|
|
48
|
-
```powershell
|
|
49
|
-
sudo npm install -g n
|
|
50
|
-
sudo n stable
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
#### Choco
|
|
54
|
-
```powershell
|
|
55
|
-
choco install nodejs-lts
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
#### Winget
|
|
59
|
-
```powershell
|
|
60
|
-
winget install OpenJS.NodeJS.LTS
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### Ubuntu / Debian
|
|
64
|
-
```bash
|
|
65
|
-
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - &&\
|
|
66
|
-
sudo apt-get install -y nodejs
|
|
67
|
-
```
|
|
37
|
+
> **Node ``v18`` or higher, is required.**
|
|
38
|
+
> See the [Guide][guide] for quick upgrade instructions.
|
|
68
39
|
|
|
69
40
|
## Example usage
|
|
70
41
|
|
|
@@ -165,7 +136,6 @@ See the License for the specific language governing permissions and
|
|
|
165
136
|
limitations under the License.
|
|
166
137
|
|
|
167
138
|
|
|
168
|
-
[website]: https://wwebjs.dev
|
|
169
139
|
[guide]: https://guide.wwebjs.dev/guide
|
|
170
140
|
[guide-source]: https://github.com/wwebjs/wwebjs.dev/tree/main
|
|
171
141
|
[documentation]: https://docs.wwebjs.dev/
|
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>
|
|
@@ -242,7 +248,26 @@ declare namespace WAWebJS {
|
|
|
242
248
|
syncHistory(chatId: string): Promise<boolean>
|
|
243
249
|
|
|
244
250
|
/** Save new contact to user's addressbook or edit the existing one */
|
|
245
|
-
saveOrEditAddressbookContact(phoneNumber: string, firstName: string, lastName: string, syncToAddressbook?: boolean): Promise<
|
|
251
|
+
saveOrEditAddressbookContact(phoneNumber: string, firstName: string, lastName: string, syncToAddressbook?: boolean): Promise<void>
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Add or edit a customer note
|
|
255
|
+
* @see https://faq.whatsapp.com/1433099287594476
|
|
256
|
+
*/
|
|
257
|
+
addOrEditCustomerNote(userId: string, note: string): Promise<void>
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Get a customer note
|
|
261
|
+
* @see https://faq.whatsapp.com/1433099287594476
|
|
262
|
+
*/
|
|
263
|
+
getCustomerNote(userId: string): Promise<{
|
|
264
|
+
chatId: string;
|
|
265
|
+
content: string;
|
|
266
|
+
createdAt: number;
|
|
267
|
+
id: string;
|
|
268
|
+
modifiedAt: number;
|
|
269
|
+
type: string;
|
|
270
|
+
}>
|
|
246
271
|
|
|
247
272
|
/** Deletes the contact from user's addressbook */
|
|
248
273
|
deleteAddressbookContact(honeNumber: string): Promise<void>
|
|
@@ -287,6 +312,9 @@ declare namespace WAWebJS {
|
|
|
287
312
|
*/
|
|
288
313
|
transferChannelOwnership(channelId: string, newOwnerId: string, options?: TransferChannelOwnershipOptions): Promise<boolean>;
|
|
289
314
|
|
|
315
|
+
/** Get Poll Votes */
|
|
316
|
+
getPollVotes(messageId: string): Promise<PollVote[]>
|
|
317
|
+
|
|
290
318
|
/** Generic event */
|
|
291
319
|
on(event: string, listener: (...args: any) => void): this
|
|
292
320
|
|
|
@@ -534,6 +562,9 @@ declare namespace WAWebJS {
|
|
|
534
562
|
/** Timeout for authentication selector in puppeteer
|
|
535
563
|
* @default 0 */
|
|
536
564
|
authTimeoutMs?: number,
|
|
565
|
+
/** function to be evaluated On New Document
|
|
566
|
+
* @default undefined */
|
|
567
|
+
evalOnNewDoc?: Function,
|
|
537
568
|
/** Puppeteer launch options. View docs here: https://github.com/puppeteer/puppeteer/ */
|
|
538
569
|
puppeteer?: puppeteer.PuppeteerNodeLaunchOptions & puppeteer.ConnectOptions
|
|
539
570
|
/** Determines how to save and restore sessions. Will use LegacySessionAuth if options.session is set. Otherwise, NoAuth will be used. */
|
|
@@ -860,12 +891,14 @@ declare namespace WAWebJS {
|
|
|
860
891
|
GROUP_MEMBERSHIP_REQUEST = 'group_membership_request',
|
|
861
892
|
GROUP_UPDATE = 'group_update',
|
|
862
893
|
QR_RECEIVED = 'qr',
|
|
894
|
+
CODE_RECEIVED = 'code',
|
|
863
895
|
LOADING_SCREEN = 'loading_screen',
|
|
864
896
|
DISCONNECTED = 'disconnected',
|
|
865
897
|
STATE_CHANGED = 'change_state',
|
|
866
898
|
BATTERY_CHANGED = 'change_battery',
|
|
867
899
|
REMOTE_SESSION_SAVED = 'remote_session_saved',
|
|
868
|
-
|
|
900
|
+
INCOMING_CALL = 'call',
|
|
901
|
+
VOTE_UPDATE = 'vote_update',
|
|
869
902
|
}
|
|
870
903
|
|
|
871
904
|
/** Group notification types */
|
|
@@ -874,6 +907,8 @@ declare namespace WAWebJS {
|
|
|
874
907
|
INVITE = 'invite',
|
|
875
908
|
REMOVE = 'remove',
|
|
876
909
|
LEAVE = 'leave',
|
|
910
|
+
PROMOTE = 'promote',
|
|
911
|
+
DEMOTE = 'demote',
|
|
877
912
|
SUBJECT = 'subject',
|
|
878
913
|
DESCRIPTION = 'description',
|
|
879
914
|
PICTURE = 'picture',
|
|
@@ -897,6 +932,7 @@ declare namespace WAWebJS {
|
|
|
897
932
|
AUDIO = 'audio',
|
|
898
933
|
VOICE = 'ptt',
|
|
899
934
|
IMAGE = 'image',
|
|
935
|
+
ALBUM = 'album',
|
|
900
936
|
VIDEO = 'video',
|
|
901
937
|
DOCUMENT = 'document',
|
|
902
938
|
STICKER = 'sticker',
|
|
@@ -1173,6 +1209,10 @@ declare namespace WAWebJS {
|
|
|
1173
1209
|
* Gets the payment details associated with a given message
|
|
1174
1210
|
*/
|
|
1175
1211
|
getPayment: () => Promise<Payment>,
|
|
1212
|
+
/**
|
|
1213
|
+
* Get Poll Votes associated with the given message
|
|
1214
|
+
*/
|
|
1215
|
+
getPollVotes: () => Promise<PollVote[]>,
|
|
1176
1216
|
/**
|
|
1177
1217
|
* Gets the reactions associated with the given message
|
|
1178
1218
|
*/
|
|
@@ -1184,6 +1224,10 @@ declare namespace WAWebJS {
|
|
|
1184
1224
|
* Once the event is canceled, it can not be edited.
|
|
1185
1225
|
*/
|
|
1186
1226
|
editScheduledEvent: (editedEventObject: Event) => Promise<Message | null>,
|
|
1227
|
+
/**
|
|
1228
|
+
* Send votes to the poll message
|
|
1229
|
+
*/
|
|
1230
|
+
vote: (selectedOptions: Array<string>) => Promise<void>,
|
|
1187
1231
|
}
|
|
1188
1232
|
|
|
1189
1233
|
/** ID that represents a message */
|
|
@@ -1247,7 +1291,7 @@ declare namespace WAWebJS {
|
|
|
1247
1291
|
endTime?: Date,
|
|
1248
1292
|
/** The location of the event */
|
|
1249
1293
|
location?: string,
|
|
1250
|
-
/** 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` */
|
|
1251
1295
|
callType?: string,
|
|
1252
1296
|
/**
|
|
1253
1297
|
* Indicates if a scheduled event should be sent as an already canceled
|
|
@@ -1274,7 +1318,7 @@ declare namespace WAWebJS {
|
|
|
1274
1318
|
messageSecret?: string;
|
|
1275
1319
|
};
|
|
1276
1320
|
|
|
1277
|
-
constructor(name: string, startTime: Date, options?:
|
|
1321
|
+
constructor(name: string, startTime: Date, options?: ScheduledEventSendOptions)
|
|
1278
1322
|
}
|
|
1279
1323
|
|
|
1280
1324
|
/** Represents a Poll Vote on WhatsApp */
|
|
@@ -1534,6 +1578,8 @@ declare namespace WAWebJS {
|
|
|
1534
1578
|
/** Gets the Contact's common groups with you. Returns empty array if you don't have any common group. */
|
|
1535
1579
|
getCommonGroups: () => Promise<ChatId[]>
|
|
1536
1580
|
|
|
1581
|
+
/** Gets the Contact's current status broadcast. */
|
|
1582
|
+
getBroadcast: () => Promise<Broadcast>
|
|
1537
1583
|
}
|
|
1538
1584
|
|
|
1539
1585
|
export interface ContactId {
|
|
@@ -1707,6 +1753,17 @@ declare namespace WAWebJS {
|
|
|
1707
1753
|
getPinnedMessages: () => Promise<[Message]|[]>
|
|
1708
1754
|
/** Sync history conversation of the Chat */
|
|
1709
1755
|
syncHistory: () => Promise<boolean>
|
|
1756
|
+
/** Add or edit a customer note */
|
|
1757
|
+
addOrEditCustomerNote: (note: string) => Promise<void>
|
|
1758
|
+
/** Get a customer note */
|
|
1759
|
+
getCustomerNote: () => Promise<{
|
|
1760
|
+
chatId: string;
|
|
1761
|
+
content: string;
|
|
1762
|
+
createdAt: number;
|
|
1763
|
+
id: string;
|
|
1764
|
+
modifiedAt: number;
|
|
1765
|
+
type: string;
|
|
1766
|
+
}>
|
|
1710
1767
|
}
|
|
1711
1768
|
|
|
1712
1769
|
export interface Channel {
|
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);
|
|
@@ -1225,11 +1268,18 @@ class Client extends EventEmitter {
|
|
|
1225
1268
|
|
|
1226
1269
|
const msgs = await window.Store.PinnedMsgUtils.getTable().equals(['chatId'], chatWid.toString());
|
|
1227
1270
|
|
|
1228
|
-
const pinnedMsgs =
|
|
1271
|
+
const pinnedMsgs = (
|
|
1272
|
+
await Promise.all(
|
|
1273
|
+
msgs.filter(msg => msg.pinType == 1).map(async (msg) => {
|
|
1274
|
+
const res = await window.Store.Msg.getMessagesById([msg.parentMsgKey]);
|
|
1275
|
+
return res?.messages?.[0];
|
|
1276
|
+
})
|
|
1277
|
+
)
|
|
1278
|
+
).filter(Boolean);
|
|
1229
1279
|
|
|
1230
1280
|
return !pinnedMsgs.length
|
|
1231
1281
|
? []
|
|
1232
|
-
: pinnedMsgs.map((msg) => window.WWebJS.getMessageModel(msg));
|
|
1282
|
+
: await Promise.all(pinnedMsgs.map((msg) => window.WWebJS.getMessageModel(msg)));
|
|
1233
1283
|
}, chatId);
|
|
1234
1284
|
|
|
1235
1285
|
return pinnedMsgs.map((msg) => new Message(this, msg));
|
|
@@ -1524,7 +1574,7 @@ class Client extends EventEmitter {
|
|
|
1524
1574
|
const commonGroups = await this.pupPage.evaluate(async (contactId) => {
|
|
1525
1575
|
let contact = window.Store.Contact.get(contactId);
|
|
1526
1576
|
if (!contact) {
|
|
1527
|
-
const wid = window.Store.WidFactory.
|
|
1577
|
+
const wid = window.Store.WidFactory.createWid(contactId);
|
|
1528
1578
|
const chatConstructor = window.Store.Contact.getModelsArray().find(c=>!c.isGroup).constructor;
|
|
1529
1579
|
contact = new chatConstructor({id: wid});
|
|
1530
1580
|
}
|
|
@@ -1963,7 +2013,7 @@ class Client extends EventEmitter {
|
|
|
1963
2013
|
|
|
1964
2014
|
return labels.map(data => new Label(this, data));
|
|
1965
2015
|
}
|
|
1966
|
-
|
|
2016
|
+
|
|
1967
2017
|
/**
|
|
1968
2018
|
* Get all current Broadcast
|
|
1969
2019
|
* @returns {Promise<Array<Broadcast>>}
|
|
@@ -1975,6 +2025,49 @@ class Client extends EventEmitter {
|
|
|
1975
2025
|
return broadcasts.map(data => new Broadcast(this, data));
|
|
1976
2026
|
}
|
|
1977
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
|
+
|
|
1978
2071
|
/**
|
|
1979
2072
|
* Get Label instance by ID
|
|
1980
2073
|
* @param {string} labelId
|
|
@@ -2310,13 +2403,15 @@ class Client extends EventEmitter {
|
|
|
2310
2403
|
* @param {string} firstName
|
|
2311
2404
|
* @param {string} lastName
|
|
2312
2405
|
* @param {boolean} [syncToAddressbook = false] If set to true, the contact will also be saved to the user's address book on their phone. False by default
|
|
2313
|
-
* @returns {Promise<
|
|
2406
|
+
* @returns {Promise<void>}
|
|
2314
2407
|
*/
|
|
2315
2408
|
async saveOrEditAddressbookContact(phoneNumber, firstName, lastName, syncToAddressbook = false)
|
|
2316
2409
|
{
|
|
2317
2410
|
return await this.pupPage.evaluate(async (phoneNumber, firstName, lastName, syncToAddressbook) => {
|
|
2318
2411
|
return await window.Store.AddressbookContactUtils.saveContactAction(
|
|
2319
2412
|
phoneNumber,
|
|
2413
|
+
phoneNumber,
|
|
2414
|
+
null,
|
|
2320
2415
|
null,
|
|
2321
2416
|
firstName,
|
|
2322
2417
|
lastName,
|
|
@@ -2356,6 +2451,83 @@ class Client extends EventEmitter {
|
|
|
2356
2451
|
}));
|
|
2357
2452
|
}, userIds);
|
|
2358
2453
|
}
|
|
2454
|
+
|
|
2455
|
+
/**
|
|
2456
|
+
* Add or edit a customer note
|
|
2457
|
+
* @see https://faq.whatsapp.com/1433099287594476
|
|
2458
|
+
* @param {string} userId The ID of a customer to add a note to
|
|
2459
|
+
* @param {string} note The note to add
|
|
2460
|
+
* @returns {Promise<void>}
|
|
2461
|
+
*/
|
|
2462
|
+
async addOrEditCustomerNote(userId, note) {
|
|
2463
|
+
return await this.pupPage.evaluate(async (userId, note) => {
|
|
2464
|
+
if (!window.Store.BusinessGatingUtils.smbNotesV1Enabled()) return;
|
|
2465
|
+
|
|
2466
|
+
return window.Store.CustomerNoteUtils.noteAddAction(
|
|
2467
|
+
'unstructured',
|
|
2468
|
+
window.Store.WidToJid.widToUserJid(window.Store.WidFactory.createWid(userId)),
|
|
2469
|
+
note
|
|
2470
|
+
);
|
|
2471
|
+
}, userId, note);
|
|
2472
|
+
}
|
|
2473
|
+
|
|
2474
|
+
/**
|
|
2475
|
+
* Get a customer note
|
|
2476
|
+
* @see https://faq.whatsapp.com/1433099287594476
|
|
2477
|
+
* @param {string} userId The ID of a customer to get a note from
|
|
2478
|
+
* @returns {Promise<{
|
|
2479
|
+
* chatId: string,
|
|
2480
|
+
* content: string,
|
|
2481
|
+
* createdAt: number,
|
|
2482
|
+
* id: string,
|
|
2483
|
+
* modifiedAt: number,
|
|
2484
|
+
* type: string
|
|
2485
|
+
* }>}
|
|
2486
|
+
*/
|
|
2487
|
+
async getCustomerNote(userId) {
|
|
2488
|
+
return await this.pupPage.evaluate(async (userId) => {
|
|
2489
|
+
if (!window.Store.BusinessGatingUtils.smbNotesV1Enabled()) return null;
|
|
2490
|
+
|
|
2491
|
+
const note = await window.Store.CustomerNoteUtils.retrieveOnlyNoteForChatJid(
|
|
2492
|
+
window.Store.WidToJid.widToUserJid(window.Store.WidFactory.createWid(userId))
|
|
2493
|
+
);
|
|
2494
|
+
|
|
2495
|
+
let serialized = note?.serialize();
|
|
2496
|
+
|
|
2497
|
+
if (!serialized) return null;
|
|
2498
|
+
|
|
2499
|
+
serialized.chatId = window.Store.JidToWid.userJidToUserWid(serialized.chatJid)._serialized;
|
|
2500
|
+
delete serialized.chatJid;
|
|
2501
|
+
|
|
2502
|
+
return serialized;
|
|
2503
|
+
}, userId);
|
|
2504
|
+
}
|
|
2505
|
+
|
|
2506
|
+
/**
|
|
2507
|
+
* Get Poll Votes
|
|
2508
|
+
* @param {string} messageId
|
|
2509
|
+
* @return {Promise<Array<PollVote>>}
|
|
2510
|
+
*/
|
|
2511
|
+
async getPollVotes(messageId) {
|
|
2512
|
+
const msg = await this.getMessageById(messageId);
|
|
2513
|
+
if (!msg) return [];
|
|
2514
|
+
if (msg.type != MessageTypes.POLL_CREATION) throw 'Invalid usage! Can only be used with a pollCreation message';
|
|
2515
|
+
|
|
2516
|
+
const pollVotes = await this.pupPage.evaluate( async (msg) => {
|
|
2517
|
+
const msgKey = window.Store.MsgKey.fromString(msg.id._serialized);
|
|
2518
|
+
let pollVotes = await window.Store.PollsVotesSchema.getTable().equals(['parentMsgKey'], msgKey.toString());
|
|
2519
|
+
|
|
2520
|
+
return pollVotes.map(item => {
|
|
2521
|
+
const typedArray = new Uint8Array(item.selectedOptionLocalIds);
|
|
2522
|
+
return {
|
|
2523
|
+
...item,
|
|
2524
|
+
selectedOptionLocalIds: Array.from(typedArray)
|
|
2525
|
+
};
|
|
2526
|
+
});
|
|
2527
|
+
}, msg);
|
|
2528
|
+
|
|
2529
|
+
return pollVotes.map((pollVote) => new PollVote(this.client, {...pollVote, parentMessage: msg}));
|
|
2530
|
+
}
|
|
2359
2531
|
}
|
|
2360
2532
|
|
|
2361
2533
|
module.exports = Client;
|
package/src/structures/Chat.js
CHANGED
|
@@ -294,6 +294,36 @@ class Chat extends Base {
|
|
|
294
294
|
async syncHistory() {
|
|
295
295
|
return this.client.syncHistory(this.id._serialized);
|
|
296
296
|
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Add or edit a customer note
|
|
300
|
+
* @see https://faq.whatsapp.com/1433099287594476
|
|
301
|
+
* @param {string} note The note to add
|
|
302
|
+
* @returns {Promise<void>}
|
|
303
|
+
*/
|
|
304
|
+
async addOrEditCustomerNote(note) {
|
|
305
|
+
if (this.isGroup || this.isChannel) return;
|
|
306
|
+
|
|
307
|
+
return this.client.addOrEditCustomerNote(this.id._serialized, note);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Get a customer note
|
|
312
|
+
* @see https://faq.whatsapp.com/1433099287594476
|
|
313
|
+
* @returns {Promise<{
|
|
314
|
+
* chatId: string,
|
|
315
|
+
* content: string,
|
|
316
|
+
* createdAt: number,
|
|
317
|
+
* id: string,
|
|
318
|
+
* modifiedAt: number,
|
|
319
|
+
* type: string
|
|
320
|
+
* }>}
|
|
321
|
+
*/
|
|
322
|
+
async getCustomerNote() {
|
|
323
|
+
if (this.isGroup || this.isChannel) return null;
|
|
324
|
+
|
|
325
|
+
return this.client.getCustomerNote(this.id._serialized);
|
|
326
|
+
}
|
|
297
327
|
}
|
|
298
328
|
|
|
299
329
|
module.exports = Chat;
|
|
@@ -186,7 +186,7 @@ class Contact extends Base {
|
|
|
186
186
|
async getAbout() {
|
|
187
187
|
const about = await this.client.pupPage.evaluate(async (contactId) => {
|
|
188
188
|
const wid = window.Store.WidFactory.createWid(contactId);
|
|
189
|
-
return window.Store.StatusUtils.getStatus(wid);
|
|
189
|
+
return window.Store.StatusUtils.getStatus({'token':'', 'wid': wid});
|
|
190
190
|
}, this.id._serialized);
|
|
191
191
|
|
|
192
192
|
if (typeof about.status !== 'string')
|
|
@@ -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
|
|
|
@@ -742,6 +749,39 @@ class Message extends Base {
|
|
|
742
749
|
|
|
743
750
|
return edittedEventMsg && new Message(this.client, edittedEventMsg);
|
|
744
751
|
}
|
|
752
|
+
/**
|
|
753
|
+
* Returns the PollVote this poll message
|
|
754
|
+
* @returns {Promise<PollVote[]>}
|
|
755
|
+
*/
|
|
756
|
+
async getPollVotes() {
|
|
757
|
+
return await this.client.getPollVotes(this.id._serialized);
|
|
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
|
+
}
|
|
745
785
|
}
|
|
746
786
|
|
|
747
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');
|
|
@@ -97,13 +102,15 @@ exports.ExposeStore = () => {
|
|
|
97
102
|
window.Store.HistorySync = window.require('WAWebSendNonMessageDataRequest');
|
|
98
103
|
window.Store.AddonReactionTable = window.require('WAWebAddonReactionTableMode').reactionTableMode;
|
|
99
104
|
window.Store.AddonPollVoteTable = window.require('WAWebAddonPollVoteTableMode').pollVoteTableMode;
|
|
100
|
-
window.Store.PinnedMsgUtils = window.require('WAWebPinInChatSchema');
|
|
101
105
|
window.Store.ChatGetters = window.require('WAWebChatGetters');
|
|
102
|
-
window.Store.PinnedMsgUtils = window.require('WAWebSendPinMessageAction');
|
|
103
106
|
window.Store.UploadUtils = window.require('WAWebUploadManager');
|
|
104
107
|
window.Store.WAWebStreamModel = window.require('WAWebStreamModel');
|
|
105
108
|
window.Store.FindOrCreateChat = window.require('WAWebFindChatAction');
|
|
106
|
-
|
|
109
|
+
window.Store.CustomerNoteUtils = window.require('WAWebNoteAction');
|
|
110
|
+
window.Store.BusinessGatingUtils = window.require('WAWebBizGatingUtils');
|
|
111
|
+
window.Store.PollsVotesSchema = window.require('WAWebPollsVotesSchema');
|
|
112
|
+
window.Store.PollsSendVote = window.require('WAWebPollsSendVoteMsgAction');
|
|
113
|
+
|
|
107
114
|
window.Store.Settings = {
|
|
108
115
|
...window.require('WAWebUserPrefsGeneral'),
|
|
109
116
|
...window.require('WAWebUserPrefsNotifications'),
|
|
@@ -116,6 +123,10 @@ exports.ExposeStore = () => {
|
|
|
116
123
|
window.Store.ForwardUtils = {
|
|
117
124
|
...window.require('WAWebChatForwardMessage')
|
|
118
125
|
};
|
|
126
|
+
window.Store.PinnedMsgUtils = {
|
|
127
|
+
...window.require('WAWebPinInChatSchema'),
|
|
128
|
+
...window.require('WAWebSendPinMessageAction')
|
|
129
|
+
};
|
|
119
130
|
window.Store.ScheduledEventMsgUtils = {
|
|
120
131
|
...window.require('WAWebGenerateEventCallLink'),
|
|
121
132
|
...window.require('WAWebSendEventEditMsgAction'),
|
|
@@ -134,7 +145,8 @@ exports.ExposeStore = () => {
|
|
|
134
145
|
...window.require('WAWebGroupCreateJob'),
|
|
135
146
|
...window.require('WAWebGroupModifyInfoJob'),
|
|
136
147
|
...window.require('WAWebExitGroupAction'),
|
|
137
|
-
...window.require('WAWebContactProfilePicThumbBridge')
|
|
148
|
+
...window.require('WAWebContactProfilePicThumbBridge'),
|
|
149
|
+
...window.require('WAWebSetPropertyGroupAction')
|
|
138
150
|
};
|
|
139
151
|
window.Store.GroupParticipants = {
|
|
140
152
|
...window.require('WAWebModifyParticipantsGroupAction'),
|
|
@@ -188,6 +200,12 @@ exports.ExposeStore = () => {
|
|
|
188
200
|
...window.require('WAWebSaveContactAction'),
|
|
189
201
|
...window.require('WAWebDeleteContactAction')
|
|
190
202
|
};
|
|
203
|
+
window.Store.StatusUtils = {
|
|
204
|
+
...window.require('WAWebContactStatusBridge'),
|
|
205
|
+
...window.require('WAWebSendStatusMsgAction'),
|
|
206
|
+
...window.require('WAWebRevokeStatusAction'),
|
|
207
|
+
...window.require('WAWebStatusGatingUtils')
|
|
208
|
+
};
|
|
191
209
|
|
|
192
210
|
if (!window.Store.Chat._find || !window.Store.Chat.findImpl) {
|
|
193
211
|
window.Store.Chat._find = e => {
|
|
@@ -211,23 +229,35 @@ exports.ExposeStore = () => {
|
|
|
211
229
|
* @param {Function} callback Modified function
|
|
212
230
|
*/
|
|
213
231
|
window.injectToFunction = (target, callback) => {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
for (const key of path) {
|
|
221
|
-
module = module[key];
|
|
222
|
-
}
|
|
232
|
+
try {
|
|
233
|
+
let module = window.require(target.module);
|
|
234
|
+
if (!module) return;
|
|
235
|
+
|
|
236
|
+
const path = target.function.split('.');
|
|
237
|
+
const funcName = path.pop();
|
|
223
238
|
|
|
224
|
-
|
|
225
|
-
|
|
239
|
+
for (const key of path) {
|
|
240
|
+
if (!module[key]) return;
|
|
241
|
+
module = module[key];
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const originalFunction = module[funcName];
|
|
245
|
+
if (typeof originalFunction !== 'function') return;
|
|
246
|
+
|
|
247
|
+
module[funcName] = (...args) => {
|
|
248
|
+
try {
|
|
249
|
+
return callback(originalFunction, ...args);
|
|
250
|
+
} catch {
|
|
251
|
+
return originalFunction(...args);
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
} catch {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
226
258
|
};
|
|
227
259
|
|
|
228
260
|
window.injectToFunction({ module: 'WAWebBackendJobsCommon', function: 'mediaTypeFromProtobuf' }, (func, ...args) => { const [proto] = args; return proto.locationMessage ? null : func(...args); });
|
|
229
261
|
|
|
230
262
|
window.injectToFunction({ module: 'WAWebE2EProtoUtils', function: 'typeAttributeFromProtobuf' }, (func, ...args) => { const [proto] = args; return proto.locationMessage || proto.groupInviteMessage ? 'text' : func(...args); });
|
|
231
|
-
|
|
232
|
-
window.injectToFunction({ module: 'WAWebLid1X1MigrationGating', function: 'Lid1X1MigrationUtils.isLidMigrated' }, () => false);
|
|
233
263
|
};
|
|
@@ -6,7 +6,7 @@ exports.LoadUtils = () => {
|
|
|
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
|
const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
|
|
9
|
-
return window.Store.ForwardUtils.forwardMessages(chat, [msg], true, true);
|
|
9
|
+
return await window.Store.ForwardUtils.forwardMessages({'chat': chat, 'msgs' : [msg], 'multicast': true, 'includeCaption': true, 'appendedText' : undefined});
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
window.WWebJS.sendSeen = async (chatId) => {
|
|
@@ -14,6 +14,7 @@ exports.LoadUtils = () => {
|
|
|
14
14
|
if (chat) {
|
|
15
15
|
window.Store.WAWebStreamModel.Stream.markAvailable();
|
|
16
16
|
await window.Store.SendSeen.sendSeen(chat);
|
|
17
|
+
window.Store.WAWebStreamModel.Stream.markUnavailable();
|
|
17
18
|
return true;
|
|
18
19
|
}
|
|
19
20
|
return false;
|
|
@@ -21,10 +22,11 @@ exports.LoadUtils = () => {
|
|
|
21
22
|
|
|
22
23
|
window.WWebJS.sendMessage = async (chat, content, options = {}) => {
|
|
23
24
|
const isChannel = window.Store.ChatGetters.getIsNewsletter(chat);
|
|
25
|
+
const isStatus = window.Store.ChatGetters.getIsBroadcast(chat);
|
|
24
26
|
|
|
25
27
|
let mediaOptions = {};
|
|
26
28
|
if (options.media) {
|
|
27
|
-
mediaOptions = options.sendMediaAsSticker && !isChannel
|
|
29
|
+
mediaOptions = options.sendMediaAsSticker && !isChannel && !isStatus
|
|
28
30
|
? await window.WWebJS.processStickerData(options.media)
|
|
29
31
|
: await window.WWebJS.processMediaData(options.media, {
|
|
30
32
|
forceSticker: options.sendMediaAsSticker,
|
|
@@ -32,7 +34,8 @@ exports.LoadUtils = () => {
|
|
|
32
34
|
forceVoice: options.sendAudioAsVoice,
|
|
33
35
|
forceDocument: options.sendMediaAsDocument,
|
|
34
36
|
forceMediaHd: options.sendMediaAsHd,
|
|
35
|
-
sendToChannel: isChannel
|
|
37
|
+
sendToChannel: isChannel,
|
|
38
|
+
sendToStatus: isStatus
|
|
36
39
|
});
|
|
37
40
|
mediaOptions.caption = options.caption;
|
|
38
41
|
content = options.sendMediaAsSticker ? undefined : mediaOptions.preview;
|
|
@@ -65,14 +68,7 @@ exports.LoadUtils = () => {
|
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
if (options.mentionedJidList) {
|
|
68
|
-
options.mentionedJidList =
|
|
69
|
-
options.mentionedJidList.map(async (id) => {
|
|
70
|
-
const wid = window.Store.WidFactory.createWid(id);
|
|
71
|
-
if (await window.Store.QueryExist(wid)) {
|
|
72
|
-
return wid;
|
|
73
|
-
}
|
|
74
|
-
})
|
|
75
|
-
);
|
|
71
|
+
options.mentionedJidList = options.mentionedJidList.map((id) => window.Store.WidFactory.createWid(id));
|
|
76
72
|
options.mentionedJidList = options.mentionedJidList.filter(Boolean);
|
|
77
73
|
}
|
|
78
74
|
|
|
@@ -98,15 +94,15 @@ exports.LoadUtils = () => {
|
|
|
98
94
|
delete options.location;
|
|
99
95
|
}
|
|
100
96
|
|
|
101
|
-
let
|
|
97
|
+
let pollOptions = {};
|
|
102
98
|
if (options.poll) {
|
|
103
|
-
const { pollName, pollOptions } = options.poll;
|
|
99
|
+
const { pollName, pollOptions: _pollOptions } = options.poll;
|
|
104
100
|
const { allowMultipleAnswers, messageSecret } = options.poll.options;
|
|
105
|
-
|
|
101
|
+
pollOptions = {
|
|
106
102
|
kind: 'pollCreation',
|
|
107
103
|
type: 'poll_creation',
|
|
108
104
|
pollName: pollName,
|
|
109
|
-
pollOptions:
|
|
105
|
+
pollOptions: _pollOptions,
|
|
110
106
|
pollSelectableOptionsCount: allowMultipleAnswers ? 0 : 1,
|
|
111
107
|
messageSecret:
|
|
112
108
|
Array.isArray(messageSecret) && messageSecret.length === 32
|
|
@@ -131,7 +127,7 @@ exports.LoadUtils = () => {
|
|
|
131
127
|
degreesLongitude: 0,
|
|
132
128
|
name: eventSendOptions.location
|
|
133
129
|
},
|
|
134
|
-
eventJoinLink: await window.Store.ScheduledEventMsgUtils.createEventCallLink(
|
|
130
|
+
eventJoinLink: eventSendOptions.callType === 'none' ? null : await window.Store.ScheduledEventMsgUtils.createEventCallLink(
|
|
135
131
|
startTimeTs,
|
|
136
132
|
eventSendOptions.callType
|
|
137
133
|
),
|
|
@@ -252,6 +248,10 @@ exports.LoadUtils = () => {
|
|
|
252
248
|
participant = window.Store.WidFactory.asUserWidOrThrow(from);
|
|
253
249
|
}
|
|
254
250
|
|
|
251
|
+
if (typeof chat.id?.isStatus === 'function' && chat.id.isStatus()) {
|
|
252
|
+
participant = window.Store.WidFactory.asUserWidOrThrow(from);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
255
|
const newMsgKey = new window.Store.MsgKey({
|
|
256
256
|
from: from,
|
|
257
257
|
to: chat.id,
|
|
@@ -270,7 +270,7 @@ exports.LoadUtils = () => {
|
|
|
270
270
|
id: newMsgKey,
|
|
271
271
|
ack: 0,
|
|
272
272
|
body: content,
|
|
273
|
-
from:
|
|
273
|
+
from: from,
|
|
274
274
|
to: chat.id,
|
|
275
275
|
local: true,
|
|
276
276
|
self: 'out',
|
|
@@ -282,7 +282,7 @@ exports.LoadUtils = () => {
|
|
|
282
282
|
...(mediaOptions.toJSON ? mediaOptions.toJSON() : {}),
|
|
283
283
|
...quotedMsgOptions,
|
|
284
284
|
...locationOptions,
|
|
285
|
-
...
|
|
285
|
+
...pollOptions,
|
|
286
286
|
...eventOptions,
|
|
287
287
|
...vcardOptions,
|
|
288
288
|
...buttonOptions,
|
|
@@ -326,6 +326,37 @@ exports.LoadUtils = () => {
|
|
|
326
326
|
return msg;
|
|
327
327
|
}
|
|
328
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
|
+
|
|
329
360
|
const [msgPromise, sendMsgResultPromise] = window.Store.SendMessage.addAndSendMsgToChat(chat, message);
|
|
330
361
|
await msgPromise;
|
|
331
362
|
|
|
@@ -339,14 +370,7 @@ exports.LoadUtils = () => {
|
|
|
339
370
|
delete options.extraOptions;
|
|
340
371
|
|
|
341
372
|
if (options.mentionedJidList) {
|
|
342
|
-
options.mentionedJidList =
|
|
343
|
-
options.mentionedJidList.map(async (id) => {
|
|
344
|
-
const wid = window.Store.WidFactory.createWid(id);
|
|
345
|
-
if (await window.Store.QueryExist(wid)) {
|
|
346
|
-
return wid;
|
|
347
|
-
}
|
|
348
|
-
})
|
|
349
|
-
);
|
|
373
|
+
options.mentionedJidList = options.mentionedJidList.map((id) => window.Store.WidFactory.createWid(id));
|
|
350
374
|
options.mentionedJidList = options.mentionedJidList.filter(Boolean);
|
|
351
375
|
}
|
|
352
376
|
|
|
@@ -420,7 +444,7 @@ exports.LoadUtils = () => {
|
|
|
420
444
|
return stickerInfo;
|
|
421
445
|
};
|
|
422
446
|
|
|
423
|
-
window.WWebJS.processMediaData = async (mediaInfo, { forceSticker, forceGif, forceVoice, forceDocument, forceMediaHd, sendToChannel }) => {
|
|
447
|
+
window.WWebJS.processMediaData = async (mediaInfo, { forceSticker, forceGif, forceVoice, forceDocument, forceMediaHd, sendToChannel, sendToStatus }) => {
|
|
424
448
|
const file = window.WWebJS.mediaInfoToFile(mediaInfo);
|
|
425
449
|
const opaqueData = await window.Store.OpaqueData.createFromData(file, file.type);
|
|
426
450
|
const mediaParams = {
|
|
@@ -443,7 +467,11 @@ exports.LoadUtils = () => {
|
|
|
443
467
|
isNewsletter: sendToChannel,
|
|
444
468
|
});
|
|
445
469
|
|
|
446
|
-
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')) {
|
|
447
475
|
const waveform = mediaObject.contentInfo.waveform;
|
|
448
476
|
mediaData.waveform =
|
|
449
477
|
waveform || await window.WWebJS.generateWaveform(file);
|
|
@@ -458,13 +486,21 @@ exports.LoadUtils = () => {
|
|
|
458
486
|
|
|
459
487
|
mediaData.renderableUrl = mediaData.mediaBlob.url();
|
|
460
488
|
mediaObject.consolidate(mediaData.toJSON());
|
|
489
|
+
|
|
461
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
|
+
}
|
|
462
498
|
|
|
463
499
|
const dataToUpload = {
|
|
464
500
|
mimetype: mediaData.mimetype,
|
|
465
501
|
mediaObject,
|
|
466
502
|
mediaType,
|
|
467
|
-
...(sendToChannel ? { calculateToken: window.Store.SendChannelMessage.getRandomFilehash } : {})
|
|
503
|
+
...(sendToChannel ? { calculateToken: window.Store.SendChannelMessage.getRandomFilehash() } : {})
|
|
468
504
|
};
|
|
469
505
|
|
|
470
506
|
const uploadedMedia = !sendToChannel
|
|
@@ -838,22 +874,22 @@ exports.LoadUtils = () => {
|
|
|
838
874
|
};
|
|
839
875
|
|
|
840
876
|
window.WWebJS.rejectCall = async (peerJid, id) => {
|
|
841
|
-
|
|
842
|
-
|
|
877
|
+
let userId = window.Store.User.getMaybeMePnUser()._serialized;
|
|
878
|
+
|
|
843
879
|
const stanza = window.Store.SocketWap.wap('call', {
|
|
844
880
|
id: window.Store.SocketWap.generateId(),
|
|
845
|
-
from:
|
|
846
|
-
to:
|
|
881
|
+
from: userId,
|
|
882
|
+
to: peerJid,
|
|
847
883
|
}, [
|
|
848
884
|
window.Store.SocketWap.wap('reject', {
|
|
849
885
|
'call-id': id,
|
|
850
|
-
'call-creator':
|
|
886
|
+
'call-creator': peerJid,
|
|
851
887
|
count: '0',
|
|
852
888
|
})
|
|
853
889
|
]);
|
|
854
890
|
await window.Store.Socket.deprecatedCastStanza(stanza);
|
|
855
891
|
};
|
|
856
|
-
|
|
892
|
+
|
|
857
893
|
window.WWebJS.cropAndResizeImage = async (media, options = {}) => {
|
|
858
894
|
if (!media.mimetype.includes('image'))
|
|
859
895
|
throw new Error('Media is not an image');
|
|
@@ -1166,4 +1202,20 @@ exports.LoadUtils = () => {
|
|
|
1166
1202
|
|
|
1167
1203
|
return { lid, phone };
|
|
1168
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
|
+
};
|
|
1169
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
|
|