whatsapp-web-sj.js 1.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +3 -0
- package/CODE_OF_CONDUCT.md +133 -0
- package/LICENSE +201 -0
- package/README.md +185 -0
- package/example.js +634 -0
- package/index.d.ts +1842 -0
- package/index.js +32 -0
- package/package.json +55 -0
- package/shell.js +36 -0
- package/src/Client.js +1747 -0
- package/src/authStrategies/BaseAuthStrategy.js +27 -0
- package/src/authStrategies/LocalAuth.js +56 -0
- package/src/authStrategies/NoAuth.js +12 -0
- package/src/authStrategies/RemoteAuth.js +204 -0
- package/src/factories/ChatFactory.js +16 -0
- package/src/factories/ContactFactory.js +16 -0
- package/src/structures/Base.js +22 -0
- package/src/structures/BusinessContact.js +21 -0
- package/src/structures/Buttons.js +82 -0
- package/src/structures/Call.js +76 -0
- package/src/structures/Chat.js +275 -0
- package/src/structures/ClientInfo.js +71 -0
- package/src/structures/Contact.js +208 -0
- package/src/structures/GroupChat.js +475 -0
- package/src/structures/GroupNotification.js +104 -0
- package/src/structures/Label.js +50 -0
- package/src/structures/List.js +79 -0
- package/src/structures/Location.js +61 -0
- package/src/structures/Message.js +711 -0
- package/src/structures/MessageMedia.js +111 -0
- package/src/structures/Order.js +52 -0
- package/src/structures/Payment.js +79 -0
- package/src/structures/Poll.js +44 -0
- package/src/structures/PollVote.js +61 -0
- package/src/structures/PrivateChat.js +13 -0
- package/src/structures/PrivateContact.js +13 -0
- package/src/structures/Product.js +68 -0
- package/src/structures/ProductMetadata.js +25 -0
- package/src/structures/Reaction.js +69 -0
- package/src/structures/index.js +24 -0
- package/src/util/Constants.js +176 -0
- package/src/util/Injected/AuthStore/AuthStore.js +17 -0
- package/src/util/Injected/AuthStore/LegacyAuthStore.js +22 -0
- package/src/util/Injected/LegacyStore.js +146 -0
- package/src/util/Injected/Store.js +167 -0
- package/src/util/Injected/Utils.js +1017 -0
- package/src/util/InterfaceController.js +127 -0
- package/src/util/Util.js +186 -0
- package/src/webCache/LocalWebCache.js +40 -0
- package/src/webCache/RemoteWebCache.js +40 -0
- package/src/webCache/WebCache.js +14 -0
- package/src/webCache/WebCacheFactory.js +20 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Base class which all authentication strategies extend
|
5
|
+
*/
|
6
|
+
class BaseAuthStrategy {
|
7
|
+
constructor() {}
|
8
|
+
setup(client) {
|
9
|
+
this.client = client;
|
10
|
+
}
|
11
|
+
async beforeBrowserInitialized() {}
|
12
|
+
async afterBrowserInitialized() {}
|
13
|
+
async onAuthenticationNeeded() {
|
14
|
+
return {
|
15
|
+
failed: false,
|
16
|
+
restart: false,
|
17
|
+
failureEventPayload: undefined
|
18
|
+
};
|
19
|
+
}
|
20
|
+
async getAuthEventPayload() {}
|
21
|
+
async afterAuthReady() {}
|
22
|
+
async disconnect() {}
|
23
|
+
async destroy() {}
|
24
|
+
async logout() {}
|
25
|
+
}
|
26
|
+
|
27
|
+
module.exports = BaseAuthStrategy;
|
@@ -0,0 +1,56 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const path = require('path');
|
4
|
+
const fs = require('fs');
|
5
|
+
const BaseAuthStrategy = require('./BaseAuthStrategy');
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Local directory-based authentication
|
9
|
+
* @param {object} options - options
|
10
|
+
* @param {string} options.clientId - Client id to distinguish instances if you are using multiple, otherwise keep null if you are using only one instance
|
11
|
+
* @param {string} options.dataPath - Change the default path for saving session files, default is: "./.wwebjs_auth/"
|
12
|
+
*/
|
13
|
+
class LocalAuth extends BaseAuthStrategy {
|
14
|
+
constructor({ clientId, dataPath }={}) {
|
15
|
+
super();
|
16
|
+
|
17
|
+
const idRegex = /^[-_\w]+$/i;
|
18
|
+
if(clientId && !idRegex.test(clientId)) {
|
19
|
+
throw new Error('Invalid clientId. Only alphanumeric characters, underscores and hyphens are allowed.');
|
20
|
+
}
|
21
|
+
|
22
|
+
this.dataPath = path.resolve(dataPath || './.wwebjs_auth/');
|
23
|
+
this.clientId = clientId;
|
24
|
+
}
|
25
|
+
|
26
|
+
async beforeBrowserInitialized() {
|
27
|
+
const puppeteerOpts = this.client.options.puppeteer;
|
28
|
+
const sessionDirName = this.clientId ? `session-${this.clientId}` : 'session';
|
29
|
+
const dirPath = path.join(this.dataPath, sessionDirName);
|
30
|
+
|
31
|
+
if(puppeteerOpts.userDataDir && puppeteerOpts.userDataDir !== dirPath) {
|
32
|
+
throw new Error('LocalAuth is not compatible with a user-supplied userDataDir.');
|
33
|
+
}
|
34
|
+
|
35
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
36
|
+
|
37
|
+
this.client.options.puppeteer = {
|
38
|
+
...puppeteerOpts,
|
39
|
+
userDataDir: dirPath
|
40
|
+
};
|
41
|
+
|
42
|
+
this.userDataDir = dirPath;
|
43
|
+
}
|
44
|
+
|
45
|
+
async logout() {
|
46
|
+
if (this.userDataDir) {
|
47
|
+
await fs.promises.rm(this.userDataDir, { recursive: true, force: true })
|
48
|
+
.catch((e) => {
|
49
|
+
throw new Error(e);
|
50
|
+
});
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
}
|
55
|
+
|
56
|
+
module.exports = LocalAuth;
|
@@ -0,0 +1,204 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
/* Require Optional Dependencies */
|
4
|
+
try {
|
5
|
+
var fs = require('fs-extra');
|
6
|
+
var unzipper = require('unzipper');
|
7
|
+
var archiver = require('archiver');
|
8
|
+
} catch {
|
9
|
+
fs = undefined;
|
10
|
+
unzipper = undefined;
|
11
|
+
archiver = undefined;
|
12
|
+
}
|
13
|
+
|
14
|
+
const path = require('path');
|
15
|
+
const { Events } = require('./../util/Constants');
|
16
|
+
const BaseAuthStrategy = require('./BaseAuthStrategy');
|
17
|
+
|
18
|
+
/**
|
19
|
+
* Remote-based authentication
|
20
|
+
* @param {object} options - options
|
21
|
+
* @param {object} options.store - Remote database store instance
|
22
|
+
* @param {string} options.clientId - Client id to distinguish instances if you are using multiple, otherwise keep null if you are using only one instance
|
23
|
+
* @param {string} options.dataPath - Change the default path for saving session files, default is: "./.wwebjs_auth/"
|
24
|
+
* @param {number} options.backupSyncIntervalMs - Sets the time interval for periodic session backups. Accepts values starting from 60000ms {1 minute}
|
25
|
+
*/
|
26
|
+
class RemoteAuth extends BaseAuthStrategy {
|
27
|
+
constructor({ clientId, dataPath, store, backupSyncIntervalMs } = {}) {
|
28
|
+
if (!fs && !unzipper && !archiver) throw new Error('Optional Dependencies [fs-extra, unzipper, archiver] are required to use RemoteAuth. Make sure to run npm install correctly and remove the --no-optional flag');
|
29
|
+
super();
|
30
|
+
|
31
|
+
const idRegex = /^[-_\w]+$/i;
|
32
|
+
if (clientId && !idRegex.test(clientId)) {
|
33
|
+
throw new Error('Invalid clientId. Only alphanumeric characters, underscores and hyphens are allowed.');
|
34
|
+
}
|
35
|
+
if (!backupSyncIntervalMs || backupSyncIntervalMs < 60000) {
|
36
|
+
throw new Error('Invalid backupSyncIntervalMs. Accepts values starting from 60000ms {1 minute}.');
|
37
|
+
}
|
38
|
+
if(!store) throw new Error('Remote database store is required.');
|
39
|
+
|
40
|
+
this.store = store;
|
41
|
+
this.clientId = clientId;
|
42
|
+
this.backupSyncIntervalMs = backupSyncIntervalMs;
|
43
|
+
this.dataPath = path.resolve(dataPath || './.wwebjs_auth/');
|
44
|
+
this.tempDir = `${this.dataPath}/wwebjs_temp_session_${this.clientId}`;
|
45
|
+
this.requiredDirs = ['Default', 'IndexedDB', 'Local Storage']; /* => Required Files & Dirs in WWebJS to restore session */
|
46
|
+
}
|
47
|
+
|
48
|
+
async beforeBrowserInitialized() {
|
49
|
+
const puppeteerOpts = this.client.options.puppeteer;
|
50
|
+
const sessionDirName = this.clientId ? `RemoteAuth-${this.clientId}` : 'RemoteAuth';
|
51
|
+
const dirPath = path.join(this.dataPath, sessionDirName);
|
52
|
+
|
53
|
+
if (puppeteerOpts.userDataDir && puppeteerOpts.userDataDir !== dirPath) {
|
54
|
+
throw new Error('RemoteAuth is not compatible with a user-supplied userDataDir.');
|
55
|
+
}
|
56
|
+
|
57
|
+
this.userDataDir = dirPath;
|
58
|
+
this.sessionName = sessionDirName;
|
59
|
+
|
60
|
+
await this.extractRemoteSession();
|
61
|
+
|
62
|
+
this.client.options.puppeteer = {
|
63
|
+
...puppeteerOpts,
|
64
|
+
userDataDir: dirPath
|
65
|
+
};
|
66
|
+
}
|
67
|
+
|
68
|
+
async logout() {
|
69
|
+
await this.disconnect();
|
70
|
+
}
|
71
|
+
|
72
|
+
async destroy() {
|
73
|
+
clearInterval(this.backupSync);
|
74
|
+
}
|
75
|
+
|
76
|
+
async disconnect() {
|
77
|
+
await this.deleteRemoteSession();
|
78
|
+
|
79
|
+
let pathExists = await this.isValidPath(this.userDataDir);
|
80
|
+
if (pathExists) {
|
81
|
+
await fs.promises.rm(this.userDataDir, {
|
82
|
+
recursive: true,
|
83
|
+
force: true
|
84
|
+
}).catch(() => {});
|
85
|
+
}
|
86
|
+
clearInterval(this.backupSync);
|
87
|
+
}
|
88
|
+
|
89
|
+
async afterAuthReady() {
|
90
|
+
const sessionExists = await this.store.sessionExists({session: this.sessionName});
|
91
|
+
if(!sessionExists) {
|
92
|
+
await this.delay(60000); /* Initial delay sync required for session to be stable enough to recover */
|
93
|
+
await this.storeRemoteSession({emit: true});
|
94
|
+
}
|
95
|
+
var self = this;
|
96
|
+
this.backupSync = setInterval(async function () {
|
97
|
+
await self.storeRemoteSession();
|
98
|
+
}, this.backupSyncIntervalMs);
|
99
|
+
}
|
100
|
+
|
101
|
+
async storeRemoteSession(options) {
|
102
|
+
/* Compress & Store Session */
|
103
|
+
const pathExists = await this.isValidPath(this.userDataDir);
|
104
|
+
if (pathExists) {
|
105
|
+
await this.compressSession();
|
106
|
+
await this.store.save({session: this.sessionName});
|
107
|
+
await fs.promises.unlink(`${this.sessionName}.zip`);
|
108
|
+
await fs.promises.rm(`${this.tempDir}`, {
|
109
|
+
recursive: true,
|
110
|
+
force: true
|
111
|
+
}).catch(() => {});
|
112
|
+
if(options && options.emit) this.client.emit(Events.REMOTE_SESSION_SAVED);
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
116
|
+
async extractRemoteSession() {
|
117
|
+
const pathExists = await this.isValidPath(this.userDataDir);
|
118
|
+
const compressedSessionPath = `${this.sessionName}.zip`;
|
119
|
+
const sessionExists = await this.store.sessionExists({session: this.sessionName});
|
120
|
+
if (pathExists) {
|
121
|
+
await fs.promises.rm(this.userDataDir, {
|
122
|
+
recursive: true,
|
123
|
+
force: true
|
124
|
+
}).catch(() => {});
|
125
|
+
}
|
126
|
+
if (sessionExists) {
|
127
|
+
await this.store.extract({session: this.sessionName, path: compressedSessionPath});
|
128
|
+
await this.unCompressSession(compressedSessionPath);
|
129
|
+
} else {
|
130
|
+
fs.mkdirSync(this.userDataDir, { recursive: true });
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
async deleteRemoteSession() {
|
135
|
+
const sessionExists = await this.store.sessionExists({session: this.sessionName});
|
136
|
+
if (sessionExists) await this.store.delete({session: this.sessionName});
|
137
|
+
}
|
138
|
+
|
139
|
+
async compressSession() {
|
140
|
+
const archive = archiver('zip');
|
141
|
+
const stream = fs.createWriteStream(`${this.sessionName}.zip`);
|
142
|
+
|
143
|
+
await fs.copy(this.userDataDir, this.tempDir).catch(() => {});
|
144
|
+
await this.deleteMetadata();
|
145
|
+
return new Promise((resolve, reject) => {
|
146
|
+
archive
|
147
|
+
.directory(this.tempDir, false)
|
148
|
+
.on('error', err => reject(err))
|
149
|
+
.pipe(stream);
|
150
|
+
|
151
|
+
stream.on('close', () => resolve());
|
152
|
+
archive.finalize();
|
153
|
+
});
|
154
|
+
}
|
155
|
+
|
156
|
+
async unCompressSession(compressedSessionPath) {
|
157
|
+
var stream = fs.createReadStream(compressedSessionPath);
|
158
|
+
await new Promise((resolve, reject) => {
|
159
|
+
stream.pipe(unzipper.Extract({
|
160
|
+
path: this.userDataDir
|
161
|
+
}))
|
162
|
+
.on('error', err => reject(err))
|
163
|
+
.on('finish', () => resolve());
|
164
|
+
});
|
165
|
+
await fs.promises.unlink(compressedSessionPath);
|
166
|
+
}
|
167
|
+
|
168
|
+
async deleteMetadata() {
|
169
|
+
const sessionDirs = [this.tempDir, path.join(this.tempDir, 'Default')];
|
170
|
+
for (const dir of sessionDirs) {
|
171
|
+
const sessionFiles = await fs.promises.readdir(dir);
|
172
|
+
for (const element of sessionFiles) {
|
173
|
+
if (!this.requiredDirs.includes(element)) {
|
174
|
+
const dirElement = path.join(dir, element);
|
175
|
+
const stats = await fs.promises.lstat(dirElement);
|
176
|
+
|
177
|
+
if (stats.isDirectory()) {
|
178
|
+
await fs.promises.rm(dirElement, {
|
179
|
+
recursive: true,
|
180
|
+
force: true
|
181
|
+
}).catch(() => {});
|
182
|
+
} else {
|
183
|
+
await fs.promises.unlink(dirElement).catch(() => {});
|
184
|
+
}
|
185
|
+
}
|
186
|
+
}
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
async isValidPath(path) {
|
191
|
+
try {
|
192
|
+
await fs.promises.access(path);
|
193
|
+
return true;
|
194
|
+
} catch {
|
195
|
+
return false;
|
196
|
+
}
|
197
|
+
}
|
198
|
+
|
199
|
+
async delay(ms) {
|
200
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
module.exports = RemoteAuth;
|
@@ -0,0 +1,16 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const PrivateChat = require('../structures/PrivateChat');
|
4
|
+
const GroupChat = require('../structures/GroupChat');
|
5
|
+
|
6
|
+
class ChatFactory {
|
7
|
+
static create(client, data) {
|
8
|
+
if(data.isGroup) {
|
9
|
+
return new GroupChat(client, data);
|
10
|
+
}
|
11
|
+
|
12
|
+
return new PrivateChat(client, data);
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
module.exports = ChatFactory;
|
@@ -0,0 +1,16 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const PrivateContact = require('../structures/PrivateContact');
|
4
|
+
const BusinessContact = require('../structures/BusinessContact');
|
5
|
+
|
6
|
+
class ContactFactory {
|
7
|
+
static create(client, data) {
|
8
|
+
if(data.isBusiness) {
|
9
|
+
return new BusinessContact(client, data);
|
10
|
+
}
|
11
|
+
|
12
|
+
return new PrivateContact(client, data);
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
module.exports = ContactFactory;
|
@@ -0,0 +1,22 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Represents a WhatsApp data structure
|
5
|
+
*/
|
6
|
+
class Base {
|
7
|
+
constructor(client) {
|
8
|
+
/**
|
9
|
+
* The client that instantiated this
|
10
|
+
* @readonly
|
11
|
+
*/
|
12
|
+
Object.defineProperty(this, 'client', { value: client });
|
13
|
+
}
|
14
|
+
|
15
|
+
_clone() {
|
16
|
+
return Object.assign(Object.create(this), this);
|
17
|
+
}
|
18
|
+
|
19
|
+
_patch(data) { return data; }
|
20
|
+
}
|
21
|
+
|
22
|
+
module.exports = Base;
|
@@ -0,0 +1,21 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const Contact = require('./Contact');
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Represents a Business Contact on WhatsApp
|
7
|
+
* @extends {Contact}
|
8
|
+
*/
|
9
|
+
class BusinessContact extends Contact {
|
10
|
+
_patch(data) {
|
11
|
+
/**
|
12
|
+
* The contact's business profile
|
13
|
+
*/
|
14
|
+
this.businessProfile = data.businessProfile;
|
15
|
+
|
16
|
+
return super._patch(data);
|
17
|
+
}
|
18
|
+
|
19
|
+
}
|
20
|
+
|
21
|
+
module.exports = BusinessContact;
|
@@ -0,0 +1,82 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const MessageMedia = require('./MessageMedia');
|
4
|
+
const Util = require('../util/Util');
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Button spec used in Buttons constructor
|
8
|
+
* @typedef {Object} ButtonSpec
|
9
|
+
* @property {string=} id - Custom ID to set on the button. A random one will be generated if one is not passed.
|
10
|
+
* @property {string} body - The text to show on the button.
|
11
|
+
*/
|
12
|
+
|
13
|
+
/**
|
14
|
+
* @typedef {Object} FormattedButtonSpec
|
15
|
+
* @property {string} buttonId
|
16
|
+
* @property {number} type
|
17
|
+
* @property {Object} buttonText
|
18
|
+
*/
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Message type buttons
|
22
|
+
*/
|
23
|
+
class Buttons {
|
24
|
+
/**
|
25
|
+
* @param {string|MessageMedia} body
|
26
|
+
* @param {ButtonSpec[]} buttons - See {@link ButtonSpec}
|
27
|
+
* @param {string?} title
|
28
|
+
* @param {string?} footer
|
29
|
+
*/
|
30
|
+
constructor(body, buttons, title, footer) {
|
31
|
+
/**
|
32
|
+
* Message body
|
33
|
+
* @type {string|MessageMedia}
|
34
|
+
*/
|
35
|
+
this.body = body;
|
36
|
+
|
37
|
+
/**
|
38
|
+
* title of message
|
39
|
+
* @type {string}
|
40
|
+
*/
|
41
|
+
this.title = title;
|
42
|
+
|
43
|
+
/**
|
44
|
+
* footer of message
|
45
|
+
* @type {string}
|
46
|
+
*/
|
47
|
+
this.footer = footer;
|
48
|
+
|
49
|
+
if (body instanceof MessageMedia) {
|
50
|
+
this.type = 'media';
|
51
|
+
this.title = '';
|
52
|
+
}else{
|
53
|
+
this.type = 'chat';
|
54
|
+
}
|
55
|
+
|
56
|
+
/**
|
57
|
+
* buttons of message
|
58
|
+
* @type {FormattedButtonSpec[]}
|
59
|
+
*/
|
60
|
+
this.buttons = this._format(buttons);
|
61
|
+
if(!this.buttons.length){ throw '[BT01] No buttons';}
|
62
|
+
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Creates button array from simple array
|
67
|
+
* @param {ButtonSpec[]} buttons
|
68
|
+
* @returns {FormattedButtonSpec[]}
|
69
|
+
* @example
|
70
|
+
* Input: [{id:'customId',body:'button1'},{body:'button2'},{body:'button3'},{body:'button4'}]
|
71
|
+
* Returns: [{ buttonId:'customId',buttonText:{'displayText':'button1'},type: 1 },{buttonId:'n3XKsL',buttonText:{'displayText':'button2'},type:1},{buttonId:'NDJk0a',buttonText:{'displayText':'button3'},type:1}]
|
72
|
+
*/
|
73
|
+
_format(buttons){
|
74
|
+
buttons = buttons.slice(0,3); // phone users can only see 3 buttons, so lets limit this
|
75
|
+
return buttons.map((btn) => {
|
76
|
+
return {'buttonId':btn.id ? String(btn.id) : Util.generateHash(6),'buttonText':{'displayText':btn.body},'type':1};
|
77
|
+
});
|
78
|
+
}
|
79
|
+
|
80
|
+
}
|
81
|
+
|
82
|
+
module.exports = Buttons;
|
@@ -0,0 +1,76 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const Base = require('./Base');
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Represents a Call on WhatsApp
|
7
|
+
* @extends {Base}
|
8
|
+
*/
|
9
|
+
class Call extends Base {
|
10
|
+
constructor(client, data) {
|
11
|
+
super(client);
|
12
|
+
|
13
|
+
if (data) this._patch(data);
|
14
|
+
}
|
15
|
+
|
16
|
+
_patch(data) {
|
17
|
+
/**
|
18
|
+
* Call ID
|
19
|
+
* @type {string}
|
20
|
+
*/
|
21
|
+
this.id = data.id;
|
22
|
+
/**
|
23
|
+
* From
|
24
|
+
* @type {string}
|
25
|
+
*/
|
26
|
+
this.from = data.peerJid;
|
27
|
+
/**
|
28
|
+
* Unix timestamp for when the call was created
|
29
|
+
* @type {number}
|
30
|
+
*/
|
31
|
+
this.timestamp = data.offerTime;
|
32
|
+
/**
|
33
|
+
* Is video
|
34
|
+
* @type {boolean}
|
35
|
+
*/
|
36
|
+
this.isVideo = data.isVideo;
|
37
|
+
/**
|
38
|
+
* Is Group
|
39
|
+
* @type {boolean}
|
40
|
+
*/
|
41
|
+
this.isGroup = data.isGroup;
|
42
|
+
/**
|
43
|
+
* Indicates if the call was sent by the current user
|
44
|
+
* @type {boolean}
|
45
|
+
*/
|
46
|
+
this.fromMe = data.outgoing;
|
47
|
+
/**
|
48
|
+
* Indicates if the call can be handled in waweb
|
49
|
+
* @type {boolean}
|
50
|
+
*/
|
51
|
+
this.canHandleLocally = data.canHandleLocally;
|
52
|
+
/**
|
53
|
+
* Indicates if the call Should be handled in waweb
|
54
|
+
* @type {boolean}
|
55
|
+
*/
|
56
|
+
this.webClientShouldHandle = data.webClientShouldHandle;
|
57
|
+
/**
|
58
|
+
* Object with participants
|
59
|
+
* @type {object}
|
60
|
+
*/
|
61
|
+
this.participants = data.participants;
|
62
|
+
|
63
|
+
return super._patch(data);
|
64
|
+
}
|
65
|
+
|
66
|
+
/**
|
67
|
+
* Reject the call
|
68
|
+
*/
|
69
|
+
async reject() {
|
70
|
+
return this.client.pupPage.evaluate((peerJid, id) => {
|
71
|
+
return window.WWebJS.rejectCall(peerJid, id);
|
72
|
+
}, this.from, this.id);
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
module.exports = Call;
|