UNPKG

wabot

Version:

Whatsapp Bot Module for automate response and interact whit users

1,209 lines (1,126 loc) 48.1 kB
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;