mirror of
https://github.com/cheveguerra/whatsapp-web.js.git
synced 2026-04-18 19:49:16 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c55fbf2ca | ||
|
|
6b1b51eacd | ||
|
|
2dc53e0820 | ||
|
|
9043e61c40 | ||
|
|
bea1ebf480 | ||
|
|
021a213de3 | ||
|
|
d0bef55b8a | ||
|
|
64912dccfd | ||
|
|
dfcf76c139 | ||
|
|
512b21e522 | ||
|
|
8babc97788 | ||
|
|
bf177ca1d4 | ||
|
|
46a7d025fe | ||
|
|
517e22381a | ||
|
|
18199d8120 | ||
|
|
cde0034d93 | ||
|
|
cdfa1760eb | ||
|
|
cf8c54879e | ||
|
|
b2a1e9368a |
20
.github/stale.yml
vendored
Normal file
20
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Number of days of inactivity before an issue becomes stale
|
||||||
|
daysUntilStale: 30
|
||||||
|
# Number of days of inactivity before a stale issue is closed
|
||||||
|
daysUntilClose: 7
|
||||||
|
# Issues with these labels will never be considered stale
|
||||||
|
exemptLabels:
|
||||||
|
- pinned
|
||||||
|
- security
|
||||||
|
- enhancement
|
||||||
|
- bug
|
||||||
|
- WhatsApp Change
|
||||||
|
# Label to use when marking an issue as stale
|
||||||
|
staleLabel: stale
|
||||||
|
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||||
|
markComment: >
|
||||||
|
This issue has been automatically marked as stale because it has not had
|
||||||
|
recent activity. It will be closed if no further activity occurs. Thank you
|
||||||
|
for your contributions.
|
||||||
|
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||||
|
closeComment: false
|
||||||
18
example.js
18
example.js
@@ -78,9 +78,27 @@ client.on('message', async msg => {
|
|||||||
} else {
|
} else {
|
||||||
msg.reply('This command can only be used in a group!');
|
msg.reply('This command can only be used in a group!');
|
||||||
}
|
}
|
||||||
|
} else if(msg.body == '!chats') {
|
||||||
|
const chats = await client.getChats();
|
||||||
|
client.sendMessage(msg.from, `The bot has ${chats.length} chats open.`);
|
||||||
|
} else if(msg.body == '!mediainfo' && msg.hasMedia) {
|
||||||
|
const attachmentData = await msg.downloadMedia();
|
||||||
|
msg.reply(`
|
||||||
|
*Media info*
|
||||||
|
MimeType: ${attachmentData.mimetype}
|
||||||
|
Filename: ${attachmentData.filename}
|
||||||
|
Data (length): ${attachmentData.data.length}
|
||||||
|
`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
client.on('message_create', (msg) => {
|
||||||
|
// Fired on all message creations, including your own
|
||||||
|
if(msg.fromMe) {
|
||||||
|
// do stuff here
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
client.on('disconnected', () => {
|
client.on('disconnected', () => {
|
||||||
console.log('Client was logged out');
|
console.log('Client was logged out');
|
||||||
})
|
})
|
||||||
|
|||||||
85
package-lock.json
generated
85
package-lock.json
generated
@@ -1,21 +1,21 @@
|
|||||||
{
|
{
|
||||||
"name": "whatsapp-web.js",
|
"name": "whatsapp-web.js",
|
||||||
"version": "0.1.1",
|
"version": "0.3.2",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"agent-base": {
|
"agent-base": {
|
||||||
"version": "4.2.1",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
|
||||||
"integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
|
"integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"es6-promisify": "^5.0.0"
|
"es6-promisify": "^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"async-limiter": {
|
"async-limiter": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
|
||||||
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
|
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
|
||||||
},
|
},
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@@ -66,9 +66,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"es6-promise": {
|
"es6-promise": {
|
||||||
"version": "4.2.6",
|
"version": "4.2.8",
|
||||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
|
||||||
"integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q=="
|
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
|
||||||
},
|
},
|
||||||
"es6-promisify": {
|
"es6-promisify": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
@@ -118,9 +118,9 @@
|
|||||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||||
},
|
},
|
||||||
"glob": {
|
"glob": {
|
||||||
"version": "7.1.3",
|
"version": "7.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
|
||||||
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
|
"integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"fs.realpath": "^1.0.0",
|
"fs.realpath": "^1.0.0",
|
||||||
"inflight": "^1.0.4",
|
"inflight": "^1.0.4",
|
||||||
@@ -131,11 +131,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"https-proxy-agent": {
|
"https-proxy-agent": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz",
|
||||||
"integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
|
"integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"agent-base": "^4.1.0",
|
"agent-base": "^4.3.0",
|
||||||
"debug": "^3.1.0"
|
"debug": "^3.1.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -159,19 +159,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
},
|
},
|
||||||
"isarray": {
|
"isarray": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||||
},
|
},
|
||||||
|
"jsqr": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsqr/-/jsqr-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-wKcQS9QC2VHGk7aphWCp1RrFyC0CM6fMgC5prZZ2KV/Lk6OKNoCod9IR6bao+yx3KPY0gZFC5dc+h+KFzCI0Wg=="
|
||||||
|
},
|
||||||
"mime": {
|
"mime": {
|
||||||
"version": "2.4.0",
|
"version": "2.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
|
||||||
"integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w=="
|
"integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
|
||||||
},
|
},
|
||||||
"minimatch": {
|
"minimatch": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
@@ -194,10 +199,14 @@
|
|||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"moduleraid": {
|
||||||
|
"version": "git+https://github.com/pixeldesu/moduleRaid.git#113b90ec709f5d4601db8d5e96b1155aa772ae97",
|
||||||
|
"from": "git+https://github.com/pixeldesu/moduleRaid.git"
|
||||||
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
},
|
},
|
||||||
"once": {
|
"once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
@@ -218,9 +227,9 @@
|
|||||||
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
|
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
|
||||||
},
|
},
|
||||||
"process-nextick-args": {
|
"process-nextick-args": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||||
},
|
},
|
||||||
"progress": {
|
"progress": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
@@ -233,9 +242,9 @@
|
|||||||
"integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4="
|
"integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4="
|
||||||
},
|
},
|
||||||
"puppeteer": {
|
"puppeteer": {
|
||||||
"version": "1.12.2",
|
"version": "1.20.0",
|
||||||
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.12.2.tgz",
|
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.20.0.tgz",
|
||||||
"integrity": "sha512-xWSyCeD6EazGlfnQweMpM+Hs6X6PhUYhNTHKFj/axNZDq4OmrVERf70isBf7HsnFgB3zOC1+23/8+wCAZYg+Pg==",
|
"integrity": "sha512-bt48RDBy2eIwZPrkgbcwHtb51mj2nKvHOPMaSH2IsWiv7lOG9k9zhaRzpDZafrk05ajMc3cu+lSQYYOfH2DkVQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
"extract-zip": "^1.6.6",
|
"extract-zip": "^1.6.6",
|
||||||
@@ -262,9 +271,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rimraf": {
|
"rimraf": {
|
||||||
"version": "2.6.3",
|
"version": "2.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||||
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
|
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"glob": "^7.1.3"
|
"glob": "^7.1.3"
|
||||||
}
|
}
|
||||||
@@ -298,9 +307,9 @@
|
|||||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||||
},
|
},
|
||||||
"ws": {
|
"ws": {
|
||||||
"version": "6.1.4",
|
"version": "6.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
|
||||||
"integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==",
|
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"async-limiter": "~1.0.0"
|
"async-limiter": "~1.0.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "whatsapp-web.js",
|
"name": "whatsapp-web.js",
|
||||||
"version": "0.1.1",
|
"version": "0.3.2",
|
||||||
"description": "Library for interacting with the WhatsApp Web API ",
|
"description": "Library for interacting with the WhatsApp Web API ",
|
||||||
"main": "./index.js",
|
"main": "./index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -25,6 +25,8 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/pedroslopez/whatsapp-web.js#readme",
|
"homepage": "https://github.com/pedroslopez/whatsapp-web.js#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"puppeteer": "^1.12.2"
|
"jsqr": "^1.2.0",
|
||||||
|
"moduleraid": "git+https://github.com/pixeldesu/moduleRaid.git",
|
||||||
|
"puppeteer": "^1.20.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const puppeteer = require('puppeteer');
|
const puppeteer = require('puppeteer');
|
||||||
|
const moduleRaid = require('moduleraid/moduleraid');
|
||||||
|
const jsQR = require('jsqr');
|
||||||
|
|
||||||
const Util = require('./util/Util');
|
const Util = require('./util/Util');
|
||||||
const { WhatsWebURL, UserAgent, DefaultOptions, Events } = require('./util/Constants');
|
const { WhatsWebURL, UserAgent, DefaultOptions, Events, WAState } = require('./util/Constants');
|
||||||
const { ExposeStore, LoadExtraProps, LoadCustomSerializers } = require('./util/Injected');
|
const { ExposeStore, LoadUtils } = require('./util/Injected');
|
||||||
const ChatFactory = require('./factories/ChatFactory');
|
const ChatFactory = require('./factories/ChatFactory');
|
||||||
const Chat = require('./structures/Chat');
|
const Message = require('./structures/Message');
|
||||||
const Message = require('./structures/Message')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starting point for interacting with the WhatsApp Web API
|
* Starting point for interacting with the WhatsApp Web API
|
||||||
@@ -31,27 +33,27 @@ class Client extends EventEmitter {
|
|||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
page.setUserAgent(UserAgent);
|
page.setUserAgent(UserAgent);
|
||||||
|
|
||||||
if(this.options.session) {
|
if (this.options.session) {
|
||||||
await page.evaluateOnNewDocument (
|
await page.evaluateOnNewDocument(
|
||||||
session => {
|
session => {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
localStorage.setItem("WABrowserId", session.WABrowserId);
|
localStorage.setItem("WABrowserId", session.WABrowserId);
|
||||||
localStorage.setItem("WASecretBundle", session.WASecretBundle);
|
localStorage.setItem("WASecretBundle", session.WASecretBundle);
|
||||||
localStorage.setItem("WAToken1", session.WAToken1);
|
localStorage.setItem("WAToken1", session.WAToken1);
|
||||||
localStorage.setItem("WAToken2", session.WAToken2);
|
localStorage.setItem("WAToken2", session.WAToken2);
|
||||||
}, this.options.session);
|
}, this.options.session);
|
||||||
}
|
}
|
||||||
|
|
||||||
await page.goto(WhatsWebURL);
|
await page.goto(WhatsWebURL);
|
||||||
|
|
||||||
const KEEP_PHONE_CONNECTED_IMG_SELECTOR = '._1wSzK';
|
const KEEP_PHONE_CONNECTED_IMG_SELECTOR = '.HGVhc';
|
||||||
|
|
||||||
if(this.options.session) {
|
if (this.options.session) {
|
||||||
// Check if session restore was successfull
|
// Check if session restore was successfull
|
||||||
try {
|
try {
|
||||||
await page.waitForSelector(KEEP_PHONE_CONNECTED_IMG_SELECTOR, {timeout: 5000});
|
await page.waitForSelector(KEEP_PHONE_CONNECTED_IMG_SELECTOR, { timeout: 15000 });
|
||||||
} catch(err) {
|
} catch (err) {
|
||||||
if(err.name === 'TimeoutError') {
|
if (err.name === 'TimeoutError') {
|
||||||
this.emit(Events.AUTHENTICATION_FAILURE, 'Unable to log in. Are the session details valid?');
|
this.emit(Events.AUTHENTICATION_FAILURE, 'Unable to log in. Are the session details valid?');
|
||||||
browser.close();
|
browser.close();
|
||||||
|
|
||||||
@@ -61,26 +63,24 @@ class Client extends EventEmitter {
|
|||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Wait for QR Code
|
// Wait for QR Code
|
||||||
|
const QR_CANVAS_SELECTOR = 'canvas';
|
||||||
|
await page.waitForSelector(QR_CANVAS_SELECTOR);
|
||||||
|
const qrImgData = await page.$eval(QR_CANVAS_SELECTOR, canvas => [].slice.call(canvas.getContext('2d').getImageData(0,0,264,264).data));
|
||||||
|
const qr = jsQR(qrImgData, 264, 264).data;
|
||||||
|
|
||||||
const QR_CONTAINER_SELECTOR = '._2d3Jz';
|
|
||||||
const QR_VALUE_SELECTOR = '._1pw2F';
|
|
||||||
|
|
||||||
await page.waitForSelector(QR_CONTAINER_SELECTOR);
|
|
||||||
|
|
||||||
const qr = await page.$eval(QR_VALUE_SELECTOR, node => node.getAttribute('data-ref'));
|
|
||||||
this.emit(Events.QR_RECEIVED, qr);
|
this.emit(Events.QR_RECEIVED, qr);
|
||||||
|
|
||||||
// Wait for code scan
|
// Wait for code scan
|
||||||
await page.waitForSelector(KEEP_PHONE_CONNECTED_IMG_SELECTOR, {timeout: 0});
|
await page.waitForSelector(KEEP_PHONE_CONNECTED_IMG_SELECTOR, { timeout: 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
await page.evaluate(ExposeStore);
|
await page.evaluate(ExposeStore, moduleRaid.toString());
|
||||||
|
|
||||||
// Get session tokens
|
// Get session tokens
|
||||||
const localStorage = JSON.parse(await page.evaluate(() => {
|
const localStorage = JSON.parse(await page.evaluate(() => {
|
||||||
return JSON.stringify(window.localStorage);
|
return JSON.stringify(window.localStorage);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const session = {
|
const session = {
|
||||||
@@ -95,22 +95,23 @@ class Client extends EventEmitter {
|
|||||||
// Check Store Injection
|
// Check Store Injection
|
||||||
await page.waitForFunction('window.Store != undefined');
|
await page.waitForFunction('window.Store != undefined');
|
||||||
|
|
||||||
//Load extra serialized props
|
//Load util functions (serializers, helper functions)
|
||||||
const models = [Message];
|
await page.evaluate(LoadUtils);
|
||||||
for (let model of models) {
|
|
||||||
await page.evaluate(LoadExtraProps, model.WAppModel, model.extraFields);
|
|
||||||
}
|
|
||||||
|
|
||||||
await page.evaluate(LoadCustomSerializers);
|
|
||||||
|
|
||||||
// Register events
|
// Register events
|
||||||
await page.exposeFunction('onAddMessageEvent', msg => {
|
await page.exposeFunction('onAddMessageEvent', msg => {
|
||||||
if (msg.id.fromMe || !msg.isNewMsg) return;
|
if (!msg.isNewMsg) return;
|
||||||
this.emit(Events.MESSAGE_CREATE, new Message(this, msg));
|
|
||||||
|
const message = new Message(this, msg);
|
||||||
|
this.emit(Events.MESSAGE_CREATE, message);
|
||||||
|
|
||||||
|
if (msg.id.fromMe) return;
|
||||||
|
this.emit(Events.MESSAGE_RECEIVED, message);
|
||||||
});
|
});
|
||||||
|
|
||||||
await page.exposeFunction('onConnectionChangedEvent', (conn, connected) => {
|
await page.exposeFunction('onAppStateChangedEvent', (AppState, state) => {
|
||||||
if (!connected) {
|
const ACCEPTED_STATES = [WAState.CONNECTED, WAState.OPENING, WAState.PAIRING];
|
||||||
|
if (!ACCEPTED_STATES.includes(state)) {
|
||||||
this.emit(Events.DISCONNECTED);
|
this.emit(Events.DISCONNECTED);
|
||||||
this.destroy();
|
this.destroy();
|
||||||
}
|
}
|
||||||
@@ -118,8 +119,8 @@ class Client extends EventEmitter {
|
|||||||
|
|
||||||
await page.evaluate(() => {
|
await page.evaluate(() => {
|
||||||
Store.Msg.on('add', onAddMessageEvent);
|
Store.Msg.on('add', onAddMessageEvent);
|
||||||
Store.Conn.on('change:connected', onConnectionChangedEvent);
|
Store.AppState.on('change:state', onAppStateChangedEvent);
|
||||||
})
|
}).catch(err => console.log(err.message));
|
||||||
|
|
||||||
this.pupBrowser = browser;
|
this.pupBrowser = browser;
|
||||||
this.pupPage = page;
|
this.pupPage = page;
|
||||||
@@ -146,12 +147,11 @@ class Client extends EventEmitter {
|
|||||||
* Get all current chat instances
|
* Get all current chat instances
|
||||||
*/
|
*/
|
||||||
async getChats() {
|
async getChats() {
|
||||||
// let chats = await this.pupPage.evaluate(() => {
|
let chats = await this.pupPage.evaluate(() => {
|
||||||
// return Store.Chat.serialize()
|
return WWebJS.getChats();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// return chats.map(chatData => ChatFactory.create(this, chatData));
|
return chats.map(chat => ChatFactory.create(this, chat));
|
||||||
throw new Error('NOT IMPLEMENTED')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,23 +17,6 @@ class Base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_patch(data) { return data; }
|
_patch(data) { return data; }
|
||||||
|
|
||||||
/**
|
|
||||||
* Name that represents this model in the WhatsApp Web Store
|
|
||||||
* @readonly
|
|
||||||
*/
|
|
||||||
static get WAppModel() {
|
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extra fields to add to model serialization
|
|
||||||
* @readonly
|
|
||||||
*/
|
|
||||||
static get extraFields() {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Base;
|
module.exports = Base;
|
||||||
@@ -86,7 +86,7 @@ class GroupChat extends Chat {
|
|||||||
*/
|
*/
|
||||||
async setSubject(subject) {
|
async setSubject(subject) {
|
||||||
let res = await this.client.pupPage.evaluate((chatId, subject) => {
|
let res = await this.client.pupPage.evaluate((chatId, subject) => {
|
||||||
return Store.Chat.get(chatId).setSubject(subject);
|
return Store.Wap.changeSubject(chatId, subject);
|
||||||
}, this.id._serialized, subject);
|
}, this.id._serialized, subject);
|
||||||
|
|
||||||
if(res.status == 200) {
|
if(res.status == 200) {
|
||||||
@@ -100,7 +100,8 @@ class GroupChat extends Chat {
|
|||||||
*/
|
*/
|
||||||
async setDescription(description) {
|
async setDescription(description) {
|
||||||
let res = await this.client.pupPage.evaluate((chatId, description) => {
|
let res = await this.client.pupPage.evaluate((chatId, description) => {
|
||||||
return Store.Chat.get(chatId).setGroupDesc(description);
|
let descId = Store.GroupMetadata.get(chatId).descId;
|
||||||
|
return Store.Wap.setGroupDescription(chatId, description, Store.genId(), descId);
|
||||||
}, this.id._serialized, description);
|
}, this.id._serialized, description);
|
||||||
|
|
||||||
if (res.status == 200) {
|
if (res.status == 200) {
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ class Message extends Base {
|
|||||||
|
|
||||||
_patch(data) {
|
_patch(data) {
|
||||||
this.id = data.id;
|
this.id = data.id;
|
||||||
this.body = data.body;
|
this.hasMedia = data.clientUrl ? true : false;
|
||||||
|
this.body = this.hasMedia ? data.caption || '' : data.body || '';
|
||||||
this.type = data.type;
|
this.type = data.type;
|
||||||
this.timestamp = data.t;
|
this.timestamp = data.t;
|
||||||
this.from = data.from;
|
this.from = data.from;
|
||||||
@@ -23,6 +24,7 @@ class Message extends Base {
|
|||||||
this.author = data.author;
|
this.author = data.author;
|
||||||
this.isForwarded = data.isForwarded;
|
this.isForwarded = data.isForwarded;
|
||||||
this.broadcast = data.broadcast;
|
this.broadcast = data.broadcast;
|
||||||
|
this.fromMe = data.id.fromMe;
|
||||||
|
|
||||||
return super._patch(data);
|
return super._patch(data);
|
||||||
}
|
}
|
||||||
@@ -60,14 +62,24 @@ class Message extends Base {
|
|||||||
}, chatId, this.id._serialized, message);
|
}, chatId, this.id._serialized, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get WAppModel() {
|
async downloadMedia() {
|
||||||
return 'Msg';
|
if (!this.hasMedia) {
|
||||||
}
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
static get extraFields() {
|
return await this.client.pupPage.evaluate(async (msgId) => {
|
||||||
return [
|
const msg = Store.Msg.get(msgId);
|
||||||
'isNewMsg'
|
const buffer = await WWebJS.downloadBuffer(msg.clientUrl);
|
||||||
];
|
const decrypted = await Store.CryptoLib.decryptE2EMedia(msg.type, buffer, msg.mediaKey, msg.mimetype);
|
||||||
|
const data = await WWebJS.readBlobAsync(decrypted._blob);
|
||||||
|
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
mimetype: msg.mimetype,
|
||||||
|
filename: msg.filename
|
||||||
|
}
|
||||||
|
|
||||||
|
}, this.id._serialized);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ exports.Events = {
|
|||||||
AUTHENTICATED: 'authenticated',
|
AUTHENTICATED: 'authenticated',
|
||||||
AUTHENTICATION_FAILURE: 'auth_failure',
|
AUTHENTICATION_FAILURE: 'auth_failure',
|
||||||
READY: 'ready',
|
READY: 'ready',
|
||||||
MESSAGE_CREATE: 'message',
|
MESSAGE_RECEIVED: 'message',
|
||||||
|
MESSAGE_CREATE: 'message_create',
|
||||||
QR_RECEIVED: 'qr',
|
QR_RECEIVED: 'qr',
|
||||||
DISCONNECTED: 'disconnected'
|
DISCONNECTED: 'disconnected'
|
||||||
}
|
}
|
||||||
@@ -41,3 +42,18 @@ exports.ChatTypes = {
|
|||||||
GROUP: 'group',
|
GROUP: 'group',
|
||||||
UNKNOWN: 'unknown'
|
UNKNOWN: 'unknown'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.WAState = {
|
||||||
|
CONFLICT: "CONFLICT",
|
||||||
|
CONNECTED: "CONNECTED",
|
||||||
|
DEPRECATED_VERSION: "DEPRECATED_VERSION",
|
||||||
|
OPENING: "OPENING",
|
||||||
|
PAIRING: "PAIRING",
|
||||||
|
PROXYBLOCK: "PROXYBLOCK",
|
||||||
|
SMB_TOS_BLOCK: "SMB_TOS_BLOCK",
|
||||||
|
TIMEOUT: "TIMEOUT",
|
||||||
|
TOS_BLOCK: "TOS_BLOCK",
|
||||||
|
UNLAUNCHED: "UNLAUNCHED",
|
||||||
|
UNPAIRED: "UNPAIRED",
|
||||||
|
UNPAIRED_IDLE: "UNPAIRED_IDLE"
|
||||||
|
}
|
||||||
@@ -3,175 +3,17 @@
|
|||||||
/**
|
/**
|
||||||
* Exposes the internal Store to the WhatsApp Web client
|
* Exposes the internal Store to the WhatsApp Web client
|
||||||
*/
|
*/
|
||||||
exports.ExposeStore = () => {
|
exports.ExposeStore = (moduleRaidStr) => {
|
||||||
// CREDITS: moduleRaid by PixelDesu
|
eval("var moduleRaid = " + moduleRaidStr);
|
||||||
// https://github.com/pixeldesu/moduleRaid/blob/master/moduleraid.js
|
window.mR = moduleRaid();
|
||||||
|
window.Store = window.mR.findModule("Chat")[1].default;
|
||||||
const moduleRaid = function (debug) {
|
window.Store.AppState = window.mR.findModule("STREAM")[0].default;
|
||||||
moduleRaid.mID = Math.random().toString(36).substring(7);
|
window.Store.CryptoLib = window.mR.findModule("decryptE2EMedia")[0];
|
||||||
moduleRaid.mObj = {};
|
window.Store.genId = window.mR.findModule((module) => module.default && typeof module.default === 'function' && module.default.toString().match(/crypto/))[0].default;
|
||||||
moduleRaid.cArr = [];
|
|
||||||
moduleRaid.mGet = null;
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
moduleRaid.debug = true;
|
|
||||||
} else if (window.mRdebug) {
|
|
||||||
moduleRaid.debug = true;
|
|
||||||
} else {
|
|
||||||
moduleRaid.debug = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
moduleRaid.log = function (message) {
|
|
||||||
if (moduleRaid.debug) {
|
|
||||||
console.warn(`[moduleRaid] ${message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
moduleRaid.args = [
|
|
||||||
[[0], [function(e, t, i) {
|
|
||||||
mCac = i.c;
|
|
||||||
Object.keys(mCac).forEach (function(mod) {
|
|
||||||
moduleRaid.mObj[mod] = mCac[mod].exports;
|
|
||||||
})
|
|
||||||
moduleRaid.cArr = i.m;
|
|
||||||
moduleRaid.mGet = i;
|
|
||||||
}]],
|
|
||||||
[[1e3], {[moduleRaid.mID]: function(e, t, i) {
|
|
||||||
mCac = i.c;
|
|
||||||
Object.keys(mCac).forEach (function(mod) {
|
|
||||||
moduleRaid.mObj[mod] = mCac[mod].exports;
|
|
||||||
})
|
|
||||||
moduleRaid.cArr = i.m;
|
|
||||||
moduleRaid.mGet = i;
|
|
||||||
}}, [[moduleRaid.mID]]]
|
|
||||||
]
|
|
||||||
|
|
||||||
fillModuleArray = function() {
|
|
||||||
if (typeof webpackJsonp === 'function') {
|
|
||||||
moduleRaid.args.forEach(function (argument, index) {
|
|
||||||
try {
|
|
||||||
webpackJsonp(...argument);
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
moduleRaid.log(`moduleRaid.args[${index}] failed: ${err}`);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
webpackJsonp.push(moduleRaid.args[1]);
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
moduleRaid.log(`Pushing moduleRaid.args[1] into webpackJsonp failed: ${err}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (moduleRaid.mObj.length == 0) {
|
|
||||||
mEnd = false;
|
|
||||||
mIter = 0;
|
|
||||||
|
|
||||||
if (!webpackJsonp([],[],[mIter])) {
|
|
||||||
throw Error('Unknown Webpack structure');
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!mEnd) {
|
|
||||||
try {
|
|
||||||
moduleRaid.mObj[mIter] = webpackJsonp([],[],[mIter]);
|
|
||||||
mIter++;
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
mEnd = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fillModuleArray()
|
|
||||||
|
|
||||||
get = function get (id) {
|
|
||||||
return moduleRaid.mObj[id]
|
|
||||||
}
|
|
||||||
|
|
||||||
findModule = function findModule (query) {
|
|
||||||
results = [];
|
|
||||||
modules = Object.keys(moduleRaid.mObj);
|
|
||||||
|
|
||||||
modules.forEach(function(mKey) {
|
|
||||||
mod = moduleRaid.mObj[mKey];
|
|
||||||
|
|
||||||
if (typeof mod !== 'undefined') {
|
|
||||||
if (typeof mod.default === 'object') {
|
|
||||||
for (key in mod.default) {
|
|
||||||
if (key == query) results.push(mod);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (key in mod) {
|
|
||||||
if (key == query) results.push(mod);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
findFunction = function(query) {
|
|
||||||
if (moduleRaid.cArr.length == 0) {
|
|
||||||
throw Error('No module constructors to search through!');
|
|
||||||
}
|
|
||||||
|
|
||||||
results = [];
|
|
||||||
|
|
||||||
if (typeof query === 'string') {
|
|
||||||
moduleRaid.cArr.forEach(function (ctor, index) {
|
|
||||||
if (ctor.toString().includes(query)) {
|
|
||||||
results.push(moduleRaid.mObj[index]);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else if (typeof query === 'function') {
|
|
||||||
modules = Object.keys(moduleRaid.mObj);
|
|
||||||
|
|
||||||
modules.forEach(function(mKey, index) {
|
|
||||||
mod = moduleRaid.mObj[mKey];
|
|
||||||
|
|
||||||
if (query(mod)) {
|
|
||||||
results.push(moduleRaid.mObj[index]);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
throw new TypeError('findFunction can only find via string and function, ' + (typeof query) + ' was passed');
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
modules: moduleRaid.mObj,
|
|
||||||
constructors: moduleRaid.cArr,
|
|
||||||
findModule: findModule,
|
|
||||||
findFunction: findFunction,
|
|
||||||
get: moduleRaid.mGet ? moduleRaid.mGet : get
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof module === 'object' && module.exports) {
|
|
||||||
module.exports = moduleRaid;
|
|
||||||
} else {
|
|
||||||
window.mR = moduleRaid();
|
|
||||||
}
|
|
||||||
|
|
||||||
window.Store = window.mR.findModule("Conn")[0].default;
|
|
||||||
window.Store.SendMessage = window.mR.findModule("sendTextMsgToChat")[0].sendTextMsgToChat;
|
window.Store.SendMessage = window.mR.findModule("sendTextMsgToChat")[0].sendTextMsgToChat;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
exports.LoadUtils = () => {
|
||||||
* Adds extra props to the serialization of a model
|
|
||||||
*/
|
|
||||||
exports.LoadExtraProps = (model, props) => {
|
|
||||||
Store[model].models[0].__props = Store[model].models[0].__props.concat(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.LoadCustomSerializers = () => {
|
|
||||||
window.WWebJS = {};
|
window.WWebJS = {};
|
||||||
|
|
||||||
window.WWebJS.getChatModel = chat => {
|
window.WWebJS.getChatModel = chat => {
|
||||||
@@ -179,7 +21,7 @@ exports.LoadCustomSerializers = () => {
|
|||||||
res.isGroup = chat.isGroup;
|
res.isGroup = chat.isGroup;
|
||||||
res.formattedTitle = chat.formattedTitle;
|
res.formattedTitle = chat.formattedTitle;
|
||||||
|
|
||||||
if(chat.groupMetadata) {
|
if (chat.groupMetadata) {
|
||||||
res.groupMetadata = chat.groupMetadata.serialize();
|
res.groupMetadata = chat.groupMetadata.serialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,6 +32,50 @@ exports.LoadCustomSerializers = () => {
|
|||||||
const chat = Store.Chat.get(chatId);
|
const chat = Store.Chat.get(chatId);
|
||||||
return WWebJS.getChatModel(chat);
|
return WWebJS.getChatModel(chat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.WWebJS.getChats = () => {
|
||||||
|
const chats = Store.Chat.models;
|
||||||
|
return chats.map(chat => WWebJS.getChatModel(chat));
|
||||||
|
}
|
||||||
|
|
||||||
|
window.WWebJS.downloadBuffer = (url) => {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
let xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", url);
|
||||||
|
xhr.responseType = 'arraybuffer';
|
||||||
|
xhr.onload = function () {
|
||||||
|
if (xhr.status == 200) {
|
||||||
|
resolve(xhr.response);
|
||||||
|
} else {
|
||||||
|
reject({
|
||||||
|
status: this.status,
|
||||||
|
statusText: xhr.statusText
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onerror = function () {
|
||||||
|
reject({
|
||||||
|
status: this.status,
|
||||||
|
statusText: xhr.statusText
|
||||||
|
});
|
||||||
|
};
|
||||||
|
xhr.send(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.WWebJS.readBlobAsync = (blob) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let reader = new FileReader();
|
||||||
|
|
||||||
|
reader.onload = () => {
|
||||||
|
resolve(reader.result);
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.onerror = reject;
|
||||||
|
|
||||||
|
reader.readAsDataURL(blob);
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.MarkAllRead = () => {
|
exports.MarkAllRead = () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user