Skip to content

Commit

Permalink
Updated Bot to latest commit of whatsapp-web.js
Browse files Browse the repository at this point in the history
bcd02aa5e4cb96387487595ff02f2c0308793160
  • Loading branch information
cstayyab committed Apr 27, 2020
1 parent 289cbfe commit 25b1d6d
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 29 deletions.
2 changes: 1 addition & 1 deletion WhatsBot/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module.exports = {
Client: require('./src/Client'),

version: "1.2.5-post",
version: "1.5.1-post",

// Structures
Chat: require('./src/structures/Chat'),
Expand Down
151 changes: 136 additions & 15 deletions WhatsBot/src/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const { WhatsWebURL, UserAgent, DefaultOptions, Events, WAState } = require('./u
const { ExposeStore, LoadUtils } = require('./util/Injected');
const ChatFactory = require('./factories/ChatFactory');
const ContactFactory = require('./factories/ContactFactory');
const { ClientInfo, Message, MessageMedia, Location, GroupNotification } = require('./structures');
const { ClientInfo, Message, MessageMedia, Contact, Location, GroupNotification } = require('./structures');
/**
* Starting point for interacting with the WhatsApp Web API
* @extends {EventEmitter}
Expand All @@ -22,11 +22,13 @@ const { ClientInfo, Message, MessageMedia, Location, GroupNotification } = requi
* @fires Client#message_create
* @fires Client#message_revoke_me
* @fires Client#message_revoke_everyone
* @fires Client#media_uploaded
* @fires Client#group_join
* @fires Client#group_leave
* @fires Client#group_update
* @fires Client#disconnected
* @fires Client#change_state
* @fires Client#change_battery
*/
class Client extends EventEmitter {
constructor(options = {}) {
Expand All @@ -42,11 +44,14 @@ class Client extends EventEmitter {
* Sets up events and requirements, kicks off authentication request
*/
async initialize(page, browser) {


this.pupBrowser = browser;
this.pupPage = page;

try {
await page.evaluate(ExposeStore, moduleRaid.toString());
await page.evaluate(ExposeStore, moduleRaid.toString());
}
catch(e) {
catch (e) {
console.log(e)
}
// Get session tokens
Expand Down Expand Up @@ -109,7 +114,7 @@ class Client extends EventEmitter {
}
return;
}

const message = new Message(this, msg);

/**
Expand Down Expand Up @@ -178,7 +183,7 @@ class Client extends EventEmitter {
await page.exposeFunction('onMessageAckEvent', (msg, ack) => {

const message = new Message(this, msg);

/**
* Emitted when an ack event occurrs on message type.
* @event Client#message_ack
Expand All @@ -188,6 +193,17 @@ class Client extends EventEmitter {
this.emit(Events.MESSAGE_ACK, message, ack);

});
await page.exposeFunction('onMessageMediaUploadedEvent', (msg) => {

const message = new Message(this, msg);

/**
* Emitted when media has been uploaded for a message sent by the client.
* @event Client#media_uploaded
* @param {Message} message The message with media that was uploaded
*/
this.emit(Events.MEDIA_UPLOADED, message);
});

await page.exposeFunction('onAppStateChangedEvent', (state) => {

Expand All @@ -199,6 +215,15 @@ class Client extends EventEmitter {
this.emit(Events.STATE_CHANGED, state);

const ACCEPTED_STATES = [WAState.CONNECTED, WAState.OPENING, WAState.PAIRING, WAState.TIMEOUT];
if (this.options.takeoverOnConflict) {
ACCEPTED_STATES.push(WAState.CONFLICT);

if (state === WAState.CONFLICT) {
setTimeout(() => {
this.pupPage.evaluate(() => window.Store.AppState.takeover());
}, this.options.takeoverTimeoutMs);
}
}
if (!ACCEPTED_STATES.includes(state)) {
/**
* Emitted when the client has been disconnected
Expand All @@ -209,19 +234,33 @@ class Client extends EventEmitter {
this.destroy();
}
});
await page.exposeFunction('onBatteryStateChangedEvent', (state) => {
const { battery, plugged } = state;

if (battery === undefined) return;

/**
* Emitted when the battery percentage for the attached device changes
* @event Client#change_battery
* @param {object} batteryInfo
* @param {number} batteryInfo.battery - The current battery percentage
* @param {boolean} batteryInfo.plugged - Indicates if the phone is plugged in (true) or not (false)
*/
this.emit(Events.BATTERY_CHANGED, { battery, plugged });
});


await page.evaluate(() => {
window.Store.Msg.on('add', (msg) => { if(msg.isNewMsg) window.onAddMessageEvent(msg); });
window.Store.Msg.on('add', (msg) => { if (msg.isNewMsg) window.onAddMessageEvent(msg); });
window.Store.Msg.on('change', (msg) => { window.onChangeMessageEvent(msg); });
window.Store.Msg.on('change:type', (msg) => { window.onChangeMessageTypeEvent(msg); });
window.Store.Msg.on('change:ack', (msg, ack) => { window.onMessageAckEvent(msg, ack); });
window.Store.Msg.on('remove', (msg) => { if(msg.isNewMsg) window.onRemoveMessageEvent(msg); });
window.Store.Msg.on('change:isUnsentMedia', (msg, unsent) => { if (msg.id.fromMe && !unsent) window.onMessageMediaUploadedEvent(msg); });
window.Store.Msg.on('remove', (msg) => { if (msg.isNewMsg) window.onRemoveMessageEvent(msg); });
window.Store.AppState.on('change:state', (_AppState, state) => { window.onAppStateChangedEvent(state); });
window.Store.Conn.on('change:battery', (state) => { window.onBatteryStateChangedEvent(state); });
});

this.pupBrowser = browser;
this.pupPage = page;

/**
* Emitted when the client has initialized and is ready to receive messages.
* @event Client#ready
Expand All @@ -237,6 +276,17 @@ class Client extends EventEmitter {
const KEEP_PHONE_CONNECTED_IMG_SELECTOR = '[data-asset-intro-image="true"]';
await page.waitForSelector(KEEP_PHONE_CONNECTED_IMG_SELECTOR, { timeout: 0 });
}

/**
* Returns the version of WhatsApp Web currently being run
* @returns Promise<string>
*/
async getWWebVersion() {
return await this.pupPage.evaluate(() => {
return window.Debug.VERSION;
});
}

/**
* Mark as seen for the Chat
* @param {string} chatId
Expand All @@ -259,11 +309,13 @@ class Client extends EventEmitter {
*/
async sendMessage(chatId, content, options = {}) {
let internalOptions = {
linkPreview: options.linkPreview === false ? undefined : true,
sendAudioAsVoice: options.sendAudioAsVoice,
caption: options.caption,
quotedMessageId: options.quotedMessageId,
mentionedJidList: Array.isArray(options.mentions) ? options.mentions.map(contact => contact.id._serialized) : []
};

const sendSeen = typeof options.sendSeen === 'undefined' ? true : options.sendSeen;

if (content instanceof MessageMedia) {
Expand Down Expand Up @@ -298,10 +350,10 @@ class Client extends EventEmitter {
}
}
else {
if(sendSeen) {
if (sendSeen) {
window.WWebJS.sendSeen(chatId);
}

msg = await window.WWebJS.sendMessage(chat, message, options, sendSeen);
}
return msg.serialize();
Expand Down Expand Up @@ -393,6 +445,15 @@ class Client extends EventEmitter {
}

/**
* Marks the client as online
*/
async sendPresenceAvailable() {
return await this.pupPage.evaluate(() => {
return window.Store.Wap.sendPresenceAvailable();
});
}

/**
* Enables and returns the archive state of the Chat
* @returns {boolean}
*/
Expand All @@ -415,16 +476,76 @@ class Client extends EventEmitter {
return chat.archive;
}, chatId);
}
/**
* Returns the contact ID's profile picture URL, if privacy settings allow it
* @param {string} contactId the whatsapp user's ID
* @returns {Promise<string>}
*/
async getProfilePicUrl(contactId) {
const profilePic = await this.pupPage.evaluate((contactId) => {
return window.Store.Wap.profilePicFind(contactId);
}, contactId);

return profilePic ? profilePic.eurl : undefined;
}

/**
* Force reset of connection state for the client
*/
async resetState(){
async resetState() {
await this.pupPage.evaluate(() => {
window.Store.AppState.phoneWatchdog.shiftTimer.forceRunNow();
});
}

/**
* Check if a given ID is registered in whatsapp
* @returns {Promise<Boolean>}
*/
async isRegisteredUser(id) {
return await this.pupPage.evaluate(async (id) => {
let result = await window.Store.Wap.queryExist(id);
return result.jid !== undefined;
}, id);
}

/**
* Create a new group
* @param {string} name group title
* @param {Array<Contact|string>} participants an array of Contacts or contact IDs to add to the group
* @returns {Object} createRes
* @returns {string} createRes.gid - ID for the group that was just created
* @returns {Object.<string,string>} createRes.missingParticipants - participants that were not added to the group. Keys represent the ID for participant that was not added and its value is a status code that represents the reason why participant could not be added. This is usually 403 if the user's privacy settings don't allow you to add them to groups.
*/
async createGroup(name, participants) {
if (!Array.isArray(participants) || participants.length == 0) {
throw 'You need to add at least one other participant to the group';
}

if (participants.every(c => c instanceof Contact)) {
participants = participants.map(c => c.id._serialized);
}

const createRes = await this.pupPage.evaluate(async (name, participantIds) => {
const res = await window.Store.Wap.createGroup(name, participantIds);
console.log(res);
if (!res.status === 200) {
throw 'An error occurred while creating the group!';
}

return res;
}, name, participants);

const missingParticipants = createRes.participants.reduce(((missing, c) => {
const id = Object.keys(c)[0];
const statusCode = c[id].code;
if (statusCode != 200) return Object.assign(missing, { [id]: statusCode });
return missing;
}), {});

return { gid: createRes.gid, missingParticipants };
}

}

module.exports = Client;
6 changes: 1 addition & 5 deletions WhatsBot/src/structures/Contact.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,7 @@ class Contact extends Base {
* @returns {Promise<string>}
*/
async getProfilePicUrl() {
const profilePic = await this.client.pupPage.evaluate((contactId) => {
return window.Store.Wap.profilePicFind(contactId);
}, this.id._serialized);

return profilePic ? profilePic.eurl : undefined;
return await this.client.getProfilePicUrl(this.id._serialized);
}

}
Expand Down
2 changes: 1 addition & 1 deletion WhatsBot/src/structures/GroupNotification.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class GroupNotification extends Base {
*
* @type {string}
*/
this.chatId = typeof (data.to) === 'object' ? data.to._serialized : data.to;
this.chatId = typeof (data.from) === 'object' ? data.from._serialized : data.from;

/**
* ContactId for the user that produced the GroupNotification.
Expand Down
15 changes: 14 additions & 1 deletion WhatsBot/src/structures/Message.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,25 @@ class Message extends Base {
}

_patch(data) {
/**
* MediaKey that represents the sticker 'ID'
* @type {string}
*/
this.mediaKey = data.mediaKey;


/**
* ID that represents the message
* @type {object}
*/
this.id = data.id;

/**
* ACK status for the message
* @type {MessageAck}
*/
this.ack = data.ack;

/**
* Indicates if the message has media available for download
* @type {boolean}
Expand Down Expand Up @@ -194,7 +207,7 @@ class Message extends Base {
await msg.downloadMedia(true, 1);
}

if(msg.mediaData.mediaStage != 'RESOLVED') {
if(msg.mediaData.mediaStage.includes('ERROR')) {
// media could not be downloaded
return undefined;
}
Expand Down
1 change: 1 addition & 0 deletions WhatsBot/src/structures/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ module.exports = {
MessageMedia: require('./MessageMedia'),
PrivateChat: require('./PrivateChat'),
PrivateContact: require('./PrivateContact'),
GroupNotification: require('./GroupNotification')
};
12 changes: 10 additions & 2 deletions WhatsBot/src/util/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ exports.UserAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit

exports.DefaultOptions = {
puppeteer: {
headless: true
headless: true,
defaultViewport: null
},
session: false
session: false,
qrTimeoutMs: 45000,
qrRefreshIntervalMs: 20000,
authTimeoutMs: 45000,
takeoverOnConflict: false,
takeoverTimeoutMs: 0
};

/**
Expand Down Expand Up @@ -36,12 +42,14 @@ exports.Events = {
MESSAGE_REVOKED_EVERYONE: 'message_revoke_everyone',
MESSAGE_REVOKED_ME: 'message_revoke_me',
MESSAGE_ACK: 'message_ack',
MEDIA_UPLOADED: 'media_uploaded',
GROUP_JOIN: 'group_join',
GROUP_LEAVE: 'group_leave',
GROUP_UPDATE: 'group_update',
QR_RECEIVED: 'qr',
DISCONNECTED: 'disconnected',
STATE_CHANGED: 'change_state',
BATTERY_CHANGED: 'change_battery'
};

/**
Expand Down

0 comments on commit 25b1d6d

Please sign in to comment.