const EventEmitter = require('events');
const Merge = require('merge-anything');
const fs = require('fs');
const path = require('path');
const _WABOT = require('../lib/browser');
const ConvertBase64 = require('../lib/convertBase64');
const Stickers = require('../lib/stickers');
const Vcards = require('../lib/vcards');
const TYPES = require('../types/validTypes');
const types = new TYPES();
const convert64 = new ConvertBase64();
const vcard = new Vcards();
const puppeteerDefault = require('../types/puppeteer.config.json');
const intentsDefault = require('../types/intents.json');
const Params = require('./params');
const getRandomItem = (array) => {
return array[Math.floor(Math.random()*array.length)]
}
const randomUUI = (a,b) => {for(b=a='';a++<36;b+=a*51&52?(a^15?8^Math.random()*(a^20?16:4):4).toString(16):'');return b}
const escapeRegExp = (string) => {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
const replaceAll = (str, term, replacement) => {
return str.replace(new RegExp(escapeRegExp(term), 'g'), replacement);
}
/**
*WABOT class for interact whit whatsapp web
*
* @class WABOT
* @extends {EventEmitter}
* @param {object} opts - Wabot options
* @param {object} opts.puppeteerConfig - Puppeteer launch options
* @param {string} opts.puppeteerConfig.WAUrl - Whatsapp Web Url
* @param {string} opts.puppeteerConfig.sessionPath - Path to save the session info for restore this in the future
* @param {boolean} opts.puppeteerConfig.viewBrowser - Show browser (headless)
* @param {boolean} opts.puppeteerConfig.opendevtools - Show devtools (console)
* @param {string} opts.puppeteerConfig.userAgent - User Agent for web browser
* @param {number} opts.puppeteerConfig.width - Width for web browser
* @param {number} opts.puppeteerConfig.heigth - Height for web browser
* @param {boolean} opts.puppeteerConfig.dowloadChromeVersion - Download chromium browser or use local google chome
* @param {number} opts.puppeteerConfig.chromeVersion - Version of chromium to download
* @param {string} opts.puppeteerConfig.localChromePath - Google chrome executable path
* @param {string} opts.puppeteerConfig.getInitScreenshot - Allows you to take a screenshot when you start WhatsApp in order to detect problems when running in headless mode
* @param {string} opts.puppeteerConfig.localChromePath - File name to save the screenshot
* @param {string} opts.puppeteerConfig.args - Args to open the web browser
* @param {object} opts.intentConfig - Execution and internal options
* @param {boolean} opts.intentConfig.showContent - Display chats in browser
* @param {string} opts.intentConfig.debug - Debug mode for view console logs
* @param {string[]} opts.intentConfig.removeBgApis - Api keys for https://www.remove.bg
* @param {object} opts.intentConfig.plugins - Options for plugins config
* @param {string} opts.intentConfig.plugins.folder - Folder containing the plugins
* @param {string[]} opts.intentConfig.plugins.plugins - Array containing the plugin names to use
* @param {object} opts.intentConfig.plugins.setup - Configuration of each plugin
* @param {object} opts.intentConfig.executions - Options for control chats
* @param {boolean} opts.intentConfig.executions.reponseUsers - Control response to users
* @param {boolean} opts.intentConfig.executions.simulateTyping - Simulate typing in chat
* @param {number} opts.intentConfig.executions.timeSimulate - Time in ms for simulate typing
* @param {boolean} opts.intentConfig.executions.contorlExecutions - Control chats to enqueue messages
* @param {number} opts.intentConfig.executions.maxExecutions - Max messages to process in the same time
* @param {number} opts.intentConfig.executions.timeInterval - Time in seconds to queue messages
* @param {number} opts.intentConfig.executions.timePending - Time in minutes to search for pending messages
* @param {boolean} opts.intentConfig.executions.sendSeen - Send seen ticket
* @param {boolean} opts.intentConfig.executions.sendSeenFull - Send seen ticket to all pending messages on login
* @param {number} opts.intentConfig.executions.intervalSendSeen - Time in minutes for search pending messages to send seen
* @param {object} opts.intentConfig.bann - Bann options
* @param {boolean} opts.intentConfig.bann.active - Control bann users
* @param {number} opts.intentConfig.bann.timeInterval - Time in seconds to validate spam messages
* @param {number} opts.intentConfig.bann.maxBann - Maximum number of messages allowed in the indicated amount of time
* @param {number} opts.intentConfig.bann.timeBann - Time in minutes for temporary ban
* @param {number} opts.intentConfig.bann.timeInactive - Time in minutes to release banned users who are inactive for the specified time
* @param {string[]} opts.intentConfig.bann.whiteList - List of users who will not be banned
* @param {object} opts.intentConfig.messages - Message settings
* @param {string} opts.intentConfig.messages.userBanned - Message to display when a user is banned
* @param {string} opts.intentConfig.messages.groupBanned - Message to display when a group is banned
* @param {string} opts.intentConfig.messages.privileges - Message to display when you do not have privileges to use the bot
* @param {string[]} opts.intentConfig.blocked - List of users who cannot use the bot
* @param {string[]} opts.intentConfig.whiteList - List of users who can use the bot
* @param {object[]} opts.intentConfig.commands - List of commands to evaluate in user messages
* @param {string} opts.intentConfig.commands.name - Name of the command
* @param {string[]} opts.intentConfig.commands.contains - Contains word on message
* @param {string[]} opts.intentConfig.commands.exact - Message is the same as what is contained here
* @param {object[]} opts.intentConfig.commands.params - Parameters to require
* @param {string} opts.intentConfig.commands.params.name - Name of the param
* @param {boolean} opts.intentConfig.commands.params.isNumber - Is a number param
* @param {string[]} opts.intentConfig.commands.params.request - Questions to request the parameter
* @param {string[]} opts.intentConfig.commands.params.values - Allowed values. If any is allowed, "any" must be indicated
* @param {string[]} opts.intentConfig.commands.params.badResponse - Messages to send in case of illegal values
* @param {object} opts.session - Object containing session information. Can be used to restore the session.
* @param {string} opts.session.WABrowserId
* @param {string} opts.session.WASecretBundle
* @param {string} opts.session.WAToken1
* @param {string} opts.session.WAToken2
*
* @fires WABOT#ready
* @fires WABOT#onStateChanged
* @fires WABOT#onMessageFromBloqued
* @fires WABOT#onMessageFromNoPrivileges
* @fires WABOT#waitNewAcknowledgements
* @fires WABOT#onBattery
* @fires WABOT#onPlugged
* @fires WABOT#onRemovedFromGroup
* @fires WABOT#onParticipantsChanged
* @fires WABOT#onMessageMediaUploadedEvent
* @fires WABOT#vcard
* @fires WABOT#message
* @fires WABOT#command
*/
class WABOT extends EventEmitter {
constructor(opts = {}){
super();
// Messages callbacks history
this.callbacks = [];
this.isLogged = false;
if(opts !== undefined && typeof opts === 'object'){
this.puppeterConfig = opts.puppeteerConfig || {};
this.intentConfig = opts.intentsConfig || {};
}else {
this.puppeterConfig = puppeteerDefault;
this.intentConfig = intentsDefault;
}
this.puppeteerConfig = this.mergeOpts(puppeteerDefault, this.puppeterConfig);
this.intentConfig = this.mergeOpts(intentsDefault, this.intentConfig);
this.sticker = new Stickers(this.intentConfig.removeBgApis);
// Add plugins
if (this.intentConfig.plugins.plugins.length > 0) {
this.addPlugins(this.intentConfig.plugins);
}
this._wabot = new _WABOT({
puppeteerConfig: this.puppeteerConfig,
intentConfig: this.intentConfig,
session: opts.session
});
this._wabot.on('message', (arg) => {
this.getNewMessages(arg);
});
this._wabot.on('onStateChanged', (arg) => {
/**
* Emitted when the connection state changes
* @event WABOT#onStateChanged
* @param {object} arg - State info
*/
this.emit('onStateChanged', arg);
});
this._wabot.on('onMessageFromBloqued', (arg) => {
/**
* Emitted when a message is received from a bloqued user
* @event WABOT#onMessageFromBloqued
* @param {object} arg - Message info
*/
this.emit('onMessageFromBloqued', arg);
});
this._wabot.on('onMessageFromNoPrivileges', (arg) => {
/**
* Emitted when a message is received from a non-privileged user
* @event WABOT#onMessageFromNoPrivileges
* @param {object} arg - Message info
*/
this.emit('onMessageFromNoPrivileges', arg);
});
this._wabot.on('waitNewAcknowledgements', (arg) => {
/**
* Emitted when a the acknowledgement state of a message changes.
* @event WABOT#waitNewAcknowledgements
* @param {object} arg
*/
this.emit('waitNewAcknowledgements', arg);
});
this._wabot.on('onBattery', (arg) => {
/**
* Emitted when the battery percentage for the attached device changes
* @event WABOT#onBattery
* @param {number} arg - The current battery percentage
*/
this.emit('onBattery', arg);
});
this._wabot.on('onPlugged', (arg) => {
/**
* Emitted when add a participant of the group
* @event WABOT#onPlugged
* @param {boolean} arg - True or False
*/
this.emit('onPlugged', arg);
});
this._wabot.on('onAddedToGroup', (arg) => {
/**
* Emitted when add a participant of the group
* @event WABOT#onAddedToGroup
* @param {object} arg
*/
this.emit('onAddedToGroup', arg);
});
this._wabot.on('onRemovedFromGroup', (arg) => {
/**
* Emitted when remove a participant of the group
* @event WABOT#onRemovedFromGroup
* @param {object} arg
*/
this.emit('onRemovedFromGroup', arg);
});
this._wabot.on('onParticipantsChanged', (arg) => {
/**
* Emitted when a participant of the group change
* @event WABOT#onParticipantsChanged
* @param {object} arg
* @param {string} arg.by
* @param {string} arg.action - Promote or Demote
* @param {string} arg.who - Id of the user
*/
this.emit('onParticipantsChanged', arg);
});
this._wabot.on('onMessageMediaUploadedEvent', (arg) => {
/**
* Emitted when media has been uploaded for a message sent by the client.
* @event WABOT#onMessageMediaUploadedEvent
* @param {object} message - The message with media that was uploaded
*/
this.emit('onMessageMediaUploadedEvent', arg);
});
this._wabot.on('ready', (session) => {
this.isLogged = true;
/**
* Emitted when WABOT is ready to work
* @event WABOT#ready
* @param {object} session Object containing session information. Can be used to restore the session.
* @param {string} session.WABrowserId
* @param {string} session.WASecretBundle
* @param {string} session.WAToken1
* @param {string} session.WAToken2
*/
this.emit('ready', session);
})
}
mergeOpts (defaultOpts, customOpts) {
return Merge.merge(defaultOpts, customOpts);
}
emitMessage (type, arg){
switch (type) {
case 'message':
/**
* Emitted when an uncontrolled message is received
* @event WABOT#message
* @param {object} arg - Message Info
*/
this.emit('message', arg);
break;
case 'vcard':
/**
* Emitted when a vcard pis received
* @event WABOT#vcard
* @param {object} arg - Message Info
*/
this.emit('message', arg);
break;
default:
/**
* Emitted when a command is detected
* @event WABOT#command
* @param {object} arg - Message Info
*/
this.emit(type, arg);
break;
}
}
getNewMessages(arg) {
let _this = this;
if (this.intentConfig.commands.length === 0) {
switch (arg.data.type) {
case "vcard":
vcard.extractVcard(arg.data.content)
.then(res => {
arg.data.vcard = res;
_this.emitMessage('vcard', arg);
});
break;
case "document": case "sticker": case "video": case "gif":
_this.emitMessage('message', arg);
break;
default:
_this.emitMessage('message', arg);
break;
}
}else {
switch (arg.data.type) {
case "vcard":
vcard.extractVcard(arg.data.content)
.then(res => {
arg.data.vcard = res;
_this.emitMessage('vcard', arg);
});
break;
case "sticker": case "video": case "gif":
_this.emitMessage('message', arg);
break;
case "document":
if (!_this.validCallbackResponse({
idChat: arg.data.from,
message: arg
})){
_this.emitMessage('message', arg);
}
break;
default:
let exactMatch, PartialMatch, _match, _find;
let response = arg;
_find = false;
let _message;
if (arg.data.type === 'chat'){
_message = arg.data.body;
}else {
_message = arg.data.caption;
}
exactMatch = this.intentConfig.commands.find(obj => obj.exact.find(ex => ex.toLowerCase() == _message.toLowerCase()));
if (exactMatch !== undefined) {
response.params = Params.getParams(exactMatch, '');
_match = exactMatch;
_find = true;
}else{
let exactMatch = this.intentConfig.commands.find(obj => obj.exact.find(ex => _message.toLowerCase().trim().indexOf(ex.toLowerCase().trim()) === 0));
if (exactMatch != undefined && exactMatch.params) {
let initCommand = exactMatch.exact.find(ex => _message.toLowerCase().trim().indexOf(ex.toLowerCase().trim()) === 0);
let _arguments = _message.toLowerCase().replace(initCommand.toLowerCase(), "").trim();
response.params = Params.getParams(exactMatch, _arguments);
if (typeof exactMatch.params !== 'undefined' && exactMatch.params.length > 0){
_match = exactMatch;
_find = true;
}
}else{
PartialMatch = this.intentConfig.commands.find(obj => obj.contains !== undefined && obj.contains.find(ex => _message.toLowerCase().search(ex.toLowerCase()) > -1));
if (PartialMatch != undefined) {
if (PartialMatch.isFile) PartialMatch['values'] = "any";
_match = PartialMatch;
_find = true;
}
}
}
if (!_find) {
if (!_this.validCallbackResponse({
idChat: arg.data.from,
message: arg
})){
_this.emitMessage('message', arg);
}
} else {
_this.releaseCallback(arg.data.from);
// Request first param else emit intent
if (_match.params && Array.isArray(_match.params) && _match.params.length > 0){
let index = Params.getNextPendingValue(_match, response.params);
if (index === 'no_data') {
_this.emitMessage(_match.name, response);
} else {
if (typeof _match.params[index] === 'object'){
_this.executeCallback({
idChat: arg.data.from,
message: arg.data,
intent: _match,
idParam: index,
values: response.params
});
} else {
_this.emitMessage(_match.name, response);
}
}
} else {
_this.emitMessage(_match.name, response);
}
}
break;
}
}
}
validCallback(args){
if (typeof this.callbacks[args.idChat] !== 'undefined'){
if (this.callbacks[args.idChat].isFinished) {
this.releaseCallback(args.idChat);
return false;
} else {
return true;
}
} else {
return false;
}
}
async validCallbackResponse(args){
if (this.validCallback({idChat: args.idChat})){
let caption = "";
if (args.message.data.type === 'chat'){
caption = args.message.data.body;
} else {
caption = args.message.data.caption;
}
caption = caption.trim().toLowerCase();
const _possibleValues = this.callbacks[args.idChat].possibleValues;
let currentParam = this.callbacks[args.idChat].currentParam;
const requireFile = this.callbacks[args.idChat].requireFile;
let response;
if (requireFile) {
if (args.message.data.type === 'document') {
const file = await this.downloadFile(args.message.data.id);
const pathFile = path.join(this.intentConfig.downloadPath, `${randomUUI()}${path.extname(args.message.data.filename)}`);
fs.writeFileSync(pathFile, file.split(';base64,').pop(), {encoding: 'base64'});
response = pathFile;
}
} else if (typeof _possibleValues === 'object'){
response = Object.keys(_possibleValues).find(key => _possibleValues[key].find(obj => obj.toLowerCase() == caption));
} else {
if ( _possibleValues === 'any' ) {
if (this.callbacks[args.idChat].intent.params[currentParam].isNumber){
try {
response = isNaN(parseInt(caption)) ? '' : parseInt(caption);
} catch (e) {
response = '';
}
} else {
response = caption;
}
}
}
if (response !== undefined && response !== '') {
let param = this.callbacks[args.idChat].intent.params[currentParam].name;
let value;
if (requireFile) value = response;
else
if (typeof _possibleValues === 'object'){
if (this.callbacks[args.idChat].customValues.length > 0) {
value = this.callbacks[args.idChat].customValues[response].value;
} else {
if (typeof this.callbacks[args.idChat].intent.params[currentParam].values[response] === 'object') {
value = this.callbacks[args.idChat].intent.params[currentParam].values[response].value;
} else {
value = this.callbacks[args.idChat].intent.params[currentParam].values[response];
}
}
} else {
value = response;
}
this.callbacks[args.idChat].values[param] = value;
currentParam = Params.getNextPendingValue(this.callbacks[args.idChat].intent, this.callbacks[args.idChat].values);
if (currentParam === 'no_data') {
this.callbacks[args.idChat].isFinished = true;
let _message = args.message;
_message.params = this.callbacks[args.idChat].values;
this.emitMessage(this.callbacks[args.idChat].intent.name, _message);
} else {
this.callbacks[args.idChat].currentParam = currentParam;
this.executeCallback({
idChat: args.idChat,
message: args.message,
intent: this.callbacks[args.idChat].intent,
idParam: currentParam,
values: this.callbacks[args.idChat].values
});
}
} else {
let text = getRandomItem(this.callbacks[args.idChat].intent.params[currentParam].badResponse);
this.sendMessage({
"idChat": args.idChat,
"message": text
});
}
return true;
} else {
return false;
}
}
releaseCallback(idChat){
if (typeof this.callbacks[idChat] !== 'undefined'){
delete this.callbacks[idChat];
}
}
executeCallback(args){
let index = args.idParam;
let _values = {};
let _possibleValues = {};
let _customValues = [];
let cont = 0;
if (this.validCallback({idChat: args.idChat})){
_values = this.callbacks[args.idChat].values;
} else {
_values = args.values;
}
let isFile = false;
if (args.intent.params[index].isFile) {
isFile = args.intent.params[index].isFile;
} else if (Array.isArray(args.intent.params[index].values)){
// If custom values are configured
let valuesToDisplay = [];
if (args.intent.params[index].customValues && args.intent.params[index].customValues.length > 0) {
args.intent.params[index].customValues.forEach(customValue => {
if (_values[customValue.param] !== undefined
&& _values[customValue.param] === customValue.paramValue
) {
_customValues.push(customValue);
valuesToDisplay.push(customValue);
}
})
}
if (valuesToDisplay.length === 0) {
valuesToDisplay = args.intent.params[index].values;
}
valuesToDisplay.forEach((value) => {
if (typeof value === 'object'){
_possibleValues[cont] = [(cont+1).toString(), value.display, value.value];
} else {
_possibleValues[cont] = [(cont+1).toString(), value];
}
++cont;
});
} else {
if (args.intent.params[index].values === 'any'){
_possibleValues = "any";
}
}
this.callbacks[args.idChat] = {
message: args.message,
intent: args.intent,
currentParam: index,
isFinished: false,
requireFile: isFile,
possibleValues: _possibleValues,
values: _values,
customValues: _customValues
}
let text = getRandomItem(args.intent.params[index].request) + String.fromCharCode(10);
for (var i=0; i<cont; i++){
let options = [];
options.push(_possibleValues[(i).toString()][0]);
options.push(_possibleValues[(i).toString()][1]);
//text += _possibleValues[(i).toString()].join('.- ') + String.fromCharCode(10);
text += options.join('.- ') + String.fromCharCode(10);
}
this.sendMessage({
"idChat": args.idChat,
"message": text
});
}
addPlugins (plugins) {
if (Array.isArray(plugins.plugins)) {
// Read plugins folder
const pathPlugins = path.join(__dirname, plugins.folder);
fs.readdir(pathPlugins, (err, files) => {
if (err) {
console.error('Error reading plugins directory');
} else {
let pluginsFiles = [];
files.forEach(file => {
if (file.indexOf('.js') !== -1){
const {id, setup, plugin, init} = require(path.join(pathPlugins, file));
const metadata = {
id: id,
setup: setup,
init: init,
plugin: plugin
};
pluginsFiles.push(metadata);
}
});
plugins.plugins.forEach(plugin => {
const pluginFile = pluginsFiles.find(el => el.id === plugin);
if (pluginFile !== undefined) {
Object.assign(this, {
[pluginFile.id]: pluginFile.plugin
});
if (typeof pluginFile.init !== 'undefined') {
pluginFile.init();
}
if (typeof plugins.setup[plugin] !== 'undefined') {
pluginFile.setup(plugins.setup[plugin]);
}
}
})
}
});
}
}
addCommand (command) {
this.intentConfig.commands.push(command);
}
deleteCommand (commandName) {
this.intentConfig.commands = this.intentConfig.commands.filter(el => el.name !== commandName);
}
/**
* Send text as image
* @param {object} args - The message info
* @param {string} args.idChat - Id Chat
* @param {string} args.idMessage - Id of message to reply
* @param {string} args.message - Message to send
*/
sendMessage(args){
let data = types.valid('text', args);
if (data.isValid){
this._wabot.sendMessage(data.data);
}else {
console.error(data.messageInvalid);
}
}
/**
* Download file from message received from others users
* @param {string} idMessage - Message id containing the file to download
*
* @returns {Promise<string>} file in base64 or error message
*/
async downloadFile(idMessage){
return new Promise(async (resolve, reject) => {
this._wabot.downloadFile(idMessage)
.then((file) => {
resolve(file);
})
.catch((err) => {
reject(err);
});
});
}
/**
* Send text as image
* @param {object} args - The message info
* @param {string} args.idChat - Id Chat
* @param {string} args.idMessage - Id of message to reply
* @param {string} args.caption - Caption to display in the message
* @param {string} args.message - Message to convert into image
*/
sendText2Image(args){
let data = types.valid('text2image', args);
if (data.isValid){
this._wabot.sendMessage(data.data);
}else {
console.error(data.messageInvalid);
}
}
/**
* Send a image file
* @param {object} args - The message info
* @param {string} args.idChat - Id Chat
* @param {string} args.idMessage - Id of message to reply
* @param {string} args.caption - Caption to display in the message
* @param {string} args.file - Url, base64 or path to the file
*/
sendImage(args){
if (typeof args.file !== 'undefined' && args.file !== ''){
convert64.convert(args.file)
.then(res => {
args.file = res;
let data = types.valid('image', args);
if (data.isValid){
this._wabot.sendMessage(data.data);
}else {
console.error(data.messageInvalid);
}
})
.catch(err => {
console.error(`Error converting to base64.`, err);
})
}
}
/**
* Send a file
* @param {object} args - The message info
* @param {string} args.idChat - Id Chat
* @param {string} args.idMessage - Id of message to reply
* @param {string} args.caption - Caption to display in the message
* @param {string} args.file - Url, base64 or path to the file
*/
sendFile(args){
if (typeof args.file !== 'undefined' && args.file !== ''){
convert64.convert(args.file)
.then(res => {
args.file = res;
let data = types.valid('document', args);
if (data.isValid){
this._wabot.sendMessage(data.data);
}else {
console.error(data.messageInvalid);
}
})
.catch(err => {
console.error(`Error converting to base64.`, err);
})
}
}
/**
* Send a video file
* @param {object} args - The message info
* @param {string} args.idChat - Id Chat
* @param {string} args.idMessage - Id of message to reply
* @param {string} args.caption - Caption to display in the message
* @param {string} args.file - Url, base64 or path to the file
*/
sendVideo(args){
if (typeof args.file !== 'undefined' && args.file !== ''){
convert64.convert(args.file)
.then(res => {
args.file = res;
let data = types.valid('video', args);
if (data.isValid){
this._wabot.sendMessage(data.data);
}else {
console.error(data.messageInvalid);
}
})
.catch(err => {
console.error(`Error converting to base64.`, err);
})
}
}
/**
* Send a gif file
* @param {object} args - The message info
* @param {string} args.idChat - Id Chat
* @param {string} args.idMessage - Id of message to reply
* @param {string} args.caption - Caption to display in the message
* @param {string} args.file - Url, base64 or path to the file
*/
sendGif(args){
if (typeof args.file !== 'undefined' && args.file !== ''){
convert64.convert(args.file)
.then(res => {
args.file = res;
let data = types.valid('gif', args);
if (data.isValid){
this._wabot.sendMessage(data.data);
}else {
console.error(data.messageInvalid);
}
})
.catch(err => {
console.error(`Error converting to base64.`, err);
})
}
}
/**
* Send a music file
* @param {object} args - The message info
* @param {string} args.idChat - Id Chat
* @param {string} args.idMessage - Id of message to reply
* @param {string} args.caption - Caption to display in the message
* @param {string} args.file - Url, base64 or path to the file
*/
sendMusic(args){
if (typeof args.file !== 'undefined' && args.file !== ''){
convert64.convert(args.file)
.then(res => {
args.file = res;
args.fileType = 'music';
let data = types.valid('music', args);
if (data.isValid){
this._wabot.sendMessage(data.data);
}else {
console.error(data.messageInvalid);
}
})
.catch(err => {
console.error(`Error converting to base64.`, err);
})
}
}
/**
* Send a link
* @param {object} args - The message info
* @param {string} args.idChat - Id Chat
* @param {string} args.idMessage - Id of message to reply
* @param {string} args.caption - Caption to display in the message
* @param {string} args.link - Url to send
*/
sendLink(args){
let data = types.valid('link', args);
if (data.isValid){
this._wabot.sendMessage(data.data);
}else {
console.error(data.messageInvalid);
}
}
/**
* Send a sticker
* @param {object} args - The message info
* @param {string} args.idChat - Id Chat
* @param {string} args.idMessage - Id of message to reply
* @param {string} args.file - Url, base64 or Path of the image (with or without background)
*/
sendSticker(args){
if (typeof args.file !== 'undefined' && args.file !== ''){
this.sticker.makeSticker(args.file)
.then(res => {
args.file = res.file;
let data = types.valid('sticker', args);
if (data.isValid){
this._wabot.sendMessage(data.data);
}else {
console.error(data.messageInvalid);
}
})
.catch(err => {
console.error(`Error creating sticker.`, err);
})
}
}
/**
* Send a location
* @param {object} args - The message info
* @param {string} args.idChat - Id Chat
* @param {string} args.idMessage - Id of message to reply
* @param {string} args.lat - Latitude of the location
* @param {string} args.lng - Location of the location
* @param {string} args.title - Title to display
*/
sendLocation(args){
let data = types.valid('location', args);
if (data.isValid){
this._wabot.sendMessage(data.data);
}else {
console.error(data.messageInvalid);
}
}
/**
* Send a contact as vcard
* @param {object} args - The message info
* @param {string} args.idChat - Id Chat
* @param {string} args.idMessage - Id of message to reply
* @param {string} args.contactName - Contact Name to display
* @param {object} args.vcard - Contact info
* @param {string} args.vcard.firstName - First Name
* @param {string} args.vcard.middleName - Middle Name
* @param {string} args.vcard.lastName - Last Name
* @param {string} args.vcard.organization - Organization
* @param {string} args.vcard.birthday - Dirthday date
* @param {string} args.vcard.title - Title to display
* @param {string} args.vcard.url - Url
* @param {string} args.vcard.note - Note
* @param {string} args.vcard.nickname - Nickname
* @param {string} args.vcard.namePrefix - Name Prefix
* @param {string} args.vcard.nameSuffix - Name Suffix
* @param {string} args.vcard.gender - Gender
* @param {string} args.vcard.role - Role
* @param {string} args.vcard.homePhone - Home Phone
* @param {string} args.vcard.workPhone - Work Phone
* @param {string} args.vcard.cellPhone - Cell Phone
* @param {string} args.vcard.pagerPhone - Pager Phone
* @param {string} args.vcard.homeFax - Home Fax
* @param {string} args.vcard.workFax - Work Fax
* @param {string} args.vcard.email - Email
* @param {string} args.vcard.workEmail - Work Email
* @param {string} args.vcard.socialUrlsFacebook - Social Urls Facebook
* @param {string} args.vcard.socialUrlsLinkedin - Social Urls Linkedin
* @param {string} args.vcard.socialUrlsTwitter - Social Urls Twitter
* @param {string} args.vcard.socialUrlsFlickr - Social Urls Flickr
* @param {string} args.vcard.socialUrlsCustom - Social Urls Custom
* @param {string} args.vcard.homeAddressLabel - Home Address Label
* @param {string} args.vcard.homeAddressStreet - Home Address Street
* @param {string} args.vcard.homeAddressCity - Home Address City
* @param {string} args.vcard.homeAddressStateProvince - Home Address State Province
* @param {string} args.vcard.homeAddressPostalCode - Home Address Postal Code
* @param {string} args.vcard.homeAddressCountryRegion - Home Address Country Region
* @param {string} args.vcard.workAddressLabel - Work Address Label
* @param {string} args.vcard.workAddressStreet - Work Address Street
* @param {string} args.vcard.workAddressCity - Work Address City
* @param {string} args.vcard.workAddressStateProvince - Work Address State Province
* @param {string} args.vcard.workAddressPostalCode - Work Address Postal Code
* @param {string} args.vcard.workAddressCountryRegion - Work Address Country Region
* @param {string} args.vcard.photo - Photo (url or path)
*/
sendVcard(args){
let data = types.valid('vcard', args);
if (data.isValid){
let _vcard = vcard.createVcard(data.data.vcard);
data.data.vcard = _vcard;
this._wabot.sendMessage(data.data);
}else {
console.error(data.messageInvalid);
}
}
/**
* Returns an object with all of your host device details
* @returns {Promise<object>}
*/
async getMe() {
return this._wabot.getMe();
}
/**
* Returns the version of WhatsApp Web currently being run
* @returns {Promise<string>}
*/
async getWAVersion() {
return this._wabot.getWAVersion();
}
/**
* Get current battery percentage and charging status for the attached device
* @returns {number} battery - The current battery percentage
*/
async getBatteryLevel() {
return this._wabot.getBatteryLevel();
}
/**
* Get all chats
* @returns {Promise<Object[]>}
*/
async getAllChats() {
return this._wabot.getAllChats();
}
/**
* Get all chats with pending messages
* @returns {Promise<Object[]>}
*/
async getAllChatsWithNewMsg() {
return this._wabot.getAllChatsWithNewMsg();
}
/**
* Get chat instance by ID
* @param {string} chatId
* @returns {Promise<Chat>}
*/
async getChatById(chatId) {
return this._wabot.getChatById(chatId);
}
/**
* Get message by Id
* @param {string} messageId - Message Id
*
* @returns {Promise<Object[]>}
*/
async getMessageById(messageId) {
return this._wabot.getMessageById(messageId);
}
/**
* Get all unread messages
* @returns {Promise<Object[]>}
*/
async getAllUnreadMessages() {
return this._wabot.getAllUnreadMessages();
}
/**
* Fetches all group metadata objects from store
*
* @returns {Array|*} List of group metadata
*/
async getAllGroupMetadata() {
return this._wabot.getAllGroupMetadata();
}
/**
* Fetches group metadata object from store by ID
*
* @param {string} groupId - ID of group
* @returns {T|*} Group metadata object
*/
async getGroupMetadata(groupId) {
return this._wabot.getGroupMetadata(groupId);
}
/**
* Create a new group
* @param {string} name group title
* @param {Array<Contact|string>} contactsId 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, contactsId) {
return this._wabot.createGroup(name, contactsId);
}
/**
* Gets the list of all users
* @param {string} contactId
* @returns {Promise<Contact[]>}
*/
async getAllContacts() {
return this._wabot.getAllContacts();
}
/**
* Get the user's registered contact list
* @param {string} contactId
* @returns {Promise<Contact[]>}
*/
async getMyContacts() {
return this._wabot.getMyContacts();
}
/**
* Get contact instance by ID
* @param {string} contactId
* @returns {Promise<Contact>}
*/
async getContactById(contactId) {
return this._wabot.getContactById(contactId);
}
/**
* Returns an object with information about the invite code's group
* @param {string} inviteCode
* @returns {Promise<object>} Invite information
*/
async getInviteInfo(inviteCode) {
return this._wabot.getInviteInfo(inviteCode);
}
/**
* Get the invite code's group
* @param {string} chatId
* @returns {Promise<string>} Invite Code
*/
async getGroupInviteLink(chatId) {
return this._wabot.getGroupInviteLink(chatId);
}
/**
* Accepts an invitation to join a group
* @param {string} inviteCode Invitation code
*/
async joinGroupViaLink(inviteCode) {
return this._wabot.joinGroupViaLink(inviteCode);
}
/**
* Sets the current user's status message
* @param {string} status New status message
*/
async setStatusMessage(newStatus){
return this._wabot.logout(newStatus);
}
/**
* Gets the current status message
* @returns {string} status message
*/
async getStatus(){
return this._wabot.getStatus();
}
/**
* Enables and returns the archive state of the Chat
* @returns {boolean}
*/
async archiveChat(idChat, archive){
return this._wabot.archiveChat(idChat, archive);
}
/**
* Marks the client as online or offline
* @param {boolean} - true for online false for offline
*/
async setPresence(presence){
return this._wabot.setPresence(presence);
}
/**
* Sets the current user's display name.
* This is the name shown to WhatsApp users that have not added you as a contact beside your number in groups and in your profile.
* @param {string} displayName New display name
*/
async setDisplayName(newName){
return this._wabot.setDisplayName(newName);
}
/**
* Check if a given ID is registered in whatsapp
* @param {string} id the whatsapp user's ID
* @returns {Promise<Boolean>}
*/
async validNumberExists(id){
return this._wabot.validNumberExists(id);
}
/**
* Mutes the Chat until a specified date
* @param {string} chatId ID of the chat that will be muted
* @param {Date} unmuteDate Date when the chat will be unmuted
*/
async muteChat(chatId, unmuteDate) {
this._wabot.muteChat(chatId, unmuteDate);
}
/**
* Unmutes the Chat
* @param {string} chatId ID of the chat that will be unmuted
*/
async unmuteChat(chatId) {
this._wabot.unmuteChat(chatId);
}
/**
* Pins the Chat
* @returns {Promise<boolean>} New pin state. Could be false if the max number of pinned chats was reached.
*/
async pinChat(chatId) {
return this._wabot.pinChat(chatId);
}
/**
* Unpins the Chat
* @returns {Promise<boolean>} New pin state
*/
async unpinChat(chatId) {
return this._wabot.unpinChat(chatId);
}
/**
* Enables and returns the archive state of the Chat
* @returns {boolean}
*/
async archiveChat(chatId) {
return this._wabot.archiveChat(chatId);
}
/**
* Changes and returns the archive state of the Chat
* @returns {boolean}
*/
async unarchiveChat(chatId) {
return this._wabot.unarchiveChat(chatId);
}
/**
* Gets the current connection state for the client
* @returns WAState
*/
async getState(){
return this._wabot.getState();
}
/**
* Force reset of connection state for the client
*/
async resetState(){
return this._wabot.resetState();
}
/**
* Logs out the client, closing the current session
*/
logout(){
if(this.isLogged){
this._wabot.logout();
}else{
console.info("You must first be logged in.");
}
}
/**
* To know if the process is ready
*/
isReady() {
return this.isLogged;
}
/**
* Start session on whatsapp web
*/
start(){
this._wabot.start();
}
}
module.exports = WABOT;
Source