Compare commits

..

8 Commits

Author SHA1 Message Date
Pedro Lopez
3c55fbf2ca 0.3.2 2020-01-17 22:06:19 -04:00
Pedro Lopez
6b1b51eacd Increase successful connection timeout 2020-01-17 22:06:04 -04:00
Pedro Lopez
2dc53e0820 [FIX] Connection success detection selector changed
close #31
2020-01-17 22:05:05 -04:00
Pedro Lopez
9043e61c40 0.3.1 2019-12-04 03:00:04 -04:00
Pedro Lopez
bea1ebf480 [FIX] Get QR code directly from canvas element (fix #26) 2019-12-04 02:58:55 -04:00
Pedro Lopez
021a213de3 0.3.0 2019-11-24 04:25:35 -04:00
Pedro S. Lopez
d0bef55b8a Merge pull request #24 from pedroslopez/development
Download message attachments (images, documents, etc)
2019-11-24 04:25:14 -04:00
Pedro Lopez
64912dccfd Download message attachments (images, documents, etc) 2019-11-24 04:23:08 -04:00
6 changed files with 90 additions and 17 deletions

View File

@@ -81,6 +81,14 @@ client.on('message', async msg => {
} 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}
`);
}
});

7
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "whatsapp-web.js",
"version": "0.2.0",
"version": "0.3.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -168,6 +168,11 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"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": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",

View File

@@ -1,6 +1,6 @@
{
"name": "whatsapp-web.js",
"version": "0.2.0",
"version": "0.3.2",
"description": "Library for interacting with the WhatsApp Web API ",
"main": "./index.js",
"scripts": {
@@ -25,6 +25,7 @@
},
"homepage": "https://github.com/pedroslopez/whatsapp-web.js#readme",
"dependencies": {
"jsqr": "^1.2.0",
"moduleraid": "git+https://github.com/pixeldesu/moduleRaid.git",
"puppeteer": "^1.20.0"
}

View File

@@ -3,12 +3,12 @@
const EventEmitter = require('events');
const puppeteer = require('puppeteer');
const moduleRaid = require('moduleraid/moduleraid');
const jsQR = require('jsqr');
const Util = require('./util/Util');
const { WhatsWebURL, UserAgent, DefaultOptions, Events, WAState } = require('./util/Constants');
const { ExposeStore, LoadCustomSerializers } = require('./util/Injected');
const { ExposeStore, LoadUtils } = require('./util/Injected');
const ChatFactory = require('./factories/ChatFactory');
const Chat = require('./structures/Chat');
const Message = require('./structures/Message');
/**
@@ -46,12 +46,12 @@ class Client extends EventEmitter {
await page.goto(WhatsWebURL);
const KEEP_PHONE_CONNECTED_IMG_SELECTOR = '._1wSzK';
const KEEP_PHONE_CONNECTED_IMG_SELECTOR = '.HGVhc';
if (this.options.session) {
// Check if session restore was successfull
try {
await page.waitForSelector(KEEP_PHONE_CONNECTED_IMG_SELECTOR, { timeout: 5000 });
await page.waitForSelector(KEEP_PHONE_CONNECTED_IMG_SELECTOR, { timeout: 15000 });
} catch (err) {
if (err.name === 'TimeoutError') {
this.emit(Events.AUTHENTICATION_FAILURE, 'Unable to log in. Are the session details valid?');
@@ -65,12 +65,11 @@ class Client extends EventEmitter {
} else {
// Wait for QR Code
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'));
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;
this.emit(Events.QR_RECEIVED, qr);
// Wait for code scan
@@ -96,8 +95,8 @@ class Client extends EventEmitter {
// Check Store Injection
await page.waitForFunction('window.Store != undefined');
//Load custom serializers
await page.evaluate(LoadCustomSerializers);
//Load util functions (serializers, helper functions)
await page.evaluate(LoadUtils);
// Register events
await page.exposeFunction('onAddMessageEvent', msg => {

View File

@@ -15,7 +15,8 @@ class Message extends Base {
_patch(data) {
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.timestamp = data.t;
this.from = data.from;
@@ -60,6 +61,26 @@ class Message extends Base {
}, chatId, this.id._serialized, message);
}
async downloadMedia() {
if (!this.hasMedia) {
return undefined;
}
return await this.client.pupPage.evaluate(async (msgId) => {
const msg = Store.Msg.get(msgId);
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);
}
}
module.exports = Message;

View File

@@ -8,12 +8,12 @@ exports.ExposeStore = (moduleRaidStr) => {
window.mR = moduleRaid();
window.Store = window.mR.findModule("Chat")[1].default;
window.Store.AppState = window.mR.findModule("STREAM")[0].default;
window.Store.CryptoLib = window.mR.findModule("decryptE2EMedia")[0];
window.Store.genId = window.mR.findModule((module) => module.default && typeof module.default === 'function' && module.default.toString().match(/crypto/))[0].default;
window.Store.SendMessage = window.mR.findModule("sendTextMsgToChat")[0].sendTextMsgToChat;
}
exports.LoadCustomSerializers = () => {
exports.LoadUtils = () => {
window.WWebJS = {};
window.WWebJS.getChatModel = chat => {
@@ -37,6 +37,45 @@ exports.LoadCustomSerializers = () => {
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 = () => {