UNPKG

bot_genshin

Version:
990 lines (860 loc) 40.4 kB
<!doctype html> <html> <head> <meta name="generator" content="JSDoc 3.6.7"> <meta charset="utf-8"> <title>whatsapp-web.js 1.14.0 &raquo; Source: Client.js</title> <link rel="stylesheet" href="https://brick.a.ssl.fastly.net/Karla:400,400i,700,700i" type="text/css"> <link rel="stylesheet" href="https://brick.a.ssl.fastly.net/Noto+Serif:400,400i,700,700i" type="text/css"> <link rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css"> <link href="css/baseline.css" rel="stylesheet"> </head> <body onload="prettyPrint()"> <nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar"> <div id="jsdoc-navbar-container"> <div id="jsdoc-navbar-content"> <a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>14.<wbr>0</a> </div> </div> </nav> <div id="jsdoc-body-container"> <div id="jsdoc-content"> <div id="jsdoc-content-container"> <div id="jsdoc-banner" role="banner"> </div> <div id="jsdoc-main" role="main"> <header class="page-header"> <h1>Source: Client.js</h1> </header> <article> <pre class="prettyprint linenums"><code>&#x27;use strict&#x27;; const EventEmitter &#x3D; require(&#x27;events&#x27;); const puppeteer &#x3D; require(&#x27;puppeteer&#x27;); const moduleRaid &#x3D; require(&#x27;@pedroslopez/moduleraid/moduleraid&#x27;); const jsQR &#x3D; require(&#x27;jsqr&#x27;); const Util &#x3D; require(&#x27;./util/Util&#x27;); const InterfaceController &#x3D; require(&#x27;./util/InterfaceController&#x27;); const { WhatsWebURL, DefaultOptions, Events, WAState } &#x3D; require(&#x27;./util/Constants&#x27;); const { ExposeStore, LoadUtils } &#x3D; require(&#x27;./util/Injected&#x27;); const ChatFactory &#x3D; require(&#x27;./factories/ChatFactory&#x27;); const ContactFactory &#x3D; require(&#x27;./factories/ContactFactory&#x27;); const { ClientInfo, Message, MessageMedia, Contact, Location, GroupNotification , Label, Call } &#x3D; require(&#x27;./structures&#x27;); /** * Starting point for interacting with the WhatsApp Web API * @extends {EventEmitter} * @param {object} options - Client options * @param {number} options.authTimeoutMs - Timeout for authentication selector in puppeteer * @param {object} options.puppeteer - Puppeteer launch options. View docs here: https://github.com/puppeteer/puppeteer/ * @param {number} options.qrRefreshIntervalMs - Refresh interval for qr code (how much time to wait before checking if the qr code has changed) * @param {number} options.qrTimeoutMs - Timeout for qr code selector in puppeteer * @param {string} options.restartOnAuthFail - Restart client with a new session (i.e. use null &#x27;session&#x27; var) if authentication fails * @param {object} options.session - Whatsapp session to restore. If not set, will start a new session * @param {string} options.session.WABrowserId * @param {string} options.session.WASecretBundle * @param {string} options.session.WAToken1 * @param {string} options.session.WAToken2 * @param {number} options.takeoverOnConflict - If another whatsapp web session is detected (another browser), take over the session in the current browser * @param {number} options.takeoverTimeoutMs - How much time to wait before taking over the session * @param {string} options.userAgent - User agent to use in puppeteer * @param {string} options.ffmpegPath - Ffmpeg path to use when formating videos to webp while sending stickers * @param {boolean} options.bypassCSP - Sets bypassing of page&#x27;s Content-Security-Policy. * * @fires Client#qr * @fires Client#authenticated * @fires Client#auth_failure * @fires Client#ready * @fires Client#message * @fires Client#message_ack * @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 &#x3D; {}) { super(); this.options &#x3D; Util.mergeDefault(DefaultOptions, options); this.pupBrowser &#x3D; null; this.pupPage &#x3D; null; Util.setFfmpegPath(this.options.ffmpegPath); } /** * Sets up events and requirements, kicks off authentication request */ async initialize() { let [browser, page] &#x3D; [null, null]; if(this.options.puppeteer &amp;amp;&amp;amp; this.options.puppeteer.browserWSEndpoint) { browser &#x3D; await puppeteer.connect(this.options.puppeteer); page &#x3D; await browser.newPage(); } else { browser &#x3D; await puppeteer.launch(this.options.puppeteer); page &#x3D; (await browser.pages())[0]; } page.setUserAgent(this.options.userAgent); this.pupBrowser &#x3D; browser; this.pupPage &#x3D; page; if (this.options.session) { await page.evaluateOnNewDocument( session &#x3D;&gt; { localStorage.clear(); localStorage.setItem(&#x27;WABrowserId&#x27;, session.WABrowserId); localStorage.setItem(&#x27;WASecretBundle&#x27;, session.WASecretBundle); localStorage.setItem(&#x27;WAToken1&#x27;, session.WAToken1); localStorage.setItem(&#x27;WAToken2&#x27;, session.WAToken2); }, this.options.session); } if(this.options.bypassCSP) { await page.setBypassCSP(true); } await page.goto(WhatsWebURL, { waitUntil: &#x27;load&#x27;, timeout: 0, }); const KEEP_PHONE_CONNECTED_IMG_SELECTOR &#x3D; &#x27;[data-asset-intro-image-light&#x3D;&quot;true&quot;], [data-asset-intro-image-dark&#x3D;&quot;true&quot;]&#x27;; if (this.options.session) { // Check if session restore was successfull try { await page.waitForSelector(KEEP_PHONE_CONNECTED_IMG_SELECTOR, { timeout: this.options.authTimeoutMs }); } catch (err) { if (err.name &#x3D;&#x3D;&#x3D; &#x27;TimeoutError&#x27;) { /** * Emitted when there has been an error while trying to restore an existing session * @event Client#auth_failure * @param {string} message */ this.emit(Events.AUTHENTICATION_FAILURE, &#x27;Unable to log in. Are the session details valid?&#x27;); browser.close(); if (this.options.restartOnAuthFail) { // session restore failed so try again but without session to force new authentication this.options.session &#x3D; null; this.initialize(); } return; } throw err; } } else { const getQrCode &#x3D; async () &#x3D;&gt; { // Check if retry button is present var QR_RETRY_SELECTOR &#x3D; &#x27;div[data-ref] &gt; span &gt; button&#x27;; var qrRetry &#x3D; await page.$(QR_RETRY_SELECTOR); if (qrRetry) { await qrRetry.click(); } // Wait for QR Code const QR_CANVAS_SELECTOR &#x3D; &#x27;canvas&#x27;; await page.waitForSelector(QR_CANVAS_SELECTOR, { timeout: this.options.qrTimeoutMs }); const qrImgData &#x3D; await page.$eval(QR_CANVAS_SELECTOR, canvas &#x3D;&gt; [].slice.call(canvas.getContext(&#x27;2d&#x27;).getImageData(0, 0, 264, 264).data)); const qr &#x3D; jsQR(qrImgData, 264, 264).data; /** * Emitted when the QR code is received * @event Client#qr * @param {string} qr QR Code */ this.emit(Events.QR_RECEIVED, qr); }; getQrCode(); this._qrRefreshInterval &#x3D; setInterval(getQrCode, this.options.qrRefreshIntervalMs); // Wait for code scan await page.waitForSelector(KEEP_PHONE_CONNECTED_IMG_SELECTOR, { timeout: 0 }); clearInterval(this._qrRefreshInterval); this._qrRefreshInterval &#x3D; undefined; } await page.evaluate(ExposeStore, moduleRaid.toString()); // Get session tokens const localStorage &#x3D; JSON.parse(await page.evaluate(() &#x3D;&gt; { return JSON.stringify(window.localStorage); })); const session &#x3D; { WABrowserId: localStorage.WABrowserId, WASecretBundle: localStorage.WASecretBundle, WAToken1: localStorage.WAToken1, WAToken2: localStorage.WAToken2 }; /** * Emitted when authentication is successful * @event Client#authenticated * @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(Events.AUTHENTICATED, session); // Check window.Store Injection await page.waitForFunction(&#x27;window.Store !&#x3D; undefined&#x27;); //Load util functions (serializers, helper functions) await page.evaluate(LoadUtils); // Expose client info /** * Current connection information * @type {ClientInfo} */ this.info &#x3D; new ClientInfo(this, await page.evaluate(() &#x3D;&gt; { return window.Store.Conn.serialize(); })); // Add InterfaceController this.interface &#x3D; new InterfaceController(this); // Register events await page.exposeFunction(&#x27;onAddMessageEvent&#x27;, msg &#x3D;&gt; { if (!msg.isNewMsg) return; if (msg.type &#x3D;&#x3D;&#x3D; &#x27;gp2&#x27;) { const notification &#x3D; new GroupNotification(this, msg); if (msg.subtype &#x3D;&#x3D;&#x3D; &#x27;add&#x27; || msg.subtype &#x3D;&#x3D;&#x3D; &#x27;invite&#x27;) { /** * Emitted when a user joins the chat via invite link or is added by an admin. * @event Client#group_join * @param {GroupNotification} notification GroupNotification with more information about the action */ this.emit(Events.GROUP_JOIN, notification); } else if (msg.subtype &#x3D;&#x3D;&#x3D; &#x27;remove&#x27; || msg.subtype &#x3D;&#x3D;&#x3D; &#x27;leave&#x27;) { /** * Emitted when a user leaves the chat or is removed by an admin. * @event Client#group_leave * @param {GroupNotification} notification GroupNotification with more information about the action */ this.emit(Events.GROUP_LEAVE, notification); } else { /** * Emitted when group settings are updated, such as subject, description or picture. * @event Client#group_update * @param {GroupNotification} notification GroupNotification with more information about the action */ this.emit(Events.GROUP_UPDATE, notification); } return; } const message &#x3D; new Message(this, msg); /** * Emitted when a new message is created, which may include the current user&#x27;s own messages. * @event Client#message_create * @param {Message} message The message that was created */ this.emit(Events.MESSAGE_CREATE, message); if (msg.id.fromMe) return; /** * Emitted when a new message is received. * @event Client#message * @param {Message} message The message that was received */ this.emit(Events.MESSAGE_RECEIVED, message); }); let last_message; await page.exposeFunction(&#x27;onChangeMessageTypeEvent&#x27;, (msg) &#x3D;&gt; { if (msg.type &#x3D;&#x3D;&#x3D; &#x27;revoked&#x27;) { const message &#x3D; new Message(this, msg); let revoked_msg; if (last_message &amp;amp;&amp;amp; msg.id.id &#x3D;&#x3D;&#x3D; last_message.id.id) { revoked_msg &#x3D; new Message(this, last_message); } /** * Emitted when a message is deleted for everyone in the chat. * @event Client#message_revoke_everyone * @param {Message} message The message that was revoked, in its current state. It will not contain the original message&#x27;s data. * @param {?Message} revoked_msg The message that was revoked, before it was revoked. It will contain the message&#x27;s original data. * Note that due to the way this data is captured, it may be possible that this param will be undefined. */ this.emit(Events.MESSAGE_REVOKED_EVERYONE, message, revoked_msg); } }); await page.exposeFunction(&#x27;onChangeMessageEvent&#x27;, (msg) &#x3D;&gt; { if (msg.type !&#x3D;&#x3D; &#x27;revoked&#x27;) { last_message &#x3D; msg; } }); await page.exposeFunction(&#x27;onRemoveMessageEvent&#x27;, (msg) &#x3D;&gt; { if (!msg.isNewMsg) return; const message &#x3D; new Message(this, msg); /** * Emitted when a message is deleted by the current user. * @event Client#message_revoke_me * @param {Message} message The message that was revoked */ this.emit(Events.MESSAGE_REVOKED_ME, message); }); await page.exposeFunction(&#x27;onMessageAckEvent&#x27;, (msg, ack) &#x3D;&gt; { const message &#x3D; new Message(this, msg); /** * Emitted when an ack event occurrs on message type. * @event Client#message_ack * @param {Message} message The message that was affected * @param {MessageAck} ack The new ACK value */ this.emit(Events.MESSAGE_ACK, message, ack); }); await page.exposeFunction(&#x27;onMessageMediaUploadedEvent&#x27;, (msg) &#x3D;&gt; { const message &#x3D; 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(&#x27;onAppStateChangedEvent&#x27;, (state) &#x3D;&gt; { /** * Emitted when the connection state changes * @event Client#change_state * @param {WAState} state the new connection state */ this.emit(Events.STATE_CHANGED, state); const ACCEPTED_STATES &#x3D; [WAState.CONNECTED, WAState.OPENING, WAState.PAIRING, WAState.TIMEOUT]; if (this.options.takeoverOnConflict) { ACCEPTED_STATES.push(WAState.CONFLICT); if (state &#x3D;&#x3D;&#x3D; WAState.CONFLICT) { setTimeout(() &#x3D;&gt; { this.pupPage.evaluate(() &#x3D;&gt; window.Store.AppState.takeover()); }, this.options.takeoverTimeoutMs); } } if (!ACCEPTED_STATES.includes(state)) { /** * Emitted when the client has been disconnected * @event Client#disconnected * @param {WAState|&quot;NAVIGATION&quot;} reason reason that caused the disconnect */ this.emit(Events.DISCONNECTED, state); this.destroy(); } }); await page.exposeFunction(&#x27;onBatteryStateChangedEvent&#x27;, (state) &#x3D;&gt; { const { battery, plugged } &#x3D; state; if (battery &#x3D;&#x3D;&#x3D; 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.exposeFunction(&#x27;onIncomingCall&#x27;, (call) &#x3D;&gt; { /** * Emitted when a call is received * @event Client#incoming_call * @param {object} call * @param {number} call.id - Call id * @param {string} call.peerJid - Who called * @param {boolean} call.isVideo - if is video * @param {boolean} call.isGroup - if is group * @param {boolean} call.canHandleLocally - if we can handle in waweb * @param {boolean} call.outgoing - if is outgoing * @param {boolean} call.webClientShouldHandle - If Waweb should handle * @param {object} call.participants - Participants */ const cll &#x3D; new Call(this,call); this.emit(Events.INCOMING_CALL, cll); }); await page.evaluate(() &#x3D;&gt; { window.Store.Msg.on(&#x27;add&#x27;, (msg) &#x3D;&gt; { if (msg.isNewMsg) window.onAddMessageEvent(window.WWebJS.getMessageModel(msg)); }); window.Store.Msg.on(&#x27;change&#x27;, (msg) &#x3D;&gt; { window.onChangeMessageEvent(window.WWebJS.getMessageModel(msg)); }); window.Store.Msg.on(&#x27;change:type&#x27;, (msg) &#x3D;&gt; { window.onChangeMessageTypeEvent(window.WWebJS.getMessageModel(msg)); }); window.Store.Msg.on(&#x27;change:ack&#x27;, (msg,ack) &#x3D;&gt; { window.onMessageAckEvent(window.WWebJS.getMessageModel(msg), ack); }); window.Store.Msg.on(&#x27;change:isUnsentMedia&#x27;, (msg, unsent) &#x3D;&gt; { if (msg.id.fromMe &amp;amp;&amp;amp; !unsent) window.onMessageMediaUploadedEvent(window.WWebJS.getMessageModel(msg)); }); window.Store.Msg.on(&#x27;remove&#x27;, (msg) &#x3D;&gt; { if (msg.isNewMsg) window.onRemoveMessageEvent(window.WWebJS.getMessageModel(msg)); }); window.Store.AppState.on(&#x27;change:state&#x27;, (_AppState, state) &#x3D;&gt; { window.onAppStateChangedEvent(state); }); window.Store.Conn.on(&#x27;change:battery&#x27;, (state) &#x3D;&gt; { window.onBatteryStateChangedEvent(state); }); window.Store.Call.on(&#x27;add&#x27;, (call) &#x3D;&gt; { window.onIncomingCall(call); }); }); /** * Emitted when the client has initialized and is ready to receive messages. * @event Client#ready */ this.emit(Events.READY); // Disconnect when navigating away // Because WhatsApp Web now reloads when logging out from the device, this also covers that case this.pupPage.on(&#x27;framenavigated&#x27;, async () &#x3D;&gt; { this.emit(Events.DISCONNECTED, &#x27;NAVIGATION&#x27;); await this.destroy(); }); } /** * Closes the client */ async destroy() { if (this._qrRefreshInterval) { clearInterval(this._qrRefreshInterval); } await this.pupBrowser.close(); } /** * Logs out the client, closing the current session */ async logout() { return await this.pupPage.evaluate(() &#x3D;&gt; { return window.Store.AppState.logout(); }); } /** * Returns the version of WhatsApp Web currently being run * @returns {Promise&amp;lt;string&gt;} */ async getWWebVersion() { return await this.pupPage.evaluate(() &#x3D;&gt; { return window.Debug.VERSION; }); } /** * Mark as seen for the Chat * @param {string} chatId * @returns {Promise&amp;lt;boolean&gt;} result * */ async sendSeen(chatId) { const result &#x3D; await this.pupPage.evaluate(async (chatId) &#x3D;&gt; { return window.WWebJS.sendSeen(chatId); }, chatId); return result; } /** * Message options. * @typedef {Object} MessageSendOptions * @property {boolean} [linkPreview&#x3D;true] - Show links preview * @property {boolean} [sendAudioAsVoice&#x3D;false] - Send audio as voice message * @property {boolean} [sendVideoAsGif&#x3D;false] - Send video as gif * @property {boolean} [sendMediaAsSticker&#x3D;false] - Send media as a sticker * @property {boolean} [sendMediaAsDocument&#x3D;false] - Send media as a document * @property {boolean} [parseVCards&#x3D;true] - Automatically parse vCards and send them as contacts * @property {string} [caption] - Image or video caption * @property {string} [quotedMessageId] - Id of the message that is being quoted (or replied to) * @property {Contact[]} [mentions] - Contacts that are being mentioned in the message * @property {boolean} [sendSeen&#x3D;true] - Mark the conversation as seen after sending the message * @property {string} [stickerAuthor&#x3D;undefined] - Sets the author of the sticker, (if sendMediaAsSticker is true). * @property {string} [stickerName&#x3D;undefined] - Sets the name of the sticker, (if sendMediaAsSticker is true). * @property {string[]} [stickerCategories&#x3D;undefined] - Sets the categories of the sticker, (if sendMediaAsSticker is true). Provide emoji char array, can be null. * @property {MessageMedia} [media] - Media to be sent */ /** * Send a message to a specific chatId * @param {string} chatId * @param {string|MessageMedia|Location|Contact|Array&amp;lt;Contact&gt;} content * @param {MessageSendOptions} [options] - Options used when sending the message * * @returns {Promise&amp;lt;Message&gt;} Message that was just sent */ async sendMessage(chatId, content, options &#x3D; {}) { let internalOptions &#x3D; { linkPreview: options.linkPreview &#x3D;&#x3D;&#x3D; false ? undefined : true, sendAudioAsVoice: options.sendAudioAsVoice, sendVideoAsGif: options.sendVideoAsGif, sendMediaAsSticker: options.sendMediaAsSticker, sendMediaAsDocument: options.sendMediaAsDocument, caption: options.caption, quotedMessageId: options.quotedMessageId, parseVCards: options.parseVCards &#x3D;&#x3D;&#x3D; false ? false : true, mentionedJidList: Array.isArray(options.mentions) ? options.mentions.map(contact &#x3D;&gt; contact.id._serialized) : [], ...options.extra }; const sendSeen &#x3D; typeof options.sendSeen &#x3D;&#x3D;&#x3D; &#x27;undefined&#x27; ? true : options.sendSeen; if (content instanceof MessageMedia) { internalOptions.attachment &#x3D; content; content &#x3D; &#x27;&#x27;; } else if (options.media instanceof MessageMedia) { internalOptions.attachment &#x3D; options.media; internalOptions.caption &#x3D; content; content &#x3D; &#x27;&#x27;; } else if (content instanceof Location) { internalOptions.location &#x3D; content; content &#x3D; &#x27;&#x27;; } else if(content instanceof Contact) { internalOptions.contactCard &#x3D; content.id._serialized; content &#x3D; &#x27;&#x27;; } else if(Array.isArray(content) &amp;amp;&amp;amp; content.length &gt; 0 &amp;amp;&amp;amp; content[0] instanceof Contact) { internalOptions.contactCardList &#x3D; content.map(contact &#x3D;&gt; contact.id._serialized); content &#x3D; &#x27;&#x27;; } if (internalOptions.sendMediaAsSticker &amp;amp;&amp;amp; internalOptions.attachment) { internalOptions.attachment &#x3D; await Util.formatToWebpSticker(internalOptions.attachment, { name: options.stickerName, author: options.stickerAuthor, categories: options.stickerCategories }); } const newMessage &#x3D; await this.pupPage.evaluate(async (chatId, message, options, sendSeen) &#x3D;&gt; { const chatWid &#x3D; window.Store.WidFactory.createWid(chatId); const chat &#x3D; await window.Store.Chat.find(chatWid); if (sendSeen) { window.WWebJS.sendSeen(chatId); } const msg &#x3D; await window.WWebJS.sendMessage(chat, message, options, sendSeen); return msg.serialize(); }, chatId, content, internalOptions, sendSeen); return new Message(this, newMessage); } /** * Searches for messages * @param {string} query * @param {Object} [options] * @param {number} [options.page] * @param {number} [options.limit] * @param {string} [options.chatId] * @returns {Promise&amp;lt;Message[]&gt;} */ async searchMessages(query, options &#x3D; {}) { const messages &#x3D; await this.pupPage.evaluate(async (query, page, count, remote) &#x3D;&gt; { const { messages } &#x3D; await window.Store.Msg.search(query, page, count, remote); return messages.map(msg &#x3D;&gt; window.WWebJS.getMessageModel(msg)); }, query, options.page, options.limit, options.chatId); return messages.map(msg &#x3D;&gt; new Message(this, msg)); } /** * Get all current chat instances * @returns {Promise&amp;lt;Array&amp;lt;Chat&gt;&gt;} */ async getChats() { let chats &#x3D; await this.pupPage.evaluate(async () &#x3D;&gt; { return await window.WWebJS.getChats(); }); return chats.map(chat &#x3D;&gt; ChatFactory.create(this, chat)); } /** * Get chat instance by ID * @param {string} chatId * @returns {Promise&amp;lt;Chat&gt;} */ async getChatById(chatId) { let chat &#x3D; await this.pupPage.evaluate(async chatId &#x3D;&gt; { return await window.WWebJS.getChat(chatId); }, chatId); return ChatFactory.create(this, chat); } /** * Get all current contact instances * @returns {Promise&amp;lt;Array&amp;lt;Contact&gt;&gt;} */ async getContacts() { let contacts &#x3D; await this.pupPage.evaluate(() &#x3D;&gt; { return window.WWebJS.getContacts(); }); return contacts.map(contact &#x3D;&gt; ContactFactory.create(this, contact)); } /** * Get contact instance by ID * @param {string} contactId * @returns {Promise&amp;lt;Contact&gt;} */ async getContactById(contactId) { let contact &#x3D; await this.pupPage.evaluate(contactId &#x3D;&gt; { return window.WWebJS.getContact(contactId); }, contactId); return ContactFactory.create(this, contact); } /** * Returns an object with information about the invite code&#x27;s group * @param {string} inviteCode * @returns {Promise&amp;lt;object&gt;} Invite information */ async getInviteInfo(inviteCode) { return await this.pupPage.evaluate(inviteCode &#x3D;&gt; { return window.Store.Wap.groupInviteInfo(inviteCode); }, inviteCode); } /** * Accepts an invitation to join a group * @param {string} inviteCode Invitation code * @returns {Promise&amp;lt;string&gt;} Id of the joined Chat */ async acceptInvite(inviteCode) { const chatId &#x3D; await this.pupPage.evaluate(async inviteCode &#x3D;&gt; { return await window.Store.Invite.sendJoinGroupViaInvite(inviteCode); }, inviteCode); return chatId._serialized; } /** * Accepts a private invitation to join a group * @param {object} inviteV4 Invite V4 Info * @returns {Promise&amp;lt;Object&gt;} */ async acceptGroupV4Invite(inviteInfo) { if(!inviteInfo.inviteCode) throw &#x27;Invalid invite code, try passing the message.inviteV4 object&#x27;; if (inviteInfo.inviteCodeExp &#x3D;&#x3D; 0) throw &#x27;Expired invite code&#x27;; return await this.pupPage.evaluate(async inviteInfo &#x3D;&gt; { let { groupId, fromId, inviteCode, inviteCodeExp, toId } &#x3D; inviteInfo; return await window.Store.Wap.acceptGroupV4Invite(groupId, fromId, inviteCode, String(inviteCodeExp), toId); }, inviteInfo); } /** * Sets the current user&#x27;s status message * @param {string} status New status message */ async setStatus(status) { await this.pupPage.evaluate(async status &#x3D;&gt; { return await window.Store.Wap.sendSetStatus(status); }, status); } /** * Sets the current user&#x27;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(displayName) { await this.pupPage.evaluate(async displayName &#x3D;&gt; { return await window.Store.Wap.setPushname(displayName); }, displayName); } /** * Gets the current connection state for the client * @returns {WAState} */ async getState() { return await this.pupPage.evaluate(() &#x3D;&gt; { return window.Store.AppState.state; }); } /** * Marks the client as online */ async sendPresenceAvailable() { return await this.pupPage.evaluate(() &#x3D;&gt; { return window.Store.Wap.sendPresenceAvailable(); }); } /** * Enables and returns the archive state of the Chat * @returns {boolean} */ async archiveChat(chatId) { return await this.pupPage.evaluate(async chatId &#x3D;&gt; { let chat &#x3D; await window.Store.Chat.get(chatId); await window.Store.Cmd.archiveChat(chat, true); return chat.archive; }, chatId); } /** * Changes and returns the archive state of the Chat * @returns {boolean} */ async unarchiveChat(chatId) { return await this.pupPage.evaluate(async chatId &#x3D;&gt; { let chat &#x3D; await window.Store.Chat.get(chatId); await window.Store.Cmd.archiveChat(chat, false); return chat.archive; }, chatId); } /** * Pins the Chat * @returns {Promise&amp;lt;boolean&gt;} New pin state. Could be false if the max number of pinned chats was reached. */ async pinChat(chatId) { return this.pupPage.evaluate(async chatId &#x3D;&gt; { let chat &#x3D; window.Store.Chat.get(chatId); if (chat.pin) { return true; } const MAX_PIN_COUNT &#x3D; 3; if (window.Store.Chat.models.length &gt; MAX_PIN_COUNT) { let maxPinned &#x3D; window.Store.Chat.models[MAX_PIN_COUNT - 1].pin; if (maxPinned) { return false; } } await window.Store.Cmd.pinChat(chat, true); return true; }, chatId); } /** * Unpins the Chat * @returns {Promise&amp;lt;boolean&gt;} New pin state */ async unpinChat(chatId) { return this.pupPage.evaluate(async chatId &#x3D;&gt; { let chat &#x3D; window.Store.Chat.get(chatId); if (!chat.pin) { return false; } await window.Store.Cmd.pinChat(chat, false); return false; }, chatId); } /** * 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) { await this.pupPage.evaluate(async (chatId, timestamp) &#x3D;&gt; { let chat &#x3D; await window.Store.Chat.get(chatId); await chat.mute.mute(timestamp, !0); }, chatId, unmuteDate.getTime() / 1000); } /** * Unmutes the Chat * @param {string} chatId ID of the chat that will be unmuted */ async unmuteChat(chatId) { await this.pupPage.evaluate(async chatId &#x3D;&gt; { let chat &#x3D; await window.Store.Chat.get(chatId); await window.Store.Cmd.muteChat(chat, false); }, chatId); } /** * Mark the Chat as unread * @param {string} chatId ID of the chat that will be marked as unread */ async markChatUnread(chatId) { await this.pupPage.evaluate(async chatId &#x3D;&gt; { let chat &#x3D; await window.Store.Chat.get(chatId); await window.Store.Cmd.markChatUnread(chat, true); }, chatId); } /** * Returns the contact ID&#x27;s profile picture URL, if privacy settings allow it * @param {string} contactId the whatsapp user&#x27;s ID * @returns {Promise&amp;lt;string&gt;} */ async getProfilePicUrl(contactId) { const profilePic &#x3D; await this.pupPage.evaluate((contactId) &#x3D;&gt; { return window.Store.Wap.profilePicFind(contactId); }, contactId); return profilePic ? profilePic.eurl : undefined; } /** * Force reset of connection state for the client */ async resetState() { await this.pupPage.evaluate(() &#x3D;&gt; { window.Store.AppState.phoneWatchdog.shiftTimer.forceRunNow(); }); } /** * Check if a given ID is registered in whatsapp * @param {string} id the whatsapp user&#x27;s ID * @returns {Promise&amp;lt;Boolean&gt;} */ async isRegisteredUser(id) { return await this.pupPage.evaluate(async (id) &#x3D;&gt; { let result &#x3D; await window.Store.Wap.queryExist(id); return result.jid !&#x3D;&#x3D; undefined; }, id); } /** * Get the registered WhatsApp ID for a number. * Will return null if the number is not registered on WhatsApp. * @param {string} number Number or ID (&quot;@c.us&quot; will be automatically appended if not specified) * @returns {Promise&amp;lt;Object|null&gt;} */ async getNumberId(number) { if(!number.endsWith(&#x27;@c.us&#x27;)) { number +&#x3D; &#x27;@c.us&#x27;; } try { return await this.pupPage.evaluate(async numberId &#x3D;&gt; { return window.WWebJS.getNumberId(numberId); }, number); } catch(_) { return null; } } /** * Create a new group * @param {string} name group title * @param {Array&amp;lt;Contact|string&gt;} 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.&amp;lt;string,string&gt;} 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&#x27;s privacy settings don&#x27;t allow you to add them to groups. */ async createGroup(name, participants) { if (!Array.isArray(participants) || participants.length &#x3D;&#x3D; 0) { throw &#x27;You need to add at least one other participant to the group&#x27;; } if (participants.every(c &#x3D;&gt; c instanceof Contact)) { participants &#x3D; participants.map(c &#x3D;&gt; c.id._serialized); } const createRes &#x3D; await this.pupPage.evaluate(async (name, participantIds) &#x3D;&gt; { const res &#x3D; await window.Store.Wap.createGroup(name, participantIds); console.log(res); if (!res.status &#x3D;&#x3D;&#x3D; 200) { throw &#x27;An error occurred while creating the group!&#x27;; } return res; }, name, participants); const missingParticipants &#x3D; createRes.participants.reduce(((missing, c) &#x3D;&gt; { const id &#x3D; Object.keys(c)[0]; const statusCode &#x3D; c[id].code; if (statusCode !&#x3D; 200) return Object.assign(missing, { [id]: statusCode }); return missing; }), {}); return { gid: createRes.gid, missingParticipants }; } /** * Get all current Labels * @returns {Promise&amp;lt;Array&amp;lt;Label&gt;&gt;} */ async getLabels() { const labels &#x3D; await this.pupPage.evaluate(async () &#x3D;&gt; { return window.WWebJS.getLabels(); }); return labels.map(data &#x3D;&gt; new Label(this , data)); } /** * Get Label instance by ID * @param {string} labelId * @returns {Promise&amp;lt;Label&gt;} */ async getLabelById(labelId) { const label &#x3D; await this.pupPage.evaluate(async (labelId) &#x3D;&gt; { return window.WWebJS.getLabel(labelId); }, labelId); return new Label(this, label); } /** * Get all Labels assigned to a chat * @param {string} chatId * @returns {Promise&amp;lt;Array&amp;lt;Label&gt;&gt;} */ async getChatLabels(chatId){ const labels &#x3D; await this.pupPage.evaluate(async (chatId) &#x3D;&gt; { return window.WWebJS.getChatLabels(chatId); }, chatId); return labels.map(data &#x3D;&gt; new Label(this, data)); } /** * Get all Chats for a specific Label * @param {string} labelId * @returns {Promise&amp;lt;Array&amp;lt;Chat&gt;&gt;} */ async getChatsByLabelId(labelId){ const chatIds &#x3D; await this.pupPage.evaluate(async (labelId) &#x3D;&gt; { const label &#x3D; window.Store.Label.get(labelId); const labelItems &#x3D; label.labelItemCollection.models; return labelItems.reduce((result, item) &#x3D;&gt; { if(item.parentType &#x3D;&#x3D;&#x3D; &#x27;Chat&#x27;){ result.push(item.parentId); } return result; },[]); }, labelId); return Promise.all(chatIds.map(id &#x3D;&gt; this.getChatById(id))); } } module.exports &#x3D; Client; </code></pre> </article> </div> </div> <nav id="jsdoc-toc-nav" role="navigation"></nav> </div> </div> <footer id="jsdoc-footer" class="jsdoc-footer"> <div id="jsdoc-footer-container"> <p> Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on August 1, 2021. </p> </div> </footer> <script src="scripts/jquery.min.js"></script> <script src="scripts/tree.jquery.js"></script> <script src="scripts/prettify.js"></script> <script src="scripts/jsdoc-toc.js"></script> <script src="scripts/linenumber.js"></script> <script src="scripts/scrollanchor.js"></script> </body> </html>