chore(): generate docs

This commit is contained in:
WWebJS Bot 2025-08-08 21:39:18 +00:00
commit 30b3f5e82e
77 changed files with 1732 additions and 368 deletions

View file

@ -4,7 +4,7 @@
<head>
<meta name="generator" content="JSDoc 3.6.11">
<meta charset="utf-8">
<title>whatsapp-web.js 1.31.1-alpha.0 &raquo; Source: Client.js</title>
<title>whatsapp-web.js 1.32.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">
@ -15,7 +15,7 @@
<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>31.<wbr>1-alpha.<wbr>0</a>
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>32.<wbr>0</a>
</div>
</div>
</nav>
@ -46,7 +46,7 @@ const { LoadUtils } &#x3D; require(&#x27;./util/Injected/Utils&#x27;);
const ChatFactory &#x3D; require(&#x27;./factories/ChatFactory&#x27;);
const ContactFactory &#x3D; require(&#x27;./factories/ContactFactory&#x27;);
const WebCacheFactory &#x3D; require(&#x27;./webCache/WebCacheFactory&#x27;);
const { Broadcast, Buttons, Call, ClientInfo, Contact, GroupNotification, Label, List, Location, Message, MessageMedia, Poll, PollVote, Reaction } &#x3D; require(&#x27;./structures&#x27;);
const { ClientInfo, Message, MessageMedia, Contact, Location, Poll, PollVote, GroupNotification, Label, Call, Buttons, List, Reaction, Broadcast, ScheduledEvent } &#x3D; require(&#x27;./structures&#x27;);
const NoAuth &#x3D; require(&#x27;./authStrategies/NoAuth&#x27;);
const {exposeFunctionIfAbsent} &#x3D; require(&#x27;./util/Puppeteer&#x27;);
@ -67,6 +67,8 @@ const {exposeFunctionIfAbsent} &#x3D; require(&#x27;./util/Puppeteer&#x27;);
* @param {string} options.userAgent - User agent to use in puppeteer
* @param {string} options.ffmpegPath - Ffmpeg path to use when formatting videos to webp while sending stickers
* @param {boolean} options.bypassCSP - Sets bypassing of page&#x27;s Content-Security-Policy.
* @param {string} options.deviceName - Sets the device name of a current linked device., i.e.: &#x27;TEST&#x27;.
* @param {string} options.browserName - Sets the browser name of a current linked device, i.e.: &#x27;Firefox&#x27;.
* @param {object} options.proxyAuthentication - Proxy Authentication object.
*
* @fires Client#qr
@ -125,7 +127,8 @@ class Client extends EventEmitter {
*/
async inject() {
await this.pupPage.waitForFunction(&#x27;window.Debug?.VERSION !&#x3D; undefined&#x27;, {timeout: this.options.authTimeoutMs});
await this.setDeviceName(this.options.deviceName, this.options.browserName);
const pairWithPhoneNumber &#x3D; this.options.pairWithPhoneNumber;
const version &#x3D; await this.getWWebVersion();
const isCometOrAbove &#x3D; parseInt(version.split(&#x27;.&#x27;)?.[1]) &gt;&#x3D; 3000;
@ -171,41 +174,55 @@ class Client extends EventEmitter {
return;
}
// Register qr events
let qrRetries &#x3D; 0;
await exposeFunctionIfAbsent(this.pupPage, &#x27;onQRChangedEvent&#x27;, async (qr) &#x3D;&gt; {
/**
* Emitted when a QR code is received
* @event Client#qr
* @param {string} qr QR Code
*/
this.emit(Events.QR_RECEIVED, qr);
if (this.options.qrMaxRetries &gt; 0) {
qrRetries++;
if (qrRetries &gt; this.options.qrMaxRetries) {
this.emit(Events.DISCONNECTED, &#x27;Max qrcode retries reached&#x27;);
await this.destroy();
// Register qr/code events
if (pairWithPhoneNumber.phoneNumber) {
await exposeFunctionIfAbsent(this.pupPage, &#x27;onCodeReceivedEvent&#x27;, async (code) &#x3D;&gt; {
/**
* Emitted when a pairing code is received
* @event Client#code
* @param {string} code Code
* @returns {string} Code that was just received
*/
this.emit(Events.CODE_RECEIVED, code);
return code;
});
this.requestPairingCode(pairWithPhoneNumber.phoneNumber, pairWithPhoneNumber.showNotification, pairWithPhoneNumber.intervalMs);
} else {
let qrRetries &#x3D; 0;
await exposeFunctionIfAbsent(this.pupPage, &#x27;onQRChangedEvent&#x27;, async (qr) &#x3D;&gt; {
/**
* Emitted when a QR code is received
* @event Client#qr
* @param {string} qr QR Code
*/
this.emit(Events.QR_RECEIVED, qr);
if (this.options.qrMaxRetries &gt; 0) {
qrRetries++;
if (qrRetries &gt; this.options.qrMaxRetries) {
this.emit(Events.DISCONNECTED, &#x27;Max qrcode retries reached&#x27;);
await this.destroy();
}
}
}
});
});
await this.pupPage.evaluate(async () &#x3D;&gt; {
const registrationInfo &#x3D; await window.AuthStore.RegistrationUtils.waSignalStore.getRegistrationInfo();
const noiseKeyPair &#x3D; await window.AuthStore.RegistrationUtils.waNoiseInfo.get();
const staticKeyB64 &#x3D; window.AuthStore.Base64Tools.encodeB64(noiseKeyPair.staticKeyPair.pubKey);
const identityKeyB64 &#x3D; window.AuthStore.Base64Tools.encodeB64(registrationInfo.identityKeyPair.pubKey);
const advSecretKey &#x3D; await window.AuthStore.RegistrationUtils.getADVSecretKey();
const platform &#x3D; window.AuthStore.RegistrationUtils.DEVICE_PLATFORM;
const getQR &#x3D; (ref) &#x3D;&gt; ref + &#x27;,&#x27; + staticKeyB64 + &#x27;,&#x27; + identityKeyB64 + &#x27;,&#x27; + advSecretKey + &#x27;,&#x27; + platform;
window.onQRChangedEvent(getQR(window.AuthStore.Conn.ref)); // initial qr
window.AuthStore.Conn.on(&#x27;change:ref&#x27;, (_, ref) &#x3D;&gt; { window.onQRChangedEvent(getQR(ref)); }); // future QR changes
});
await this.pupPage.evaluate(async () &#x3D;&gt; {
const registrationInfo &#x3D; await window.AuthStore.RegistrationUtils.waSignalStore.getRegistrationInfo();
const noiseKeyPair &#x3D; await window.AuthStore.RegistrationUtils.waNoiseInfo.get();
const staticKeyB64 &#x3D; window.AuthStore.Base64Tools.encodeB64(noiseKeyPair.staticKeyPair.pubKey);
const identityKeyB64 &#x3D; window.AuthStore.Base64Tools.encodeB64(registrationInfo.identityKeyPair.pubKey);
const advSecretKey &#x3D; await window.AuthStore.RegistrationUtils.getADVSecretKey();
const platform &#x3D; window.AuthStore.RegistrationUtils.DEVICE_PLATFORM;
const getQR &#x3D; (ref) &#x3D;&gt; ref + &#x27;,&#x27; + staticKeyB64 + &#x27;,&#x27; + identityKeyB64 + &#x27;,&#x27; + advSecretKey + &#x27;,&#x27; + platform;
window.onQRChangedEvent(getQR(window.AuthStore.Conn.ref)); // initial qr
window.AuthStore.Conn.on(&#x27;change:ref&#x27;, (_, ref) &#x3D;&gt; { window.onQRChangedEvent(getQR(ref)); }); // future QR changes
});
}
}
await exposeFunctionIfAbsent(this.pupPage, &#x27;onAuthAppStateChangedEvent&#x27;, async (state) &#x3D;&gt; {
if (state &#x3D;&#x3D; &#x27;UNPAIRED_IDLE&#x27;) {
if (state &#x3D;&#x3D; &#x27;UNPAIRED_IDLE&#x27; &amp;amp;&amp;amp; !pairWithPhoneNumber.phoneNumber) {
// refresh qr code
window.Store.Cmd.refreshQR();
}
@ -374,15 +391,32 @@ class Client extends EventEmitter {
/**
* Request authentication via pairing code instead of QR code
* @param {string} phoneNumber - Phone number in international, symbol-free format (e.g. 12025550108 for US, 551155501234 for Brazil)
* @param {boolean} showNotification - Show notification to pair on phone number
* @param {boolean} [showNotification &#x3D; true] - Show notification to pair on phone number
* @param {number} [intervalMs &#x3D; 180000] - The interval in milliseconds on how frequent to generate pairing code (WhatsApp default to 3 minutes)
* @returns {Promise&amp;lt;string&gt;} - Returns a pairing code in format &quot;ABCDEFGH&quot;
*/
async requestPairingCode(phoneNumber, showNotification &#x3D; true) {
return await this.pupPage.evaluate(async (phoneNumber, showNotification) &#x3D;&gt; {
window.AuthStore.PairingCodeLinkUtils.setPairingType(&#x27;ALT_DEVICE_LINKING&#x27;);
await window.AuthStore.PairingCodeLinkUtils.initializeAltDeviceLinking();
return window.AuthStore.PairingCodeLinkUtils.startAltLinkingFlow(phoneNumber, showNotification);
}, phoneNumber, showNotification);
async requestPairingCode(phoneNumber, showNotification &#x3D; true, intervalMs &#x3D; 180000) {
return await this.pupPage.evaluate(async (phoneNumber, showNotification, intervalMs) &#x3D;&gt; {
const getCode &#x3D; async () &#x3D;&gt; {
while (!window.AuthStore.PairingCodeLinkUtils) {
await new Promise(resolve &#x3D;&gt; setTimeout(resolve, 250));
}
window.AuthStore.PairingCodeLinkUtils.setPairingType(&#x27;ALT_DEVICE_LINKING&#x27;);
await window.AuthStore.PairingCodeLinkUtils.initializeAltDeviceLinking();
return window.AuthStore.PairingCodeLinkUtils.startAltLinkingFlow(phoneNumber, showNotification);
};
if (window.codeInterval) {
clearInterval(window.codeInterval); // remove existing interval
}
window.codeInterval &#x3D; setInterval(async () &#x3D;&gt; {
if (window.AuthStore.AppState.state !&#x3D; &#x27;UNPAIRED&#x27; &amp;amp;&amp;amp; window.AuthStore.AppState.state !&#x3D; &#x27;UNPAIRED_IDLE&#x27;) {
clearInterval(window.codeInterval);
return;
}
window.onCodeReceivedEvent(await getCode());
}, intervalMs);
return window.onCodeReceivedEvent(await getCode());
}, phoneNumber, showNotification, intervalMs);
}
/**
@ -844,6 +878,19 @@ class Client extends EventEmitter {
});
}
async setDeviceName(deviceName, browserName) {
(deviceName || browserName) &amp;amp;&amp;amp; await this.pupPage.evaluate((deviceName, browserName) &#x3D;&gt; {
const func &#x3D; window.require(&#x27;WAWebMiscBrowserUtils&#x27;).info;
window.require(&#x27;WAWebMiscBrowserUtils&#x27;).info &#x3D; () &#x3D;&gt; {
return {
...func(),
...(deviceName ? { os: deviceName } : {}),
...(browserName ? { name: browserName } : {})
};
};
}, deviceName, browserName);
}
/**
* Mark as seen for the Chat
* @param {string} chatId
@ -954,6 +1001,9 @@ class Client extends EventEmitter {
} else if (content instanceof Poll) {
internalOptions.poll &#x3D; content;
content &#x3D; &#x27;&#x27;;
} else if (content instanceof ScheduledEvent) {
internalOptions.event &#x3D; content;
content &#x3D; &#x27;&#x27;;
} else if (content instanceof Contact) {
internalOptions.contactCard &#x3D; content.id._serialized;
content &#x3D; &#x27;&#x27;;
@ -1158,6 +1208,29 @@ class Client extends EventEmitter {
return null;
}
/**
* Gets instances of all pinned messages in a chat
* @param {string} chatId The chat ID
* @returns {Promise&amp;lt;[Message]|[]&gt;}
*/
async getPinnedMessages(chatId) {
const pinnedMsgs &#x3D; await this.pupPage.evaluate(async (chatId) &#x3D;&gt; {
const chatWid &#x3D; window.Store.WidFactory.createWid(chatId);
const chat &#x3D; window.Store.Chat.get(chatWid) ?? await window.Store.Chat.find(chatWid);
if (!chat) return [];
const msgs &#x3D; await window.Store.PinnedMsgUtils.getTable().equals([&#x27;chatId&#x27;], chatWid.toString());
const pinnedMsgs &#x3D; msgs.map((msg) &#x3D;&gt; window.Store.Msg.get(msg.parentMsgKey));
return !pinnedMsgs.length
? []
: pinnedMsgs.map((msg) &#x3D;&gt; window.WWebJS.getMessageModel(msg));
}, chatId);
return pinnedMsgs.map((msg) &#x3D;&gt; new Message(this, msg));
}
/**
* Returns an object with information about the invite code&#x27;s group
* @param {string} inviteCode
@ -1559,6 +1632,10 @@ class Client extends EventEmitter {
* @property {string|undefined} parentGroupId The ID of a parent community group to link the newly created group with (won&#x27;t take an effect if the group is been creating with myself only)
* @property {boolean} [autoSendInviteV4 &#x3D; true] If true, the inviteV4 will be sent to those participants who have restricted others from being automatically added to groups, otherwise the inviteV4 won&#x27;t be sent (true by default)
* @property {string} [comment &#x3D; &#x27;&#x27;] The comment to be added to an inviteV4 (empty string by default)
* @property {boolean} [memberAddMode &#x3D; false] If true, only admins can add members to the group (false by default)
* @property {boolean} [membershipApprovalMode &#x3D; false] If true, group admins will be required to approve anyone who wishes to join the group (false by default)
* @property {boolean} [isRestrict &#x3D; true] If true, only admins can change group group info (true by default)
* @property {boolean} [isAnnounce &#x3D; false] If true, only admins can send messages (false by default)
*/
/**
@ -1573,7 +1650,12 @@ class Client extends EventEmitter {
participants.map(p &#x3D;&gt; (p instanceof Contact) ? p.id._serialized : p);
return await this.pupPage.evaluate(async (title, participants, options) &#x3D;&gt; {
const { messageTimer &#x3D; 0, parentGroupId, autoSendInviteV4 &#x3D; true, comment &#x3D; &#x27;&#x27; } &#x3D; options;
const {
messageTimer &#x3D; 0,
parentGroupId,
autoSendInviteV4 &#x3D; true,
comment &#x3D; &#x27;&#x27;,
} &#x3D; options;
const participantData &#x3D; {}, participantWids &#x3D; [], failedParticipants &#x3D; [];
let createGroupResult, parentGroupWid;
@ -1586,7 +1668,9 @@ class Client extends EventEmitter {
for (const participant of participants) {
const pWid &#x3D; window.Store.WidFactory.createWid(participant);
if ((await window.Store.QueryExist(pWid))?.wid) participantWids.push(pWid);
if ((await window.Store.QueryExist(pWid))?.wid) {
participantWids.push({ phoneNumber: pWid });
}
else failedParticipants.push(participant);
}
@ -1595,14 +1679,13 @@ class Client extends EventEmitter {
try {
createGroupResult &#x3D; await window.Store.GroupUtils.createGroup(
{
&#x27;memberAddMode&#x27;: options.memberAddMode &#x3D;&#x3D;&#x3D; undefined ? true : options.memberAddMode,
&#x27;membershipApprovalMode&#x27;: options.membershipApprovalMode &#x3D;&#x3D;&#x3D; undefined ? false : options.membershipApprovalMode,
&#x27;announce&#x27;: options.announce &#x3D;&#x3D;&#x3D; undefined ? true : options.announce,
&#x27;addressingModeOverride&#x27;: &#x27;lid&#x27;,
&#x27;memberAddMode&#x27;: options.memberAddMode ?? false,
&#x27;membershipApprovalMode&#x27;: options.membershipApprovalMode ?? false,
&#x27;announce&#x27;: options.announce ?? false,
&#x27;restrict&#x27;: options.isRestrict !&#x3D;&#x3D; undefined ? !options.isRestrict : false,
&#x27;ephemeralDuration&#x27;: messageTimer,
&#x27;full&#x27;: undefined,
&#x27;parentGroupId&#x27;: parentGroupWid,
&#x27;restrict&#x27;: options.restrict &#x3D;&#x3D;&#x3D; undefined ? true : options.restrict,
&#x27;thumb&#x27;: undefined,
&#x27;title&#x27;: title,
},
participantWids
@ -1613,13 +1696,14 @@ class Client extends EventEmitter {
for (const participant of createGroupResult.participants) {
let isInviteV4Sent &#x3D; false;
participant.wid.server &#x3D;&#x3D; &#x27;lid&#x27; &amp;amp;&amp;amp; (participant.wid &#x3D; window.Store.LidUtils.getPhoneNumber(participant.wid));
const participantId &#x3D; participant.wid._serialized;
const statusCode &#x3D; participant.error || 200;
if (autoSendInviteV4 &amp;amp;&amp;amp; statusCode &#x3D;&#x3D;&#x3D; 403) {
window.Store.Contact.gadd(participant.wid, { silent: true });
const addParticipantResult &#x3D; await window.Store.GroupInviteV4.sendGroupInviteMessage(
await window.Store.Chat.find(participant.wid),
window.Store.Chat.get(participant.wid) || await window.Store.Chat.find(participant.wid),
createGroupResult.wid._serialized,
createGroupResult.subject,
participant.invite_code,
@ -1627,9 +1711,7 @@ class Client extends EventEmitter {
comment,
await window.WWebJS.getProfilePicThumbToBase64(createGroupResult.wid)
);
isInviteV4Sent &#x3D; window.compareWwebVersions(window.Debug.VERSION, &#x27;&amp;lt;&#x27;, &#x27;2.2335.6&#x27;)
? addParticipantResult &#x3D;&#x3D;&#x3D; &#x27;OK&#x27;
: addParticipantResult.messageSendResult &#x3D;&#x3D;&#x3D; &#x27;OK&#x27;;
isInviteV4Sent &#x3D; addParticipantResult.messageSendResult &#x3D;&#x3D;&#x3D; &#x27;OK&#x27;;
}
participantData[participantId] &#x3D; {
@ -2179,6 +2261,45 @@ class Client extends EventEmitter {
}, chatId);
}
/**
* Generates a WhatsApp call link (video call or voice call)
* @param {Date} startTime The start time of the call
* @param {string} callType The type of a WhatsApp call link to generate, valid values are: &#x60;video&#x60; | &#x60;voice&#x60;
* @returns {Promise&amp;lt;string&gt;} The WhatsApp call link (https://call.whatsapp.com/video/XxXxXxXxXxXxXx) or an empty string if a generation failed.
*/
async createCallLink(startTime, callType) {
if (![&#x27;video&#x27;, &#x27;voice&#x27;].includes(callType)) {
throw new class CreateCallLinkError extends Error {
constructor(m) { super(m); }
}(&#x27;Invalid \&#x27;callType\&#x27; parameter value is provided. Valid values are: \&#x27;voice\&#x27; | \&#x27;video\&#x27;.&#x27;);
}
startTime &#x3D; Math.floor(startTime.getTime() / 1000);
return await this.pupPage.evaluate(async (startTimeTs, callType) &#x3D;&gt; {
const response &#x3D; await window.Store.ScheduledEventMsgUtils.createEventCallLink(startTimeTs, callType);
return response ?? &#x27;&#x27;;
}, startTime, callType);
}
/**
* Sends a response to the scheduled event message, indicating whether a user is going to attend the event or not
* @param {number} response The response code to the scheduled event message. Valid values are: &#x60;0&#x60; for NONE response (removes a previous response) | &#x60;1&#x60; for GOING | &#x60;2&#x60; for NOT GOING | &#x60;3&#x60; for MAYBE going
* @param {string} eventMessageId The scheduled event message ID
* @returns {Promise&amp;lt;boolean&gt;}
*/
async sendResponseToScheduledEvent(response, eventMessageId) {
if (![0, 1, 2, 3].includes(response)) return false;
return await this.pupPage.evaluate(async (response, msgId) &#x3D;&gt; {
const eventMsg &#x3D; window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
if (!eventMsg) return false;
await window.Store.ScheduledEventMsgUtils.sendEventResponseMsg(response, eventMsg);
return true;
}, response, eventMessageId);
}
/**
* Save new contact to user&#x27;s addressbook or edit the existing one
* @param {string} phoneNumber The contact&#x27;s phone number in a format &quot;17182222222&quot;, where &quot;1&quot; is a country code
@ -2211,6 +2332,28 @@ class Client extends EventEmitter {
return await window.Store.AddressbookContactUtils.deleteContactAction(phoneNumber);
}, phoneNumber);
}
/**
* Get lid and phone number for multiple users
* @param {string[]} userIds - Array of user IDs
* @returns {Promise&amp;lt;Array&amp;lt;{ lid: string, pn: string }&gt;&gt;}
*/
async getContactLidAndPhone(userIds) {
return await this.pupPage.evaluate((userIds) &#x3D;&gt; {
!Array.isArray(userIds) &amp;amp;&amp;amp; (userIds &#x3D; [userIds]);
return userIds.map(userId &#x3D;&gt; {
const wid &#x3D; window.Store.WidFactory.createWid(userId);
const isLid &#x3D; wid.server &#x3D;&#x3D;&#x3D; &#x27;lid&#x27;;
const lid &#x3D; isLid ? wid : window.Store.LidUtils.getCurrentLid(wid);
const phone &#x3D; isLid ? window.Store.LidUtils.getPhoneNumber(wid) : wid;
return {
lid: lid._serialized,
pn: phone._serialized
};
});
}, userIds);
}
}
module.exports &#x3D; Client;
@ -2224,7 +2367,7 @@ module.exports &#x3D; Client;
<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.11 on June 30, 2025.
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.11 on August 8, 2025.
</p>
</div>
</footer>