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,111 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const fs = require('fs');
|
4
|
+
const path = require('path');
|
5
|
+
const mime = require('mime');
|
6
|
+
const fetch = require('node-fetch');
|
7
|
+
const { URL } = require('url');
|
8
|
+
|
9
|
+
/**
|
10
|
+
* Media attached to a message
|
11
|
+
* @param {string} mimetype MIME type of the attachment
|
12
|
+
* @param {string} data Base64-encoded data of the file
|
13
|
+
* @param {?string} filename Document file name. Value can be null
|
14
|
+
* @param {?number} filesize Document file size in bytes. Value can be null
|
15
|
+
*/
|
16
|
+
class MessageMedia {
|
17
|
+
constructor(mimetype, data, filename, filesize) {
|
18
|
+
/**
|
19
|
+
* MIME type of the attachment
|
20
|
+
* @type {string}
|
21
|
+
*/
|
22
|
+
this.mimetype = mimetype;
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Base64 encoded data that represents the file
|
26
|
+
* @type {string}
|
27
|
+
*/
|
28
|
+
this.data = data;
|
29
|
+
|
30
|
+
/**
|
31
|
+
* Document file name. Value can be null
|
32
|
+
* @type {?string}
|
33
|
+
*/
|
34
|
+
this.filename = filename;
|
35
|
+
|
36
|
+
/**
|
37
|
+
* Document file size in bytes. Value can be null
|
38
|
+
* @type {?number}
|
39
|
+
*/
|
40
|
+
this.filesize = filesize;
|
41
|
+
}
|
42
|
+
|
43
|
+
/**
|
44
|
+
* Creates a MessageMedia instance from a local file path
|
45
|
+
* @param {string} filePath
|
46
|
+
* @returns {MessageMedia}
|
47
|
+
*/
|
48
|
+
static fromFilePath(filePath) {
|
49
|
+
const b64data = fs.readFileSync(filePath, {encoding: 'base64'});
|
50
|
+
const mimetype = mime.getType(filePath);
|
51
|
+
const filename = path.basename(filePath);
|
52
|
+
|
53
|
+
return new MessageMedia(mimetype, b64data, filename);
|
54
|
+
}
|
55
|
+
|
56
|
+
/**
|
57
|
+
* Creates a MessageMedia instance from a URL
|
58
|
+
* @param {string} url
|
59
|
+
* @param {Object} [options]
|
60
|
+
* @param {boolean} [options.unsafeMime=false]
|
61
|
+
* @param {string} [options.filename]
|
62
|
+
* @param {object} [options.client]
|
63
|
+
* @param {object} [options.reqOptions]
|
64
|
+
* @param {number} [options.reqOptions.size=0]
|
65
|
+
* @returns {Promise<MessageMedia>}
|
66
|
+
*/
|
67
|
+
static async fromUrl(url, options = {}) {
|
68
|
+
const pUrl = new URL(url);
|
69
|
+
let mimetype = mime.getType(pUrl.pathname);
|
70
|
+
|
71
|
+
if (!mimetype && !options.unsafeMime)
|
72
|
+
throw new Error('Unable to determine MIME type using URL. Set unsafeMime to true to download it anyway.');
|
73
|
+
|
74
|
+
async function fetchData (url, options) {
|
75
|
+
const reqOptions = Object.assign({ headers: { accept: 'image/* video/* text/* audio/*' } }, options);
|
76
|
+
const response = await fetch(url, reqOptions);
|
77
|
+
const mime = response.headers.get('Content-Type');
|
78
|
+
const size = response.headers.get('Content-Length');
|
79
|
+
|
80
|
+
const contentDisposition = response.headers.get('Content-Disposition');
|
81
|
+
const name = contentDisposition ? contentDisposition.match(/((?<=filename=")(.*)(?="))/) : null;
|
82
|
+
|
83
|
+
let data = '';
|
84
|
+
if (response.buffer) {
|
85
|
+
data = (await response.buffer()).toString('base64');
|
86
|
+
} else {
|
87
|
+
const bArray = new Uint8Array(await response.arrayBuffer());
|
88
|
+
bArray.forEach((b) => {
|
89
|
+
data += String.fromCharCode(b);
|
90
|
+
});
|
91
|
+
data = btoa(data);
|
92
|
+
}
|
93
|
+
|
94
|
+
return { data, mime, name, size };
|
95
|
+
}
|
96
|
+
|
97
|
+
const res = options.client
|
98
|
+
? (await options.client.pupPage.evaluate(fetchData, url, options.reqOptions))
|
99
|
+
: (await fetchData(url, options.reqOptions));
|
100
|
+
|
101
|
+
const filename = options.filename ||
|
102
|
+
(res.name ? res.name[0] : (pUrl.pathname.split('/').pop() || 'file'));
|
103
|
+
|
104
|
+
if (!mimetype)
|
105
|
+
mimetype = res.mime;
|
106
|
+
|
107
|
+
return new MessageMedia(mimetype, res.data, filename, res.size || null);
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
module.exports = MessageMedia;
|
@@ -0,0 +1,52 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const Base = require('./Base');
|
4
|
+
const Product = require('./Product');
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Represents a Order on WhatsApp
|
8
|
+
* @extends {Base}
|
9
|
+
*/
|
10
|
+
class Order extends Base {
|
11
|
+
constructor(client, data) {
|
12
|
+
super(client);
|
13
|
+
|
14
|
+
if (data) this._patch(data);
|
15
|
+
}
|
16
|
+
|
17
|
+
_patch(data) {
|
18
|
+
/**
|
19
|
+
* List of products
|
20
|
+
* @type {Array<Product>}
|
21
|
+
*/
|
22
|
+
if (data.products) {
|
23
|
+
this.products = data.products.map(product => new Product(this.client, product));
|
24
|
+
}
|
25
|
+
/**
|
26
|
+
* Order Subtotal
|
27
|
+
* @type {string}
|
28
|
+
*/
|
29
|
+
this.subtotal = data.subtotal;
|
30
|
+
/**
|
31
|
+
* Order Total
|
32
|
+
* @type {string}
|
33
|
+
*/
|
34
|
+
this.total = data.total;
|
35
|
+
/**
|
36
|
+
* Order Currency
|
37
|
+
* @type {string}
|
38
|
+
*/
|
39
|
+
this.currency = data.currency;
|
40
|
+
/**
|
41
|
+
* Order Created At
|
42
|
+
* @type {number}
|
43
|
+
*/
|
44
|
+
this.createdAt = data.createdAt;
|
45
|
+
|
46
|
+
return super._patch(data);
|
47
|
+
}
|
48
|
+
|
49
|
+
|
50
|
+
}
|
51
|
+
|
52
|
+
module.exports = Order;
|
@@ -0,0 +1,79 @@
|
|
1
|
+
const Base = require('./Base');
|
2
|
+
|
3
|
+
class Payment extends Base {
|
4
|
+
constructor(client, data) {
|
5
|
+
super(client);
|
6
|
+
|
7
|
+
if (data) this._patch(data);
|
8
|
+
}
|
9
|
+
|
10
|
+
_patch(data) {
|
11
|
+
/**
|
12
|
+
* The payment Id
|
13
|
+
* @type {object}
|
14
|
+
*/
|
15
|
+
this.id = data.id;
|
16
|
+
|
17
|
+
/**
|
18
|
+
* The payment currency
|
19
|
+
* @type {string}
|
20
|
+
*/
|
21
|
+
this.paymentCurrency = data.paymentCurrency;
|
22
|
+
|
23
|
+
/**
|
24
|
+
* The payment ammount ( R$ 1.00 = 1000 )
|
25
|
+
* @type {number}
|
26
|
+
*/
|
27
|
+
this.paymentAmount1000 = data.paymentAmount1000;
|
28
|
+
|
29
|
+
/**
|
30
|
+
* The payment receiver
|
31
|
+
* @type {object}
|
32
|
+
*/
|
33
|
+
this.paymentMessageReceiverJid = data.paymentMessageReceiverJid;
|
34
|
+
|
35
|
+
/**
|
36
|
+
* The payment transaction timestamp
|
37
|
+
* @type {number}
|
38
|
+
*/
|
39
|
+
this.paymentTransactionTimestamp = data.paymentTransactionTimestamp;
|
40
|
+
|
41
|
+
/**
|
42
|
+
* The paymentStatus
|
43
|
+
*
|
44
|
+
* Possible Status
|
45
|
+
* 0:UNKNOWN_STATUS
|
46
|
+
* 1:PROCESSING
|
47
|
+
* 2:SENT
|
48
|
+
* 3:NEED_TO_ACCEPT
|
49
|
+
* 4:COMPLETE
|
50
|
+
* 5:COULD_NOT_COMPLETE
|
51
|
+
* 6:REFUNDED
|
52
|
+
* 7:EXPIRED
|
53
|
+
* 8:REJECTED
|
54
|
+
* 9:CANCELLED
|
55
|
+
* 10:WAITING_FOR_PAYER
|
56
|
+
* 11:WAITING
|
57
|
+
*
|
58
|
+
* @type {number}
|
59
|
+
*/
|
60
|
+
this.paymentStatus = data.paymentStatus;
|
61
|
+
|
62
|
+
/**
|
63
|
+
* Integer that represents the payment Text
|
64
|
+
* @type {number}
|
65
|
+
*/
|
66
|
+
this.paymentTxnStatus = data.paymentTxnStatus;
|
67
|
+
|
68
|
+
/**
|
69
|
+
* The note sent with the payment
|
70
|
+
* @type {string}
|
71
|
+
*/
|
72
|
+
this.paymentNote = !data.paymentNoteMsg ? undefined : data.paymentNoteMsg.body ? data.paymentNoteMsg.body : undefined ;
|
73
|
+
|
74
|
+
return super._patch(data);
|
75
|
+
}
|
76
|
+
|
77
|
+
}
|
78
|
+
|
79
|
+
module.exports = Payment;
|
@@ -0,0 +1,44 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Poll send options
|
5
|
+
* @typedef {Object} PollSendOptions
|
6
|
+
* @property {boolean} [allowMultipleAnswers=false] If false it is a single choice poll, otherwise it is a multiple choice poll (false by default)
|
7
|
+
* @property {?Array<number>} messageSecret The custom message secret, can be used as a poll ID. NOTE: it has to be a unique vector with a length of 32
|
8
|
+
*/
|
9
|
+
|
10
|
+
/** Represents a Poll on WhatsApp */
|
11
|
+
class Poll {
|
12
|
+
/**
|
13
|
+
* @param {string} pollName
|
14
|
+
* @param {Array<string>} pollOptions
|
15
|
+
* @param {PollSendOptions} options
|
16
|
+
*/
|
17
|
+
constructor(pollName, pollOptions, options = {}) {
|
18
|
+
/**
|
19
|
+
* The name of the poll
|
20
|
+
* @type {string}
|
21
|
+
*/
|
22
|
+
this.pollName = pollName.trim();
|
23
|
+
|
24
|
+
/**
|
25
|
+
* The array of poll options
|
26
|
+
* @type {Array.<{name: string, localId: number}>}
|
27
|
+
*/
|
28
|
+
this.pollOptions = pollOptions.map((option, index) => ({
|
29
|
+
name: option.trim(),
|
30
|
+
localId: index
|
31
|
+
}));
|
32
|
+
|
33
|
+
/**
|
34
|
+
* The send options for the poll
|
35
|
+
* @type {PollSendOptions}
|
36
|
+
*/
|
37
|
+
this.options = {
|
38
|
+
allowMultipleAnswers: options.allowMultipleAnswers === true,
|
39
|
+
messageSecret: options.messageSecret
|
40
|
+
};
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
module.exports = Poll;
|
@@ -0,0 +1,61 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const Message = require('./Message');
|
4
|
+
const Base = require('./Base');
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Selected poll option structure
|
8
|
+
* @typedef {Object} SelectedPollOption
|
9
|
+
* @property {number} id The local selected or deselected option ID
|
10
|
+
* @property {string} name The option name
|
11
|
+
*/
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Represents a Poll Vote on WhatsApp
|
15
|
+
* @extends {Base}
|
16
|
+
*/
|
17
|
+
class PollVote extends Base {
|
18
|
+
constructor(client, data) {
|
19
|
+
super(client);
|
20
|
+
|
21
|
+
if (data) this._patch(data);
|
22
|
+
}
|
23
|
+
|
24
|
+
_patch(data) {
|
25
|
+
/**
|
26
|
+
* The person who voted
|
27
|
+
* @type {string}
|
28
|
+
*/
|
29
|
+
this.voter = data.sender;
|
30
|
+
|
31
|
+
/**
|
32
|
+
* The selected poll option(s)
|
33
|
+
* If it's an empty array, the user hasn't selected any options on the poll,
|
34
|
+
* may occur when they deselected all poll options
|
35
|
+
* @type {SelectedPollOption[]}
|
36
|
+
*/
|
37
|
+
this.selectedOptions =
|
38
|
+
data.selectedOptionLocalIds.length > 0
|
39
|
+
? data.selectedOptionLocalIds.map((e) => ({
|
40
|
+
name: data.parentMessage.pollOptions.find((x) => x.localId === e).name,
|
41
|
+
localId: e
|
42
|
+
}))
|
43
|
+
: [];
|
44
|
+
|
45
|
+
/**
|
46
|
+
* Timestamp the option was selected or deselected at
|
47
|
+
* @type {number}
|
48
|
+
*/
|
49
|
+
this.interractedAtTs = data.senderTimestampMs;
|
50
|
+
|
51
|
+
/**
|
52
|
+
* The poll creation message associated with the poll vote
|
53
|
+
* @type {Message}
|
54
|
+
*/
|
55
|
+
this.parentMessage = new Message(this.client, data.parentMessage);
|
56
|
+
|
57
|
+
return super._patch(data);
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
module.exports = PollVote;
|
@@ -0,0 +1,68 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const Base = require('./Base');
|
4
|
+
const ProductMetadata = require('./ProductMetadata');
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Represents a Product on WhatsAppBusiness
|
8
|
+
* @extends {Base}
|
9
|
+
*/
|
10
|
+
class Product extends Base {
|
11
|
+
constructor(client, data) {
|
12
|
+
super(client);
|
13
|
+
|
14
|
+
if (data) this._patch(data);
|
15
|
+
}
|
16
|
+
|
17
|
+
_patch(data) {
|
18
|
+
/**
|
19
|
+
* Product ID
|
20
|
+
* @type {string}
|
21
|
+
*/
|
22
|
+
this.id = data.id;
|
23
|
+
/**
|
24
|
+
* Price
|
25
|
+
* @type {string}
|
26
|
+
*/
|
27
|
+
this.price = data.price ? data.price : '';
|
28
|
+
/**
|
29
|
+
* Product Thumbnail
|
30
|
+
* @type {string}
|
31
|
+
*/
|
32
|
+
this.thumbnailUrl = data.thumbnailUrl;
|
33
|
+
/**
|
34
|
+
* Currency
|
35
|
+
* @type {string}
|
36
|
+
*/
|
37
|
+
this.currency = data.currency;
|
38
|
+
/**
|
39
|
+
* Product Name
|
40
|
+
* @type {string}
|
41
|
+
*/
|
42
|
+
this.name = data.name;
|
43
|
+
/**
|
44
|
+
* Product Quantity
|
45
|
+
* @type {number}
|
46
|
+
*/
|
47
|
+
this.quantity = data.quantity;
|
48
|
+
/** Product metadata */
|
49
|
+
this.data = null;
|
50
|
+
return super._patch(data);
|
51
|
+
}
|
52
|
+
|
53
|
+
async getData() {
|
54
|
+
if (this.data === null) {
|
55
|
+
let result = await this.client.pupPage.evaluate((productId) => {
|
56
|
+
return window.WWebJS.getProductMetadata(productId);
|
57
|
+
}, this.id);
|
58
|
+
if (!result) {
|
59
|
+
this.data = undefined;
|
60
|
+
} else {
|
61
|
+
this.data = new ProductMetadata(this.client, result);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
return this.data;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
module.exports = Product;
|
@@ -0,0 +1,25 @@
|
|
1
|
+
const Base = require('./Base');
|
2
|
+
|
3
|
+
class ProductMetadata extends Base {
|
4
|
+
constructor(client, data) {
|
5
|
+
super(client);
|
6
|
+
|
7
|
+
if (data) this._patch(data);
|
8
|
+
}
|
9
|
+
|
10
|
+
_patch(data) {
|
11
|
+
/** Product ID */
|
12
|
+
this.id = data.id;
|
13
|
+
/** Retailer ID */
|
14
|
+
this.retailer_id = data.retailer_id;
|
15
|
+
/** Product Name */
|
16
|
+
this.name = data.name;
|
17
|
+
/** Product Description */
|
18
|
+
this.description = data.description;
|
19
|
+
|
20
|
+
return super._patch(data);
|
21
|
+
}
|
22
|
+
|
23
|
+
}
|
24
|
+
|
25
|
+
module.exports = ProductMetadata;
|
@@ -0,0 +1,69 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const Base = require('./Base');
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Represents a Reaction on WhatsApp
|
7
|
+
* @extends {Base}
|
8
|
+
*/
|
9
|
+
class Reaction extends Base {
|
10
|
+
constructor(client, data) {
|
11
|
+
super(client);
|
12
|
+
|
13
|
+
if (data) this._patch(data);
|
14
|
+
}
|
15
|
+
|
16
|
+
_patch(data) {
|
17
|
+
/**
|
18
|
+
* Reaction ID
|
19
|
+
* @type {object}
|
20
|
+
*/
|
21
|
+
this.id = data.msgKey;
|
22
|
+
/**
|
23
|
+
* Orphan
|
24
|
+
* @type {number}
|
25
|
+
*/
|
26
|
+
this.orphan = data.orphan;
|
27
|
+
/**
|
28
|
+
* Orphan reason
|
29
|
+
* @type {?string}
|
30
|
+
*/
|
31
|
+
this.orphanReason = data.orphanReason;
|
32
|
+
/**
|
33
|
+
* Unix timestamp for when the reaction was created
|
34
|
+
* @type {number}
|
35
|
+
*/
|
36
|
+
this.timestamp = data.timestamp;
|
37
|
+
/**
|
38
|
+
* Reaction
|
39
|
+
* @type {string}
|
40
|
+
*/
|
41
|
+
this.reaction = data.reactionText;
|
42
|
+
/**
|
43
|
+
* Read
|
44
|
+
* @type {boolean}
|
45
|
+
*/
|
46
|
+
this.read = data.read;
|
47
|
+
/**
|
48
|
+
* Message ID
|
49
|
+
* @type {object}
|
50
|
+
*/
|
51
|
+
this.msgId = data.parentMsgKey;
|
52
|
+
/**
|
53
|
+
* Sender ID
|
54
|
+
* @type {string}
|
55
|
+
*/
|
56
|
+
this.senderId = data.senderUserJid;
|
57
|
+
/**
|
58
|
+
* ACK
|
59
|
+
* @type {?number}
|
60
|
+
*/
|
61
|
+
this.ack = data.ack;
|
62
|
+
|
63
|
+
|
64
|
+
return super._patch(data);
|
65
|
+
}
|
66
|
+
|
67
|
+
}
|
68
|
+
|
69
|
+
module.exports = Reaction;
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module.exports = {
|
2
|
+
Base: require('./Base'),
|
3
|
+
BusinessContact: require('./BusinessContact'),
|
4
|
+
Chat: require('./Chat'),
|
5
|
+
ClientInfo: require('./ClientInfo'),
|
6
|
+
Contact: require('./Contact'),
|
7
|
+
GroupChat: require('./GroupChat'),
|
8
|
+
Location: require('./Location'),
|
9
|
+
Message: require('./Message'),
|
10
|
+
MessageMedia: require('./MessageMedia'),
|
11
|
+
PrivateChat: require('./PrivateChat'),
|
12
|
+
PrivateContact: require('./PrivateContact'),
|
13
|
+
GroupNotification: require('./GroupNotification'),
|
14
|
+
Label: require('./Label.js'),
|
15
|
+
Order: require('./Order'),
|
16
|
+
Product: require('./Product'),
|
17
|
+
Call: require('./Call'),
|
18
|
+
Buttons: require('./Buttons'),
|
19
|
+
List: require('./List'),
|
20
|
+
Payment: require('./Payment'),
|
21
|
+
Reaction: require('./Reaction'),
|
22
|
+
Poll: require('./Poll'),
|
23
|
+
PollVote: require('./PollVote')
|
24
|
+
};
|