-
takeoverOnConflict
@@ -1540,6 +1519,38 @@ Private function
+
+
+
+
+
+
+ async
cancelPairingCode () Cancels an active pairing code session and returns to QR code mode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -4996,6 +5007,86 @@ the lastMessage property of a found channel will be 'null'
+
+
+
+
+
+ async
sendReaction (messageId, reaction) → Promise Send an emoji reaction to a specific message
+
+
+
+ Parameters
+
+
+
+ Name
+ Type
+ Optional
+ Description
+
+
+
+
+
+ messageId
+
+
+ string
+
+
+
+
+
+ Id of the message to add the reaction.
+
+
+
+
+
+ reaction
+
+
+ string
+
+
+
+
+
+ Emoji to react with. Send an empty string to remove the reaction.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Returns
+ Promise
@@ -7526,7 +7617,69 @@ that has the membership approval mode turned on
- message_ciphertext Emitted when messages are edited
+ message_ciphertext Emitted when a message is received as ciphertext (not yet decrypted)
+
+
+
+ Parameter
+
+
+
+ Name
+ Type
+ Optional
+ Description
+
+
+
+
+
+ message
+
+
+ Message
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ message_ciphertext_failed Emitted when a ciphertext message failed to decrypt after recovery attempt
@@ -8237,7 +8390,7 @@ shows a user's current selected option(s) on the poll
diff --git a/docs/Client.js.html b/docs/Client.js.html
index f3ee343..5a9a3d3 100644
--- a/docs/Client.js.html
+++ b/docs/Client.js.html
@@ -1,77 +1,92 @@
-
-
-
-
- whatsapp-web.js 1.34.6 » Source: Client.js
-
-
-
-
-
-
-
-
+
+
+
+ whatsapp-web.js 1.34.7 » Source: Client.js
+
+
+
+
+
+
+
-
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+ 'use strict';
const EventEmitter = require('events');
const puppeteer = require('puppeteer');
-const moduleRaid = require('@pedroslopez/moduleraid/moduleraid');
const Util = require('./util/Util');
const InterfaceController = require('./util/InterfaceController');
-const { WhatsWebURL, DefaultOptions, Events, WAState, MessageTypes } = require('./util/Constants');
+const {
+ WhatsWebURL,
+ DefaultOptions,
+ Events,
+ WAState,
+ MessageTypes,
+} = require('./util/Constants');
const { ExposeAuthStore } = require('./util/Injected/AuthStore/AuthStore');
-const { ExposeStore } = require('./util/Injected/Store');
-const { ExposeLegacyAuthStore } = require('./util/Injected/AuthStore/LegacyAuthStore');
-const { ExposeLegacyStore } = require('./util/Injected/LegacyStore');
const { LoadUtils } = require('./util/Injected/Utils');
const ChatFactory = require('./factories/ChatFactory');
const ContactFactory = require('./factories/ContactFactory');
const WebCacheFactory = require('./webCache/WebCacheFactory');
-const { ClientInfo, Message, MessageMedia, Contact, Location, Poll, PollVote, GroupNotification, Label, Call, Buttons, List, Reaction, Broadcast, ScheduledEvent } = require('./structures');
+const {
+ ClientInfo,
+ Message,
+ MessageMedia,
+ Contact,
+ Location,
+ Poll,
+ PollVote,
+ GroupNotification,
+ Label,
+ Call,
+ Buttons,
+ List,
+ Reaction,
+ Broadcast,
+ ScheduledEvent,
+} = require('./structures');
const NoAuth = require('./authStrategies/NoAuth');
-const {exposeFunctionIfAbsent} = require('./util/Puppeteer');
+const { exposeFunctionIfAbsent } = require('./util/Puppeteer');
/**
* Starting point for interacting with the WhatsApp Web API
* @extends {EventEmitter}
* @param {object} options - Client options
- * @param {AuthStrategy} options.authStrategy - Determines how to save and restore sessions. Will use LegacySessionAuth if options.session is set. Otherwise, NoAuth will be used.
+ * @param {AuthStrategy} options.authStrategy - Determines how to save and restore sessions. If not set, NoAuth will be used.
* @param {string} options.webVersion - The version of WhatsApp Web to use. Use options.webVersionCache to configure how the version is retrieved.
* @param {object} options.webVersionCache - Determines how to retrieve the WhatsApp Web version. Defaults to a local cache (LocalWebCache) that falls back to latest if the requested version is not found.
* @param {number} options.authTimeoutMs - Timeout for authentication selector in puppeteer
* @param {function} options.evalOnNewDoc - function to eval on new doc
* @param {object} options.puppeteer - Puppeteer launch options. View docs here: https://github.com/puppeteer/puppeteer/
* @param {number} options.qrMaxRetries - How many times should the qrcode be refreshed before giving up
- * @param {string} options.restartOnAuthFail - @deprecated This option should be set directly on the LegacySessionAuth.
- * @param {object} options.session - @deprecated Only here for backwards-compatibility. You should move to using LocalAuth, or set the authStrategy to LegacySessionAuth explicitly.
* @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 formatting videos to webp while sending stickers
+ * @param {string} options.ffmpegPath - Ffmpeg path to use when formatting videos to webp while sending stickers
* @param {boolean} options.bypassCSP - Sets bypassing of page's Content-Security-Policy.
* @param {string} options.deviceName - Sets the device name of a current linked device., i.e.: 'TEST'.
* @param {string} options.browserName - Sets the browser name of a current linked device, i.e.: 'Firefox'.
* @param {object} options.proxyAuthentication - Proxy Authentication object.
- *
+ *
* @fires Client#qr
* @fires Client#authenticated
* @fires Client#auth_failure
@@ -99,8 +114,8 @@ class Client extends EventEmitter {
super();
this.options = Util.mergeDefault(DefaultOptions, options);
-
- if(!this.options.authStrategy) {
+
+ if (!this.options.authStrategy) {
this.authStrategy = new NoAuth();
} else {
this.authStrategy = this.options.authStrategy;
@@ -122,58 +137,83 @@ class Client extends EventEmitter {
Util.setFfmpegPath(this.options.ffmpegPath);
}
+
/**
* Injection logic
* Private function
*/
async inject() {
- if(this.options.authTimeoutMs === undefined || this.options.authTimeoutMs==0){
+ if (
+ this.options.authTimeoutMs === undefined ||
+ this.options.authTimeoutMs == 0
+ ) {
this.options.authTimeoutMs = 30000;
}
let start = Date.now();
let timeout = this.options.authTimeoutMs;
let res = false;
- while(start > (Date.now() - timeout)){
- res = await this.pupPage.evaluate('window.Debug?.VERSION != undefined');
- if(res){break;}
- await new Promise(r => setTimeout(r, 200));
+ while (start > Date.now() - timeout) {
+ res = await this.pupPage.evaluate(
+ 'window.Debug?.VERSION != undefined',
+ );
+ if (res) {
+ break;
+ }
+ await new Promise((r) => setTimeout(r, 200));
}
- if(!res){
+ if (!res) {
throw 'auth timeout';
- }
- await this.setDeviceName(this.options.deviceName, this.options.browserName);
+ }
+ await this.setDeviceName(
+ this.options.deviceName,
+ this.options.browserName,
+ );
const pairWithPhoneNumber = this.options.pairWithPhoneNumber;
const version = await this.getWWebVersion();
- const isCometOrAbove = parseInt(version.split('.')?.[1]) >= 3000;
- if (isCometOrAbove) {
- await this.pupPage.evaluate(ExposeAuthStore);
- } else {
- await this.pupPage.evaluate(ExposeLegacyAuthStore, moduleRaid.toString());
- }
+ await this.pupPage.evaluate(ExposeAuthStore);
const needAuthentication = await this.pupPage.evaluate(async () => {
- let state = window.AuthStore.AppState.state;
+ let state = window.require('WAWebSocketModel').Socket.state;
- if (state === 'OPENING' || state === 'UNLAUNCHED' || state === 'PAIRING') {
+ if (
+ state === 'OPENING' ||
+ state === 'UNLAUNCHED' ||
+ state === 'PAIRING'
+ ) {
// wait till state changes
- await new Promise(r => {
- window.AuthStore.AppState.on('change:state', function waitTillInit(_AppState, state) {
- if (state !== 'OPENING' && state !== 'UNLAUNCHED' && state !== 'PAIRING') {
- window.AuthStore.AppState.off('change:state', waitTillInit);
- r();
- }
- });
- });
+ await new Promise((r) => {
+ window
+ .require('WAWebSocketModel')
+ .Socket.on(
+ 'change:state',
+ function waitTillInit(_AppState, state) {
+ if (
+ state !== 'OPENING' &&
+ state !== 'UNLAUNCHED' &&
+ state !== 'PAIRING'
+ ) {
+ window
+ .require('WAWebSocketModel')
+ .Socket.off(
+ 'change:state',
+ waitTillInit,
+ );
+ r();
+ }
+ },
+ );
+ });
}
- state = window.AuthStore.AppState.state;
+ state = window.require('WAWebSocketModel').Socket.state;
return state == 'UNPAIRED' || state == 'UNPAIRED_IDLE';
});
if (needAuthentication) {
- const { failed, failureEventPayload, restart } = await this.authStrategy.onAuthenticationNeeded();
+ const { failed, failureEventPayload, restart } =
+ await this.authStrategy.onAuthenticationNeeded();
- if(failed) {
+ if (failed) {
/**
* Emitted when there has been an error while trying to restore an existing session
* @event Client#auth_failure
@@ -190,138 +230,224 @@ class Client extends EventEmitter {
// Register qr/code events
if (pairWithPhoneNumber.phoneNumber) {
- await exposeFunctionIfAbsent(this.pupPage, 'onCodeReceivedEvent', async (code) => {
- /**
- * 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);
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onCodeReceivedEvent',
+ async (code) => {
+ /**
+ * 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 = 0;
- await exposeFunctionIfAbsent(this.pupPage, 'onQRChangedEvent', async (qr) => {
- /**
- * 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 > 0) {
- qrRetries++;
- if (qrRetries > this.options.qrMaxRetries) {
- this.emit(Events.DISCONNECTED, 'Max qrcode retries reached');
- await this.destroy();
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onQRChangedEvent',
+ async (qr) => {
+ /**
+ * 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 > 0) {
+ qrRetries++;
+ if (qrRetries > this.options.qrMaxRetries) {
+ this.emit(
+ Events.DISCONNECTED,
+ 'Max qrcode retries reached',
+ );
+ await this.destroy();
+ }
}
- }
- });
-
+ },
+ );
await this.pupPage.evaluate(async () => {
- const registrationInfo = await window.AuthStore.RegistrationUtils.waSignalStore.getRegistrationInfo();
- const noiseKeyPair = await window.AuthStore.RegistrationUtils.waNoiseInfo.get();
- const staticKeyB64 = window.AuthStore.Base64Tools.encodeB64(noiseKeyPair.staticKeyPair.pubKey);
- const identityKeyB64 = window.AuthStore.Base64Tools.encodeB64(registrationInfo.identityKeyPair.pubKey);
- const advSecretKey = await window.AuthStore.RegistrationUtils.getADVSecretKey();
- const platform = window.AuthStore.RegistrationUtils.DEVICE_PLATFORM;
- const getQR = (ref) => ref + ',' + staticKeyB64 + ',' + identityKeyB64 + ',' + advSecretKey + ',' + platform;
-
+ const registrationInfo =
+ await window.AuthStore.RegistrationUtils.waSignalStore.getRegistrationInfo();
+ const noiseKeyPair =
+ await window.AuthStore.RegistrationUtils.waNoiseInfo.get();
+ const staticKeyB64 = window.AuthStore.Base64Tools.encodeB64(
+ noiseKeyPair.staticKeyPair.pubKey,
+ );
+ const identityKeyB64 =
+ window.AuthStore.Base64Tools.encodeB64(
+ registrationInfo.identityKeyPair.pubKey,
+ );
+ const platform =
+ window.AuthStore.RegistrationUtils.DEVICE_PLATFORM;
+ const getQR = (ref) =>
+ ref +
+ ',' +
+ staticKeyB64 +
+ ',' +
+ identityKeyB64 +
+ ',' +
+ window
+ .require('WAWebUserPrefsMultiDevice')
+ .getADVSecretKey() +
+ ',' +
+ platform;
window.onQRChangedEvent(getQR(window.AuthStore.Conn.ref)); // initial qr
- window.AuthStore.Conn.on('change:ref', (_, ref) => { window.onQRChangedEvent(getQR(ref)); }); // future QR changes
+ window.AuthStore.Conn.on('change:ref', (_, ref) => {
+ window.onQRChangedEvent(getQR(ref));
+ }); // future QR changes
});
}
}
- await exposeFunctionIfAbsent(this.pupPage, 'onAuthAppStateChangedEvent', async (state) => {
- if (state == 'UNPAIRED_IDLE' && !pairWithPhoneNumber.phoneNumber) {
- // refresh qr code
- window.Store.Cmd.refreshQR();
- }
- });
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onAuthAppStateChangedEvent',
+ async (state) => {
+ if (
+ state == 'UNPAIRED_IDLE' &&
+ !pairWithPhoneNumber.phoneNumber
+ ) {
+ // refresh qr code
+ window.require('WAWebCmd').Cmd.refreshQR();
+ }
+ },
+ );
- await exposeFunctionIfAbsent(this.pupPage, 'onAppStateHasSyncedEvent', async () => {
- const authEventPayload = await this.authStrategy.getAuthEventPayload();
- /**
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onAppStateHasSyncedEvent',
+ async () => {
+ const authEventPayload =
+ await this.authStrategy.getAuthEventPayload();
+ /**
* Emitted when authentication is successful
* @event Client#authenticated
*/
- this.emit(Events.AUTHENTICATED, authEventPayload);
+ this.emit(Events.AUTHENTICATED, authEventPayload);
- const injected = await this.pupPage.evaluate(async () => {
- return typeof window.Store !== 'undefined' && typeof window.WWebJS !== 'undefined';
- });
+ const injected = await this.pupPage.evaluate(async () => {
+ return typeof window.WWebJS !== 'undefined';
+ });
- if (!injected) {
- if (this.options.webVersionCache.type === 'local' && this.currentIndexHtml) {
- const { type: webCacheType, ...webCacheOptions } = this.options.webVersionCache;
- const webCache = WebCacheFactory.createWebCache(webCacheType, webCacheOptions);
-
- await webCache.persist(this.currentIndexHtml, version);
- }
+ if (!injected) {
+ if (
+ this.options.webVersionCache.type === 'local' &&
+ this.currentIndexHtml
+ ) {
+ const { type: webCacheType, ...webCacheOptions } =
+ this.options.webVersionCache;
+ const webCache = WebCacheFactory.createWebCache(
+ webCacheType,
+ webCacheOptions,
+ );
- if (isCometOrAbove) {
- await this.pupPage.evaluate(ExposeStore);
- } else {
- // make sure all modules are ready before injection
- // 2 second delay after authentication makes sense and does not need to be made dyanmic or removed
- await new Promise(r => setTimeout(r, 2000));
- await this.pupPage.evaluate(ExposeLegacyStore);
- }
- let start = Date.now();
- let res = false;
- while(start > (Date.now() - 30000)){
- // Check window.Store Injection
- res = await this.pupPage.evaluate('window.Store != undefined');
- if(res){break;}
- await new Promise(r => setTimeout(r, 200));
- }
- if(!res){
- throw 'ready timeout';
- }
-
- /**
+ await webCache.persist(this.currentIndexHtml, version);
+ }
+
+ // Load util functions (serializers, helper functions)
+ await this.pupPage.evaluate(LoadUtils);
+
+ let start = Date.now();
+ let res = false;
+ while (start > Date.now() - 30000) {
+ // Check window.WWebJS Injection
+ res = await this.pupPage.evaluate(
+ 'window.WWebJS != undefined',
+ );
+ if (res) {
+ break;
+ }
+ await new Promise((r) => setTimeout(r, 200));
+ }
+ if (!res) {
+ throw 'ready timeout';
+ }
+
+ /**
* Current connection information
* @type {ClientInfo}
*/
- this.info = new ClientInfo(this, await this.pupPage.evaluate(() => {
- return { ...window.Store.Conn.serialize(), wid: window.Store.User.getMaybeMePnUser() || window.Store.User.getMaybeMeLidUser() };
- }));
+ this.info = new ClientInfo(
+ this,
+ await this.pupPage.evaluate(() => {
+ return {
+ ...window
+ .require('WAWebConnModel')
+ .Conn.serialize(),
+ wid:
+ window
+ .require('WAWebUserPrefsMeUser')
+ .getMaybeMePnUser() ||
+ window
+ .require('WAWebUserPrefsMeUser')
+ .getMaybeMeLidUser(),
+ };
+ }),
+ );
- this.interface = new InterfaceController(this);
+ this.interface = new InterfaceController(this);
- //Load util functions (serializers, helper functions)
- await this.pupPage.evaluate(LoadUtils);
-
- await this.attachEventListeners();
- }
- /**
+ await this.attachEventListeners();
+ }
+ /**
* Emitted when the client has initialized and is ready to receive messages.
* @event Client#ready
*/
- this.emit(Events.READY);
- this.authStrategy.afterAuthReady();
- });
+ this.emit(Events.READY);
+ this.authStrategy.afterAuthReady();
+ },
+ );
let lastPercent = null;
- await exposeFunctionIfAbsent(this.pupPage, 'onOfflineProgressUpdateEvent', async (percent) => {
- if (lastPercent !== percent) {
- lastPercent = percent;
- this.emit(Events.LOADING_SCREEN, percent, 'WhatsApp'); // Message is hardcoded as "WhatsApp" for now
- }
- });
- await exposeFunctionIfAbsent(this.pupPage, 'onLogoutEvent', async () => {
- this.lastLoggedOut = true;
- await this.pupPage.waitForNavigation({waitUntil: 'load', timeout: 5000}).catch((_) => _);
- });
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onOfflineProgressUpdateEvent',
+ async (percent) => {
+ if (lastPercent !== percent) {
+ lastPercent = percent;
+ this.emit(Events.LOADING_SCREEN, percent, 'WhatsApp'); // Message is hardcoded as "WhatsApp" for now
+ }
+ },
+ );
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onLogoutEvent',
+ async () => {
+ this.lastLoggedOut = true;
+ await this.pupPage
+ .waitForNavigation({ waitUntil: 'load', timeout: 5000 })
+ .catch((_) => _);
+ },
+ );
await this.pupPage.evaluate(() => {
- window.AuthStore.AppState.on('change:state', (_AppState, state) => { window.onAuthAppStateChangedEvent(state); });
- window.AuthStore.AppState.on('change:hasSynced', () => { window.onAppStateHasSyncedEvent(); });
- window.AuthStore.Cmd.on('offline_progress_update', () => {
- window.onOfflineProgressUpdateEvent(window.AuthStore.OfflineMessageHandler.getOfflineDeliveryProgress());
+ window
+ .require('WAWebSocketModel')
+ .Socket.on('change:state', (_AppState, state) => {
+ window.onAuthAppStateChangedEvent(state);
+ });
+ window
+ .require('WAWebSocketModel')
+ .Socket.on('change:hasSynced', () => {
+ window.onAppStateHasSyncedEvent();
+ });
+ const Cmd = window.require('WAWebCmd').Cmd;
+ Cmd.on('offline_progress_update_from_bridge', () => {
+ window.onOfflineProgressUpdateEvent(
+ window.AuthStore.OfflineMessageHandler.getOfflineDeliveryProgress(),
+ );
});
- window.AuthStore.Cmd.on('logout', async () => {
+ Cmd.on('logout', async () => {
+ await window.onLogoutEvent();
+ });
+ Cmd.on('logout_from_bridge', async () => {
await window.onLogoutEvent();
});
});
@@ -331,12 +457,10 @@ class Client extends EventEmitter {
* Sets up events and requirements, kicks off authentication request
*/
async initialize() {
-
- let
- /**
+ let /**
* @type {puppeteer.Browser}
*/
- browser,
+ browser,
/**
* @type {puppeteer.Page}
*/
@@ -348,25 +472,34 @@ class Client extends EventEmitter {
await this.authStrategy.beforeBrowserInitialized();
const puppeteerOpts = this.options.puppeteer;
- if (puppeteerOpts && (puppeteerOpts.browserWSEndpoint || puppeteerOpts.browserURL)) {
+ if (
+ puppeteerOpts &&
+ (puppeteerOpts.browserWSEndpoint || puppeteerOpts.browserURL)
+ ) {
browser = await puppeteer.connect(puppeteerOpts);
page = await browser.newPage();
} else {
const browserArgs = [...(puppeteerOpts.args || [])];
- if(this.options.userAgent !== false && !browserArgs.find(arg => arg.includes('--user-agent'))) {
+ if (
+ this.options.userAgent !== false &&
+ !browserArgs.find((arg) => arg.includes('--user-agent'))
+ ) {
browserArgs.push(`--user-agent=${this.options.userAgent}`);
}
// navigator.webdriver fix
browserArgs.push('--disable-blink-features=AutomationControlled');
- browser = await puppeteer.launch({...puppeteerOpts, args: browserArgs});
+ browser = await puppeteer.launch({
+ ...puppeteerOpts,
+ args: browserArgs,
+ });
page = (await browser.pages())[0];
}
if (this.options.proxyAuthentication !== undefined) {
await page.authenticate(this.options.proxyAuthentication);
}
- if(this.options.userAgent !== false) {
+ if (this.options.userAgent !== false) {
await page.setUserAgent(this.options.userAgent);
}
if (this.options.bypassCSP) await page.setBypassCSP(true);
@@ -376,35 +509,21 @@ class Client extends EventEmitter {
await this.authStrategy.afterBrowserInitialized();
await this.initWebVersionCache();
-
+
if (this.options.evalOnNewDoc !== undefined) {
await page.evaluateOnNewDocument(this.options.evalOnNewDoc);
}
-
- // ocVersion (isOfficialClient patch)
- // remove after 2.3000.x hard release
- await page.evaluateOnNewDocument(() => {
- const originalError = Error;
- window.originalError = originalError;
- //eslint-disable-next-line no-global-assign
- Error = function (message) {
- const error = new originalError(message);
- const originalStack = error.stack;
- if (error.stack.includes('moduleRaid')) error.stack = originalStack + '\n at https://web.whatsapp.com/vendors~lazy_loaded_low_priority_components.05e98054dbd60f980427.js:2:44';
- return error;
- };
- });
-
+
await page.goto(WhatsWebURL, {
waitUntil: 'load',
timeout: 0,
- referer: 'https://whatsapp.com/'
+ referer: 'https://whatsapp.com/',
});
await this.inject();
this.pupPage.on('framenavigated', async (frame) => {
- if(frame.url().includes('post_logout=1') || this.lastLoggedOut) {
+ if (frame.url().includes('post_logout=1') || this.lastLoggedOut) {
this.emit(Events.DISCONNECTED, 'LOGOUT');
await this.authStrategy.logout();
await this.authStrategy.beforeBrowserInitialized();
@@ -422,28 +541,70 @@ class Client extends EventEmitter {
* @param {number} [intervalMs = 180000] - The interval in milliseconds on how frequent to generate pairing code (WhatsApp default to 3 minutes)
* @returns {Promise<string>} - Returns a pairing code in format "ABCDEFGH"
*/
- async requestPairingCode(phoneNumber, showNotification = true, intervalMs = 180000) {
- return await this.pupPage.evaluate(async (phoneNumber, showNotification, intervalMs) => {
- const getCode = async () => {
- while (!window.AuthStore.PairingCodeLinkUtils) {
- await new Promise(resolve => setTimeout(resolve, 250));
+ async requestPairingCode(
+ phoneNumber,
+ showNotification = true,
+ intervalMs = 180000,
+ ) {
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onCodeReceivedEvent',
+ async (code) => {
+ this.emit(Events.CODE_RECEIVED, code);
+ return code;
+ },
+ );
+ return await this.pupPage.evaluate(
+ async (phoneNumber, showNotification, intervalMs) => {
+ const getCode = async () => {
+ while (!window.AuthStore.PairingCodeLinkUtils) {
+ await new Promise((resolve) =>
+ setTimeout(resolve, 250),
+ );
+ }
+ window.AuthStore.PairingCodeLinkUtils.setPairingType(
+ 'ALT_DEVICE_LINKING',
+ );
+ await window.AuthStore.PairingCodeLinkUtils.initializeAltDeviceLinking();
+ return window.AuthStore.PairingCodeLinkUtils.startAltLinkingFlow(
+ phoneNumber,
+ showNotification,
+ );
+ };
+ if (window.codeInterval) {
+ clearInterval(window.codeInterval); // remove existing interval
}
- window.AuthStore.PairingCodeLinkUtils.setPairingType('ALT_DEVICE_LINKING');
- await window.AuthStore.PairingCodeLinkUtils.initializeAltDeviceLinking();
- return window.AuthStore.PairingCodeLinkUtils.startAltLinkingFlow(phoneNumber, showNotification);
- };
+ window.codeInterval = setInterval(async () => {
+ const state =
+ window.require('WAWebSocketModel').Socket.state;
+ if (state != 'UNPAIRED' && state != 'UNPAIRED_IDLE') {
+ clearInterval(window.codeInterval);
+ return;
+ }
+ window.onCodeReceivedEvent(await getCode());
+ }, intervalMs);
+ return window.onCodeReceivedEvent(await getCode());
+ },
+ phoneNumber,
+ showNotification,
+ intervalMs,
+ );
+ }
+
+ /**
+ * Cancels an active pairing code session and returns to QR code mode
+ */
+ async cancelPairingCode() {
+ await this.pupPage.evaluate(async () => {
if (window.codeInterval) {
- clearInterval(window.codeInterval); // remove existing interval
+ clearInterval(window.codeInterval);
+ window.codeInterval = undefined;
}
- window.codeInterval = setInterval(async () => {
- if (window.AuthStore.AppState.state != 'UNPAIRED' && window.AuthStore.AppState.state != 'UNPAIRED_IDLE') {
- clearInterval(window.codeInterval);
- return;
- }
- window.onCodeReceivedEvent(await getCode());
- }, intervalMs);
- return window.onCodeReceivedEvent(await getCode());
- }, phoneNumber, showNotification, intervalMs);
+ window.require('WAWebLaunchSocketUtils').refreshQR();
+ await window
+ .require('WAWebAltDeviceLinkingApi')
+ .initializeQRLinking();
+ });
}
/**
@@ -452,32 +613,45 @@ class Client extends EventEmitter {
* @property {boolean} reinject is this a reinject?
*/
async attachEventListeners() {
- await exposeFunctionIfAbsent(this.pupPage, 'onAddMessageEvent', msg => {
- if (msg.type === 'gp2') {
- const notification = new GroupNotification(this, msg);
- if (['add', 'invite', 'linked_group_join'].includes(msg.subtype)) {
- /**
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onAddMessageEvent',
+ (msg) => {
+ if (msg.type === 'gp2') {
+ const notification = new GroupNotification(this, msg);
+ if (
+ ['add', 'invite', 'linked_group_join'].includes(
+ msg.subtype,
+ )
+ ) {
+ /**
* 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 === 'remove' || msg.subtype === 'leave') {
- /**
+ this.emit(Events.GROUP_JOIN, notification);
+ } else if (
+ msg.subtype === 'remove' ||
+ msg.subtype === 'leave'
+ ) {
+ /**
* 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 if (msg.subtype === 'promote' || msg.subtype === 'demote') {
- /**
+ this.emit(Events.GROUP_LEAVE, notification);
+ } else if (
+ msg.subtype === 'promote' ||
+ msg.subtype === 'demote'
+ ) {
+ /**
* Emitted when a current user is promoted to an admin or demoted to a regular user.
* @event Client#group_admin_changed
* @param {GroupNotification} notification GroupNotification with more information about the action
*/
- this.emit(Events.GROUP_ADMIN_CHANGED, notification);
- } else if (msg.subtype === 'membership_approval_request') {
- /**
+ this.emit(Events.GROUP_ADMIN_CHANGED, notification);
+ } else if (msg.subtype === 'membership_approval_request') {
+ /**
* Emitted when some user requested to join the group
* that has the membership approval mode turned on
* @event Client#group_membership_request
@@ -486,89 +660,106 @@ class Client extends EventEmitter {
* @param {string} notification.author The user ID that made a request
* @param {number} notification.timestamp The timestamp the request was made at
*/
- this.emit(Events.GROUP_MEMBERSHIP_REQUEST, notification);
- } else {
- /**
+ this.emit(
+ Events.GROUP_MEMBERSHIP_REQUEST,
+ 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);
+ this.emit(Events.GROUP_UPDATE, notification);
+ }
+ return;
}
- return;
- }
- const message = new Message(this, msg);
+ const message = new Message(this, msg);
- /**
+ /**
* Emitted when a new message is created, which may include the current user's own messages.
* @event Client#message_create
* @param {Message} message The message that was created
*/
- this.emit(Events.MESSAGE_CREATE, message);
+ this.emit(Events.MESSAGE_CREATE, message);
- if (msg.id.fromMe) return;
+ 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);
- });
+ this.emit(Events.MESSAGE_RECEIVED, message);
+ },
+ );
let last_message;
- await exposeFunctionIfAbsent(this.pupPage, 'onChangeMessageTypeEvent', (msg) => {
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onChangeMessageTypeEvent',
+ (msg) => {
+ if (msg.type === 'revoked') {
+ const message = new Message(this, msg);
+ let revoked_msg;
+ if (last_message && msg.id.id === last_message.id.id) {
+ revoked_msg = new Message(this, last_message);
- if (msg.type === 'revoked') {
- const message = new Message(this, msg);
- let revoked_msg;
- if (last_message && msg.id.id === last_message.id.id) {
- revoked_msg = new Message(this, last_message);
+ if (message.protocolMessageKey)
+ revoked_msg.id = { ...message.protocolMessageKey };
+ }
- if (message.protocolMessageKey)
- revoked_msg.id = { ...message.protocolMessageKey };
- }
-
- /**
+ /**
* 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's data.
- * @param {?Message} revoked_msg The message that was revoked, before it was revoked. It will contain the message's original data.
+ * @param {?Message} revoked_msg The message that was revoked, before it was revoked. It will contain the message'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);
- }
+ this.emit(
+ Events.MESSAGE_REVOKED_EVERYONE,
+ message,
+ revoked_msg,
+ );
+ }
+ },
+ );
- });
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onChangeMessageEvent',
+ (msg) => {
+ if (msg.type !== 'revoked') {
+ last_message = msg;
+ }
- await exposeFunctionIfAbsent(this.pupPage, 'onChangeMessageEvent', (msg) => {
-
- if (msg.type !== 'revoked') {
- last_message = msg;
- }
-
- /**
+ /**
* The event notification that is received when one of
* the group participants changes their phone number.
*/
- const isParticipant = msg.type === 'gp2' && msg.subtype === 'modify';
+ const isParticipant =
+ msg.type === 'gp2' && msg.subtype === 'modify';
- /**
+ /**
* The event notification that is received when one of
* the contacts changes their phone number.
*/
- const isContact = msg.type === 'notification_template' && msg.subtype === 'change_number';
+ const isContact =
+ msg.type === 'notification_template' &&
+ msg.subtype === 'change_number';
- if (isParticipant || isContact) {
- /** @type {GroupNotification} object does not provide enough information about this event, so a @type {Message} object is used. */
- const message = new Message(this, msg);
+ if (isParticipant || isContact) {
+ /** @type {GroupNotification} object does not provide enough information about this event, so a @type {Message} object is used. */
+ const message = new Message(this, msg);
- const newId = isParticipant ? msg.recipients[0] : msg.to;
- const oldId = isParticipant ? msg.author : msg.templateParams.find(id => id !== newId);
+ const newId = isParticipant ? msg.recipients[0] : msg.to;
+ const oldId = isParticipant
+ ? msg.author
+ : msg.templateParams.find((id) => id !== newId);
- /**
+ /**
* Emitted when a contact or a group participant changes their phone number.
* @event Client#contact_changed
* @param {Message} message Message with more information about the event.
@@ -577,98 +768,132 @@ class Client extends EventEmitter {
* @param {String} newId The user's new id after the change.
* @param {Boolean} isContact Indicates if a contact or a group participant changed their phone number.
*/
- this.emit(Events.CONTACT_CHANGED, message, oldId, newId, isContact);
- }
- });
+ this.emit(
+ Events.CONTACT_CHANGED,
+ message,
+ oldId,
+ newId,
+ isContact,
+ );
+ }
+ },
+ );
- await exposeFunctionIfAbsent(this.pupPage, 'onRemoveMessageEvent', (msg) => {
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onRemoveMessageEvent',
+ (msg) => {
+ if (!msg.isNewMsg) return;
- if (!msg.isNewMsg) return;
+ const message = new Message(this, msg);
- const message = 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);
+ this.emit(Events.MESSAGE_REVOKED_ME, message);
+ },
+ );
- });
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onMessageAckEvent',
+ (msg, ack) => {
+ const message = new Message(this, msg);
- await exposeFunctionIfAbsent(this.pupPage, 'onMessageAckEvent', (msg, ack) => {
-
- const message = 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);
+ this.emit(Events.MESSAGE_ACK, message, ack);
+ },
+ );
- });
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onChatUnreadCountEvent',
+ async (data) => {
+ const chat = await this.getChatById(data.id);
- await exposeFunctionIfAbsent(this.pupPage, 'onChatUnreadCountEvent', async (data) =>{
- const chat = await this.getChatById(data.id);
-
- /**
+ /**
* Emitted when the chat unread count changes
*/
- this.emit(Events.UNREAD_COUNT, chat);
- });
+ this.emit(Events.UNREAD_COUNT, chat);
+ },
+ );
- await exposeFunctionIfAbsent(this.pupPage, 'onMessageMediaUploadedEvent', (msg) => {
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onMessageMediaUploadedEvent',
+ (msg) => {
+ const message = new Message(this, msg);
- const message = new Message(this, msg);
-
- /**
+ /**
* Emitted when media has been uploaded for a message sent by the client.
* @event Client#media_uploaded
* @param {Message} message The message with media that was uploaded
*/
- this.emit(Events.MEDIA_UPLOADED, message);
- });
+ this.emit(Events.MEDIA_UPLOADED, message);
+ },
+ );
- await exposeFunctionIfAbsent(this.pupPage, 'onAppStateChangedEvent', async (state) => {
- /**
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onAppStateChangedEvent',
+ async (state) => {
+ /**
* Emitted when the connection state changes
* @event Client#change_state
* @param {WAState} state the new connection state
*/
- this.emit(Events.STATE_CHANGED, state);
+ this.emit(Events.STATE_CHANGED, state);
- const ACCEPTED_STATES = [WAState.CONNECTED, WAState.OPENING, WAState.PAIRING, WAState.TIMEOUT];
+ const ACCEPTED_STATES = [
+ WAState.CONNECTED,
+ WAState.OPENING,
+ WAState.PAIRING,
+ WAState.TIMEOUT,
+ ];
- if (this.options.takeoverOnConflict) {
- ACCEPTED_STATES.push(WAState.CONFLICT);
+ if (this.options.takeoverOnConflict) {
+ ACCEPTED_STATES.push(WAState.CONFLICT);
- if (state === WAState.CONFLICT) {
- setTimeout(() => {
- this.pupPage.evaluate(() => window.Store.AppState.takeover());
- }, this.options.takeoverTimeoutMs);
+ if (state === WAState.CONFLICT) {
+ setTimeout(() => {
+ this.pupPage.evaluate(() =>
+ window
+ .require('WAWebSocketModel')
+ .Socket.takeover(),
+ );
+ }, this.options.takeoverTimeoutMs);
+ }
}
- }
- if (!ACCEPTED_STATES.includes(state)) {
- /**
+ if (!ACCEPTED_STATES.includes(state)) {
+ /**
* Emitted when the client has been disconnected
* @event Client#disconnected
* @param {WAState|"LOGOUT"} reason reason that caused the disconnect
*/
- await this.authStrategy.disconnect();
- this.emit(Events.DISCONNECTED, state);
- this.destroy();
- }
- });
+ await this.authStrategy.disconnect();
+ this.emit(Events.DISCONNECTED, state);
+ this.destroy();
+ }
+ },
+ );
- await exposeFunctionIfAbsent(this.pupPage, 'onBatteryStateChangedEvent', (state) => {
- const { battery, plugged } = state;
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onBatteryStateChangedEvent',
+ (state) => {
+ const { battery, plugged } = state;
- if (battery === undefined) return;
+ if (battery === undefined) return;
- /**
+ /**
* Emitted when the battery percentage for the attached device changes. Will not be sent if using multi-device.
* @event Client#change_battery
* @param {object} batteryInfo
@@ -676,30 +901,34 @@ class Client extends EventEmitter {
* @param {boolean} batteryInfo.plugged - Indicates if the phone is plugged in (true) or not (false)
* @deprecated
*/
- this.emit(Events.BATTERY_CHANGED, { battery, plugged });
- });
+ this.emit(Events.BATTERY_CHANGED, { battery, plugged });
+ },
+ );
await exposeFunctionIfAbsent(this.pupPage, 'onIncomingCall', (call) => {
/**
- * 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
- */
+ * 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 = new Call(this, call);
this.emit(Events.INCOMING_CALL, cll);
});
- await exposeFunctionIfAbsent(this.pupPage, 'onReaction', (reactions) => {
- for (const reaction of reactions) {
- /**
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onReaction',
+ (reactions) => {
+ for (const reaction of reactions) {
+ /**
* Emitted when a reaction is sent, received, updated or removed
* @event Client#message_reaction
* @param {object} reaction
@@ -714,188 +943,357 @@ class Client extends EventEmitter {
* @param {?number} reaction.ack - Ack
*/
- this.emit(Events.MESSAGE_REACTION, new Reaction(this, reaction));
- }
- });
+ this.emit(
+ Events.MESSAGE_REACTION,
+ new Reaction(this, reaction),
+ );
+ }
+ },
+ );
- await exposeFunctionIfAbsent(this.pupPage, 'onRemoveChatEvent', async (chat) => {
- const _chat = await this.getChatById(chat.id);
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onRemoveChatEvent',
+ async (chat) => {
+ const _chat = await this.getChatById(chat.id);
- /**
+ /**
* Emitted when a chat is removed
* @event Client#chat_removed
* @param {Chat} chat
*/
- this.emit(Events.CHAT_REMOVED, _chat);
- });
-
- await exposeFunctionIfAbsent(this.pupPage, 'onArchiveChatEvent', async (chat, currState, prevState) => {
- const _chat = await this.getChatById(chat.id);
-
- /**
+ this.emit(Events.CHAT_REMOVED, _chat);
+ },
+ );
+
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onArchiveChatEvent',
+ async (chat, currState, prevState) => {
+ const _chat = await this.getChatById(chat.id);
+
+ /**
* Emitted when a chat is archived/unarchived
* @event Client#chat_archived
* @param {Chat} chat
* @param {boolean} currState
* @param {boolean} prevState
*/
- this.emit(Events.CHAT_ARCHIVED, _chat, currState, prevState);
- });
+ this.emit(Events.CHAT_ARCHIVED, _chat, currState, prevState);
+ },
+ );
- await exposeFunctionIfAbsent(this.pupPage, 'onEditMessageEvent', (msg, newBody, prevBody) => {
-
- if(msg.type === 'revoked'){
- return;
- }
- /**
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onEditMessageEvent',
+ (msg, newBody, prevBody) => {
+ if (msg.type === 'revoked') {
+ return;
+ }
+ /**
* Emitted when messages are edited
* @event Client#message_edit
* @param {Message} message
* @param {string} newBody
* @param {string} prevBody
*/
- this.emit(Events.MESSAGE_EDIT, new Message(this, msg), newBody, prevBody);
- });
-
- await exposeFunctionIfAbsent(this.pupPage, 'onAddMessageCiphertextEvent', msg => {
-
- /**
- * Emitted when messages are edited
+ this.emit(
+ Events.MESSAGE_EDIT,
+ new Message(this, msg),
+ newBody,
+ prevBody,
+ );
+ },
+ );
+
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onAddMessageCiphertextEvent',
+ (msg) => {
+ /**
+ * Emitted when a message is received as ciphertext (not yet decrypted)
* @event Client#message_ciphertext
* @param {Message} message
*/
- this.emit(Events.MESSAGE_CIPHERTEXT, new Message(this, msg));
- });
+ this.emit(Events.MESSAGE_CIPHERTEXT, new Message(this, msg));
+ },
+ );
- await exposeFunctionIfAbsent(this.pupPage, 'onPollVoteEvent', (votes) => {
- for (const vote of votes) {
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onCiphertextFailedEvent',
+ (msg) => {
/**
- * Emitted when some poll option is selected or deselected,
- * shows a user's current selected option(s) on the poll
- * @event Client#vote_update
+ * Emitted when a ciphertext message failed to decrypt after recovery attempt
+ * @event Client#message_ciphertext_failed
+ * @param {Message} message
*/
- this.emit(Events.VOTE_UPDATE, new PollVote(this, vote));
- }
- });
+ this.emit(
+ Events.MESSAGE_CIPHERTEXT_FAILED,
+ new Message(this, msg),
+ );
+ },
+ );
+
+ await exposeFunctionIfAbsent(
+ this.pupPage,
+ 'onPollVoteEvent',
+ (votes) => {
+ for (const vote of votes) {
+ /**
+ * Emitted when some poll option is selected or deselected,
+ * shows a user's current selected option(s) on the poll
+ * @event Client#vote_update
+ */
+ this.emit(Events.VOTE_UPDATE, new PollVote(this, vote));
+ }
+ },
+ );
await this.pupPage.evaluate(() => {
- window.Store.Msg.on('change', (msg) => { window.onChangeMessageEvent(window.WWebJS.getMessageModel(msg)); });
- window.Store.Msg.on('change:type', (msg) => { window.onChangeMessageTypeEvent(window.WWebJS.getMessageModel(msg)); });
- window.Store.Msg.on('change:ack', (msg, ack) => { window.onMessageAckEvent(window.WWebJS.getMessageModel(msg), ack); });
- window.Store.Msg.on('change:isUnsentMedia', (msg, unsent) => { if (msg.id.fromMe && !unsent) window.onMessageMediaUploadedEvent(window.WWebJS.getMessageModel(msg)); });
- window.Store.Msg.on('remove', (msg) => { if (msg.isNewMsg) window.onRemoveMessageEvent(window.WWebJS.getMessageModel(msg)); });
- window.Store.Msg.on('change:body change:caption', (msg, newBody, prevBody) => { window.onEditMessageEvent(window.WWebJS.getMessageModel(msg), newBody, prevBody); });
- window.Store.AppState.on('change:state', (_AppState, state) => { window.onAppStateChangedEvent(state); });
- window.Store.Conn.on('change:battery', (state) => { window.onBatteryStateChangedEvent(state); });
- const callCollection = (window.Store && window.Store.Call) || (window.Store && window.Store.WAWebCallCollection);
- if (callCollection && typeof callCollection.on === 'function') {
- callCollection.on('add', (call) => { window.onIncomingCall(call); });
- }
- window.Store.Chat.on('remove', async (chat) => { window.onRemoveChatEvent(await window.WWebJS.getChatModel(chat)); });
- window.Store.Chat.on('change:archive', async (chat, currState, prevState) => { window.onArchiveChatEvent(await window.WWebJS.getChatModel(chat), currState, prevState); });
- window.Store.Msg.on('add', (msg) => {
- if (msg.isNewMsg) {
- if(msg.type === 'ciphertext') {
- // defer message event until ciphertext is resolved (type changed)
- msg.once('change:type', (_msg) => window.onAddMessageEvent(window.WWebJS.getMessageModel(_msg)));
- window.onAddMessageCiphertextEvent(window.WWebJS.getMessageModel(msg));
- } else {
- window.onAddMessageEvent(window.WWebJS.getMessageModel(msg));
- }
- }
+ const { Msg, Chat } = window.require('WAWebCollections');
+ const AppState = window.require('WAWebSocketModel').Socket;
+
+ // Enable placeholder message resend (recovery for ciphertext messages)
+ const gatingUtils = window.require('WAWebSyncGatingUtils');
+ gatingUtils.isPlaceholderMessageResendEnabled = () => true;
+
+ Msg.on('change', (msg) => {
+ window.onChangeMessageEvent(window.WWebJS.getMessageModel(msg));
});
- window.Store.Chat.on('change:unreadCount', (chat) => {window.onChatUnreadCountEvent(chat);});
+ Msg.on('change:type', (msg) => {
+ window.onChangeMessageTypeEvent(
+ window.WWebJS.getMessageModel(msg),
+ );
+ });
+ Msg.on('change:ack', (msg, ack) => {
+ window.onMessageAckEvent(
+ window.WWebJS.getMessageModel(msg),
+ ack,
+ );
+ });
+ Msg.on('change:isUnsentMedia', (msg, unsent) => {
+ if (msg.id.fromMe && !unsent)
+ window.onMessageMediaUploadedEvent(
+ window.WWebJS.getMessageModel(msg),
+ );
+ });
+ Msg.on('remove', (msg) => {
+ if (msg.isNewMsg)
+ window.onRemoveMessageEvent(
+ window.WWebJS.getMessageModel(msg),
+ );
+ });
+ Msg.on('change:body change:caption', (msg, newBody, prevBody) => {
+ window.onEditMessageEvent(
+ window.WWebJS.getMessageModel(msg),
+ newBody,
+ prevBody,
+ );
+ });
+ AppState.on('change:state', (_AppState, state) => {
+ window.onAppStateChangedEvent(state);
+ });
+ window
+ .require('WAWebConnModel')
+ .Conn.on('change:battery', (state) => {
+ window.onBatteryStateChangedEvent(state);
+ });
+ const WAWebCallCollection = window.require('WAWebCallCollection');
+ if (
+ WAWebCallCollection &&
+ typeof WAWebCallCollection.on === 'function'
+ ) {
+ const mapKey = Object.keys(WAWebCallCollection).find(
+ (k) => WAWebCallCollection[k] instanceof Map,
+ );
+ const internalCallMap = WAWebCallCollection[mapKey];
+ const originalMapSet =
+ internalCallMap.set.bind(internalCallMap);
- if (window.compareWwebVersions(window.Debug.VERSION, '>=', '2.3000.1014111620')) {
- const module = window.Store.AddonReactionTable;
- const ogMethod = module.bulkUpsert;
- module.bulkUpsert = ((...args) => {
- window.onReaction(args[0].map(reaction => {
- const msgKey = reaction.id;
- const parentMsgKey = reaction.reactionParentKey;
- const timestamp = reaction.reactionTimestamp / 1000;
- const sender = reaction.author ?? reaction.from;
- const senderUserJid = sender._serialized;
+ internalCallMap.set = function (key, value) {
+ window.onIncomingCall({
+ id: value.id,
+ peerJid: value.peerJid,
+ isVideo: value.isVideo,
+ isGroup: value.isGroup,
+ canHandleLocally: value.canHandleLocally,
+ outgoing: value.outgoing,
+ webClientShouldHandle: value.webClientShouldHandle,
+ participants: value.participants,
+ });
+ return originalMapSet(key, value);
+ };
+ }
+ Chat.on('remove', async (chat) => {
+ window.onRemoveChatEvent(
+ await window.WWebJS.getChatModel(chat),
+ );
+ });
+ Chat.on('change:archive', async (chat, currState, prevState) => {
+ window.onArchiveChatEvent(
+ await window.WWebJS.getChatModel(chat),
+ currState,
+ prevState,
+ );
+ });
+ const pendingResend = new Set();
+ let resendFlush = null;
- return {...reaction, msgKey, parentMsgKey, senderUserJid, timestamp };
- }));
+ function requestResend(msg) {
+ pendingResend.add(msg);
+ if (resendFlush) return;
+ resendFlush = setTimeout(() => {
+ resendFlush = null;
+ const msgs = [...pendingResend];
+ pendingResend.clear();
+ if (msgs.length === 0) return;
+ window
+ .require(
+ 'WAWebNonMessageDataRequestPlaceholderMessageResendUtils',
+ )
+ .handlePlaceholderMsgsSeen(msgs, true);
+ }, 5000);
+ }
- return ogMethod(...args);
- }).bind(module);
+ Msg.on('add', (msg) => {
+ if (!msg.isNewMsg) return;
- const pollVoteModule = window.Store.AddonPollVoteTable;
- const ogPollVoteMethod = pollVoteModule.bulkUpsert;
+ if (msg.type !== 'ciphertext') {
+ window.onAddMessageEvent(
+ window.WWebJS.getMessageModel(msg),
+ );
+ return;
+ }
- pollVoteModule.bulkUpsert = (async (...args) => {
- const votes = await Promise.all(args[0].map(async vote => {
- const msgKey = vote.id;
- const parentMsgKey = vote.pollUpdateParentKey;
- const timestamp = vote.t / 1000;
- const sender = vote.author ?? vote.from;
- const senderUserJid = sender._serialized;
+ window.onAddMessageCiphertextEvent(
+ window.WWebJS.getMessageModel(msg),
+ );
- let parentMessage = window.Store.Msg.get(parentMsgKey._serialized);
- if (!parentMessage) {
- const fetched = await window.Store.Msg.getMessagesById([parentMsgKey._serialized]);
- parentMessage = fetched?.messages?.[0] || null;
- }
+ if (msg.subtype && msg.subtype.endsWith('_unavailable_fanout'))
+ return;
- return {
- ...vote,
- msgKey,
- sender,
- parentMsgKey,
- senderUserJid,
- timestamp,
- parentMessage
- };
- }));
+ requestResend(msg);
+
+ const failTimer = setTimeout(() => {
+ if (msg.type !== 'ciphertext') return;
+ window.onCiphertextFailedEvent(
+ window.WWebJS.getMessageModel(msg),
+ );
+ }, 15000);
+
+ msg.once('change:type', (_msg) => {
+ clearTimeout(failTimer);
+ pendingResend.delete(_msg);
+ if (_msg.type === 'revoked') return;
+ window.onAddMessageEvent(
+ window.WWebJS.getMessageModel(_msg),
+ );
+ });
+ });
+ Chat.on('change:unreadCount', (chat) => {
+ window.onChatUnreadCountEvent(chat);
+ });
+
+ window.WWebJS.injectToFunction(
+ {
+ module: 'WAWebAddonReactionTableMode',
+ function: 'reactionTableMode.bulkUpsert',
+ },
+ (module, origFunction, ...args) => {
+ window.onReaction(
+ args[0].map((reaction) => {
+ const msgKey = reaction.id;
+ const parentMsgKey = reaction.reactionParentKey;
+ const timestamp = reaction.reactionTimestamp / 1000;
+ const sender = reaction.author ?? reaction.from;
+ const senderUserJid = sender._serialized;
+
+ return {
+ ...reaction,
+ msgKey,
+ parentMsgKey,
+ senderUserJid,
+ timestamp,
+ };
+ }),
+ );
+
+ return origFunction.apply(module, args);
+ },
+ );
+
+ window.WWebJS.injectToFunction(
+ {
+ module: 'WAWebAddonPollVoteTableMode',
+ function: 'pollVoteTableMode.bulkUpsert',
+ },
+ async (module, origFunction, ...args) => {
+ const votes = await Promise.all(
+ args[0].map(async (vote) => {
+ const msgKey = vote.id;
+ const parentMsgKey = vote.pollUpdateParentKey;
+ const timestamp = vote.t / 1000;
+ const sender = vote.author ?? vote.from;
+ const senderUserJid = sender._serialized;
+
+ let parentMessage = Msg.get(
+ parentMsgKey._serialized,
+ );
+ if (!parentMessage) {
+ const fetched = await Msg.getMessagesById([
+ parentMsgKey._serialized,
+ ]);
+ parentMessage = fetched?.messages?.[0] || null;
+ }
+
+ return {
+ ...vote,
+ msgKey,
+ sender,
+ parentMsgKey,
+ senderUserJid,
+ timestamp,
+ parentMessage,
+ };
+ }),
+ );
window.onPollVoteEvent(votes);
- return ogPollVoteMethod.apply(pollVoteModule, args);
- }).bind(pollVoteModule);
- } else {
- const module = window.Store.createOrUpdateReactionsModule;
- const ogMethod = module.createOrUpdateReactions;
- module.createOrUpdateReactions = ((...args) => {
- window.onReaction(args[0].map(reaction => {
- const msgKey = window.Store.MsgKey.fromString(reaction.msgKey);
- const parentMsgKey = window.Store.MsgKey.fromString(reaction.parentMsgKey);
- const timestamp = reaction.timestamp / 1000;
-
- return {...reaction, msgKey, parentMsgKey, timestamp };
- }));
-
- return ogMethod(...args);
- }).bind(module);
- }
+ return origFunction.apply(module, args);
+ },
+ );
});
- }
+ }
async initWebVersionCache() {
- const { type: webCacheType, ...webCacheOptions } = this.options.webVersionCache;
- const webCache = WebCacheFactory.createWebCache(webCacheType, webCacheOptions);
+ const { type: webCacheType, ...webCacheOptions } =
+ this.options.webVersionCache;
+ const webCache = WebCacheFactory.createWebCache(
+ webCacheType,
+ webCacheOptions,
+ );
const requestedVersion = this.options.webVersion;
const versionContent = await webCache.resolve(requestedVersion);
- if(versionContent) {
+ if (versionContent) {
await this.pupPage.setRequestInterception(true);
this.pupPage.on('request', async (req) => {
- if(req.url() === WhatsWebURL) {
+ if (req.url() === WhatsWebURL) {
req.respond({
status: 200,
contentType: 'text/html',
- body: versionContent
- });
+ body: versionContent,
+ });
} else {
req.continue();
}
});
} else {
this.pupPage.on('response', async (res) => {
- if(res.ok() && res.url() === WhatsWebURL) {
+ if (res.ok() && res.url() === WhatsWebURL) {
const indexHtml = await res.text();
this.currentIndexHtml = indexHtml;
}
@@ -920,18 +1318,17 @@ class Client extends EventEmitter {
*/
async logout() {
await this.pupPage.evaluate(() => {
- if (window.Store && window.Store.AppState && typeof window.Store.AppState.logout === 'function') {
- return window.Store.AppState.logout();
- }
+ return window.require('WAWebSocketModel').Socket.logout();
});
await this.pupBrowser.close();
-
+
let maxDelay = 0;
- while (this.pupBrowser.isConnected() && (maxDelay < 10)) { // waits a maximum of 1 second before calling the AuthStrategy
- await new Promise(resolve => setTimeout(resolve, 100));
- maxDelay++;
+ while (this.pupBrowser.isConnected() && maxDelay < 10) {
+ // waits a maximum of 1 second before calling the AuthStrategy
+ await new Promise((resolve) => setTimeout(resolve, 100));
+ maxDelay++;
}
-
+
await this.authStrategy.logout();
}
@@ -946,23 +1343,28 @@ class Client extends EventEmitter {
}
async setDeviceName(deviceName, browserName) {
- (deviceName || browserName) && await this.pupPage.evaluate((deviceName, browserName) => {
- const func = window.require('WAWebMiscBrowserUtils').info;
- window.require('WAWebMiscBrowserUtils').info = () => {
- return {
- ...func(),
- ...(deviceName ? { os: deviceName } : {}),
- ...(browserName ? { name: browserName } : {})
- };
- };
- }, deviceName, browserName);
+ (deviceName || browserName) &&
+ (await this.pupPage.evaluate(
+ (deviceName, browserName) => {
+ const func = window.require('WAWebMiscBrowserUtils').info;
+ window.require('WAWebMiscBrowserUtils').info = () => {
+ return {
+ ...func(),
+ ...(deviceName ? { os: deviceName } : {}),
+ ...(browserName ? { name: browserName } : {}),
+ };
+ };
+ },
+ deviceName,
+ browserName,
+ ));
}
/**
* Mark as seen for the Chat
* @param {string} chatId
* @returns {Promise<boolean>} result
- *
+ *
*/
async sendSeen(chatId) {
return await this.pupPage.evaluate(async (chatId) => {
@@ -1002,50 +1404,84 @@ class Client extends EventEmitter {
* @property {MessageMedia} [media] - Media to be sent
* @property {any} [extra] - Extra options
*/
-
+
/**
* Send a message to a specific chatId
* @param {string} chatId
* @param {string|MessageMedia|Location|Poll|Contact|Array<Contact>|Buttons|List} content
* @param {MessageSendOptions} [options] - Options used when sending the message
- *
+ *
* @returns {Promise<Message>} Message that was just sent
*/
async sendMessage(chatId, content, options = {}) {
const isChannel = /@\w*newsletter\b/.test(chatId);
const isStatus = /@\w*broadcast\b/.test(chatId);
- if (isChannel && [
- options.sendMediaAsDocument, options.quotedMessageId,
- options.parseVCards, options.isViewOnce,
- content instanceof Location, content instanceof Contact,
- content instanceof Buttons, content instanceof List,
- Array.isArray(content) && content.length > 0 && content[0] instanceof Contact
- ].includes(true)) {
- console.warn('The message type is currently not supported for sending in channels,\nthe supported message types are: text, image, sticker, gif, video, voice and poll.');
+ if (
+ isChannel &&
+ [
+ options.sendMediaAsDocument,
+ options.quotedMessageId,
+ options.parseVCards,
+ options.isViewOnce,
+ content instanceof Location,
+ content instanceof Contact,
+ content instanceof Buttons,
+ content instanceof List,
+ Array.isArray(content) &&
+ content.length > 0 &&
+ content[0] instanceof Contact,
+ ].includes(true)
+ ) {
+ console.warn(
+ 'The message type is currently not supported for sending in channels,\nthe supported message types are: text, image, sticker, gif, video, voice and poll.',
+ );
return null;
-
- } else if (isStatus && [
- options.sendMediaAsDocument, options.quotedMessageId,
- options.parseVCards, options.isViewOnce, options.sendMediaAsSticker,
- content instanceof Location, content instanceof Contact,
- content instanceof Poll, content instanceof Buttons, content instanceof List,
- Array.isArray(content) && content.length > 0 && content[0] instanceof Contact
- ].includes(true)) {
- console.warn('The message type is currently not supported for sending in status broadcast,\nthe supported message types are: text, image, gif, audio and video.');
+ } else if (
+ isStatus &&
+ [
+ options.sendMediaAsDocument,
+ options.quotedMessageId,
+ options.parseVCards,
+ options.isViewOnce,
+ options.sendMediaAsSticker,
+ content instanceof Location,
+ content instanceof Contact,
+ content instanceof Poll,
+ content instanceof Buttons,
+ content instanceof List,
+ Array.isArray(content) &&
+ content.length > 0 &&
+ content[0] instanceof Contact,
+ ].includes(true)
+ ) {
+ console.warn(
+ 'The message type is currently not supported for sending in status broadcast,\nthe supported message types are: text, image, gif, audio and video.',
+ );
return null;
}
-
+
if (options.mentions) {
- !Array.isArray(options.mentions) && (options.mentions = [options.mentions]);
- if (options.mentions.some((possiblyContact) => possiblyContact instanceof Contact)) {
- console.warn('Mentions with an array of Contact are now deprecated. See more at https://github.com/pedroslopez/whatsapp-web.js/pull/2166.');
- options.mentions = options.mentions.map((a) => a.id._serialized);
+ !Array.isArray(options.mentions) &&
+ (options.mentions = [options.mentions]);
+ if (
+ options.mentions.some(
+ (possiblyContact) => possiblyContact instanceof Contact,
+ )
+ ) {
+ console.warn(
+ 'Mentions with an array of Contact are now deprecated. See more at https://github.com/wwebjssapp-web.js/pull/2166.',
+ );
+ options.mentions = options.mentions.map(
+ (a) => a.id._serialized,
+ );
}
}
- options.groupMentions && !Array.isArray(options.groupMentions) && (options.groupMentions = [options.groupMentions]);
-
+ options.groupMentions &&
+ !Array.isArray(options.groupMentions) &&
+ (options.groupMentions = [options.groupMentions]);
+
let internalOptions = {
linkPreview: options.linkPreview === false ? undefined : true,
sendAudioAsVoice: options.sendAudioAsVoice,
@@ -1054,6 +1490,7 @@ class Client extends EventEmitter {
sendMediaAsDocument: options.sendMediaAsDocument,
sendMediaAsHd: options.sendMediaAsHd,
caption: options.caption,
+ isCaptionByUser: options.caption ? true : false,
quotedMessageId: options.quotedMessageId,
parseVCards: options.parseVCards !== false,
mentionedJidList: options.mentions || [],
@@ -1061,20 +1498,18 @@ class Client extends EventEmitter {
invokedBotWid: options.invokedBotWid,
ignoreQuoteErrors: options.ignoreQuoteErrors !== false,
waitUntilMsgSent: options.waitUntilMsgSent || false,
- extraOptions: options.extra
+ extraOptions: options.extra,
};
const sendSeen = options.sendSeen !== false;
if (content instanceof MessageMedia) {
internalOptions.media = content;
- internalOptions.isViewOnce = options.isViewOnce,
- content = '';
+ ((internalOptions.isViewOnce = options.isViewOnce), (content = ''));
} else if (options.media instanceof MessageMedia) {
internalOptions.media = options.media;
internalOptions.caption = content;
- internalOptions.isViewOnce = options.isViewOnce,
- content = '';
+ ((internalOptions.isViewOnce = options.isViewOnce), (content = ''));
} else if (content instanceof Location) {
internalOptions.location = content;
content = '';
@@ -1087,48 +1522,97 @@ class Client extends EventEmitter {
} else if (content instanceof Contact) {
internalOptions.contactCard = content.id._serialized;
content = '';
- } else if (Array.isArray(content) && content.length > 0 && content[0] instanceof Contact) {
- internalOptions.contactCardList = content.map(contact => contact.id._serialized);
+ } else if (
+ Array.isArray(content) &&
+ content.length > 0 &&
+ content[0] instanceof Contact
+ ) {
+ internalOptions.contactCardList = content.map(
+ (contact) => contact.id._serialized,
+ );
content = '';
} else if (content instanceof Buttons) {
- console.warn('Buttons are now deprecated. See more at https://www.youtube.com/watch?v=hv1R1rLeVVE.');
- if (content.type !== 'chat') { internalOptions.attachment = content.body; }
+ console.warn(
+ 'Buttons are now deprecated. See more at https://www.youtube.com/watch?v=hv1R1rLeVVE.',
+ );
+ if (content.type !== 'chat') {
+ internalOptions.attachment = content.body;
+ }
internalOptions.buttons = content;
content = '';
} else if (content instanceof List) {
- console.warn('Lists are now deprecated. See more at https://www.youtube.com/watch?v=hv1R1rLeVVE.');
+ console.warn(
+ 'Lists are now deprecated. See more at https://www.youtube.com/watch?v=hv1R1rLeVVE.',
+ );
internalOptions.list = content;
content = '';
}
if (internalOptions.sendMediaAsSticker && internalOptions.media) {
internalOptions.media = await Util.formatToWebpSticker(
- internalOptions.media, {
+ internalOptions.media,
+ {
name: options.stickerName,
author: options.stickerAuthor,
- categories: options.stickerCategories
- }, this.pupPage
+ categories: options.stickerCategories,
+ },
+ this.pupPage,
);
}
- const sentMsg = await this.pupPage.evaluate(async (chatId, content, options, sendSeen) => {
- const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
+ const sentMsg = await this.pupPage.evaluate(
+ async (chatId, content, options, sendSeen) => {
+ const chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
- if (!chat) return null;
+ if (!chat) return null;
- if (sendSeen) {
- await window.WWebJS.sendSeen(chatId);
- }
+ if (sendSeen) {
+ await window.WWebJS.sendSeen(chatId);
+ }
- const msg = await window.WWebJS.sendMessage(chat, content, options);
- return msg
- ? window.WWebJS.getMessageModel(msg)
- : undefined;
- }, chatId, content, internalOptions, sendSeen);
+ const msg = await window.WWebJS.sendMessage(
+ chat,
+ content,
+ options,
+ );
+ return msg ? window.WWebJS.getMessageModel(msg) : undefined;
+ },
+ chatId,
+ content,
+ internalOptions,
+ sendSeen,
+ );
- return sentMsg
- ? new Message(this, sentMsg)
- : undefined;
+ return sentMsg ? new Message(this, sentMsg) : undefined;
+ }
+
+ /**
+ * Send an emoji reaction to a specific message
+ * @param {string} messageId - Id of the message to add the reaction.
+ * @param {string} reaction - Emoji to react with. Send an empty string to remove the reaction.
+ * @return {Promise}
+ */
+ async sendReaction(messageId, reaction) {
+ await this.pupPage.evaluate(
+ async (messageId, reaction) => {
+ if (!messageId) return null;
+ const msg =
+ window.require('WAWebCollections').Msg.get(messageId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([messageId])
+ )?.messages?.[0];
+ if (!msg) return null;
+ await window
+ .require('WAWebSendReactionMsgAction')
+ .sendReactionToMsg(msg, reaction);
+ },
+ messageId,
+ reaction,
+ );
}
/**
@@ -1140,33 +1624,45 @@ class Client extends EventEmitter {
* Sends a channel admin invitation to a user, allowing them to become an admin of the channel
* @param {string} chatId The ID of a user to send the channel admin invitation to
* @param {string} channelId The ID of a channel for which the invitation is being sent
- * @param {SendChannelAdminInviteOptions} options
+ * @param {SendChannelAdminInviteOptions} options
* @returns {Promise<boolean>} Returns true if an invitation was sent successfully, false otherwise
*/
async sendChannelAdminInvite(chatId, channelId, options = {}) {
- const response = await this.pupPage.evaluate(async (chatId, channelId, options) => {
- const channelWid = window.Store.WidFactory.createWid(channelId);
- const chatWid = window.Store.WidFactory.createWid(chatId);
- const chat = window.Store.Chat.get(chatWid) || (await window.Store.Chat.find(chatWid));
+ const response = await this.pupPage.evaluate(
+ async (chatId, channelId, options) => {
+ const { createWid } = window.require('WAWebWidFactory');
+ const channelWid = createWid(channelId);
+ const chatWid = createWid(chatId);
+ const chat =
+ window.require('WAWebCollections').Chat.get(chatWid) ||
+ (await window
+ .require('WAWebCollections')
+ .Chat.find(chatWid));
- if (!chatWid.isUser()) {
- return false;
- }
-
- return await window.Store.SendChannelMessage.sendNewsletterAdminInviteMessage(
- chat,
- {
- newsletterWid: channelWid,
- invitee: chatWid,
- inviteMessage: options.comment,
- base64Thumb: await window.WWebJS.getProfilePicThumbToBase64(channelWid)
+ if (!chatWid.isUser()) {
+ return false;
}
- );
- }, chatId, channelId, options);
+
+ return await window
+ .require('WAWebNewsletterSendMsgAction')
+ .sendNewsletterAdminInviteMessage(chat, {
+ newsletterWid: channelWid,
+ invitee: chatWid,
+ inviteMessage: options.comment,
+ base64Thumb:
+ await window.WWebJS.getProfilePicThumbToBase64(
+ channelWid,
+ ),
+ });
+ },
+ chatId,
+ channelId,
+ options,
+ );
return response.messageSendResult === 'OK';
}
-
+
/**
* Searches for messages
* @param {string} query
@@ -1177,12 +1673,22 @@ class Client extends EventEmitter {
* @returns {Promise<Message[]>}
*/
async searchMessages(query, options = {}) {
- const messages = await this.pupPage.evaluate(async (query, page, count, remote) => {
- const { messages } = await window.Store.Msg.search(query, page, count, remote);
- return messages.map(msg => window.WWebJS.getMessageModel(msg));
- }, query, options.page, options.limit, options.chatId);
+ const messages = await this.pupPage.evaluate(
+ async (query, page, count, remote) => {
+ const { messages } = await window
+ .require('WAWebCollections')
+ .Msg.search(query, page, count, remote);
+ return messages.map((msg) =>
+ window.WWebJS.getMessageModel(msg),
+ );
+ },
+ query,
+ options.page,
+ options.limit,
+ options.chatId,
+ );
- return messages.map(msg => new Message(this, msg));
+ return messages.map((msg) => new Message(this, msg));
}
/**
@@ -1194,7 +1700,7 @@ class Client extends EventEmitter {
return await window.WWebJS.getChats();
});
- return chats.map(chat => ChatFactory.create(this, chat));
+ return chats.map((chat) => ChatFactory.create(this, chat));
}
/**
@@ -1211,16 +1717,14 @@ class Client extends EventEmitter {
/**
* Gets chat or channel instance by ID
- * @param {string} chatId
+ * @param {string} chatId
* @returns {Promise<Chat|Channel>}
*/
async getChatById(chatId) {
- const chat = await this.pupPage.evaluate(async chatId => {
+ const chat = await this.pupPage.evaluate(async (chatId) => {
return await window.WWebJS.getChat(chatId);
}, chatId);
- return chat
- ? ChatFactory.create(this, chat)
- : undefined;
+ return chat ? ChatFactory.create(this, chat) : undefined;
}
/**
@@ -1232,7 +1736,8 @@ class Client extends EventEmitter {
const channel = await this.pupPage.evaluate(async (inviteCode) => {
let channelMetadata;
try {
- channelMetadata = await window.WWebJS.getChannelMetadata(inviteCode);
+ channelMetadata =
+ await window.WWebJS.getChannelMetadata(inviteCode);
} catch (err) {
if (err.name === 'ServerStatusCodeError') return null;
throw err;
@@ -1240,9 +1745,7 @@ class Client extends EventEmitter {
return await window.WWebJS.getChat(channelMetadata.id);
}, inviteCode);
- return channel
- ? ChatFactory.create(this, channel)
- : undefined;
+ return channel ? ChatFactory.create(this, channel) : undefined;
}
/**
@@ -1254,7 +1757,7 @@ class Client extends EventEmitter {
return window.WWebJS.getContacts();
});
- return contacts.map(contact => ContactFactory.create(this, contact));
+ return contacts.map((contact) => ContactFactory.create(this, contact));
}
/**
@@ -1263,7 +1766,7 @@ class Client extends EventEmitter {
* @returns {Promise<Contact>}
*/
async getContactById(contactId) {
- let contact = await this.pupPage.evaluate(contactId => {
+ let contact = await this.pupPage.evaluate((contactId) => {
return window.WWebJS.getContact(contactId);
}, contactId);
@@ -1276,20 +1779,24 @@ class Client extends EventEmitter {
* @returns {Promise<Message>}
*/
async getMessageById(messageId) {
- const msg = await this.pupPage.evaluate(async messageId => {
- let msg = window.Store.Msg.get(messageId);
- if(msg) return window.WWebJS.getMessageModel(msg);
+ const msg = await this.pupPage.evaluate(async (messageId) => {
+ let msg = window.require('WAWebCollections').Msg.get(messageId);
+ if (msg) return window.WWebJS.getMessageModel(msg);
const params = messageId.split('_');
- if (params.length !== 3 && params.length !== 4) throw new Error('Invalid serialized message id specified');
+ if (params.length !== 3 && params.length !== 4)
+ throw new Error('Invalid serialized message id specified');
- let messagesObject = await window.Store.Msg.getMessagesById([messageId]);
- if (messagesObject && messagesObject.messages.length) msg = messagesObject.messages[0];
-
- if(msg) return window.WWebJS.getMessageModel(msg);
+ let messagesObject = await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([messageId]);
+ if (messagesObject && messagesObject.messages.length)
+ msg = messagesObject.messages[0];
+
+ if (msg) return window.WWebJS.getMessageModel(msg);
}, messageId);
- if(msg) return new Message(this, msg);
+ if (msg) return new Message(this, msg);
return null;
}
@@ -1300,24 +1807,37 @@ class Client extends EventEmitter {
*/
async getPinnedMessages(chatId) {
const pinnedMsgs = await this.pupPage.evaluate(async (chatId) => {
- const chatWid = window.Store.WidFactory.createWid(chatId);
- const chat = window.Store.Chat.get(chatWid) ?? await window.Store.Chat.find(chatWid);
+ const chatWid = window.require('WAWebWidFactory').createWid(chatId);
+ const chat =
+ window.require('WAWebCollections').Chat.get(chatWid) ??
+ (await window.require('WAWebCollections').Chat.find(chatWid));
if (!chat) return [];
-
- const msgs = await window.Store.PinnedMsgUtils.getTable().equals(['chatId'], chatWid.toString());
+
+ const msgs = await window
+ .require('WAWebPinInChatSchema')
+ .getTable()
+ .equals(['chatId'], chatWid.toString());
const pinnedMsgs = (
await Promise.all(
- msgs.filter(msg => msg.pinType == 1).map(async (msg) => {
- const res = await window.Store.Msg.getMessagesById([msg.parentMsgKey]);
- return res?.messages?.[0];
- })
+ msgs
+ .filter((msg) => msg.pinType == 1)
+ .map(async (msg) => {
+ const res = await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msg.parentMsgKey]);
+ return res?.messages?.[0];
+ }),
)
).filter(Boolean);
return !pinnedMsgs.length
? []
- : await Promise.all(pinnedMsgs.map((msg) => window.WWebJS.getMessageModel(msg)));
+ : await Promise.all(
+ pinnedMsgs.map((msg) =>
+ window.WWebJS.getMessageModel(msg),
+ ),
+ );
}, chatId);
return pinnedMsgs.map((msg) => new Message(this, msg));
@@ -1325,12 +1845,14 @@ class Client extends EventEmitter {
/**
* Returns an object with information about the invite code's group
- * @param {string} inviteCode
+ * @param {string} inviteCode
* @returns {Promise<object>} Invite information
*/
async getInviteInfo(inviteCode) {
- return await this.pupPage.evaluate(inviteCode => {
- return window.Store.GroupInvite.queryGroupInvite(inviteCode);
+ return await this.pupPage.evaluate((inviteCode) => {
+ return window
+ .require('WAWebGroupQueryJob')
+ .queryGroupInvite(inviteCode);
}, inviteCode);
}
@@ -1340,8 +1862,10 @@ class Client extends EventEmitter {
* @returns {Promise<string>} Id of the joined Chat
*/
async acceptInvite(inviteCode) {
- const res = await this.pupPage.evaluate(async inviteCode => {
- return await window.Store.GroupInvite.joinGroupViaInvite(inviteCode);
+ const res = await this.pupPage.evaluate(async (inviteCode) => {
+ return await window
+ .require('WAWebGroupInviteJob')
+ .joinGroupViaInvite(inviteCode);
}, inviteCode);
return res.gid._serialized;
@@ -1355,7 +1879,9 @@ class Client extends EventEmitter {
async acceptChannelAdminInvite(channelId) {
return await this.pupPage.evaluate(async (channelId) => {
try {
- await window.Store.ChannelUtils.acceptNewsletterAdminInvite(channelId);
+ await window
+ .require('WAWebMexAcceptNewsletterAdminInviteJob')
+ .acceptNewsletterAdminInvite(channelId);
return true;
} catch (err) {
if (err.name === 'ServerStatusCodeError') return false;
@@ -1371,16 +1897,24 @@ class Client extends EventEmitter {
* @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
*/
async revokeChannelAdminInvite(channelId, userId) {
- return await this.pupPage.evaluate(async (channelId, userId) => {
- try {
- const userWid = window.Store.WidFactory.createWid(userId);
- await window.Store.ChannelUtils.revokeNewsletterAdminInvite(channelId, userWid);
- return true;
- } catch (err) {
- if (err.name === 'ServerStatusCodeError') return false;
- throw err;
- }
- }, channelId, userId);
+ return await this.pupPage.evaluate(
+ async (channelId, userId) => {
+ try {
+ const userWid = window
+ .require('WAWebWidFactory')
+ .createWid(userId);
+ await window
+ .require('WAWebMexRevokeNewsletterAdminInviteJob')
+ .revokeNewsletterAdminInvite(channelId, userWid);
+ return true;
+ } catch (err) {
+ if (err.name === 'ServerStatusCodeError') return false;
+ throw err;
+ }
+ },
+ channelId,
+ userId,
+ );
}
/**
@@ -1390,16 +1924,24 @@ class Client extends EventEmitter {
* @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
*/
async demoteChannelAdmin(channelId, userId) {
- return await this.pupPage.evaluate(async (channelId, userId) => {
- try {
- const userWid = window.Store.WidFactory.createWid(userId);
- await window.Store.ChannelUtils.demoteNewsletterAdmin(channelId, userWid);
- return true;
- } catch (err) {
- if (err.name === 'ServerStatusCodeError') return false;
- throw err;
- }
- }, channelId, userId);
+ return await this.pupPage.evaluate(
+ async (channelId, userId) => {
+ try {
+ const userWid = window
+ .require('WAWebWidFactory')
+ .createWid(userId);
+ await window
+ .require('WAWebDemoteNewsletterAdminAction')
+ .demoteNewsletterAdmin(channelId, userWid);
+ return true;
+ } catch (err) {
+ if (err.name === 'ServerStatusCodeError') return false;
+ throw err;
+ }
+ },
+ channelId,
+ userId,
+ );
}
/**
@@ -1408,12 +1950,20 @@ class Client extends EventEmitter {
* @returns {Promise<Object>}
*/
async acceptGroupV4Invite(inviteInfo) {
- if (!inviteInfo.inviteCode) throw 'Invalid invite code, try passing the message.inviteV4 object';
+ if (!inviteInfo.inviteCode)
+ throw 'Invalid invite code, try passing the message.inviteV4 object';
if (inviteInfo.inviteCodeExp == 0) throw 'Expired invite code';
- return this.pupPage.evaluate(async inviteInfo => {
+ return this.pupPage.evaluate(async (inviteInfo) => {
let { groupId, fromId, inviteCode, inviteCodeExp } = inviteInfo;
- let userWid = window.Store.WidFactory.createWid(fromId);
- return await window.Store.GroupInviteV4.joinGroupViaInviteV4(inviteCode, String(inviteCodeExp), groupId, userWid);
+ let userWid = window.require('WAWebWidFactory').createWid(fromId);
+ return await window
+ .require('WAWebGroupInviteV4Job')
+ .joinGroupViaInviteV4(
+ inviteCode,
+ String(inviteCodeExp),
+ groupId,
+ userWid,
+ );
}, inviteInfo);
}
@@ -1422,35 +1972,39 @@ class Client extends EventEmitter {
* @param {string} status New status message
*/
async setStatus(status) {
- await this.pupPage.evaluate(async status => {
- return await window.Store.StatusUtils.setMyStatus(status);
+ await this.pupPage.evaluate(async (status) => {
+ return await window
+ .require('WAWebContactStatusBridge')
+ .setMyStatus(status);
}, status);
}
/**
- * Sets the current user's display name.
+ * 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
* @returns {Promise<Boolean>}
*/
async setDisplayName(displayName) {
- const couldSet = await this.pupPage.evaluate(async displayName => {
- if(!window.Store.Conn.canSetMyPushname()) return false;
- await window.Store.Settings.setPushname(displayName);
+ const couldSet = await this.pupPage.evaluate(async (displayName) => {
+ if (!window.require('WAWebConnModel').Conn.canSetMyPushname())
+ return false;
+ await window
+ .require('WAWebSetPushnameConnAction')
+ .setPushname(displayName);
return true;
}, displayName);
return couldSet;
}
-
+
/**
* Gets the current connection state for the client
- * @returns {WAState}
+ * @returns {WAState}
*/
async getState() {
return await this.pupPage.evaluate(() => {
- if(!window.Store) return null;
- return window.Store.AppState.state;
+ return window.require('WAWebSocketModel').Socket.state ?? null;
});
}
@@ -1459,7 +2013,9 @@ class Client extends EventEmitter {
*/
async sendPresenceAvailable() {
return await this.pupPage.evaluate(() => {
- return window.Store.PresenceUtils.sendPresenceAvailable();
+ return window
+ .require('WAWebPresenceChatAction')
+ .sendPresenceAvailable();
});
}
@@ -1468,7 +2024,9 @@ class Client extends EventEmitter {
*/
async sendPresenceUnavailable() {
return await this.pupPage.evaluate(() => {
- return window.Store.PresenceUtils.sendPresenceUnavailable();
+ return window
+ .require('WAWebPresenceChatAction')
+ .sendPresenceUnavailable();
});
}
@@ -1477,9 +2035,11 @@ class Client extends EventEmitter {
* @returns {boolean}
*/
async archiveChat(chatId) {
- return await this.pupPage.evaluate(async chatId => {
- let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
- await window.Store.Cmd.archiveChat(chat, true);
+ return await this.pupPage.evaluate(async (chatId) => {
+ let chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
+ await window.require('WAWebCmd').Cmd.archiveChat(chat, true);
return true;
}, chatId);
}
@@ -1489,9 +2049,11 @@ class Client extends EventEmitter {
* @returns {boolean}
*/
async unarchiveChat(chatId) {
- return await this.pupPage.evaluate(async chatId => {
- let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
- await window.Store.Cmd.archiveChat(chat, false);
+ return await this.pupPage.evaluate(async (chatId) => {
+ let chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
+ await window.require('WAWebCmd').Cmd.archiveChat(chat, false);
return false;
}, chatId);
}
@@ -1501,20 +2063,24 @@ class Client extends EventEmitter {
* @returns {Promise<boolean>} New pin state. Could be false if the max number of pinned chats was reached.
*/
async pinChat(chatId) {
- return this.pupPage.evaluate(async chatId => {
- let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
+ return this.pupPage.evaluate(async (chatId) => {
+ let chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
if (chat.pin) {
return true;
}
const MAX_PIN_COUNT = 3;
- const chatModels = window.Store.Chat.getModelsArray();
+ const chatModels = window
+ .require('WAWebCollections')
+ .Chat.getModelsArray();
if (chatModels.length > MAX_PIN_COUNT) {
let maxPinned = chatModels[MAX_PIN_COUNT - 1].pin;
if (maxPinned) {
return false;
}
}
- await window.Store.Cmd.pinChat(chat, true);
+ await window.require('WAWebCmd').Cmd.pinChat(chat, true);
return true;
}, chatId);
}
@@ -1524,12 +2090,14 @@ class Client extends EventEmitter {
* @returns {Promise<boolean>} New pin state
*/
async unpinChat(chatId) {
- return this.pupPage.evaluate(async chatId => {
- let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
+ return this.pupPage.evaluate(async (chatId) => {
+ let chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
if (!chat.pin) {
return false;
}
- await window.Store.Cmd.pinChat(chat, false);
+ await window.require('WAWebCmd').Cmd.pinChat(chat, false);
return false;
}, chatId);
}
@@ -1561,14 +2129,29 @@ class Client extends EventEmitter {
* @param {number} unmuteDateTs Timestamp at which the chat will be unmuted
* @returns {Promise<{isMuted: boolean, muteExpiration: number}>}
*/
- async _muteUnmuteChat (chatId, action, unmuteDateTs) {
- return this.pupPage.evaluate(async (chatId, action, unmuteDateTs) => {
- const chat = window.Store.Chat.get(chatId) ?? await window.Store.Chat.find(chatId);
- action === 'MUTE'
- ? await chat.mute.mute({ expiration: unmuteDateTs, sendDevice: true })
- : await chat.mute.unmute({ sendDevice: true });
- return { isMuted: chat.mute.expiration !== 0, muteExpiration: chat.mute.expiration };
- }, chatId, action, unmuteDateTs || -1);
+ async _muteUnmuteChat(chatId, action, unmuteDateTs) {
+ return this.pupPage.evaluate(
+ async (chatId, action, unmuteDateTs) => {
+ const chat =
+ window.require('WAWebCollections').Chat.get(chatId) ??
+ (await window
+ .require('WAWebCollections')
+ .Chat.find(chatId));
+ action === 'MUTE'
+ ? await chat.mute.mute({
+ expiration: unmuteDateTs,
+ sendDevice: true,
+ })
+ : await chat.mute.unmute({ sendDevice: true });
+ return {
+ isMuted: chat.mute.expiration !== 0,
+ muteExpiration: chat.mute.expiration,
+ };
+ },
+ chatId,
+ action,
+ unmuteDateTs || -1,
+ );
}
/**
@@ -1576,9 +2159,11 @@ class Client extends EventEmitter {
* @param {string} chatId ID of the chat that will be marked as unread
*/
async markChatUnread(chatId) {
- await this.pupPage.evaluate(async chatId => {
- let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
- await window.Store.Cmd.markChatUnread(chat, true);
+ await this.pupPage.evaluate(async (chatId) => {
+ let chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
+ await window.require('WAWebCmd').Cmd.markChatUnread(chat, true);
}, chatId);
}
@@ -1588,18 +2173,18 @@ class Client extends EventEmitter {
* @returns {Promise<string>}
*/
async getProfilePicUrl(contactId) {
- const profilePic = await this.pupPage.evaluate(async contactId => {
+ const profilePic = await this.pupPage.evaluate(async (contactId) => {
try {
- const chatWid = window.Store.WidFactory.createWid(contactId);
- return window.compareWwebVersions(window.Debug.VERSION, '<', '2.3000.0')
- ? await window.Store.ProfilePic.profilePicFind(chatWid)
- : await window.Store.ProfilePic.requestProfilePicFromServer(chatWid);
+ const chat = await window.WWebJS.getChat(contactId);
+ return await window
+ .require('WAWebContactProfilePicThumbBridge')
+ .requestProfilePicFromServer(chat);
} catch (err) {
- if(err.name === 'ServerStatusCodeError') return undefined;
+ if (err.name === 'ServerStatusCodeError') return undefined;
throw err;
}
}, contactId);
-
+
return profilePic ? profilePic.eurl : undefined;
}
@@ -1610,17 +2195,26 @@ class Client extends EventEmitter {
*/
async getCommonGroups(contactId) {
const commonGroups = await this.pupPage.evaluate(async (contactId) => {
- let contact = window.Store.Contact.get(contactId);
+ let contact = window
+ .require('WAWebCollections')
+ .Contact.get(contactId);
if (!contact) {
- const wid = window.Store.WidFactory.createWid(contactId);
- const chatConstructor = window.Store.Contact.getModelsArray().find(c=>!c.isGroup).constructor;
- contact = new chatConstructor({id: wid});
+ const wid = window
+ .require('WAWebWidFactory')
+ .createWid(contactId);
+ const chatConstructor = window
+ .require('WAWebCollections')
+ .Contact.getModelsArray()
+ .find((c) => !c.isGroup).constructor;
+ contact = new chatConstructor({ id: wid });
}
if (contact.commonGroups) {
return contact.commonGroups.serialize();
}
- const status = await window.Store.findCommonGroups(contact);
+ const status = await window
+ .require('WAWebFindCommonGroupsContactAction')
+ .findCommonGroups(contact);
if (status) {
return contact.commonGroups.serialize();
}
@@ -1635,10 +2229,10 @@ class Client extends EventEmitter {
/**
* Force reset of connection state for the client
- */
+ */
async resetState() {
await this.pupPage.evaluate(() => {
- window.Store.AppState.reconnect();
+ window.require('WAWebSocketModel').Socket.reconnect();
});
}
@@ -1652,7 +2246,7 @@ class Client extends EventEmitter {
}
/**
- * Get the registered WhatsApp ID for a number.
+ * 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 ("@c.us" will be automatically appended if not specified)
* @returns {Promise<Object|null>}
@@ -1662,9 +2256,11 @@ class Client extends EventEmitter {
number += '@c.us';
}
- return await this.pupPage.evaluate(async number => {
- const wid = window.Store.WidFactory.createWid(number);
- const result = await window.Store.QueryExist(wid);
+ return await this.pupPage.evaluate(async (number) => {
+ const wid = window.require('WAWebWidFactory').createWid(number);
+ const result = await window
+ .require('WAWebQueryExistsJob')
+ .queryWidExists(wid);
if (!result || result.wid === undefined) return null;
return result.wid;
}, number);
@@ -1676,11 +2272,15 @@ class Client extends EventEmitter {
* @returns {Promise<string>}
*/
async getFormattedNumber(number) {
- if (!number.endsWith('@s.whatsapp.net')) number = number.replace('c.us', 's.whatsapp.net');
- if (!number.includes('@s.whatsapp.net')) number = `${number}@s.whatsapp.net`;
+ if (!number.endsWith('@s.whatsapp.net'))
+ number = number.replace('c.us', 's.whatsapp.net');
+ if (!number.includes('@s.whatsapp.net'))
+ number = `${number}@s.whatsapp.net`;
- return await this.pupPage.evaluate(async numberId => {
- return window.Store.NumberInfo.formattedPhoneNumber(numberId);
+ return await this.pupPage.evaluate(async (numberId) => {
+ return window
+ .require('WAWebPhoneUtils')
+ .formattedPhoneNumber(numberId);
}, number);
}
@@ -1692,8 +2292,8 @@ class Client extends EventEmitter {
async getCountryCode(number) {
number = number.replace(' ', '').replace('+', '').replace('@c.us', '');
- return await this.pupPage.evaluate(async numberId => {
- return window.Store.NumberInfo.findCC(numberId);
+ return await this.pupPage.evaluate(async (numberId) => {
+ return window.require('WAPhoneFindCC').findCC(numberId);
}, number);
}
@@ -1739,92 +2339,137 @@ class Client extends EventEmitter {
*/
async createGroup(title, participants = [], options = {}) {
!Array.isArray(participants) && (participants = [participants]);
- participants.map(p => (p instanceof Contact) ? p.id._serialized : p);
+ participants.map((p) => (p instanceof Contact ? p.id._serialized : p));
- return await this.pupPage.evaluate(async (title, participants, options) => {
- const {
- messageTimer = 0,
- parentGroupId,
- autoSendInviteV4 = true,
- comment = '',
- } = options;
- const participantData = {}, participantWids = [], failedParticipants = [];
- let createGroupResult, parentGroupWid;
+ return await this.pupPage.evaluate(
+ async (title, participants, options) => {
+ const {
+ messageTimer = 0,
+ parentGroupId,
+ autoSendInviteV4 = true,
+ comment = '',
+ } = options;
+ const participantData = {},
+ participantWids = [],
+ failedParticipants = [];
+ let createGroupResult, parentGroupWid;
- const addParticipantResultCodes = {
- default: 'An unknown error occupied while adding a participant',
- 200: 'The participant was added successfully',
- 403: 'The participant can be added by sending private invitation only',
- 404: 'The phone number is not registered on WhatsApp'
- };
+ const addParticipantResultCodes = {
+ default:
+ 'An unknown error occupied while adding a participant',
+ 200: 'The participant was added successfully',
+ 403: 'The participant can be added by sending private invitation only',
+ 404: 'The phone number is not registered on WhatsApp',
+ };
- for (const participant of participants) {
- const pWid = window.Store.WidFactory.createWid(participant);
- if ((await window.Store.QueryExist(pWid))?.wid) {
- participantWids.push({ phoneNumber: pWid });
- }
- else failedParticipants.push(participant);
- }
-
- parentGroupId && (parentGroupWid = window.Store.WidFactory.createWid(parentGroupId));
-
- try {
- createGroupResult = await window.Store.GroupUtils.createGroup(
- {
- 'addressingModeOverride': 'lid',
- 'memberAddMode': options.memberAddMode ?? false,
- 'membershipApprovalMode': options.membershipApprovalMode ?? false,
- 'announce': options.announce ?? false,
- 'restrict': options.isRestrict !== undefined ? !options.isRestrict : false,
- 'ephemeralDuration': messageTimer,
- 'parentGroupId': parentGroupWid,
- 'title': title,
- },
- participantWids
- );
- } catch (err) {
- return 'CreateGroupError: An unknown error occupied while creating a group';
- }
-
- for (const participant of createGroupResult.participants) {
- let isInviteV4Sent = false;
- participant.wid.server == 'lid' && (participant.wid = window.Store.LidUtils.getPhoneNumber(participant.wid));
- const participantId = participant.wid._serialized;
- const statusCode = participant.error || 200;
-
- if (autoSendInviteV4 && statusCode === 403) {
- window.Store.Contact.gadd(participant.wid, { silent: true });
- const addParticipantResult = await window.Store.GroupInviteV4.sendGroupInviteMessage(
- window.Store.Chat.get(participant.wid) || await window.Store.Chat.find(participant.wid),
- createGroupResult.wid._serialized,
- createGroupResult.subject,
- participant.invite_code,
- participant.invite_code_exp,
- comment,
- await window.WWebJS.getProfilePicThumbToBase64(createGroupResult.wid)
- );
- isInviteV4Sent = addParticipantResult.messageSendResult === 'OK';
+ for (const participant of participants) {
+ const pWid = window
+ .require('WAWebWidFactory')
+ .createWid(participant);
+ if (
+ (
+ await window
+ .require('WAWebQueryExistsJob')
+ .queryWidExists(pWid)
+ )?.wid
+ ) {
+ participantWids.push({ phoneNumber: pWid });
+ } else failedParticipants.push(participant);
}
- participantData[participantId] = {
- statusCode: statusCode,
- message: addParticipantResultCodes[statusCode] || addParticipantResultCodes.default,
- isGroupCreator: participant.type === 'superadmin',
- isInviteV4Sent: isInviteV4Sent
- };
- }
+ parentGroupId &&
+ (parentGroupWid = window
+ .require('WAWebWidFactory')
+ .createWid(parentGroupId));
- for (const f of failedParticipants) {
- participantData[f] = {
- statusCode: 404,
- message: addParticipantResultCodes[404],
- isGroupCreator: false,
- isInviteV4Sent: false
- };
- }
+ try {
+ createGroupResult = await window
+ .require('WAWebGroupCreateJob')
+ .createGroup(
+ {
+ addressingModeOverride: 'lid',
+ memberAddMode: options.memberAddMode ?? false,
+ membershipApprovalMode:
+ options.membershipApprovalMode ?? false,
+ announce: options.announce ?? false,
+ restrict:
+ options.isRestrict !== undefined
+ ? !options.isRestrict
+ : false,
+ ephemeralDuration: messageTimer,
+ parentGroupId: parentGroupWid,
+ title: title,
+ },
+ participantWids,
+ );
+ } catch (ignoredError) {
+ return 'CreateGroupError: An unknown error occupied while creating a group';
+ }
- return { title: title, gid: createGroupResult.wid, participants: participantData };
- }, title, participants, options);
+ for (const participant of createGroupResult.participants) {
+ let isInviteV4Sent = false;
+ participant.wid.server == 'lid' &&
+ (participant.wid = window
+ .require('WAWebApiContact')
+ .getPhoneNumber(participant.wid));
+ const participantId = participant.wid._serialized;
+ const statusCode = participant.error || 200;
+
+ if (autoSendInviteV4 && statusCode === 403) {
+ window
+ .require('WAWebCollections')
+ .Contact.gadd(participant.wid, { silent: true });
+ const addParticipantResult = await window
+ .require('WAWebChatSendMessages')
+ .sendGroupInviteMessage(
+ window
+ .require('WAWebCollections')
+ .Chat.get(participant.wid) ||
+ (await window
+ .require('WAWebCollections')
+ .Chat.find(participant.wid)),
+ createGroupResult.wid._serialized,
+ createGroupResult.subject,
+ participant.invite_code,
+ participant.invite_code_exp,
+ comment,
+ await window.WWebJS.getProfilePicThumbToBase64(
+ createGroupResult.wid,
+ ),
+ );
+ isInviteV4Sent =
+ addParticipantResult.messageSendResult === 'OK';
+ }
+
+ participantData[participantId] = {
+ statusCode: statusCode,
+ message:
+ addParticipantResultCodes[statusCode] ||
+ addParticipantResultCodes.default,
+ isGroupCreator: participant.type === 'superadmin',
+ isInviteV4Sent: isInviteV4Sent,
+ };
+ }
+
+ for (const f of failedParticipants) {
+ participantData[f] = {
+ statusCode: 404,
+ message: addParticipantResultCodes[404],
+ isGroupCreator: false,
+ isInviteV4Sent: false,
+ };
+ }
+
+ return {
+ title: title,
+ gid: createGroupResult.wid,
+ participants: participantData,
+ };
+ },
+ title,
+ participants,
+ options,
+ );
}
/**
@@ -1849,46 +2494,61 @@ class Client extends EventEmitter {
/**
* Creates a new channel
* @param {string} title The channel name
- * @param {CreateChannelOptions} options
+ * @param {CreateChannelOptions} options
* @returns {Promise<CreateChannelResult|string>} Returns an object that handles the result for the channel creation or an error message as a string
*/
async createChannel(title, options = {}) {
- return await this.pupPage.evaluate(async (title, options) => {
- let response, { description = null, picture = null } = options;
+ return await this.pupPage.evaluate(
+ async (title, options) => {
+ let response,
+ { description = null, picture = null } = options;
- if (!window.Store.ChannelUtils.isNewsletterCreationEnabled()) {
- return 'CreateChannelError: A channel creation is not enabled';
- }
-
- if (picture) {
- picture = await window.WWebJS.cropAndResizeImage(picture, {
- asDataUrl: true,
- mimetype: 'image/jpeg',
- size: 640,
- quality: 1
- });
- }
-
- try {
- response = await window.Store.ChannelUtils.createNewsletterQuery({
- name: title,
- description: description,
- picture: picture,
- });
- } catch (err) {
- if (err.name === 'ServerStatusCodeError') {
- return 'CreateChannelError: An error occupied while creating a channel';
+ if (
+ !window
+ .require('WAWebNewsletterGatingUtils')
+ .isNewsletterCreationEnabled()
+ ) {
+ return 'CreateChannelError: A channel creation is not enabled';
}
- throw err;
- }
- return {
- title: title,
- nid: window.Store.JidToWid.newsletterJidToWid(response.idJid),
- inviteLink: `https://whatsapp.com/channel/${response.newsletterInviteLinkMetadataMixin.inviteCode}`,
- createdAtTs: response.newsletterCreationTimeMetadataMixin.creationTimeValue
- };
- }, title, options);
+ if (picture) {
+ picture = await window.WWebJS.cropAndResizeImage(picture, {
+ asDataUrl: true,
+ mimetype: 'image/jpeg',
+ size: 640,
+ quality: 1,
+ });
+ }
+
+ try {
+ response = await window
+ .require('WAWebNewsletterCreateQueryJob')
+ .createNewsletterQuery({
+ name: title,
+ description: description,
+ picture: picture,
+ });
+ } catch (err) {
+ if (err.name === 'ServerStatusCodeError') {
+ return 'CreateChannelError: An error occupied while creating a channel';
+ }
+ throw err;
+ }
+
+ return {
+ title: title,
+ nid: window
+ .require('WAWebJidToWid')
+ .newsletterJidToWid(response.idJid),
+ inviteLink: `https://whatsapp.com/channel/${response.newsletterInviteLinkMetadataMixin.inviteCode}`,
+ createdAtTs:
+ response.newsletterCreationTimeMetadataMixin
+ .creationTimeValue,
+ };
+ },
+ title,
+ options,
+ );
}
/**
@@ -1898,7 +2558,10 @@ class Client extends EventEmitter {
*/
async subscribeToChannel(channelId) {
return await this.pupPage.evaluate(async (channelId) => {
- return await window.WWebJS.subscribeToUnsubscribeFromChannel(channelId, 'Subscribe');
+ return await window.WWebJS.subscribeToUnsubscribeFromChannel(
+ channelId,
+ 'Subscribe',
+ );
}, channelId);
}
@@ -1915,9 +2578,17 @@ class Client extends EventEmitter {
* @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
*/
async unsubscribeFromChannel(channelId, options) {
- return await this.pupPage.evaluate(async (channelId, options) => {
- return await window.WWebJS.subscribeToUnsubscribeFromChannel(channelId, 'Unsubscribe', options);
- }, channelId, options);
+ return await this.pupPage.evaluate(
+ async (channelId, options) => {
+ return await window.WWebJS.subscribeToUnsubscribeFromChannel(
+ channelId,
+ 'Unsubscribe',
+ options,
+ );
+ },
+ channelId,
+ options,
+ );
}
/**
@@ -1935,26 +2606,51 @@ class Client extends EventEmitter {
* @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
*/
async transferChannelOwnership(channelId, newOwnerId, options = {}) {
- return await this.pupPage.evaluate(async (channelId, newOwnerId, options) => {
- const channel = await window.WWebJS.getChat(channelId, { getAsModel: false });
- const newOwner = window.Store.Contact.get(newOwnerId) || (await window.Store.Contact.find(newOwnerId));
- if (!channel.newsletterMetadata) {
- await window.Store.NewsletterMetadataCollection.update(channel.id);
- }
-
- try {
- await window.Store.ChannelUtils.changeNewsletterOwnerAction(channel, newOwner);
-
- if (options.shouldDismissSelfAsAdmin) {
- const meContact = window.Store.ContactCollection.getMeContact();
- meContact && (await window.Store.ChannelUtils.demoteNewsletterAdminAction(channel, meContact));
+ return await this.pupPage.evaluate(
+ async (channelId, newOwnerId, options) => {
+ const channel = await window.WWebJS.getChat(channelId, {
+ getAsModel: false,
+ });
+ const newOwner =
+ window
+ .require('WAWebCollections')
+ .Contact.get(newOwnerId) ||
+ (await window
+ .require('WAWebCollections')
+ .Contact.find(newOwnerId));
+ if (!channel.newsletterMetadata) {
+ await window
+ .require('WAWebCollections')
+ .NewsletterMetadataCollection.update(channel.id);
}
- } catch (error) {
- return false;
- }
- return true;
- }, channelId, newOwnerId, options);
+ try {
+ await window
+ .require('WAWebChangeNewsletterOwnerAction')
+ .changeNewsletterOwnerAction(channel, newOwner);
+
+ if (options.shouldDismissSelfAsAdmin) {
+ const meContact = window
+ .require('WAWebContactCollection')
+ .getMeContact();
+ meContact &&
+ (await window
+ .require('WAWebNewsletterDemoteAdminJob')
+ .demoteNewsletterAdminAction(
+ channel,
+ meContact,
+ ));
+ }
+ } catch (ignoredError) {
+ return false;
+ }
+
+ return true;
+ },
+ channelId,
+ newOwnerId,
+ options,
+ );
}
/**
@@ -1977,48 +2673,78 @@ class Client extends EventEmitter {
* @returns {Promise<Array<Channel>>} Returns an array of Channel objects or an empty array if no channels were found
*/
async searchChannels(searchOptions = {}) {
- return await this.pupPage.evaluate(async ({
- searchText = '',
- countryCodes = [window.Store.ChannelUtils.currentRegion],
- skipSubscribedNewsletters = false,
- view = 0,
- limit = 50
- }) => {
- searchText = searchText.trim();
- const currentRegion = window.Store.ChannelUtils.currentRegion;
- if (![0, 1, 2, 3].includes(view)) view = 0;
+ return await this.pupPage.evaluate(
+ async ({
+ searchText = '',
+ countryCodes = [],
+ skipSubscribedNewsletters = false,
+ view = 0,
+ limit = 50,
+ }) => {
+ searchText = searchText.trim();
+ const currentRegion = window.require('WAWebL10N').getRegion();
+ if (countryCodes.length === 0) countryCodes[0] = currentRegion;
+ if (![0, 1, 2, 3].includes(view)) view = 0;
- countryCodes = countryCodes.length === 1 && countryCodes[0] === currentRegion
- ? countryCodes
- : countryCodes.filter((code) => Object.keys(window.Store.ChannelUtils.countryCodesIso).includes(code));
+ const { countryCodesIso } = window.require(
+ 'WAWebCountriesNativeCountryNames',
+ );
- const viewTypeMapping = {
- 0: 'RECOMMENDED',
- 1: 'TRENDING',
- 2: 'POPULAR',
- 3: 'NEW'
- };
+ countryCodes =
+ countryCodes.length === 1 &&
+ countryCodes[0] === currentRegion
+ ? countryCodes
+ : countryCodes.filter((code) =>
+ Object.keys(countryCodesIso).includes(code),
+ );
- searchOptions = {
- searchText: searchText,
- countryCodes: countryCodes,
- skipSubscribedNewsletters: skipSubscribedNewsletters,
- view: viewTypeMapping[view],
- categories: [],
- cursorToken: ''
- };
-
- const originalFunction = window.Store.ChannelUtils.getNewsletterDirectoryPageSize;
- limit !== 50 && (window.Store.ChannelUtils.getNewsletterDirectoryPageSize = () => limit);
+ const viewTypeMapping = {
+ 0: 'RECOMMENDED',
+ 1: 'TRENDING',
+ 2: 'POPULAR',
+ 3: 'NEW',
+ };
- const channels = (await window.Store.ChannelUtils.fetchNewsletterDirectories(searchOptions)).newsletters;
+ searchOptions = {
+ searchText: searchText,
+ countryCodes: countryCodes,
+ skipSubscribedNewsletters: skipSubscribedNewsletters,
+ view: viewTypeMapping[view],
+ categories: [],
+ cursorToken: '',
+ };
- limit !== 50 && (window.Store.ChannelUtils.getNewsletterDirectoryPageSize = originalFunction);
+ const originalFunction = window.require(
+ 'WAWebNewsletterGatingUtils',
+ ).getNewsletterDirectoryPageSize;
+ limit !== 50 &&
+ (window.require(
+ 'WAWebNewsletterGatingUtils',
+ ).getNewsletterDirectoryPageSize = () => limit);
- return channels
- ? await Promise.all(channels.map((channel) => window.WWebJS.getChatModel(channel, { isChannel: true })))
- : [];
- }, searchOptions);
+ const channels = (
+ await window
+ .require('WAWebNewsletterDirectorySearchAction')
+ .fetchNewsletterDirectories(searchOptions)
+ ).newsletters;
+
+ limit !== 50 &&
+ (window.require(
+ 'WAWebNewsletterGatingUtils',
+ ).getNewsletterDirectoryPageSize = originalFunction);
+
+ return channels
+ ? await Promise.all(
+ channels.map((channel) =>
+ window.WWebJS.getChatModel(channel, {
+ isChannel: true,
+ }),
+ ),
+ )
+ : [];
+ },
+ searchOptions,
+ );
}
/**
@@ -2027,11 +2753,15 @@ class Client extends EventEmitter {
* @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
*/
async deleteChannel(channelId) {
- return await this.client.pupPage.evaluate(async (channelId) => {
- const channel = await window.WWebJS.getChat(channelId, { getAsModel: false });
+ return await this.pupPage.evaluate(async (channelId) => {
+ const channel = await window.WWebJS.getChat(channelId, {
+ getAsModel: false,
+ });
if (!channel) return false;
try {
- await window.Store.ChannelUtils.deleteNewsletterAction(channel);
+ await window
+ .require('WAWebNewsletterDeleteAction')
+ .deleteNewsletterAction(channel);
return true;
} catch (err) {
if (err.name === 'ServerStatusCodeError') return false;
@@ -2049,7 +2779,7 @@ class Client extends EventEmitter {
return window.WWebJS.getLabels();
});
- return labels.map(data => new Label(this, data));
+ return labels.map((data) => new Label(this, data));
}
/**
@@ -2060,7 +2790,7 @@ class Client extends EventEmitter {
const broadcasts = await this.pupPage.evaluate(async () => {
return window.WWebJS.getAllStatuses();
});
- return broadcasts.map(data => new Broadcast(this, data));
+ return broadcasts.map((data) => new Broadcast(this, data));
}
/**
@@ -2072,9 +2802,11 @@ class Client extends EventEmitter {
const broadcast = await this.pupPage.evaluate(async (userId) => {
let status;
try {
- status = window.Store.Status.get(userId);
+ status = window.require('WAWebCollections').Status.get(userId);
if (!status) {
- status = await window.Store.Status.find(userId);
+ status = await window
+ .require('WAWebCollections')
+ .Status.find(userId);
}
} catch {
status = null;
@@ -2092,17 +2824,26 @@ class Client extends EventEmitter {
*/
async revokeStatusMessage(messageId) {
return await this.pupPage.evaluate(async (msgId) => {
- const status = window.Store.Status.getMyStatus();
+ const status = window
+ .require('WAWebCollections')
+ .Status.getMyStatus();
if (!status) return;
const msg =
- window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
if (!msg) return;
if (!msg.id.fromMe || !msg.id.remote.isStatus())
throw 'Invalid usage! Can only revoke the message its from own status broadcast';
- return await window.Store.StatusUtils.sendStatusRevokeMsgAction(status, msg);
+ return await window
+ .require('WAWebRevokeStatusAction')
+ .sendStatusRevokeMsgAction(status, msg);
}, messageId);
}
@@ -2120,7 +2861,7 @@ class Client extends EventEmitter {
}
/**
- * Get all Labels assigned to a chat
+ * Get all Labels assigned to a chat
* @param {string} chatId
* @returns {Promise<Array<Label>>}
*/
@@ -2129,7 +2870,7 @@ class Client extends EventEmitter {
return window.WWebJS.getChatLabels(chatId);
}, chatId);
- return labels.map(data => new Label(this, data));
+ return labels.map((data) => new Label(this, data));
}
/**
@@ -2139,7 +2880,7 @@ class Client extends EventEmitter {
*/
async getChatsByLabelId(labelId) {
const chatIds = await this.pupPage.evaluate(async (labelId) => {
- const label = window.Store.Label.get(labelId);
+ const label = window.require('WAWebCollections').Label.get(labelId);
const labelItems = label.labelItemCollection.getModelsArray();
return labelItems.reduce((result, item) => {
if (item.parentType === 'Chat') {
@@ -2149,7 +2890,7 @@ class Client extends EventEmitter {
}, []);
}, labelId);
- return Promise.all(chatIds.map(id => this.getChatById(id)));
+ return Promise.all(chatIds.map((id) => this.getChatById(id)));
}
/**
@@ -2158,11 +2899,18 @@ class Client extends EventEmitter {
*/
async getBlockedContacts() {
const blockedContacts = await this.pupPage.evaluate(() => {
- let chatIds = window.Store.Blocklist.getModelsArray().map(a => a.id._serialized);
- return Promise.all(chatIds.map(id => window.WWebJS.getContact(id)));
+ let chatIds = window
+ .require('WAWebCollections')
+ .Blocklist.getModelsArray()
+ .map((a) => a.id._serialized);
+ return Promise.all(
+ chatIds.map((id) => window.WWebJS.getContact(id)),
+ );
});
- return blockedContacts.map(contact => ContactFactory.create(this.client, contact));
+ return blockedContacts.map((contact) =>
+ ContactFactory.create(this.client, contact),
+ );
}
/**
@@ -2171,9 +2919,13 @@ class Client extends EventEmitter {
* @returns {Promise<boolean>} Returns true if the picture was properly updated.
*/
async setProfilePicture(media) {
- const success = await this.pupPage.evaluate((chatid, media) => {
- return window.WWebJS.setPicture(chatid, media);
- }, this.info.wid._serialized, media);
+ const success = await this.pupPage.evaluate(
+ (chatid, media) => {
+ return window.WWebJS.setPicture(chatid, media);
+ },
+ this.info.wid._serialized,
+ media,
+ );
return success;
}
@@ -2189,7 +2941,7 @@ class Client extends EventEmitter {
return success;
}
-
+
/**
* Change labels in chats
* @param {Array<number|string>} labelIds
@@ -2197,26 +2949,42 @@ class Client extends EventEmitter {
* @returns {Promise<void>}
*/
async addOrRemoveLabels(labelIds, chatIds) {
+ return this.pupPage.evaluate(
+ async (labelIds, chatIds) => {
+ if (
+ ['smba', 'smbi'].indexOf(
+ window.require('WAWebConnModel').Conn.platform,
+ ) === -1
+ ) {
+ throw '[LT01] Only Whatsapp business';
+ }
+ const labels = window.WWebJS.getLabels().filter(
+ (e) => labelIds.find((l) => l == e.id) !== undefined,
+ );
+ const chats = window
+ .require('WAWebCollections')
+ .Chat.filter((e) => chatIds.includes(e.id._serialized));
- return this.pupPage.evaluate(async (labelIds, chatIds) => {
- if (['smba', 'smbi'].indexOf(window.Store.Conn.platform) === -1) {
- throw '[LT01] Only Whatsapp business';
- }
- const labels = window.WWebJS.getLabels().filter(e => labelIds.find(l => l == e.id) !== undefined);
- const chats = window.Store.Chat.filter(e => chatIds.includes(e.id._serialized));
+ let actions = labels.map((label) => ({
+ id: label.id,
+ type: 'add',
+ }));
- let actions = labels.map(label => ({id: label.id, type: 'add'}));
-
- chats.forEach(chat => {
- (chat.labels || []).forEach(n => {
- if (!actions.find(e => e.id == n)) {
- actions.push({id: n, type: 'remove'});
- }
+ chats.forEach((chat) => {
+ (chat.labels || []).forEach((n) => {
+ if (!actions.find((e) => e.id == n)) {
+ actions.push({ id: n, type: 'remove' });
+ }
+ });
});
- });
- return await window.Store.Label.addOrRemoveLabels(actions, chats);
- }, labelIds, chatIds);
+ return await window
+ .require('WAWebCollections')
+ .Label.addOrRemoveLabels(actions, chats);
+ },
+ labelIds,
+ chatIds,
+ );
}
/**
@@ -2236,8 +3004,12 @@ class Client extends EventEmitter {
*/
async getGroupMembershipRequests(groupId) {
return await this.pupPage.evaluate(async (groupId) => {
- const groupWid = window.Store.WidFactory.createWid(groupId);
- return await window.Store.MembershipRequestUtils.getMembershipApprovalRequests(groupWid);
+ const groupWid = window
+ .require('WAWebWidFactory')
+ .createWid(groupId);
+ return await window
+ .require('WAWebApiMembershipApprovalRequestStore')
+ .getMembershipApprovalRequests(groupWid);
}, groupId);
}
@@ -2263,10 +3035,19 @@ class Client extends EventEmitter {
* @returns {Promise<Array<MembershipRequestActionResult>>} Returns an array of requester IDs whose membership requests were approved and an error for each requester, if any occurred during the operation. If there are no requests, an empty array will be returned
*/
async approveGroupMembershipRequests(groupId, options = {}) {
- return await this.pupPage.evaluate(async (groupId, options) => {
- const { requesterIds = null, sleep = [250, 500] } = options;
- return await window.WWebJS.membershipRequestAction(groupId, 'Approve', requesterIds, sleep);
- }, groupId, options);
+ return await this.pupPage.evaluate(
+ async (groupId, options) => {
+ const { requesterIds = null, sleep = [250, 500] } = options;
+ return await window.WWebJS.membershipRequestAction(
+ groupId,
+ 'Approve',
+ requesterIds,
+ sleep,
+ );
+ },
+ groupId,
+ options,
+ );
}
/**
@@ -2276,24 +3057,36 @@ class Client extends EventEmitter {
* @returns {Promise<Array<MembershipRequestActionResult>>} Returns an array of requester IDs whose membership requests were rejected and an error for each requester, if any occurred during the operation. If there are no requests, an empty array will be returned
*/
async rejectGroupMembershipRequests(groupId, options = {}) {
- return await this.pupPage.evaluate(async (groupId, options) => {
- const { requesterIds = null, sleep = [250, 500] } = options;
- return await window.WWebJS.membershipRequestAction(groupId, 'Reject', requesterIds, sleep);
- }, groupId, options);
+ return await this.pupPage.evaluate(
+ async (groupId, options) => {
+ const { requesterIds = null, sleep = [250, 500] } = options;
+ return await window.WWebJS.membershipRequestAction(
+ groupId,
+ 'Reject',
+ requesterIds,
+ sleep,
+ );
+ },
+ groupId,
+ options,
+ );
}
-
/**
* Setting autoload download audio
* @param {boolean} flag true/false
*/
async setAutoDownloadAudio(flag) {
- await this.pupPage.evaluate(async flag => {
- const autoDownload = window.Store.Settings.getAutoDownloadAudio();
+ await this.pupPage.evaluate(async (flag) => {
+ const autoDownload = window
+ .require('WAWebUserPrefsGeneral')
+ .getAutoDownloadAudio();
if (autoDownload === flag) {
return flag;
}
- await window.Store.Settings.setAutoDownloadAudio(flag);
+ await window
+ .require('WAWebUserPrefsGeneral')
+ .setAutoDownloadAudio(flag);
return flag;
}, flag);
}
@@ -2303,12 +3096,16 @@ class Client extends EventEmitter {
* @param {boolean} flag true/false
*/
async setAutoDownloadDocuments(flag) {
- await this.pupPage.evaluate(async flag => {
- const autoDownload = window.Store.Settings.getAutoDownloadDocuments();
+ await this.pupPage.evaluate(async (flag) => {
+ const autoDownload = window
+ .require('WAWebUserPrefsGeneral')
+ .getAutoDownloadDocuments();
if (autoDownload === flag) {
return flag;
}
- await window.Store.Settings.setAutoDownloadDocuments(flag);
+ await window
+ .require('WAWebUserPrefsGeneral')
+ .setAutoDownloadDocuments(flag);
return flag;
}, flag);
}
@@ -2318,12 +3115,16 @@ class Client extends EventEmitter {
* @param {boolean} flag true/false
*/
async setAutoDownloadPhotos(flag) {
- await this.pupPage.evaluate(async flag => {
- const autoDownload = window.Store.Settings.getAutoDownloadPhotos();
+ await this.pupPage.evaluate(async (flag) => {
+ const autoDownload = window
+ .require('WAWebUserPrefsGeneral')
+ .getAutoDownloadPhotos();
if (autoDownload === flag) {
return flag;
}
- await window.Store.Settings.setAutoDownloadPhotos(flag);
+ await window
+ .require('WAWebUserPrefsGeneral')
+ .setAutoDownloadPhotos(flag);
return flag;
}, flag);
}
@@ -2333,12 +3134,16 @@ class Client extends EventEmitter {
* @param {boolean} flag true/false
*/
async setAutoDownloadVideos(flag) {
- await this.pupPage.evaluate(async flag => {
- const autoDownload = window.Store.Settings.getAutoDownloadVideos();
+ await this.pupPage.evaluate(async (flag) => {
+ const autoDownload = window
+ .require('WAWebUserPrefsGeneral')
+ .getAutoDownloadVideos();
if (autoDownload === flag) {
return flag;
}
- await window.Store.Settings.setAutoDownloadVideos(flag);
+ await window
+ .require('WAWebUserPrefsGeneral')
+ .setAutoDownloadVideos(flag);
return flag;
}, flag);
}
@@ -2350,16 +3155,20 @@ class Client extends EventEmitter {
* @returns {Promise<boolean>}
*/
async setBackgroundSync(flag) {
- return await this.pupPage.evaluate(async flag => {
- const backSync = window.Store.Settings.getGlobalOfflineNotifications();
+ return await this.pupPage.evaluate(async (flag) => {
+ const backSync = window
+ .require('WAWebUserPrefsNotifications')
+ .getGlobalOfflineNotifications();
if (backSync === flag) {
return flag;
}
- await window.Store.Settings.setGlobalOfflineNotifications(flag);
+ await window
+ .require('WAWebUserPrefsNotifications')
+ .setGlobalOfflineNotifications(flag);
return flag;
}, flag);
}
-
+
/**
* Get user device count by ID
* Each WaWeb Connection counts as one device, and the phone (if exists) counts as one
@@ -2369,8 +3178,17 @@ class Client extends EventEmitter {
*/
async getContactDeviceCount(userId) {
return await this.pupPage.evaluate(async (userId) => {
- const devices = await window.Store.DeviceList.getDeviceIds([window.Store.WidFactory.createWid(userId)]);
- if (devices && devices.length && devices[0] != null && typeof devices[0].devices == 'object') {
+ const devices = await window
+ .require('WAWebApiDeviceList')
+ .getDeviceIds([
+ window.require('WAWebWidFactory').createWid(userId),
+ ]);
+ if (
+ devices &&
+ devices.length &&
+ devices[0] != null &&
+ typeof devices[0].devices == 'object'
+ ) {
return devices[0].devices.length;
}
return 0;
@@ -2384,18 +3202,22 @@ class Client extends EventEmitter {
*/
async syncHistory(chatId) {
return await this.pupPage.evaluate(async (chatId) => {
- const chatWid = window.Store.WidFactory.createWid(chatId);
- const chat = window.Store.Chat.get(chatWid) ?? (await window.Store.Chat.find(chatWid));
+ const chatWid = window.require('WAWebWidFactory').createWid(chatId);
+ const chat =
+ window.require('WAWebCollections').Chat.get(chatWid) ??
+ (await window.require('WAWebCollections').Chat.find(chatWid));
if (chat?.endOfHistoryTransferType === 0) {
- await window.Store.HistorySync.sendPeerDataOperationRequest(3, {
- chatId: chat.id
- });
+ await window
+ .require('WAWebSendNonMessageDataRequest')
+ .sendPeerDataOperationRequest(3, {
+ chatId: chat.id,
+ });
return true;
}
return false;
}, chatId);
}
-
+
/**
* Generates a WhatsApp call link (video call or voice call)
* @param {Date} startTime The start time of the call
@@ -2404,17 +3226,27 @@ class Client extends EventEmitter {
*/
async createCallLink(startTime, callType) {
if (!['video', 'voice'].includes(callType)) {
- throw new class CreateCallLinkError extends Error {
- constructor(m) { super(m); }
- }('Invalid \'callType\' parameter value is provided. Valid values are: \'voice\' | \'video\'.');
+ throw new (class CreateCallLinkError extends Error {
+ constructor(m) {
+ super(m);
+ }
+ })(
+ "Invalid 'callType' parameter value is provided. Valid values are: 'voice' | 'video'.",
+ );
}
startTime = Math.floor(startTime.getTime() / 1000);
-
- return await this.pupPage.evaluate(async (startTimeTs, callType) => {
- const response = await window.Store.ScheduledEventMsgUtils.createEventCallLink(startTimeTs, callType);
- return response ?? '';
- }, startTime, callType);
+
+ return await this.pupPage.evaluate(
+ async (startTimeTs, callType) => {
+ const response = await window
+ .require('WAWebGenerateEventCallLink')
+ .createEventCallLink(startTimeTs, callType);
+ return response ?? '';
+ },
+ startTime,
+ callType,
+ );
}
/**
@@ -2426,35 +3258,59 @@ class Client extends EventEmitter {
async sendResponseToScheduledEvent(response, eventMessageId) {
if (![0, 1, 2, 3].includes(response)) return false;
- return await this.pupPage.evaluate(async (response, msgId) => {
- const eventMsg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
- if (!eventMsg) return false;
+ return await this.pupPage.evaluate(
+ async (response, msgId) => {
+ const eventMsg =
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
+ if (!eventMsg) return false;
- await window.Store.ScheduledEventMsgUtils.sendEventResponseMsg(response, eventMsg);
- return true;
- }, response, eventMessageId);
+ await window
+ .require('WAWebSendEventResponseMsgAction')
+ .sendEventResponseMsg(response, eventMsg);
+ return true;
+ },
+ response,
+ eventMessageId,
+ );
}
-
+
/**
* Save new contact to user's addressbook or edit the existing one
* @param {string} phoneNumber The contact's phone number in a format "17182222222", where "1" is a country code
- * @param {string} firstName
- * @param {string} lastName
+ * @param {string} firstName
+ * @param {string} lastName
* @param {boolean} [syncToAddressbook = false] If set to true, the contact will also be saved to the user's address book on their phone. False by default
* @returns {Promise<void>}
*/
- async saveOrEditAddressbookContact(phoneNumber, firstName, lastName, syncToAddressbook = false)
- {
- return await this.pupPage.evaluate(async (phoneNumber, firstName, lastName, syncToAddressbook) => {
- return await window.Store.AddressbookContactUtils.saveContactAction({
- 'firstName' : firstName,
- 'lastName' : lastName,
- 'phoneNumber' : phoneNumber,
- 'prevPhoneNumber' : phoneNumber,
- 'syncToAddressbook': syncToAddressbook,
- 'username' : undefined
- });
- }, phoneNumber, firstName, lastName, syncToAddressbook);
+ async saveOrEditAddressbookContact(
+ phoneNumber,
+ firstName,
+ lastName,
+ syncToAddressbook = false,
+ ) {
+ return await this.pupPage.evaluate(
+ async (phoneNumber, firstName, lastName, syncToAddressbook) => {
+ return await window
+ .require('WAWebSaveContactAction')
+ .saveContactAction({
+ firstName: firstName,
+ lastName: lastName,
+ phoneNumber: phoneNumber,
+ prevPhoneNumber: phoneNumber,
+ syncToAddressbook: syncToAddressbook,
+ username: undefined,
+ });
+ },
+ phoneNumber,
+ firstName,
+ lastName,
+ syncToAddressbook,
+ );
}
/**
@@ -2462,11 +3318,14 @@ class Client extends EventEmitter {
* @param {string} phoneNumber The contact's phone number in a format "17182222222", where "1" is a country code
* @returns {Promise<void>}
*/
- async deleteAddressbookContact(phoneNumber)
- {
+ async deleteAddressbookContact(phoneNumber) {
return await this.pupPage.evaluate(async (phoneNumber) => {
- const wid = window.Store.WidFactory.createWid(phoneNumber);
- return await window.Store.AddressbookContactUtils.deleteContactAction({phoneNumber: wid});
+ const wid = window
+ .require('WAWebWidFactory')
+ .createWid(phoneNumber);
+ return await window
+ .require('WAWebDeleteContactAction')
+ .deleteContactAction({ phoneNumber: wid });
}, phoneNumber);
}
@@ -2479,14 +3338,17 @@ class Client extends EventEmitter {
return await this.pupPage.evaluate(async (userIds) => {
if (!Array.isArray(userIds)) userIds = [userIds];
- return await Promise.all(userIds.map(async (userId) => {
- const { lid, phone } = await window.WWebJS.enforceLidAndPnRetrieval(userId);
+ return await Promise.all(
+ userIds.map(async (userId) => {
+ const { lid, phone } =
+ await window.WWebJS.enforceLidAndPnRetrieval(userId);
- return {
- lid: lid?._serialized,
- pn: phone?._serialized
- };
- }));
+ return {
+ lid: lid?._serialized,
+ pn: phone?._serialized,
+ };
+ }),
+ );
}, userIds);
}
@@ -2498,15 +3360,28 @@ class Client extends EventEmitter {
* @returns {Promise<void>}
*/
async addOrEditCustomerNote(userId, note) {
- return await this.pupPage.evaluate(async (userId, note) => {
- if (!window.Store.BusinessGatingUtils.smbNotesV1Enabled()) return;
+ return await this.pupPage.evaluate(
+ async (userId, note) => {
+ if (!window.require('WAWebBizGatingUtils').smbNotesV1Enabled())
+ return;
- return window.Store.CustomerNoteUtils.noteAddAction(
- 'unstructured',
- window.Store.WidToJid.widToUserJid(window.Store.WidFactory.createWid(userId)),
- note
- );
- }, userId, note);
+ return window
+ .require('WAWebNoteAction')
+ .noteAddAction(
+ 'unstructured',
+ window
+ .require('WAWebWidToJid')
+ .widToUserJid(
+ window
+ .require('WAWebWidFactory')
+ .createWid(userId),
+ ),
+ note,
+ );
+ },
+ userId,
+ note,
+ );
}
/**
@@ -2524,71 +3399,88 @@ class Client extends EventEmitter {
*/
async getCustomerNote(userId) {
return await this.pupPage.evaluate(async (userId) => {
- if (!window.Store.BusinessGatingUtils.smbNotesV1Enabled()) return null;
+ if (!window.require('WAWebBizGatingUtils').smbNotesV1Enabled())
+ return null;
- const note = await window.Store.CustomerNoteUtils.retrieveOnlyNoteForChatJid(
- window.Store.WidToJid.widToUserJid(window.Store.WidFactory.createWid(userId))
- );
+ const note = await window
+ .require('WAWebNoteAction')
+ .retrieveOnlyNoteForChatJid(
+ window
+ .require('WAWebWidToJid')
+ .widToUserJid(
+ window.require('WAWebWidFactory').createWid(userId),
+ ),
+ );
let serialized = note?.serialize();
if (!serialized) return null;
- serialized.chatId = window.Store.JidToWid.userJidToUserWid(serialized.chatJid)._serialized;
+ serialized.chatId = window
+ .require('WAWebJidToWid')
+ .userJidToUserWid(serialized.chatJid)._serialized;
delete serialized.chatJid;
return serialized;
}, userId);
}
-
+
/**
* Get Poll Votes
* @param {string} messageId
- * @return {Promise<Array<PollVote>>}
+ * @return {Promise<Array<PollVote>>}
*/
async getPollVotes(messageId) {
const msg = await this.getMessageById(messageId);
if (!msg) return [];
- if (msg.type != MessageTypes.POLL_CREATION) throw 'Invalid usage! Can only be used with a pollCreation message';
+ if (msg.type != MessageTypes.POLL_CREATION)
+ throw 'Invalid usage! Can only be used with a pollCreation message';
- const pollVotes = await this.pupPage.evaluate( async (msg) => {
- const msgKey = window.Store.MsgKey.fromString(msg.id._serialized);
- let pollVotes = await window.Store.PollsVotesSchema.getTable().equals(['parentMsgKey'], msgKey.toString());
-
- return pollVotes.map(item => {
+ const pollVotes = await this.pupPage.evaluate(async (msg) => {
+ const msgKey = window
+ .require('WAWebMsgKey')
+ .fromString(msg.id._serialized);
+ let pollVotes = await window
+ .require('WAWebPollsVotesSchema')
+ .getTable()
+ .equals(['parentMsgKey'], msgKey.toString());
+
+ return pollVotes.map((item) => {
const typedArray = new Uint8Array(item.selectedOptionLocalIds);
return {
...item,
- selectedOptionLocalIds: Array.from(typedArray)
+ selectedOptionLocalIds: Array.from(typedArray),
};
});
}, msg);
- return pollVotes.map((pollVote) => new PollVote(this.client, {...pollVote, parentMessage: msg}));
+ return pollVotes.map(
+ (pollVote) =>
+ new PollVote(this.client, { ...pollVote, parentMessage: msg }),
+ );
}
}
module.exports = Client;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/ClientInfo.html b/docs/ClientInfo.html
index cb73d9e..d73786e 100644
--- a/docs/ClientInfo.html
+++ b/docs/ClientInfo.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Class: ClientInfo
+ whatsapp-web.js 1.34.7 » Class: ClientInfo
@@ -15,7 +15,7 @@
@@ -242,7 +242,7 @@
diff --git a/docs/Contact.html b/docs/Contact.html
index 67cb0b1..4ab6efc 100644
--- a/docs/Contact.html
+++ b/docs/Contact.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Class: Contact
+ whatsapp-web.js 1.34.7 » Class: Contact
@@ -15,7 +15,7 @@
@@ -305,7 +305,7 @@
diff --git a/docs/GroupChat.html b/docs/GroupChat.html
index d95e970..b8dbcdb 100644
--- a/docs/GroupChat.html
+++ b/docs/GroupChat.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Class: GroupChat
+ whatsapp-web.js 1.34.7 » Class: GroupChat
@@ -15,7 +15,7 @@
@@ -54,6 +54,9 @@
isGroup
+ isLocked
+
+
- owner
-
-
participants
@@ -272,6 +275,13 @@
Inherited from
Chat#isGroup
+
isLocked
+ unknown
+
Indicates if the Chat is locked
+
+ Inherited from
+ Chat#isLocked
+
isMuted
unknown
Indicates if the chat is muted or not
@@ -1294,7 +1304,7 @@
diff --git a/docs/GroupNotification.html b/docs/GroupNotification.html
index 6638f7d..284035c 100644
--- a/docs/GroupNotification.html
+++ b/docs/GroupNotification.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: GroupNotification
+
whatsapp-web.js 1.34.7 » Class: GroupNotification
@@ -15,7 +15,7 @@
@@ -233,7 +233,7 @@
diff --git a/docs/InterfaceController.html b/docs/InterfaceController.html
index 33628d4..6f7f0b5 100644
--- a/docs/InterfaceController.html
+++ b/docs/InterfaceController.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: InterfaceController
+
whatsapp-web.js 1.34.7 » Class: InterfaceController
@@ -15,7 +15,7 @@
@@ -382,7 +382,7 @@
diff --git a/docs/Label.html b/docs/Label.html
index 271d38a..b958016 100644
--- a/docs/Label.html
+++ b/docs/Label.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: Label
+
whatsapp-web.js 1.34.7 » Class: Label
@@ -15,7 +15,7 @@
@@ -163,7 +163,7 @@
diff --git a/docs/List.html b/docs/List.html
index 28c1d00..e7e704e 100644
--- a/docs/List.html
+++ b/docs/List.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: List
+
whatsapp-web.js 1.34.7 » Class: List
@@ -15,7 +15,7 @@
@@ -256,7 +256,7 @@ Returns: [{'title':'sectionTitle','rows':[{'r
diff --git a/docs/LocalAuth.html b/docs/LocalAuth.html
index c3a5285..b63b2e4 100644
--- a/docs/LocalAuth.html
+++ b/docs/LocalAuth.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: LocalAuth
+
whatsapp-web.js 1.34.7 » Class: LocalAuth
@@ -15,7 +15,7 @@
@@ -134,7 +134,7 @@
diff --git a/docs/LocalWebCache.html b/docs/LocalWebCache.html
index af5ddd5..6ad77ef 100644
--- a/docs/LocalWebCache.html
+++ b/docs/LocalWebCache.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: LocalWebCache
+
whatsapp-web.js 1.34.7 » Class: LocalWebCache
@@ -15,7 +15,7 @@
@@ -120,7 +120,7 @@
diff --git a/docs/Location.html b/docs/Location.html
index ce89bae..094b96e 100644
--- a/docs/Location.html
+++ b/docs/Location.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: Location
+
whatsapp-web.js 1.34.7 » Class: Location
@@ -15,7 +15,7 @@
@@ -173,7 +173,7 @@
diff --git a/docs/Message.html b/docs/Message.html
index 7338dc4..5cb3d37 100644
--- a/docs/Message.html
+++ b/docs/Message.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: Message
+
whatsapp-web.js 1.34.7 » Class: Message
@@ -15,7 +15,7 @@
@@ -911,7 +911,7 @@
diff --git a/docs/MessageMedia.html b/docs/MessageMedia.html
index 5c3d07f..f55b94d 100644
--- a/docs/MessageMedia.html
+++ b/docs/MessageMedia.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: MessageMedia
+
whatsapp-web.js 1.34.7 » Class: MessageMedia
@@ -15,7 +15,7 @@
@@ -364,7 +364,7 @@
diff --git a/docs/NoAuth.html b/docs/NoAuth.html
index 3d33e3a..527655f 100644
--- a/docs/NoAuth.html
+++ b/docs/NoAuth.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: NoAuth
+
whatsapp-web.js 1.34.7 » Class: NoAuth
@@ -15,7 +15,7 @@
@@ -51,7 +51,7 @@
diff --git a/docs/Order.html b/docs/Order.html
index 79008b8..a3b867c 100644
--- a/docs/Order.html
+++ b/docs/Order.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: Order
+
whatsapp-web.js 1.34.7 » Class: Order
@@ -15,7 +15,7 @@
@@ -102,7 +102,7 @@
diff --git a/docs/Poll.html b/docs/Poll.html
index bdb56bd..c577797 100644
--- a/docs/Poll.html
+++ b/docs/Poll.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: Poll
+
whatsapp-web.js 1.34.7 » Class: Poll
@@ -15,7 +15,7 @@
@@ -148,7 +148,7 @@
diff --git a/docs/PollVote.html b/docs/PollVote.html
index a78b135..50e24bf 100644
--- a/docs/PollVote.html
+++ b/docs/PollVote.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: PollVote
+
whatsapp-web.js 1.34.7 » Class: PollVote
@@ -15,7 +15,7 @@
@@ -102,7 +102,7 @@
diff --git a/docs/PrivateChat.html b/docs/PrivateChat.html
index ab51157..ad71a1f 100644
--- a/docs/PrivateChat.html
+++ b/docs/PrivateChat.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: PrivateChat
+
whatsapp-web.js 1.34.7 » Class: PrivateChat
@@ -15,7 +15,7 @@
@@ -48,13 +48,16 @@
isGroup
-
isMuted
+
isLocked
+ name
+
+
pinned
@@ -199,6 +202,13 @@
Inherited from
Chat#isGroup
+
isLocked
+ unknown
+
Indicates if the Chat is locked
+
+ Inherited from
+ Chat#isLocked
+
isMuted
unknown
Indicates if the chat is muted or not
@@ -670,7 +680,7 @@
diff --git a/docs/PrivateContact.html b/docs/PrivateContact.html
index 660feb3..d40f1a9 100644
--- a/docs/PrivateContact.html
+++ b/docs/PrivateContact.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: PrivateContact
+
whatsapp-web.js 1.34.7 » Class: PrivateContact
@@ -15,7 +15,7 @@
@@ -331,7 +331,7 @@
diff --git a/docs/Product.html b/docs/Product.html
index e3d2f99..18f6420 100644
--- a/docs/Product.html
+++ b/docs/Product.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: Product
+
whatsapp-web.js 1.34.7 » Class: Product
@@ -15,7 +15,7 @@
@@ -127,7 +127,7 @@
diff --git a/docs/Reaction.html b/docs/Reaction.html
index a209ee4..3cce2aa 100644
--- a/docs/Reaction.html
+++ b/docs/Reaction.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: Reaction
+
whatsapp-web.js 1.34.7 » Class: Reaction
@@ -15,7 +15,7 @@
@@ -144,7 +144,7 @@
diff --git a/docs/RemoteAuth.html b/docs/RemoteAuth.html
index 116b3c4..e498fad 100644
--- a/docs/RemoteAuth.html
+++ b/docs/RemoteAuth.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: RemoteAuth
+
whatsapp-web.js 1.34.7 » Class: RemoteAuth
@@ -15,7 +15,7 @@
@@ -162,7 +162,7 @@
diff --git a/docs/RemoteWebCache.html b/docs/RemoteWebCache.html
index 027052a..426531f 100644
--- a/docs/RemoteWebCache.html
+++ b/docs/RemoteWebCache.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: RemoteWebCache
+
whatsapp-web.js 1.34.7 » Class: RemoteWebCache
@@ -15,7 +15,7 @@
@@ -120,7 +120,7 @@
diff --git a/docs/ScheduledEvent.html b/docs/ScheduledEvent.html
index 1538d26..845754d 100644
--- a/docs/ScheduledEvent.html
+++ b/docs/ScheduledEvent.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: ScheduledEvent
+
whatsapp-web.js 1.34.7 » Class: ScheduledEvent
@@ -15,7 +15,7 @@
@@ -220,7 +220,7 @@
diff --git a/docs/Util.html b/docs/Util.html
index 8287d33..fb1ba27 100644
--- a/docs/Util.html
+++ b/docs/Util.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: Util
+
whatsapp-web.js 1.34.7 » Class: Util
@@ -15,7 +15,7 @@
@@ -243,7 +243,7 @@
diff --git a/docs/WebCache.html b/docs/WebCache.html
index 82b4d60..eda9e64 100644
--- a/docs/WebCache.html
+++ b/docs/WebCache.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Class: WebCache
+
whatsapp-web.js 1.34.7 » Class: WebCache
@@ -15,7 +15,7 @@
@@ -50,7 +50,7 @@
diff --git a/docs/authStrategies_BaseAuthStrategy.js.html b/docs/authStrategies_BaseAuthStrategy.js.html
index d3b69d8..52b9350 100644
--- a/docs/authStrategies_BaseAuthStrategy.js.html
+++ b/docs/authStrategies_BaseAuthStrategy.js.html
@@ -4,7 +4,7 @@
-
whatsapp-web.js 1.34.6 » Source: authStrategies/BaseAuthStrategy.js
+
whatsapp-web.js 1.34.7 » Source: authStrategies/BaseAuthStrategy.js
@@ -15,7 +15,7 @@
@@ -39,15 +39,17 @@ class BaseAuthStrategy {
setup(client) {
this.client = client;
}
+
async beforeBrowserInitialized() {}
async afterBrowserInitialized() {}
async onAuthenticationNeeded() {
return {
failed: false,
restart: false,
- failureEventPayload: undefined
+ failureEventPayload: undefined,
};
}
+
async getAuthEventPayload() {}
async afterAuthReady() {}
async disconnect() {}
@@ -55,7 +57,8 @@ class BaseAuthStrategy {
async logout() {}
}
-module.exports = BaseAuthStrategy;
+module.exports = BaseAuthStrategy;
+
@@ -65,7 +68,7 @@ module.exports = BaseAuthStrategy;
diff --git a/docs/authStrategies_LocalAuth.js.html b/docs/authStrategies_LocalAuth.js.html
index de6b3f9..176a971 100644
--- a/docs/authStrategies_LocalAuth.js.html
+++ b/docs/authStrategies_LocalAuth.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: authStrategies/LocalAuth.js
+ whatsapp-web.js 1.34.7 » Source: authStrategies/LocalAuth.js
@@ -15,7 +15,7 @@
@@ -39,16 +39,18 @@ const BaseAuthStrategy = require('./BaseAuthStrategy');
* Local directory-based authentication
* @param {object} options - options
* @param {string} options.clientId - Client id to distinguish instances if you are using multiple, otherwise keep null if you are using only one instance
- * @param {string} options.dataPath - Change the default path for saving session files, default is: "./.wwebjs_auth/"
+ * @param {string} options.dataPath - Change the default path for saving session files, default is: "./.wwebjs_auth/"
* @param {number} options.rmMaxRetries - Sets the maximum number of retries for removing the session directory
-*/
+ */
class LocalAuth extends BaseAuthStrategy {
- constructor({ clientId, dataPath, rmMaxRetries }={}) {
+ constructor({ clientId, dataPath, rmMaxRetries } = {}) {
super();
const idRegex = /^[-_\w]+$/i;
- if(clientId && !idRegex.test(clientId)) {
- throw new Error('Invalid clientId. Only alphanumeric characters, underscores and hyphens are allowed.');
+ if (clientId && !idRegex.test(clientId)) {
+ throw new Error(
+ 'Invalid clientId. Only alphanumeric characters, underscores and hyphens are allowed.',
+ );
}
this.dataPath = path.resolve(dataPath || './.wwebjs_auth/');
@@ -58,18 +60,25 @@ class LocalAuth extends BaseAuthStrategy {
async beforeBrowserInitialized() {
const puppeteerOpts = this.client.options.puppeteer;
- const sessionDirName = this.clientId ? `session-${this.clientId}` : 'session';
+ const sessionDirName = this.clientId
+ ? `session-${this.clientId}`
+ : 'session';
const dirPath = path.join(this.dataPath, sessionDirName);
- if(puppeteerOpts.userDataDir && puppeteerOpts.userDataDir !== dirPath) {
- throw new Error('LocalAuth is not compatible with a user-supplied userDataDir.');
+ if (
+ puppeteerOpts.userDataDir &&
+ puppeteerOpts.userDataDir !== dirPath
+ ) {
+ throw new Error(
+ 'LocalAuth is not compatible with a user-supplied userDataDir.',
+ );
}
fs.mkdirSync(dirPath, { recursive: true });
-
+
this.client.options.puppeteer = {
...puppeteerOpts,
- userDataDir: dirPath
+ userDataDir: dirPath,
};
this.userDataDir = dirPath;
@@ -77,13 +86,17 @@ class LocalAuth extends BaseAuthStrategy {
async logout() {
if (this.userDataDir) {
- await fs.promises.rm(this.userDataDir, { recursive: true, force: true, maxRetries: this.rmMaxRetries })
+ await fs.promises
+ .rm(this.userDataDir, {
+ recursive: true,
+ force: true,
+ maxRetries: this.rmMaxRetries,
+ })
.catch((e) => {
throw new Error(e);
});
}
}
-
}
module.exports = LocalAuth;
@@ -97,7 +110,7 @@ module.exports = LocalAuth;
diff --git a/docs/authStrategies_NoAuth.js.html b/docs/authStrategies_NoAuth.js.html
index b6b4699..07e73c6 100644
--- a/docs/authStrategies_NoAuth.js.html
+++ b/docs/authStrategies_NoAuth.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: authStrategies/NoAuth.js
+ whatsapp-web.js 1.34.7 » Source: authStrategies/NoAuth.js
@@ -15,7 +15,7 @@
@@ -36,11 +36,11 @@ const BaseAuthStrategy = require('./BaseAuthStrategy');
/**
* No session restoring functionality
* Will need to authenticate via QR code every time
-*/
-class NoAuth extends BaseAuthStrategy { }
+ */
+class NoAuth extends BaseAuthStrategy {}
-
-module.exports = NoAuth;
+module.exports = NoAuth;
+
@@ -50,7 +50,7 @@ module.exports = NoAuth;
diff --git a/docs/authStrategies_RemoteAuth.js.html b/docs/authStrategies_RemoteAuth.js.html
index e201391..4d86617 100644
--- a/docs/authStrategies_RemoteAuth.js.html
+++ b/docs/authStrategies_RemoteAuth.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: authStrategies/RemoteAuth.js
+ whatsapp-web.js 1.34.7 » Source: authStrategies/RemoteAuth.js
@@ -15,7 +15,7 @@
@@ -51,40 +51,64 @@ const BaseAuthStrategy = require('./BaseAuthStrategy');
* @param {object} options - options
* @param {object} options.store - Remote database store instance
* @param {string} options.clientId - Client id to distinguish instances if you are using multiple, otherwise keep null if you are using only one instance
- * @param {string} options.dataPath - Change the default path for saving session files, default is: "./.wwebjs_auth/"
+ * @param {string} options.dataPath - Change the default path for saving session files, default is: "./.wwebjs_auth/"
* @param {number} options.backupSyncIntervalMs - Sets the time interval for periodic session backups. Accepts values starting from 60000ms {1 minute}
* @param {number} options.rmMaxRetries - Sets the maximum number of retries for removing the session directory
*/
class RemoteAuth extends BaseAuthStrategy {
- constructor({ clientId, dataPath, store, backupSyncIntervalMs, rmMaxRetries } = {}) {
- if (!fs && !unzipper && !archiver) throw new Error('Optional Dependencies [fs-extra, unzipper, archiver] are required to use RemoteAuth. Make sure to run npm install correctly and remove the --no-optional flag');
+ constructor({
+ clientId,
+ dataPath,
+ store,
+ backupSyncIntervalMs,
+ rmMaxRetries,
+ } = {}) {
+ if (!fs && !unzipper && !archiver)
+ throw new Error(
+ 'Optional Dependencies [fs-extra, unzipper, archiver] are required to use RemoteAuth. Make sure to run npm install correctly and remove the --no-optional flag',
+ );
super();
const idRegex = /^[-_\w]+$/i;
if (clientId && !idRegex.test(clientId)) {
- throw new Error('Invalid clientId. Only alphanumeric characters, underscores and hyphens are allowed.');
+ throw new Error(
+ 'Invalid clientId. Only alphanumeric characters, underscores and hyphens are allowed.',
+ );
}
if (!backupSyncIntervalMs || backupSyncIntervalMs < 60000) {
- throw new Error('Invalid backupSyncIntervalMs. Accepts values starting from 60000ms {1 minute}.');
+ throw new Error(
+ 'Invalid backupSyncIntervalMs. Accepts values starting from 60000ms {1 minute}.',
+ );
}
- if(!store) throw new Error('Remote database store is required.');
+ if (!store) throw new Error('Remote database store is required.');
this.store = store;
this.clientId = clientId;
this.backupSyncIntervalMs = backupSyncIntervalMs;
this.dataPath = path.resolve(dataPath || './.wwebjs_auth/');
this.tempDir = `${this.dataPath}/wwebjs_temp_session_${this.clientId}`;
- this.requiredDirs = ['Default', 'IndexedDB', 'Local Storage']; /* => Required Files & Dirs in WWebJS to restore session */
+ this.requiredDirs = [
+ 'Default',
+ 'IndexedDB',
+ 'Local Storage',
+ ]; /* => Required Files & Dirs in WWebJS to restore session */
this.rmMaxRetries = rmMaxRetries ?? 4;
}
async beforeBrowserInitialized() {
const puppeteerOpts = this.client.options.puppeteer;
- const sessionDirName = this.clientId ? `RemoteAuth-${this.clientId}` : 'RemoteAuth';
+ const sessionDirName = this.clientId
+ ? `RemoteAuth-${this.clientId}`
+ : 'RemoteAuth';
const dirPath = path.join(this.dataPath, sessionDirName);
- if (puppeteerOpts.userDataDir && puppeteerOpts.userDataDir !== dirPath) {
- throw new Error('RemoteAuth is not compatible with a user-supplied userDataDir.');
+ if (
+ puppeteerOpts.userDataDir &&
+ puppeteerOpts.userDataDir !== dirPath
+ ) {
+ throw new Error(
+ 'RemoteAuth is not compatible with a user-supplied userDataDir.',
+ );
}
this.userDataDir = dirPath;
@@ -94,7 +118,7 @@ class RemoteAuth extends BaseAuthStrategy {
this.client.options.puppeteer = {
...puppeteerOpts,
- userDataDir: dirPath
+ userDataDir: dirPath,
};
}
@@ -111,20 +135,26 @@ class RemoteAuth extends BaseAuthStrategy {
let pathExists = await this.isValidPath(this.userDataDir);
if (pathExists) {
- await fs.promises.rm(this.userDataDir, {
- recursive: true,
- force: true,
- maxRetries: this.rmMaxRetries,
- }).catch(() => {});
+ await fs.promises
+ .rm(this.userDataDir, {
+ recursive: true,
+ force: true,
+ maxRetries: this.rmMaxRetries,
+ })
+ .catch(() => {});
}
clearInterval(this.backupSync);
}
async afterAuthReady() {
- const sessionExists = await this.store.sessionExists({session: this.sessionName});
- if(!sessionExists) {
- await this.delay(60000); /* Initial delay sync required for session to be stable enough to recover */
- await this.storeRemoteSession({emit: true});
+ const sessionExists = await this.store.sessionExists({
+ session: this.sessionName,
+ });
+ if (!sessionExists) {
+ await this.delay(
+ 60000,
+ ); /* Initial delay sync required for session to be stable enough to recover */
+ await this.storeRemoteSession({ emit: true });
}
var self = this;
this.backupSync = setInterval(async function () {
@@ -133,34 +163,57 @@ class RemoteAuth extends BaseAuthStrategy {
}
async storeRemoteSession(options) {
- /* Compress & Store Session */
const pathExists = await this.isValidPath(this.userDataDir);
- if (pathExists) {
- await this.compressSession();
- await this.store.save({session: path.join(this.dataPath, this.sessionName)});
- await fs.promises.unlink(path.join(this.dataPath, `${this.sessionName}.zip`));
- await fs.promises.rm(`${this.tempDir}`, {
- recursive: true,
- force: true,
- maxRetries: this.rmMaxRetries,
- }).catch(() => {});
- if(options && options.emit) this.client.emit(Events.REMOTE_SESSION_SAVED);
+ if (!pathExists) return;
+
+ let compressedSessionPath;
+ try {
+ compressedSessionPath = await this.compressSession();
+ await this.store.save({
+ session: this.sessionName,
+ });
+ if (options && options.emit)
+ this.client.emit(Events.REMOTE_SESSION_SAVED);
+ } finally {
+ const paths = [
+ this.tempDir,
+ ...(compressedSessionPath ? [compressedSessionPath] : []),
+ ];
+ await Promise.allSettled(
+ paths.map((p) =>
+ fs.promises.rm(p, {
+ recursive: true,
+ force: true,
+ maxRetries: this.rmMaxRetries,
+ }),
+ ),
+ );
}
}
async extractRemoteSession() {
const pathExists = await this.isValidPath(this.userDataDir);
- const compressedSessionPath = path.join(this.dataPath, `${this.sessionName}.zip`);
- const sessionExists = await this.store.sessionExists({session: this.sessionName});
+ const compressedSessionPath = path.join(
+ this.dataPath,
+ `${this.sessionName}.zip`,
+ );
+ const sessionExists = await this.store.sessionExists({
+ session: this.sessionName,
+ });
if (pathExists) {
- await fs.promises.rm(this.userDataDir, {
- recursive: true,
- force: true,
- maxRetries: this.rmMaxRetries,
- }).catch(() => {});
+ await fs.promises
+ .rm(this.userDataDir, {
+ recursive: true,
+ force: true,
+ maxRetries: this.rmMaxRetries,
+ })
+ .catch(() => {});
}
if (sessionExists) {
- await this.store.extract({session: this.sessionName, path: compressedSessionPath});
+ await this.store.extract({
+ session: this.sessionName,
+ path: compressedSessionPath,
+ });
await this.unCompressSession(compressedSessionPath);
} else {
fs.mkdirSync(this.userDataDir, { recursive: true });
@@ -168,59 +221,62 @@ class RemoteAuth extends BaseAuthStrategy {
}
async deleteRemoteSession() {
- const sessionExists = await this.store.sessionExists({session: this.sessionName});
- if (sessionExists) await this.store.delete({session: this.sessionName});
+ const sessionExists = await this.store.sessionExists({
+ session: this.sessionName,
+ });
+ if (sessionExists)
+ await this.store.delete({ session: this.sessionName });
}
async compressSession() {
+ const stageDefaultPath = path.join(this.tempDir, 'Default');
+ const userDataDefaultPath = path.join(this.userDataDir, 'Default');
+
+ await fs.emptyDir(stageDefaultPath);
+ await this.copyByRequiredDirs(userDataDefaultPath, stageDefaultPath);
+
const archive = archiver('zip');
- const stream = fs.createWriteStream(path.join(this.dataPath, `${this.sessionName}.zip`));
+ const outPath = path.join(this.dataPath, `${this.sessionName}.zip`);
+ const out = fs.createWriteStream(outPath);
- await fs.copy(this.userDataDir, this.tempDir).catch(() => {});
- await this.deleteMetadata();
- return new Promise((resolve, reject) => {
- archive
- .directory(this.tempDir, false)
- .on('error', err => reject(err))
- .pipe(stream);
+ await new Promise((resolve, reject) => {
+ out.once('close', resolve);
+ out.once('error', reject);
+ archive.once('error', reject);
- stream.on('close', () => resolve());
+ archive.pipe(out);
+ archive.directory(this.tempDir, false);
archive.finalize();
});
+ return outPath;
}
async unCompressSession(compressedSessionPath) {
var stream = fs.createReadStream(compressedSessionPath);
await new Promise((resolve, reject) => {
- stream.pipe(unzipper.Extract({
- path: this.userDataDir,
- concurrency: 10
- }))
- .on('error', err => reject(err))
+ stream
+ .pipe(
+ unzipper.Extract({
+ path: this.userDataDir,
+ concurrency: 10,
+ }),
+ )
+ .on('error', (err) => reject(err))
.on('finish', () => resolve());
});
await fs.promises.unlink(compressedSessionPath);
}
- async deleteMetadata() {
- const sessionDirs = [this.tempDir, path.join(this.tempDir, 'Default')];
- for (const dir of sessionDirs) {
- const sessionFiles = await fs.promises.readdir(dir);
- for (const element of sessionFiles) {
- if (!this.requiredDirs.includes(element)) {
- const dirElement = path.join(dir, element);
- const stats = await fs.promises.lstat(dirElement);
-
- if (stats.isDirectory()) {
- await fs.promises.rm(dirElement, {
- recursive: true,
- force: true,
- maxRetries: this.rmMaxRetries,
- }).catch(() => {});
- } else {
- await fs.promises.unlink(dirElement).catch(() => {});
- }
- }
+ async copyByRequiredDirs(from, to) {
+ for (const d of this.requiredDirs) {
+ const src = path.join(from, d);
+ if (await this.isValidPath(src)) {
+ const dest = path.join(to, path.basename(src));
+ await fs.promises.cp(src, dest, {
+ recursive: true,
+ force: true,
+ errorOnExist: false,
+ });
}
}
}
@@ -235,7 +291,7 @@ class RemoteAuth extends BaseAuthStrategy {
}
async delay(ms) {
- return new Promise(resolve => setTimeout(resolve, ms));
+ return new Promise((resolve) => setTimeout(resolve, ms));
}
}
@@ -250,7 +306,7 @@ module.exports = RemoteAuth;
diff --git a/docs/global.html b/docs/global.html
index 0019e9e..203cce7 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Globals
+ whatsapp-web.js 1.34.7 » Globals
@@ -15,7 +15,7 @@
@@ -188,9 +188,6 @@
TargetOptions
- TargetOptions
-
-
TransferChannelOwnershipOptions
@@ -375,6 +372,19 @@
+
MESSAGE_CREATE
@@ -4163,68 +4173,6 @@
TargetOptions
Object
Target options object description
-
- Properties
-
-
-
- Name
- Type
- Optional
- Description
-
-
-
-
-
- module
-
-
- (string or number)
-
-
-
-
-
- The name or a key of the target module to search
-
-
-
-
- index
-
-
- number
-
-
-
-
-
- The index value of the target module
-
-
-
-
- function
-
-
- string
-
-
-
-
-
- The function name to get from a module
-
-
-
-
-
-
-
- TargetOptions
- Object
- Target options object description
Properties
@@ -4385,7 +4333,7 @@
diff --git a/docs/index.html b/docs/index.html
index 68a76fb..a00f047 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -3,7 +3,7 @@
- whatsapp-web.js 1.34.6 » Home
+ whatsapp-web.js 1.34.7 » Home
@@ -13,7 +13,7 @@
@@ -26,61 +26,62 @@
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
About
-A WhatsApp API client that operates via the WhatsApp Web browser.
-The library launches the WhatsApp Web browser app via Puppeteer, accessing its internal functions and creating a managed instance to reduce the risk of being blocked. This gives the API client nearly all WhatsApp Web features for dynamic use in a Node.js application.
-
-[!IMPORTANT]
-It is not guaranteed you will not be blocked by using this method. WhatsApp does not allow bots or unofficial clients on their platform, so this shouldn't be considered totally safe.
-
+whatsapp‑web.js is a powerful Node.js library that lets you interact with WhatsApp Web, making it easy to build a dynamic WhatsApp API with nearly all features of the web client. It uses Puppeteer to access WhatsApp Web’s internal functions and runs them in a managed browser instance to reduce the risk of being blocked.
Links
Installation
-The module is available on npm via npm i whatsapp-web.js!
-
-[!NOTE]
-Node v18 or higher, is required.
-See the Guide for quick upgrade instructions.
-
+Node.js v18.0.0 or higher, is required.
+npm install whatsapp-web.js
+yarn add whatsapp-web.js
+pnpm add whatsapp-web.js
+
+Having trouble installing? Take a peak at the Guide for more detailed instructions.
Example usage
const { Client } = require('whatsapp-web.js');
+const qrcode = require('qrcode-terminal');
const client = new Client();
client.on('qr', (qr) => {
- // Generate and scan this code with your phone
- console.log('QR RECEIVED', qr);
+ qrcode.generate(qr, { small: true });
});
client.on('ready', () => {
console.log('Client is ready!');
});
-client.on('message', msg => {
+client.on('message', (msg) => {
if (msg.body == '!ping') {
msg.reply('pong');
}
@@ -88,8 +89,8 @@ client.on('message', msg => {
client.initialize();
-Take a look at example.js for another examples with additional use cases.
-For further details on saving and restoring sessions, explore the provided Authentication Strategies .
+Take a look at example.js for additional examples and use cases.
+For more details on saving and restoring sessions, check out the Authentication Strategies .
Supported features
Something missing? Make an issue and let us know!
-Contributing
-Feel free to open pull requests; we welcome contributions! However, for significant changes, it's best to open an issue beforehand. Make sure to review our contribution guidelines before creating a pull request. Before creating your own issue or pull request, always check to see if one already exists!
Supporting the project
-You can support the maintainer of this project through the links below
+You can support the maintainer of this project through the links below:
+Contributing
+Feel free to open pull requests; we welcome contributions! However, for significant changes, it's best to open an issue beforehand. Make sure to review our contribution guidelines before creating a pull request. Before creating your own issue or pull request, always check to see if one already exists!
Disclaimer
This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with WhatsApp or any of its subsidiaries or its affiliates. The official WhatsApp website can be found at whatsapp.com . "WhatsApp" as well as related names, marks, emblems and images are registered trademarks of their respective owners. Also it is not guaranteed you will not be blocked by using this method. WhatsApp does not allow bots or unofficial clients on their platform, so this shouldn't be considered totally safe.
License
Copyright 2019 Pedro S Lopez
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this project except in compliance with the License.
-You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
+You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 .
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -898,6 +898,11 @@ limitations under the License.
+
+ Chat#isLocked
+
+
+
Chat#isMuted
@@ -938,16 +943,16 @@ limitations under the License.
-
- Chat#pinned
-
-
-
+
+ Chat#pinned
+
+
+
Chat#sendMessage(content[, options])
@@ -1097,6 +1102,11 @@ limitations under the License.
+
+ Client#cancelPairingCode()
+
+
+
Client#createCallLink(startTime, callType)
@@ -1233,7 +1243,7 @@ limitations under the License.
- Client#event:message_create
+ Client#event:message_ciphertext_failed
@@ -1242,6 +1252,11 @@ limitations under the License.
-
-
+
+
-
-
+
+
+
+ PrivateChat#pinned
+
+
+
PrivateChat#sendMessage(content[, options])
@@ -4391,7 +4426,7 @@ limitations under the License.
- window.compareWwebVersions(lOperand, operator, rOperand)
+ window.WWebJS.compareWwebVersions(lOperand, operator, rOperand)
@@ -4401,7 +4436,7 @@ limitations under the License.
- window.injectToFunction(target, callback)
+ window.WWebJS.injectToFunction(target, callback)
@@ -4426,7 +4461,7 @@ limitations under the License.
diff --git a/docs/structures_Base.js.html b/docs/structures_Base.js.html
index f60a2ec..6086ac2 100644
--- a/docs/structures_Base.js.html
+++ b/docs/structures_Base.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/Base.js
+ whatsapp-web.js 1.34.7 » Source: structures/Base.js
@@ -15,7 +15,7 @@
@@ -46,11 +46,14 @@ class Base {
_clone() {
return Object.assign(Object.create(this), this);
}
-
- _patch(data) { return data; }
+
+ _patch(data) {
+ return data;
+ }
}
-module.exports = Base;
+module.exports = Base;
+
@@ -60,7 +63,7 @@ module.exports = Base;
diff --git a/docs/structures_Broadcast.js.html b/docs/structures_Broadcast.js.html
index 5fb7b3c..8ac81b1 100644
--- a/docs/structures_Broadcast.js.html
+++ b/docs/structures_Broadcast.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/Broadcast.js
+ whatsapp-web.js 1.34.7 » Source: structures/Broadcast.js
@@ -15,7 +15,7 @@
@@ -74,7 +74,7 @@ class Broadcast extends Base {
* Messages statuses
* @type {Message[]}
*/
- this.msgs = data.msgs?.map(msg => new Message(this.client, msg));
+ this.msgs = data.msgs?.map((msg) => new Message(this.client, msg));
return super._patch(data);
}
@@ -94,7 +94,6 @@ class Broadcast extends Base {
getContact() {
return this.client.getContactById(this.id._serialized);
}
-
}
module.exports = Broadcast;
@@ -108,7 +107,7 @@ module.exports = Broadcast;
diff --git a/docs/structures_BusinessContact.js.html b/docs/structures_BusinessContact.js.html
index 972d392..6bbe16d 100644
--- a/docs/structures_BusinessContact.js.html
+++ b/docs/structures_BusinessContact.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/BusinessContact.js
+ whatsapp-web.js 1.34.7 » Source: structures/BusinessContact.js
@@ -15,7 +15,7 @@
@@ -46,10 +46,10 @@ class BusinessContact extends Contact {
return super._patch(data);
}
-
}
-module.exports = BusinessContact;
+module.exports = BusinessContact;
+
@@ -59,7 +59,7 @@ module.exports = BusinessContact;
diff --git a/docs/structures_Buttons.js.html b/docs/structures_Buttons.js.html
index 4c64918..2523107 100644
--- a/docs/structures_Buttons.js.html
+++ b/docs/structures_Buttons.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/Buttons.js
+ whatsapp-web.js 1.34.7 » Source: structures/Buttons.js
@@ -15,7 +15,7 @@
@@ -70,7 +70,7 @@ class Buttons {
* @type {string}
*/
this.title = title;
-
+
/**
* footer of message
* @type {string}
@@ -80,7 +80,7 @@ class Buttons {
if (body instanceof MessageMedia) {
this.type = 'media';
this.title = '';
- }else{
+ } else {
this.type = 'chat';
}
@@ -89,28 +89,33 @@ class Buttons {
* @type {FormattedButtonSpec[]}
*/
this.buttons = this._format(buttons);
- if(!this.buttons.length){ throw '[BT01] No buttons';}
-
+ if (!this.buttons.length) {
+ throw '[BT01] No buttons';
+ }
}
/**
* Creates button array from simple array
* @param {ButtonSpec[]} buttons
* @returns {FormattedButtonSpec[]}
- * @example
+ * @example
* Input: [{id:'customId',body:'button1'},{body:'button2'},{body:'button3'},{body:'button4'}]
* Returns: [{ buttonId:'customId',buttonText:{'displayText':'button1'},type: 1 },{buttonId:'n3XKsL',buttonText:{'displayText':'button2'},type:1},{buttonId:'NDJk0a',buttonText:{'displayText':'button3'},type:1}]
*/
- _format(buttons){
- buttons = buttons.slice(0,3); // phone users can only see 3 buttons, so lets limit this
+ _format(buttons) {
+ buttons = buttons.slice(0, 3); // phone users can only see 3 buttons, so lets limit this
return buttons.map((btn) => {
- return {'buttonId':btn.id ? String(btn.id) : Util.generateHash(6),'buttonText':{'displayText':btn.body},'type':1};
+ return {
+ buttonId: btn.id ? String(btn.id) : Util.generateHash(6),
+ buttonText: { displayText: btn.body },
+ type: 1,
+ };
});
}
-
}
-module.exports = Buttons;
+module.exports = Buttons;
+
@@ -120,7 +125,7 @@ module.exports = Buttons;
diff --git a/docs/structures_Call.js.html b/docs/structures_Call.js.html
index 82626a0..c03bacf 100644
--- a/docs/structures_Call.js.html
+++ b/docs/structures_Call.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/Call.js
+ whatsapp-web.js 1.34.7 » Source: structures/Call.js
@@ -15,7 +15,7 @@
@@ -90,21 +90,26 @@ class Call extends Base {
* @type {object}
*/
this.participants = data.participants;
-
+
return super._patch(data);
}
/**
* Reject the call
- */
+ */
async reject() {
- return this.client.pupPage.evaluate((peerJid, id) => {
- return window.WWebJS.rejectCall(peerJid, id);
- }, this.from, this.id);
+ return this.client.pupPage.evaluate(
+ (peerJid, id) => {
+ return window.WWebJS.rejectCall(peerJid, id);
+ },
+ this.from,
+ this.id,
+ );
}
}
-module.exports = Call;
+module.exports = Call;
+
@@ -114,7 +119,7 @@ module.exports = Call;
diff --git a/docs/structures_Channel.js.html b/docs/structures_Channel.js.html
index 0d51937..c5d7ae0 100644
--- a/docs/structures_Channel.js.html
+++ b/docs/structures_Channel.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/Channel.js
+ whatsapp-web.js 1.34.7 » Source: structures/Channel.js
@@ -15,7 +15,7 @@
@@ -68,11 +68,12 @@ class Channel extends Base {
*/
this.name = data.name;
- /**
+ /**
* The channel description
* @type {string}
*/
- this.description = data.channelMetadata.description;
+ this.description =
+ data.channelMetadata?.description ?? data.description ?? '';
/**
* Indicates if it is a Channel
@@ -120,7 +121,9 @@ class Channel extends Base {
* Last message in the channel
* @type {Message}
*/
- this.lastMessage = data.lastMessage ? new Message(super.client, data.lastMessage) : undefined;
+ this.lastMessage = data.lastMessage
+ ? new Message(super.client, data.lastMessage)
+ : undefined;
return super._patch(data);
}
@@ -131,58 +134,82 @@ class Channel extends Base {
* @returns {Promise<Array<{contact: Contact, role: string}>>} Returns an array of objects that handle the subscribed contacts and their roles in the channel
*/
async getSubscribers(limit) {
- return await this.client.pupPage.evaluate(async (channelId, limit) => {
- const channel = await window.WWebJS.getChat(channelId, { getAsModel: false });
- if (!channel) return [];
- !limit && (limit = window.Store.ChannelUtils.getMaxSubscriberNumber());
- const response = await window.Store.ChannelSubscribers.mexFetchNewsletterSubscribers(channelId, limit);
- const contacts = window.Store.ChannelSubscribers.getSubscribersInContacts(response.subscribers);
- return Promise.all(contacts.map((obj) => ({
- ...obj,
- contact: window.WWebJS.getContactModel(obj.contact)
- })));
- }, this.id._serialized, limit);
+ return await this.client.pupPage.evaluate(
+ async (channelId, limit) => {
+ const channel = await window.WWebJS.getChat(channelId, {
+ getAsModel: false,
+ });
+ if (!channel) return [];
+ !limit &&
+ (limit = window
+ .require('WAWebNewsletterGatingUtils')
+ .getMaxSubscriberNumber());
+ const response = await window
+ .require('WAWebMexFetchNewsletterSubscribersJob')
+ .mexFetchNewsletterSubscribers(channelId, limit);
+ const contacts = window
+ .require('WAWebNewsletterSubscriberListAction')
+ .getSubscribersInContacts(response.subscribers);
+ return Promise.all(
+ contacts.map((obj) => ({
+ ...obj,
+ contact: window.WWebJS.getContactModel(obj.contact),
+ })),
+ );
+ },
+ this.id._serialized,
+ limit,
+ );
}
/**
* Updates the channel subject
- * @param {string} newSubject
+ * @param {string} newSubject
* @returns {Promise<boolean>} Returns true if the subject was properly updated. This can return false if the user does not have the necessary permissions.
*/
async setSubject(newSubject) {
- const success = await this._setChannelMetadata({ name: newSubject }, { editName: true });
+ const success = await this._setChannelMetadata(
+ { name: newSubject },
+ { editName: true },
+ );
success && (this.name = newSubject);
return success;
}
/**
* Updates the channel description
- * @param {string} newDescription
+ * @param {string} newDescription
* @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
*/
async setDescription(newDescription) {
- const success = await this._setChannelMetadata({ description: newDescription }, { editDescription: true });
+ const success = await this._setChannelMetadata(
+ { description: newDescription },
+ { editDescription: true },
+ );
success && (this.description = newDescription);
return success;
}
/**
* Updates the channel profile picture
- * @param {MessageMedia} newProfilePicture
+ * @param {MessageMedia} newProfilePicture
* @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
*/
async setProfilePicture(newProfilePicture) {
- return await this._setChannelMetadata({ picture: newProfilePicture }, { editPicture: true });
+ return await this._setChannelMetadata(
+ { picture: newProfilePicture },
+ { editPicture: true },
+ );
}
/**
* Updates available reactions to use in the channel
- *
+ *
* Valid values for passing to the method are:
* 0 for NONE reactions to be avaliable
* 1 for BASIC reactions to be available: 👍, ❤️, 😂, 😮, 😢, 🙏
* 2 for ALL reactions to be available
- * @param {number} reactionCode
+ * @param {number} reactionCode
* @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
*/
async setReactionSetting(reactionCode) {
@@ -190,11 +217,11 @@ class Channel extends Base {
const reactionMapper = {
0: 3,
1: 1,
- 2: 0
+ 2: 0,
};
const success = await this._setChannelMetadata(
{ reactionCodesSetting: reactionMapper[reactionCode] },
- { editReactionCodesSetting: true }
+ { editReactionCodesSetting: true },
);
success && (this.channelMetadata.reactionCodesSetting = reactionCode);
return success;
@@ -212,7 +239,7 @@ class Channel extends Base {
}
return success;
}
-
+
/**
* Unmutes the channel
* @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
@@ -260,11 +287,15 @@ class Channel extends Base {
/**
* Sends a channel admin invitation to a user, allowing them to become an admin of the channel
* @param {string} chatId The ID of a user to send the channel admin invitation to
- * @param {SendChannelAdminInviteOptions} options
+ * @param {SendChannelAdminInviteOptions} options
* @returns {Promise<boolean>} Returns true if an invitation was sent successfully, false otherwise
*/
async sendChannelAdminInvite(chatId, options = {}) {
- return this.client.sendChannelAdminInvite(chatId, this.id._serialized, options);
+ return this.client.sendChannelAdminInvite(
+ chatId,
+ this.id._serialized,
+ options,
+ );
}
/**
@@ -281,7 +312,10 @@ class Channel extends Base {
* @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
*/
async revokeChannelAdminInvite(userId) {
- return this.client.revokeChannelAdminInvite(this.id._serialized, userId);
+ return this.client.revokeChannelAdminInvite(
+ this.id._serialized,
+ userId,
+ );
}
/**
@@ -307,7 +341,11 @@ class Channel extends Base {
* @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
*/
async transferChannelOwnership(newOwnerId, options = {}) {
- return this.client.transferChannelOwnership(this.id._serialized, newOwnerId, options);
+ return this.client.transferChannelOwnership(
+ this.id._serialized,
+ newOwnerId,
+ options,
+ );
}
/**
@@ -318,36 +356,50 @@ class Channel extends Base {
* @returns {Promise<Array<Message>>}
*/
async fetchMessages(searchOptions) {
- let messages = await this.client.pupPage.evaluate(async (channelId, searchOptions) => {
- const msgFilter = (m) => {
- if (m.isNotification || m.type === 'newsletter_notification') {
- return false; // dont include notification messages
- }
- if (searchOptions && searchOptions.fromMe !== undefined && m.id.fromMe !== searchOptions.fromMe) {
- return false;
- }
- return true;
- };
+ let messages = await this.client.pupPage.evaluate(
+ async (channelId, searchOptions) => {
+ const msgFilter = (m) => {
+ if (
+ m.isNotification ||
+ m.type === 'newsletter_notification'
+ ) {
+ return false; // dont include notification messages
+ }
+ if (
+ searchOptions &&
+ searchOptions.fromMe !== undefined &&
+ m.id.fromMe !== searchOptions.fromMe
+ ) {
+ return false;
+ }
+ return true;
+ };
- const channel = await window.WWebJS.getChat(channelId, { getAsModel: false });
- let msgs = channel.msgs.getModelsArray().filter(msgFilter);
+ const channel = await window.WWebJS.getChat(channelId, {
+ getAsModel: false,
+ });
+ let msgs = channel.msgs.getModelsArray().filter(msgFilter);
- if (searchOptions && searchOptions.limit > 0) {
- while (msgs.length < searchOptions.limit) {
- const loadedMessages = await window.Store.ConversationMsgs.loadEarlierMsgs(channel);
- if (!loadedMessages || !loadedMessages.length) break;
- msgs = [...loadedMessages.filter(msgFilter), ...msgs];
+ if (searchOptions && searchOptions.limit > 0) {
+ while (msgs.length < searchOptions.limit) {
+ const loadedMessages = await window
+ .require('WAWebChatLoadMessages')
+ .loadEarlierMsgs({ chat: channel });
+ if (!loadedMessages || !loadedMessages.length) break;
+ msgs = [...loadedMessages.filter(msgFilter), ...msgs];
+ }
+
+ if (msgs.length > searchOptions.limit) {
+ msgs.sort((a, b) => (a.t > b.t ? 1 : -1));
+ msgs = msgs.splice(msgs.length - searchOptions.limit);
+ }
}
-
- if (msgs.length > searchOptions.limit) {
- msgs.sort((a, b) => (a.t > b.t) ? 1 : -1);
- msgs = msgs.splice(msgs.length - searchOptions.limit);
- }
- }
- return msgs.map(m => window.WWebJS.getMessageModel(m));
-
- }, this.id._serialized, searchOptions);
+ return msgs.map((m) => window.WWebJS.getMessageModel(m));
+ },
+ this.id._serialized,
+ searchOptions,
+ );
return messages.map((msg) => new Message(this.client, msg));
}
@@ -367,27 +419,39 @@ class Channel extends Base {
* @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
*/
async _setChannelMetadata(value, property) {
- return await this.client.pupPage.evaluate(async (channelId, value, property) => {
- const channel = await window.WWebJS.getChat(channelId, { getAsModel: false });
- if (!channel) return false;
- if (property.editPicture) {
- value.picture = value.picture
- ? await window.WWebJS.cropAndResizeImage(value.picture, {
- asDataUrl: true,
- mimetype: 'image/jpeg',
- size: 640,
- quality: 1
- })
- : null;
- }
- try {
- await window.Store.ChannelUtils.editNewsletterMetadataAction(channel, property, value);
- return true;
- } catch (err) {
- if (err.name === 'ServerStatusCodeError') return false;
- throw err;
- }
- }, this.id._serialized, value, property);
+ return await this.client.pupPage.evaluate(
+ async (channelId, value, property) => {
+ const channel = await window.WWebJS.getChat(channelId, {
+ getAsModel: false,
+ });
+ if (!channel) return false;
+ if (property.editPicture) {
+ value.picture = value.picture
+ ? await window.WWebJS.cropAndResizeImage(
+ value.picture,
+ {
+ asDataUrl: true,
+ mimetype: 'image/jpeg',
+ size: 640,
+ quality: 1,
+ },
+ )
+ : null;
+ }
+ try {
+ await window
+ .require('WAWebEditNewsletterMetadataAction')
+ .editNewsletterMetadataAction(channel, property, value);
+ return true;
+ } catch (err) {
+ if (err.name === 'ServerStatusCodeError') return false;
+ throw err;
+ }
+ },
+ this.id._serialized,
+ value,
+ property,
+ );
}
/**
@@ -396,17 +460,35 @@ class Channel extends Base {
* @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
*/
async _muteUnmuteChannel(action) {
- return await this.client.pupPage.evaluate(async (channelId, action) => {
- try {
- action === 'MUTE'
- ? await window.Store.ChannelUtils.muteNewsletter([channelId])
- : await window.Store.ChannelUtils.unmuteNewsletter([channelId]);
- return true;
- } catch (err) {
- if (err.name === 'ServerStatusCodeError') return false;
- throw err;
- }
- }, this.id._serialized, action);
+ return await this.client.pupPage.evaluate(
+ async (channelId, action) => {
+ try {
+ await window
+ .require('WAWebNewsletterUpdateUserSettingJob')
+ .updateNewsletterUserSetting({
+ newsletterJid: window
+ .require('WAJids')
+ .toNewsletterJid(channelId),
+ type: window.require('WAWebNewsletterModelUtils')
+ .ADMIN_NOTIFICATIONS,
+ muteExpirationValue:
+ action === 'MUTE'
+ ? window.require(
+ 'WAWebNewsletterModelUtils',
+ ).MUTED_STATE
+ : window.require(
+ 'WAWebNewsletterModelUtils',
+ ).UNMUTED_STATE,
+ });
+ return true;
+ } catch (err) {
+ if (err.name === 'ServerStatusCodeError') return false;
+ throw err;
+ }
+ },
+ this.id._serialized,
+ action,
+ );
}
}
@@ -421,7 +503,7 @@ module.exports = Channel;
diff --git a/docs/structures_Chat.js.html b/docs/structures_Chat.js.html
index fddbf81..2b305f4 100644
--- a/docs/structures_Chat.js.html
+++ b/docs/structures_Chat.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/Chat.js
+ whatsapp-web.js 1.34.7 » Source: structures/Chat.js
@@ -15,7 +15,7 @@
@@ -94,6 +94,12 @@ class Chat extends Base {
*/
this.pinned = !!data.pin;
+ /**
+ * Indicates if the Chat is locked
+ * @type {boolean}
+ */
+ this.isLocked = data.isLocked;
+
/**
* Indicates if the chat is muted or not
* @type {boolean}
@@ -110,15 +116,17 @@ class Chat extends Base {
* Last message fo chat
* @type {Message}
*/
- this.lastMessage = data.lastMessage ? new Message(this.client, data.lastMessage) : undefined;
-
+ this.lastMessage = data.lastMessage
+ ? new Message(this.client, data.lastMessage)
+ : undefined;
+
return super._patch(data);
}
/**
* Send a message to this chat
* @param {string|MessageMedia|Location} content
- * @param {MessageSendOptions} [options]
+ * @param {MessageSendOptions} [options]
* @returns {Promise<Message>} Message that was just sent
*/
async sendMessage(content, options) {
@@ -138,7 +146,7 @@ class Chat extends Base {
* @returns {Promise<boolean>} result
*/
async clearMessages() {
- return this.client.pupPage.evaluate(chatId => {
+ return this.client.pupPage.evaluate((chatId) => {
return window.WWebJS.sendClearChat(chatId);
}, this.id._serialized);
}
@@ -148,7 +156,7 @@ class Chat extends Base {
* @returns {Promise<Boolean>} result
*/
async delete() {
- return this.client.pupPage.evaluate(chatId => {
+ return this.client.pupPage.evaluate((chatId) => {
return window.WWebJS.sendDeleteChat(chatId);
}, this.id._serialized);
}
@@ -189,7 +197,10 @@ class Chat extends Base {
* @returns {Promise<{isMuted: boolean, muteExpiration: number}>}
*/
async mute(unmuteDate) {
- const result = await this.client.muteChat(this.id._serialized, unmuteDate);
+ const result = await this.client.muteChat(
+ this.id._serialized,
+ unmuteDate,
+ );
this.isMuted = result.isMuted;
this.muteExpiration = result.muteExpiration;
return result;
@@ -209,7 +220,7 @@ class Chat extends Base {
/**
* Mark this chat as unread
*/
- async markUnread(){
+ async markUnread() {
return this.client.markChatUnread(this.id._serialized);
}
@@ -221,45 +232,56 @@ class Chat extends Base {
* @returns {Promise<Array<Message>>}
*/
async fetchMessages(searchOptions) {
- let messages = await this.client.pupPage.evaluate(async (chatId, searchOptions) => {
- const msgFilter = (m) => {
- if (m.isNotification) {
- return false; // dont include notification messages
+ let messages = await this.client.pupPage.evaluate(
+ async (chatId, searchOptions) => {
+ const msgFilter = (m) => {
+ if (m.isNotification) {
+ return false; // dont include notification messages
+ }
+ if (
+ searchOptions &&
+ searchOptions.fromMe !== undefined &&
+ m.id.fromMe !== searchOptions.fromMe
+ ) {
+ return false;
+ }
+ return true;
+ };
+
+ const chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
+ let msgs = chat.msgs.getModelsArray().filter(msgFilter);
+
+ if (searchOptions && searchOptions.limit > 0) {
+ while (msgs.length < searchOptions.limit) {
+ const loadedMessages = await window
+ .require('WAWebChatLoadMessages')
+ .loadEarlierMsgs({ chat });
+ if (!loadedMessages || !loadedMessages.length) break;
+ msgs = [...loadedMessages.filter(msgFilter), ...msgs];
+ }
+
+ if (msgs.length > searchOptions.limit) {
+ msgs.sort((a, b) => (a.t > b.t ? 1 : -1));
+ msgs = msgs.splice(msgs.length - searchOptions.limit);
+ }
}
- if (searchOptions && searchOptions.fromMe !== undefined && m.id.fromMe !== searchOptions.fromMe) {
- return false;
- }
- return true;
- };
- const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
- let msgs = chat.msgs.getModelsArray().filter(msgFilter);
+ return msgs.map((m) => window.WWebJS.getMessageModel(m));
+ },
+ this.id._serialized,
+ searchOptions,
+ );
- if (searchOptions && searchOptions.limit > 0) {
- while (msgs.length < searchOptions.limit) {
- const loadedMessages = await window.Store.ConversationMsgs.loadEarlierMsgs(chat,chat.msgs);
- if (!loadedMessages || !loadedMessages.length) break;
- msgs = [...loadedMessages.filter(msgFilter), ...msgs];
- }
-
- if (msgs.length > searchOptions.limit) {
- msgs.sort((a, b) => (a.t > b.t) ? 1 : -1);
- msgs = msgs.splice(msgs.length - searchOptions.limit);
- }
- }
-
- return msgs.map(m => window.WWebJS.getMessageModel(m));
-
- }, this.id._serialized, searchOptions);
-
- return messages.map(m => new Message(this.client, m));
+ return messages.map((m) => new Message(this.client, m));
}
/**
* Simulate typing in chat. This will last for 25 seconds.
*/
async sendStateTyping() {
- return this.client.pupPage.evaluate(chatId => {
+ return this.client.pupPage.evaluate((chatId) => {
window.WWebJS.sendChatstate('typing', chatId);
return true;
}, this.id._serialized);
@@ -269,7 +291,7 @@ class Chat extends Base {
* Simulate recording audio in chat. This will last for 25 seconds.
*/
async sendStateRecording() {
- return this.client.pupPage.evaluate(chatId => {
+ return this.client.pupPage.evaluate((chatId) => {
window.WWebJS.sendChatstate('recording', chatId);
return true;
}, this.id._serialized);
@@ -279,7 +301,7 @@ class Chat extends Base {
* Stops typing or recording in chat immediately.
*/
async clearState() {
- return this.client.pupPage.evaluate(chatId => {
+ return this.client.pupPage.evaluate((chatId) => {
window.WWebJS.sendChatstate('stop', chatId);
return true;
}, this.id._serialized);
@@ -317,7 +339,7 @@ class Chat extends Base {
async getPinnedMessages() {
return this.client.getPinnedMessages(this.id._serialized);
}
-
+
/**
* Sync chat history conversation
* @return {Promise<boolean>} True if operation completed successfully, false otherwise.
@@ -352,7 +374,7 @@ class Chat extends Base {
*/
async getCustomerNote() {
if (this.isGroup || this.isChannel) return null;
-
+
return this.client.getCustomerNote(this.id._serialized);
}
}
@@ -368,7 +390,7 @@ module.exports = Chat;
diff --git a/docs/structures_ClientInfo.js.html b/docs/structures_ClientInfo.js.html
index c50df99..5eaf5d1 100644
--- a/docs/structures_ClientInfo.js.html
+++ b/docs/structures_ClientInfo.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/ClientInfo.js
+ whatsapp-web.js 1.34.7 » Source: structures/ClientInfo.js
@@ -15,7 +15,7 @@
@@ -93,13 +93,14 @@ class ClientInfo extends Base {
*/
async getBatteryStatus() {
return await this.client.pupPage.evaluate(() => {
- const { battery, plugged } = window.Store.Conn;
+ const { battery, plugged } = window.require('WAWebConnModel').Conn;
return { battery, plugged };
});
}
}
-module.exports = ClientInfo;
+module.exports = ClientInfo;
+
@@ -109,7 +110,7 @@ module.exports = ClientInfo;
diff --git a/docs/structures_Contact.js.html b/docs/structures_Contact.js.html
index 1eae943..f368a8b 100644
--- a/docs/structures_Contact.js.html
+++ b/docs/structures_Contact.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/Contact.js
+ whatsapp-web.js 1.34.7 » Source: structures/Contact.js
@@ -15,7 +15,7 @@
@@ -49,7 +49,7 @@ class Contact extends Base {
constructor(client, data) {
super(client);
- if(data) this._patch(data);
+ if (data) this._patch(data);
}
_patch(data) {
@@ -139,7 +139,7 @@ class Contact extends Base {
* @type {boolean}
*/
this.isBlocked = data.isBlocked;
-
+
return super._patch(data);
}
@@ -158,7 +158,7 @@ class Contact extends Base {
async getFormattedNumber() {
return await this.client.getFormattedNumber(this.id._serialized);
}
-
+
/**
* Returns the contact's countrycode, (1541859685@c.us) => (1)
* @returns {Promise<string>}
@@ -166,14 +166,14 @@ class Contact extends Base {
async getCountryCode() {
return await this.client.getCountryCode(this.id._serialized);
}
-
+
/**
- * Returns the Chat that corresponds to this Contact.
+ * Returns the Chat that corresponds to this Contact.
* Will return null when getting chat for currently logged in user.
* @returns {Promise<Chat>}
*/
async getChat() {
- if(this.isMe) return null;
+ if (this.isMe) return null;
return await this.client.getChatById(this.id._serialized);
}
@@ -183,11 +183,21 @@ class Contact extends Base {
* @returns {Promise<boolean>}
*/
async block() {
- if(this.isGroup) return false;
+ if (this.isGroup) return false;
await this.client.pupPage.evaluate(async (contactId) => {
- const contact = window.Store.Contact.get(contactId);
- await window.Store.BlockContact.blockContact({contact});
+ const contact = await window
+ .require('WAWebCollections')
+ .Contact.find(contactId);
+ const resolved = window
+ .require('WAWebBlockContactUtils')
+ .getContactToBlockOnlyUseIfNoAssociatedChat(
+ contact,
+ 'ChatListBlock',
+ );
+ await window
+ .require('WAWebBlockContactAction')
+ .blockContact({ contact: resolved });
}, this.id._serialized);
this.isBlocked = true;
@@ -199,11 +209,21 @@ class Contact extends Base {
* @returns {Promise<boolean>}
*/
async unblock() {
- if(this.isGroup) return false;
+ if (this.isGroup) return false;
await this.client.pupPage.evaluate(async (contactId) => {
- const contact = window.Store.Contact.get(contactId);
- await window.Store.BlockContact.unblockContact(contact);
+ const contact = await window
+ .require('WAWebCollections')
+ .Contact.find(contactId);
+ const resolved = window
+ .require('WAWebBlockContactUtils')
+ .getContactToBlockOnlyUseIfNoAssociatedChat(
+ contact,
+ 'ChatListBlock',
+ );
+ await window
+ .require('WAWebBlockContactAction')
+ .unblockContact(resolved);
}, this.id._serialized);
this.isBlocked = false;
@@ -216,12 +236,13 @@ class Contact extends Base {
*/
async getAbout() {
const about = await this.client.pupPage.evaluate(async (contactId) => {
- const wid = window.Store.WidFactory.createWid(contactId);
- return window.Store.StatusUtils.getStatus({'token':'', 'wid': wid});
+ const wid = window.require('WAWebWidFactory').createWid(contactId);
+ return window
+ .require('WAWebContactStatusBridge')
+ .getStatus({ token: '', wid: wid });
}, this.id._serialized);
- if (typeof about.status !== 'string')
- return null;
+ if (typeof about.status !== 'string') return null;
return about.status;
}
@@ -237,7 +258,7 @@ class Contact extends Base {
/**
* Gets the Contact's current status broadcast.
* @returns {Promise<Broadcast>}
- */
+ */
async getBroadcast() {
return await this.client.getBroadcastById(this.id._serialized);
}
@@ -254,7 +275,7 @@ module.exports = Contact;
diff --git a/docs/structures_GroupChat.js.html b/docs/structures_GroupChat.js.html
index 7eee2ba..ec31925 100644
--- a/docs/structures_GroupChat.js.html
+++ b/docs/structures_GroupChat.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/GroupChat.js
+ whatsapp-web.js 1.34.7 » Source: structures/GroupChat.js
@@ -15,7 +15,7 @@
@@ -59,7 +59,7 @@ class GroupChat extends Chat {
get owner() {
return this.groupMetadata.owner;
}
-
+
/**
* Gets the date at which the group was created
* @type {date}
@@ -68,7 +68,7 @@ class GroupChat extends Chat {
return new Date(this.groupMetadata.creation * 1000);
}
- /**
+ /**
* Gets the group description
* @type {string}
*/
@@ -102,264 +102,440 @@ class GroupChat extends Chat {
/**
* Adds a list of participants by ID to the group
- * @param {string|Array<string>} participantIds
+ * @param {string|Array<string>} participantIds
* @param {AddParticipnatsOptions} options An object thay handles options for adding participants
* @returns {Promise<Object.<string, AddParticipantsResult>|string>} Returns an object with the resulting data or an error message as a string
*/
async addParticipants(participantIds, options = {}) {
- return await this.client.pupPage.evaluate(async (groupId, participantIds, options) => {
- const { sleep = [250, 500], autoSendInviteV4 = true, comment = '' } = options;
- const participantData = {};
+ return await this.client.pupPage.evaluate(
+ async (groupId, participantIds, options) => {
+ const {
+ sleep = [250, 500],
+ autoSendInviteV4 = true,
+ comment = '',
+ } = options;
+ const participantData = {};
- !Array.isArray(participantIds) && (participantIds = [participantIds]);
- const groupWid = window.Store.WidFactory.createWid(groupId);
- const group = window.Store.Chat.get(groupWid) || (await window.Store.Chat.find(groupWid));
- const participantWids = participantIds.map((p) => window.Store.WidFactory.createWid(p));
+ !Array.isArray(participantIds) &&
+ (participantIds = [participantIds]);
+ const groupWid = window
+ .require('WAWebWidFactory')
+ .createWid(groupId);
+ const group =
+ window.require('WAWebCollections').Chat.get(groupWid) ||
+ (await window
+ .require('WAWebCollections')
+ .Chat.find(groupWid));
+ const participantWids = participantIds.map((p) =>
+ window.require('WAWebWidFactory').createWid(p),
+ );
- const errorCodes = {
- default: 'An unknown error occupied while adding a participant',
- isGroupEmpty: 'AddParticipantsError: The participant can\'t be added to an empty group',
- iAmNotAdmin: 'AddParticipantsError: You have no admin rights to add a participant to a group',
- 200: 'The participant was added successfully',
- 403: 'The participant can be added by sending private invitation only',
- 404: 'The phone number is not registered on WhatsApp',
- 408: 'You cannot add this participant because they recently left the group',
- 409: 'The participant is already a group member',
- 417: 'The participant can\'t be added to the community. You can invite them privately to join this group through its invite link',
- 419: 'The participant can\'t be added because the group is full'
- };
-
- await window.Store.GroupQueryAndUpdate({ id: groupId });
-
- let groupParticipants = group.groupMetadata?.participants.serialize();
-
- if (!groupParticipants) {
- return errorCodes.isGroupEmpty;
- }
-
- if (!group.iAmAdmin()) {
- return errorCodes.iAmNotAdmin;
- }
-
- groupParticipants.map(({ id }) => {
- return id.server === 'lid' ? window.Store.LidUtils.getPhoneNumber(id) : id;
- });
-
- const _getSleepTime = (sleep) => {
- if (!Array.isArray(sleep) || sleep.length === 2 && sleep[0] === sleep[1]) {
- return sleep;
- }
- if (sleep.length === 1) {
- return sleep[0];
- }
- (sleep[1] - sleep[0]) < 100 && (sleep[0] = sleep[1]) && (sleep[1] += 100);
- return Math.floor(Math.random() * (sleep[1] - sleep[0] + 1)) + sleep[0];
- };
-
- for (let pWid of participantWids) {
- const pId = pWid._serialized;
- pWid = pWid.server === 'lid' ? window.Store.LidUtils.getPhoneNumber(pWid) : pWid;
-
- participantData[pId] = {
- code: undefined,
- message: undefined,
- isInviteV4Sent: false
+ const errorCodes = {
+ default:
+ 'An unknown error occupied while adding a participant',
+ isGroupEmpty:
+ "AddParticipantsError: The participant can't be added to an empty group",
+ iAmNotAdmin:
+ 'AddParticipantsError: You have no admin rights to add a participant to a group',
+ 200: 'The participant was added successfully',
+ 403: 'The participant can be added by sending private invitation only',
+ 404: 'The phone number is not registered on WhatsApp',
+ 408: 'You cannot add this participant because they recently left the group',
+ 409: 'The participant is already a group member',
+ 417: "The participant can't be added to the community. You can invite them privately to join this group through its invite link",
+ 419: "The participant can't be added because the group is full",
};
- if (groupParticipants.some(p => p._serialized === pId)) {
- participantData[pId].code = 409;
- participantData[pId].message = errorCodes[409];
- continue;
+ await window
+ .require('WAWebGroupQueryJob')
+ .queryAndUpdateGroupMetadataById({ id: groupId });
+
+ let groupParticipants =
+ group.groupMetadata?.participants.serialize();
+
+ if (!groupParticipants) {
+ return errorCodes.isGroupEmpty;
}
- if (!(await window.Store.QueryExist(pWid))?.wid) {
- participantData[pId].code = 404;
- participantData[pId].message = errorCodes[404];
- continue;
+ if (!group.iAmAdmin()) {
+ return errorCodes.iAmNotAdmin;
}
- const rpcResult =
- await window.WWebJS.getAddParticipantsRpcResult(groupWid, pWid);
- const { code: rpcResultCode } = rpcResult;
+ groupParticipants.map(({ id }) => {
+ return id.server === 'lid'
+ ? window.require('WAWebApiContact').getPhoneNumber(id)
+ : id;
+ });
- participantData[pId].code = rpcResultCode;
- participantData[pId].message =
- errorCodes[rpcResultCode] || errorCodes.default;
+ const _getSleepTime = (sleep) => {
+ if (
+ !Array.isArray(sleep) ||
+ (sleep.length === 2 && sleep[0] === sleep[1])
+ ) {
+ return sleep;
+ }
+ if (sleep.length === 1) {
+ return sleep[0];
+ }
+ sleep[1] - sleep[0] < 100 &&
+ (sleep[0] = sleep[1]) &&
+ (sleep[1] += 100);
+ return (
+ Math.floor(Math.random() * (sleep[1] - sleep[0] + 1)) +
+ sleep[0]
+ );
+ };
- if (autoSendInviteV4 && rpcResultCode === 403) {
- let userChat, isInviteV4Sent = false;
- window.Store.Contact.gadd(pWid, { silent: true });
+ for (let pWid of participantWids) {
+ const pId = pWid._serialized;
+ pWid =
+ pWid.server === 'lid'
+ ? window
+ .require('WAWebApiContact')
+ .getPhoneNumber(pWid)
+ : pWid;
- if (rpcResult.name === 'ParticipantRequestCodeCanBeSent' &&
- (userChat = window.Store.Chat.get(pWid) || (await window.Store.Chat.find(pWid)))) {
- const groupName = group.formattedTitle || group.name;
- const res = await window.Store.GroupInviteV4.sendGroupInviteMessage(
- userChat,
- group.id._serialized,
- groupName,
- rpcResult.inviteV4Code,
- rpcResult.inviteV4CodeExp,
- comment,
- await window.WWebJS.getProfilePicThumbToBase64(groupWid)
- );
- isInviteV4Sent = res.messageSendResult === 'OK';
+ participantData[pId] = {
+ code: undefined,
+ message: undefined,
+ isInviteV4Sent: false,
+ };
+
+ if (groupParticipants.some((p) => p._serialized === pId)) {
+ participantData[pId].code = 409;
+ participantData[pId].message = errorCodes[409];
+ continue;
}
- participantData[pId].isInviteV4Sent = isInviteV4Sent;
+ if (
+ !(
+ await window
+ .require('WAWebQueryExistsJob')
+ .queryWidExists(pWid)
+ )?.wid
+ ) {
+ participantData[pId].code = 404;
+ participantData[pId].message = errorCodes[404];
+ continue;
+ }
+
+ const rpcResult =
+ await window.WWebJS.getAddParticipantsRpcResult(
+ groupWid,
+ pWid,
+ );
+ const { code: rpcResultCode } = rpcResult;
+
+ participantData[pId].code = rpcResultCode;
+ participantData[pId].message =
+ errorCodes[rpcResultCode] || errorCodes.default;
+
+ if (autoSendInviteV4 && rpcResultCode === 403) {
+ let userChat,
+ isInviteV4Sent = false;
+ window
+ .require('WAWebCollections')
+ .Contact.gadd(pWid, { silent: true });
+
+ if (
+ rpcResult.name ===
+ 'ParticipantRequestCodeCanBeSent' &&
+ (userChat =
+ window
+ .require('WAWebCollections')
+ .Chat.get(pWid) ||
+ (await window
+ .require('WAWebCollections')
+ .Chat.find(pWid)))
+ ) {
+ const groupName =
+ group.formattedTitle || group.name;
+ const res = await window
+ .require('WAWebChatSendMessages')
+ .sendGroupInviteMessage(
+ userChat,
+ group.id._serialized,
+ groupName,
+ rpcResult.inviteV4Code,
+ rpcResult.inviteV4CodeExp,
+ comment,
+ await window.WWebJS.getProfilePicThumbToBase64(
+ groupWid,
+ ),
+ );
+ isInviteV4Sent = res.messageSendResult === 'OK';
+ }
+
+ participantData[pId].isInviteV4Sent = isInviteV4Sent;
+ }
+
+ sleep &&
+ participantWids.length > 1 &&
+ participantWids.indexOf(pWid) !==
+ participantWids.length - 1 &&
+ (await new Promise((resolve) =>
+ setTimeout(resolve, _getSleepTime(sleep)),
+ ));
}
- sleep &&
- participantWids.length > 1 &&
- participantWids.indexOf(pWid) !== participantWids.length - 1 &&
- (await new Promise((resolve) => setTimeout(resolve, _getSleepTime(sleep))));
- }
-
- return participantData;
- }, this.id._serialized, participantIds, options);
+ return participantData;
+ },
+ this.id._serialized,
+ participantIds,
+ options,
+ );
}
/**
* Removes a list of participants by ID to the group
- * @param {Array<string>} participantIds
+ * @param {Array<string>} participantIds
* @returns {Promise<{ status: number }>}
*/
async removeParticipants(participantIds) {
- return await this.client.pupPage.evaluate(async (chatId, participantIds) => {
- const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
- const participants = (await Promise.all(participantIds.map(async p => {
- const { lid, phone } = await window.WWebJS.enforceLidAndPnRetrieval(p);
+ return await this.client.pupPage.evaluate(
+ async (chatId, participantIds) => {
+ const chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
+ const participants = (
+ await Promise.all(
+ participantIds.map(async (p) => {
+ const { lid, phone } =
+ await window.WWebJS.enforceLidAndPnRetrieval(p);
- return chat.groupMetadata.participants.get(lid?._serialized) ||
- chat.groupMetadata.participants.get(phone?._serialized);
- }))).filter(Boolean);
- await window.Store.GroupParticipants.removeParticipants(chat, participants);
- return { status: 200 };
- }, this.id._serialized, participantIds);
+ return (
+ chat.groupMetadata.participants.get(
+ lid?._serialized,
+ ) ||
+ chat.groupMetadata.participants.get(
+ phone?._serialized,
+ )
+ );
+ }),
+ )
+ ).filter(Boolean);
+ await window
+ .require('WAWebModifyParticipantsGroupAction')
+ .removeParticipants(chat, participants);
+ return { status: 200 };
+ },
+ this.id._serialized,
+ participantIds,
+ );
}
/**
* Promotes participants by IDs to admins
- * @param {Array<string>} participantIds
+ * @param {Array<string>} participantIds
* @returns {Promise<{ status: number }>} Object with status code indicating if the operation was successful
*/
async promoteParticipants(participantIds) {
- return await this.client.pupPage.evaluate(async (chatId, participantIds) => {
- const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
- const participants = (await Promise.all(participantIds.map(async p => {
- const { lid, phone } = await window.WWebJS.enforceLidAndPnRetrieval(p);
+ return await this.client.pupPage.evaluate(
+ async (chatId, participantIds) => {
+ const chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
+ const participants = (
+ await Promise.all(
+ participantIds.map(async (p) => {
+ const { lid, phone } =
+ await window.WWebJS.enforceLidAndPnRetrieval(p);
- return chat.groupMetadata.participants.get(lid?._serialized) ||
- chat.groupMetadata.participants.get(phone?._serialized);
- }))).filter(Boolean);
- await window.Store.GroupParticipants.promoteParticipants(chat, participants);
- return { status: 200 };
- }, this.id._serialized, participantIds);
+ return (
+ chat.groupMetadata.participants.get(
+ lid?._serialized,
+ ) ||
+ chat.groupMetadata.participants.get(
+ phone?._serialized,
+ )
+ );
+ }),
+ )
+ ).filter(Boolean);
+ await window
+ .require('WAWebModifyParticipantsGroupAction')
+ .promoteParticipants(chat, participants);
+ return { status: 200 };
+ },
+ this.id._serialized,
+ participantIds,
+ );
}
/**
* Demotes participants by IDs to regular users
- * @param {Array<string>} participantIds
+ * @param {Array<string>} participantIds
* @returns {Promise<{ status: number }>} Object with status code indicating if the operation was successful
*/
async demoteParticipants(participantIds) {
- return await this.client.pupPage.evaluate(async (chatId, participantIds) => {
- const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
- const participants = (await Promise.all(participantIds.map(async p => {
- const { lid, phone } = await window.WWebJS.enforceLidAndPnRetrieval(p);
+ return await this.client.pupPage.evaluate(
+ async (chatId, participantIds) => {
+ const chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
+ const participants = (
+ await Promise.all(
+ participantIds.map(async (p) => {
+ const { lid, phone } =
+ await window.WWebJS.enforceLidAndPnRetrieval(p);
- return chat.groupMetadata.participants.get(lid?._serialized) ||
- chat.groupMetadata.participants.get(phone?._serialized);
- }))).filter(Boolean);
- await window.Store.GroupParticipants.demoteParticipants(chat, participants);
- return { status: 200 };
- }, this.id._serialized, participantIds);
+ return (
+ chat.groupMetadata.participants.get(
+ lid?._serialized,
+ ) ||
+ chat.groupMetadata.participants.get(
+ phone?._serialized,
+ )
+ );
+ }),
+ )
+ ).filter(Boolean);
+ await window
+ .require('WAWebModifyParticipantsGroupAction')
+ .demoteParticipants(chat, participants);
+ return { status: 200 };
+ },
+ this.id._serialized,
+ participantIds,
+ );
}
/**
* Updates the group subject
- * @param {string} subject
+ * @param {string} subject
* @returns {Promise<boolean>} Returns true if the subject was properly updated. This can return false if the user does not have the necessary permissions.
*/
async setSubject(subject) {
- const success = await this.client.pupPage.evaluate(async (chatId, subject) => {
- const chatWid = window.Store.WidFactory.createWid(chatId);
- try {
- await window.Store.GroupUtils.setGroupSubject(chatWid, subject);
- return true;
- } catch (err) {
- if(err.name === 'ServerStatusCodeError') return false;
- throw err;
- }
- }, this.id._serialized, subject);
+ const success = await this.client.pupPage.evaluate(
+ async (chatId, subject) => {
+ const chatWid = window
+ .require('WAWebWidFactory')
+ .createWid(chatId);
+ try {
+ await window
+ .require('WAWebGroupModifyInfoJob')
+ .setGroupSubject(chatWid, subject);
+ return true;
+ } catch (err) {
+ if (err.name === 'ServerStatusCodeError') return false;
+ throw err;
+ }
+ },
+ this.id._serialized,
+ subject,
+ );
- if(!success) return false;
+ if (!success) return false;
this.name = subject;
return true;
}
/**
* Updates the group description
- * @param {string} description
+ * @param {string} description
* @returns {Promise<boolean>} Returns true if the description was properly updated. This can return false if the user does not have the necessary permissions.
*/
async setDescription(description) {
- const success = await this.client.pupPage.evaluate(async (chatId, description) => {
- const chatWid = window.Store.WidFactory.createWid(chatId);
- let descId = window.Store.GroupMetadata.get(chatWid).descId;
- let newId = await window.Store.MsgKey.newId();
- try {
- await window.Store.GroupUtils.setGroupDescription(chatWid, description, newId, descId);
- return true;
- } catch (err) {
- if(err.name === 'ServerStatusCodeError') return false;
- throw err;
- }
- }, this.id._serialized, description);
+ const success = await this.client.pupPage.evaluate(
+ async (chatId, description) => {
+ const chatWid = window
+ .require('WAWebWidFactory')
+ .createWid(chatId);
+ const chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
+ let descId = chat.groupMetadata.descId;
+ let newId = await window.require('WAWebMsgKey').newId();
+ try {
+ await window
+ .require('WAWebGroupModifyInfoJob')
+ .setGroupDescription(
+ chatWid,
+ description,
+ newId,
+ descId,
+ );
+ return true;
+ } catch (err) {
+ if (err.name === 'ServerStatusCodeError') return false;
+ throw err;
+ }
+ },
+ this.id._serialized,
+ description,
+ );
- if(!success) return false;
+ if (!success) return false;
this.groupMetadata.desc = description;
return true;
}
-
+
/**
* Updates the group setting to allow only admins to add members to the group.
- * @param {boolean} [adminsOnly=true] Enable or disable this option
+ * @param {boolean} [adminsOnly=true] Enable or disable this option
* @returns {Promise<boolean>} Returns true if the setting was properly updated. This can return false if the user does not have the necessary permissions.
*/
- async setAddMembersAdminsOnly(adminsOnly=true) {
- const success = await this.client.pupPage.evaluate(async (groupId, adminsOnly) => {
- const chat = await window.WWebJS.getChat(groupId, { getAsModel: false });
- try {
- await window.Store.GroupUtils.setGroupProperty(chat, 'member_add_mode', adminsOnly ? 0 : 1);
- return true;
- } catch (err) {
- if(err.name === 'ServerStatusCodeError') return false;
- throw err;
- }
- }, this.id._serialized, adminsOnly);
+ async setAddMembersAdminsOnly(adminsOnly = true) {
+ const success = await this.client.pupPage.evaluate(
+ async (groupId, adminsOnly) => {
+ const chat = await window.WWebJS.getChat(groupId, {
+ getAsModel: false,
+ });
+ try {
+ await window
+ .require('WAWebSetPropertyGroupAction')
+ .setGroupProperty(
+ chat,
+ 'member_add_mode',
+ adminsOnly ? 0 : 1,
+ );
+ return true;
+ } catch (err) {
+ if (err.name === 'ServerStatusCodeError') return false;
+ throw err;
+ }
+ },
+ this.id._serialized,
+ adminsOnly,
+ );
- success && (this.groupMetadata.memberAddMode = adminsOnly ? 'admin_add' : 'all_member_add');
+ success &&
+ (this.groupMetadata.memberAddMode = adminsOnly
+ ? 'admin_add'
+ : 'all_member_add');
return success;
}
-
+
/**
* Updates the group settings to only allow admins to send messages.
- * @param {boolean} [adminsOnly=true] Enable or disable this option
+ * @param {boolean} [adminsOnly=true] Enable or disable this option
* @returns {Promise<boolean>} Returns true if the setting was properly updated. This can return false if the user does not have the necessary permissions.
*/
- async setMessagesAdminsOnly(adminsOnly=true) {
- const success = await this.client.pupPage.evaluate(async (chatId, adminsOnly) => {
- const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
- try {
- await window.Store.GroupUtils.setGroupProperty(chat, 'announcement', adminsOnly ? 1 : 0);
- return true;
- } catch (err) {
- if(err.name === 'ServerStatusCodeError') return false;
- throw err;
- }
- }, this.id._serialized, adminsOnly);
+ async setMessagesAdminsOnly(adminsOnly = true) {
+ const success = await this.client.pupPage.evaluate(
+ async (chatId, adminsOnly) => {
+ const chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
+ try {
+ await window
+ .require('WAWebSetPropertyGroupAction')
+ .setGroupProperty(
+ chat,
+ 'announcement',
+ adminsOnly ? 1 : 0,
+ );
+ return true;
+ } catch (err) {
+ if (err.name === 'ServerStatusCodeError') return false;
+ throw err;
+ }
+ },
+ this.id._serialized,
+ adminsOnly,
+ );
- if(!success) return false;
+ if (!success) return false;
this.groupMetadata.announce = adminsOnly;
return true;
@@ -367,27 +543,35 @@ class GroupChat extends Chat {
/**
* Updates the group settings to only allow admins to edit group info (title, description, photo).
- * @param {boolean} [adminsOnly=true] Enable or disable this option
+ * @param {boolean} [adminsOnly=true] Enable or disable this option
* @returns {Promise<boolean>} Returns true if the setting was properly updated. This can return false if the user does not have the necessary permissions.
*/
- async setInfoAdminsOnly(adminsOnly=true) {
- const success = await this.client.pupPage.evaluate(async (chatId, adminsOnly) => {
- const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
- try {
- await window.Store.GroupUtils.setGroupProperty(chat, 'restrict', adminsOnly ? 1 : 0);
- return true;
- } catch (err) {
- if(err.name === 'ServerStatusCodeError') return false;
- throw err;
- }
- }, this.id._serialized, adminsOnly);
+ async setInfoAdminsOnly(adminsOnly = true) {
+ const success = await this.client.pupPage.evaluate(
+ async (chatId, adminsOnly) => {
+ const chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
+ try {
+ await window
+ .require('WAWebSetPropertyGroupAction')
+ .setGroupProperty(chat, 'restrict', adminsOnly ? 1 : 0);
+ return true;
+ } catch (err) {
+ if (err.name === 'ServerStatusCodeError') return false;
+ throw err;
+ }
+ },
+ this.id._serialized,
+ adminsOnly,
+ );
+
+ if (!success) return false;
- if(!success) return false;
-
this.groupMetadata.restrict = adminsOnly;
return true;
}
-
+
/**
* Deletes the group's picture.
* @returns {Promise<boolean>} Returns true if the picture was properly deleted. This can return false if the user does not have the necessary permissions.
@@ -406,9 +590,13 @@ class GroupChat extends Chat {
* @returns {Promise<boolean>} Returns true if the picture was properly updated. This can return false if the user does not have the necessary permissions.
*/
async setPicture(media) {
- const success = await this.client.pupPage.evaluate((chatid, media) => {
- return window.WWebJS.setPicture(chatid, media);
- }, this.id._serialized, media);
+ const success = await this.client.pupPage.evaluate(
+ (chatid, media) => {
+ return window.WWebJS.setPicture(chatid, media);
+ },
+ this.id._serialized,
+ media,
+ );
return success;
}
@@ -418,37 +606,35 @@ class GroupChat extends Chat {
* @returns {Promise<string>} Group's invite code
*/
async getInviteCode() {
- const codeRes = await this.client.pupPage.evaluate(async chatId => {
- const chatWid = window.Store.WidFactory.createWid(chatId);
+ const codeRes = await this.client.pupPage.evaluate(async (chatId) => {
try {
- return window.compareWwebVersions(window.Debug.VERSION, '>=', '2.3000.1020730154')
- ? await window.Store.GroupInvite.fetchMexGroupInviteCode(chatId)
- : await window.Store.GroupInvite.queryGroupInviteCode(chatWid, true);
- }
- catch (err) {
- if(err.name === 'ServerStatusCodeError') return undefined;
+ return await window
+ .require('WAWebMexFetchGroupInviteCodeJob')
+ .fetchMexGroupInviteCode(chatId);
+ } catch (err) {
+ if (err.name === 'ServerStatusCodeError') return undefined;
throw err;
}
}, this.id._serialized);
- return codeRes?.code
- ? codeRes?.code
- : codeRes;
+ return codeRes?.code ? codeRes?.code : codeRes;
}
-
+
/**
* Invalidates the current group invite code and generates a new one
* @returns {Promise<string>} New invite code
*/
async revokeInvite() {
- const codeRes = await this.client.pupPage.evaluate(chatId => {
- const chatWid = window.Store.WidFactory.createWid(chatId);
- return window.Store.GroupInvite.resetGroupInviteCode(chatWid);
+ const codeRes = await this.client.pupPage.evaluate((chatId) => {
+ const chatWid = window.require('WAWebWidFactory').createWid(chatId);
+ return window
+ .require('WAWebGroupQueryJob')
+ .resetGroupInviteCode(chatWid);
}, this.id._serialized);
return codeRes.code;
}
-
+
/**
* An object that handles the information about the group membership request
* @typedef {Object} GroupMembershipRequest
@@ -458,13 +644,15 @@ class GroupChat extends Chat {
* @property {string} requestMethod The method used to create the request: NonAdminAdd/InviteLink/LinkedGroupJoin
* @property {number} t The timestamp the request was created at
*/
-
+
/**
* Gets an array of membership requests
* @returns {Promise<Array<GroupMembershipRequest>>} An array of membership requests
*/
async getGroupMembershipRequests() {
- return await this.client.getGroupMembershipRequests(this.id._serialized);
+ return await this.client.getGroupMembershipRequests(
+ this.id._serialized,
+ );
}
/**
@@ -488,7 +676,10 @@ class GroupChat extends Chat {
* @returns {Promise<Array<MembershipRequestActionResult>>} Returns an array of requester IDs whose membership requests were approved and an error for each requester, if any occurred during the operation. If there are no requests, an empty array will be returned
*/
async approveGroupMembershipRequests(options = {}) {
- return await this.client.approveGroupMembershipRequests(this.id._serialized, options);
+ return await this.client.approveGroupMembershipRequests(
+ this.id._serialized,
+ options,
+ );
}
/**
@@ -497,7 +688,10 @@ class GroupChat extends Chat {
* @returns {Promise<Array<MembershipRequestActionResult>>} Returns an array of requester IDs whose membership requests were rejected and an error for each requester, if any occurred during the operation. If there are no requests, an empty array will be returned
*/
async rejectGroupMembershipRequests(options = {}) {
- return await this.client.rejectGroupMembershipRequests(this.id._serialized, options);
+ return await this.client.rejectGroupMembershipRequests(
+ this.id._serialized,
+ options,
+ );
}
/**
@@ -505,12 +699,13 @@ class GroupChat extends Chat {
* @returns {Promise}
*/
async leave() {
- await this.client.pupPage.evaluate(async chatId => {
- const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
- return window.Store.GroupUtils.sendExitGroup(chat);
+ await this.client.pupPage.evaluate(async (chatId) => {
+ const chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
+ return window.require('WAWebExitGroupAction').sendExitGroup(chat);
}, this.id._serialized);
}
-
}
module.exports = GroupChat;
@@ -524,7 +719,7 @@ module.exports = GroupChat;
diff --git a/docs/structures_GroupNotification.js.html b/docs/structures_GroupNotification.js.html
index 085bdda..7f26107 100644
--- a/docs/structures_GroupNotification.js.html
+++ b/docs/structures_GroupNotification.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/GroupNotification.js
+ whatsapp-web.js 1.34.7 » Source: structures/GroupNotification.js
@@ -15,7 +15,7 @@
@@ -41,7 +41,7 @@ class GroupNotification extends Base {
constructor(client, data) {
super(client);
- if(data) this._patch(data);
+ if (data) this._patch(data);
}
_patch(data) {
@@ -57,12 +57,12 @@ class GroupNotification extends Base {
*/
this.body = data.body || '';
- /**
+ /**
* GroupNotification type
* @type {GroupNotificationTypes}
*/
this.type = data.subtype;
-
+
/**
* Unix timestamp for when the groupNotification was created
* @type {number}
@@ -71,17 +71,23 @@ class GroupNotification extends Base {
/**
* ID for the Chat that this groupNotification was sent for.
- *
+ *
* @type {string}
*/
- this.chatId = typeof (data.id.remote) === 'object' ? data.id.remote._serialized : data.id.remote;
+ this.chatId =
+ typeof data.id.remote === 'object'
+ ? data.id.remote._serialized
+ : data.id.remote;
/**
* ContactId for the user that produced the GroupNotification.
* @type {string}
*/
- this.author = typeof (data.author) === 'object' ? data.author._serialized : data.author;
-
+ this.author =
+ typeof data.author === 'object'
+ ? data.author._serialized
+ : data.author;
+
/**
* Contact IDs for the users that were affected by this GroupNotification.
* @type {Array<string>}
@@ -116,20 +122,23 @@ class GroupNotification extends Base {
* @returns {Promise<Array<Contact>>}
*/
async getRecipients() {
- return await Promise.all(this.recipientIds.map(async m => await this.client.getContactById(m)));
+ return await Promise.all(
+ this.recipientIds.map(
+ async (m) => await this.client.getContactById(m),
+ ),
+ );
}
/**
* Sends a message to the same chat this GroupNotification was produced in.
- *
- * @param {string|MessageMedia|Location} content
+ *
+ * @param {string|MessageMedia|Location} content
* @param {object} options
* @returns {Promise<Message>}
*/
- async reply(content, options={}) {
+ async reply(content, options = {}) {
return this.client.sendMessage(this.chatId, content, options);
}
-
}
module.exports = GroupNotification;
@@ -143,7 +152,7 @@ module.exports = GroupNotification;
diff --git a/docs/structures_Label.js.html b/docs/structures_Label.js.html
index 3426c2f..1f4d8ec 100644
--- a/docs/structures_Label.js.html
+++ b/docs/structures_Label.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/Label.js
+ whatsapp-web.js 1.34.7 » Source: structures/Label.js
@@ -15,7 +15,7 @@
@@ -43,13 +43,13 @@ class Label extends Base {
* @param {Base} client
* @param {object} labelData
*/
- constructor(client, labelData){
+ constructor(client, labelData) {
super(client);
- if(labelData) this._patch(labelData);
+ if (labelData) this._patch(labelData);
}
- _patch(labelData){
+ _patch(labelData) {
/**
* Label ID
* @type {string}
@@ -68,17 +68,18 @@ class Label extends Base {
*/
this.hexColor = labelData.hexColor;
}
+
/**
* Get all chats that have been assigned this Label
* @returns {Promise<Array<Chat>>}
*/
- async getChats(){
+ async getChats() {
return this.client.getChatsByLabelId(this.id);
}
-
}
-module.exports = Label;
+module.exports = Label;
+
@@ -88,7 +89,7 @@ module.exports = Label;
diff --git a/docs/structures_List.js.html b/docs/structures_List.js.html
index 3c4d64f..c446399 100644
--- a/docs/structures_List.js.html
+++ b/docs/structures_List.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/List.js
+ whatsapp-web.js 1.34.7 » Source: structures/List.js
@@ -15,7 +15,7 @@
@@ -56,13 +56,12 @@ class List {
* @type {string}
*/
this.buttonText = buttonText;
-
+
/**
* title of message
* @type {string}
*/
this.title = title;
-
/**
* footer of message
@@ -75,9 +74,8 @@ class List {
* @type {Array<any>}
*/
this.sections = this._format(sections);
-
}
-
+
/**
* Creates section array from simple array
* @param {Array<any>} sections
@@ -86,25 +84,35 @@ class List {
* Input: [{title:'sectionTitle',rows:[{id:'customId', title:'ListItem2', description: 'desc'},{title:'ListItem2'}]}}]
* Returns: [{'title':'sectionTitle','rows':[{'rowId':'customId','title':'ListItem1','description':'desc'},{'rowId':'oGSRoD','title':'ListItem2','description':''}]}]
*/
- _format(sections){
- if(!sections.length){throw '[LT02] List without sections';}
- if(sections.length > 1 && sections.filter(s => typeof s.title == 'undefined').length > 1){throw '[LT05] You can\'t have more than one empty title.';}
- return sections.map( (section) =>{
- if(!section.rows.length){throw '[LT03] Section without rows';}
+ _format(sections) {
+ if (!sections.length) {
+ throw '[LT02] List without sections';
+ }
+ if (
+ sections.length > 1 &&
+ sections.filter((s) => typeof s.title == 'undefined').length > 1
+ ) {
+ throw "[LT05] You can't have more than one empty title.";
+ }
+ return sections.map((section) => {
+ if (!section.rows.length) {
+ throw '[LT03] Section without rows';
+ }
return {
title: section.title ? section.title : undefined,
- rows: section.rows.map( (row) => {
- if(!row.title){throw '[LT04] Row without title';}
+ rows: section.rows.map((row) => {
+ if (!row.title) {
+ throw '[LT04] Row without title';
+ }
return {
rowId: row.id ? row.id : Util.generateHash(6),
title: row.title,
- description: row.description ? row.description : ''
+ description: row.description ? row.description : '',
};
- })
+ }),
};
});
}
-
}
module.exports = List;
@@ -118,7 +126,7 @@ module.exports = List;
diff --git a/docs/structures_Location.js.html b/docs/structures_Location.js.html
index 83df218..c63f9ef 100644
--- a/docs/structures_Location.js.html
+++ b/docs/structures_Location.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/Location.js
+ whatsapp-web.js 1.34.7 » Source: structures/Location.js
@@ -15,7 +15,7 @@
@@ -84,13 +84,15 @@ class Location {
* Location full description
* @type {string|undefined}
*/
- this.description = this.name && this.address
- ? `${this.name}\n${this.address}`
- : this.name || this.address || '';
+ this.description =
+ this.name && this.address
+ ? `${this.name}\n${this.address}`
+ : this.name || this.address || '';
}
}
-module.exports = Location;
+module.exports = Location;
+
@@ -100,7 +102,7 @@ module.exports = Location;
diff --git a/docs/structures_Message.js.html b/docs/structures_Message.js.html
index fe82a90..a331463 100644
--- a/docs/structures_Message.js.html
+++ b/docs/structures_Message.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/Message.js
+ whatsapp-web.js 1.34.7 » Source: structures/Message.js
@@ -15,7 +15,7 @@
@@ -54,13 +54,13 @@ class Message extends Base {
_patch(data) {
this._data = data;
-
+
/**
* MediaKey that represents the sticker 'ID'
* @type {string}
*/
this.mediaKey = data.mediaKey;
-
+
/**
* ID that represents the message
* @type {object}
@@ -83,7 +83,9 @@ class Message extends Base {
* Message content
* @type {string}
*/
- this.body = this.hasMedia ? data.caption || '' : data.body || data.pollName || data.eventName || '';
+ this.body = this.hasMedia
+ ? data.caption || ''
+ : data.body || data.pollName || data.eventName || '';
/**
* Message type
@@ -101,7 +103,10 @@ class Message extends Base {
* ID for the Chat that this message was sent to, except if the message was sent by the current user.
* @type {string}
*/
- this.from = (typeof (data.from) === 'object' && data.from !== null) ? data.from._serialized : data.from;
+ this.from =
+ typeof data.from === 'object' && data.from !== null
+ ? data.from._serialized
+ : data.from;
/**
* ID for who this message is for.
@@ -110,19 +115,31 @@ class Message extends Base {
* If the message is sent by another user, it will be the ID for the current user.
* @type {string}
*/
- this.to = (typeof (data.to) === 'object' && data.to !== null) ? data.to._serialized : data.to;
+ this.to =
+ typeof data.to === 'object' && data.to !== null
+ ? data.to._serialized
+ : data.to;
/**
* If the message was sent to a group, this field will contain the user that sent the message.
* @type {string}
*/
- this.author = (typeof (data.author) === 'object' && data.author !== null) ? data.author._serialized : data.author;
+ this.author =
+ typeof data.author === 'object' && data.author !== null
+ ? data.author._serialized
+ : data.author;
/**
* String that represents from which device type the message was sent
* @type {string}
*/
- this.deviceType = typeof data.id.id === 'string' && data.id.id.length > 21 ? 'android' : typeof data.id.id === 'string' && data.id.id.substring(0, 2) === '3A' ? 'ios' : 'web';
+ this.deviceType =
+ typeof data.id.id === 'string' && data.id.id.length > 25
+ ? 'android'
+ : typeof data.id.id === 'string' &&
+ data.id.id.substring(0, 2) === '3A'
+ ? 'ios'
+ : 'web';
/**
* Indicates if the message was forwarded
* @type {boolean}
@@ -141,7 +158,8 @@ class Message extends Base {
* Indicates if the message is a status update
* @type {boolean}
*/
- this.isStatus = data.isStatusV3 || data.id.remote === 'status@broadcast';
+ this.isStatus =
+ data.isStatusV3 || data.id.remote === 'status@broadcast';
/**
* Indicates if the message was starred
@@ -193,7 +211,7 @@ class Message extends Base {
description = {
name: splitted[0],
address: splitted[1],
- url: data.clientUrl
+ url: data.clientUrl,
};
}
return new Location(data.lat, data.lng, description);
@@ -203,20 +221,36 @@ class Message extends Base {
* List of vCards contained in the message.
* @type {Array<string>}
*/
- this.vCards = data.type === MessageTypes.CONTACT_CARD_MULTI ? data.vcardList.map((c) => c.vcard) : data.type === MessageTypes.CONTACT_CARD ? [data.body] : [];
+ this.vCards =
+ data.type === MessageTypes.CONTACT_CARD_MULTI
+ ? data.vcardList.map((c) => c.vcard)
+ : data.type === MessageTypes.CONTACT_CARD
+ ? [data.body]
+ : [];
/**
* Group Invite Data
* @type {object}
*/
- this.inviteV4 = data.type === MessageTypes.GROUP_INVITE ? {
- inviteCode: data.inviteCode,
- inviteCodeExp: data.inviteCodeExp,
- groupId: data.inviteGrp,
- groupName: data.inviteGrpName,
- fromId: typeof data.from === 'object' && '_serialized' in data.from ? data.from._serialized : data.from,
- toId: typeof data.to === 'object' && '_serialized' in data.to ? data.to._serialized : data.to
- } : undefined;
+ this.inviteV4 =
+ data.type === MessageTypes.GROUP_INVITE
+ ? {
+ inviteCode: data.inviteCode,
+ inviteCodeExp: data.inviteCodeExp,
+ groupId: data.inviteGrp,
+ groupName: data.inviteGrpName,
+ fromId:
+ typeof data.from === 'object' &&
+ '_serialized' in data.from
+ ? data.from._serialized
+ : data.from,
+ toId:
+ typeof data.to === 'object' &&
+ '_serialized' in data.to
+ ? data.to._serialized
+ : data.to,
+ }
+ : undefined;
/**
* Indicates the mentions in the message body.
@@ -247,7 +281,7 @@ class Message extends Base {
*/
this.token = data.token ? data.token : undefined;
- /**
+ /**
* Indicates whether the message is a Gif
* @type {boolean}
*/
@@ -288,7 +322,7 @@ class Message extends Base {
if (data.latestEditMsgKey) {
this.latestEditMsgKey = data.latestEditMsgKey;
}
-
+
/**
* Protocol message key.
* Can be used to retrieve the ID of an original message that was revoked.
@@ -315,17 +349,27 @@ class Message extends Base {
}
/** Selected List row Id **/
- if (data.listResponse && data.listResponse.singleSelectReply.selectedRowId) {
- this.selectedRowId = data.listResponse.singleSelectReply.selectedRowId;
+ if (
+ data.listResponse &&
+ data.listResponse.singleSelectReply.selectedRowId
+ ) {
+ this.selectedRowId =
+ data.listResponse.singleSelectReply.selectedRowId;
}
if (this.type === MessageTypes.POLL_CREATION) {
this.pollName = data.pollName;
this.pollOptions = data.pollOptions;
- this.allowMultipleAnswers = Boolean(!data.pollSelectableOptionsCount);
+ this.allowMultipleAnswers = Boolean(
+ !data.pollSelectableOptionsCount,
+ );
this.pollInvalidated = data.pollInvalidated;
this.isSentCagPollCreation = data.isSentCagPollCreation;
- this.messageSecret = data.messageSecret ? Object.keys(data.messageSecret).map((key) => data.messageSecret[key]) : [];
+ this.messageSecret = data.messageSecret
+ ? Object.keys(data.messageSecret).map(
+ (key) => data.messageSecret[key],
+ )
+ : [];
}
return super._patch(data);
@@ -336,19 +380,25 @@ class Message extends Base {
}
/**
- * Reloads this Message object's data in-place with the latest values from WhatsApp Web.
+ * Reloads this Message object's data in-place with the latest values from WhatsApp Web.
* Note that the Message must still be in the web app cache for this to work, otherwise will return null.
* @returns {Promise<Message>}
*/
async reload() {
const newData = await this.client.pupPage.evaluate(async (msgId) => {
- const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
+ const msg =
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
if (!msg) return null;
return window.WWebJS.getMessageModel(msg);
}, this.id._serialized);
- if(!newData) return null;
-
+ if (!newData) return null;
+
this._patch(newData);
return this;
}
@@ -360,7 +410,7 @@ class Message extends Base {
get rawData() {
return this._data;
}
-
+
/**
* Returns the Chat this message was sent in
* @returns {Promise<Chat>}
@@ -382,15 +432,27 @@ class Message extends Base {
* @returns {Promise<Array<Contact>>}
*/
async getMentions() {
- return await Promise.all(this.mentionedIds.map(async m => await this.client.getContactById(m)));
+ return await Promise.all(
+ this.mentionedIds.map(
+ async (m) =>
+ await this.client.getContactById(
+ typeof m === 'string' ? m : m._serialized,
+ ),
+ ),
+ );
}
-
+
/**
* Returns groups mentioned in this message
* @returns {Promise<Array<GroupChat>>}
*/
async getGroupMentions() {
- return await Promise.all(this.groupMentions.map(async (m) => await this.client.getChatById(m.groupJid._serialized)));
+ return await Promise.all(
+ this.groupMentions.map(
+ async (m) =>
+ await this.client.getChatById(m.groupJid._serialized),
+ ),
+ );
}
/**
@@ -401,8 +463,16 @@ class Message extends Base {
if (!this.hasQuotedMsg) return undefined;
const quotedMsg = await this.client.pupPage.evaluate(async (msgId) => {
- const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
- const quotedMsg = window.Store.QuotedMsg.getQuotedMsgObj(msg);
+ const msg =
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
+ const quotedMsg = window
+ .require('WAWebQuotedMsgModelUtils')
+ .getQuotedMsgObj(msg);
return window.WWebJS.getMessageModel(quotedMsg);
}, this.id._serialized);
@@ -426,7 +496,7 @@ class Message extends Base {
options = {
...options,
- quotedMessageId: this.id._serialized
+ quotedMessageId: this.id._serialized,
};
return this.client.sendMessage(chatId, content, options);
@@ -437,14 +507,8 @@ class Message extends Base {
* @param {string} reaction - Emoji to react with. Send an empty string to remove the reaction.
* @return {Promise}
*/
- async react(reaction){
- await this.client.pupPage.evaluate(async (messageId, reaction) => {
- if (!messageId) return null;
- const msg =
- window.Store.Msg.get(messageId) || (await window.Store.Msg.getMessagesById([messageId]))?.messages?.[0];
- if(!msg) return null;
- await window.Store.sendReactionToMsg(msg, reaction);
- }, this.id._serialized, reaction);
+ async react(reaction) {
+ return this.client.sendReaction(this.id._serialized, reaction);
}
/**
@@ -464,9 +528,13 @@ class Message extends Base {
async forward(chat) {
const chatId = typeof chat === 'string' ? chat : chat.id._serialized;
- await this.client.pupPage.evaluate(async (msgId, chatId) => {
- return window.WWebJS.forwardMessage(chatId, msgId);
- }, this.id._serialized, chatId);
+ await this.client.pupPage.evaluate(
+ async (msgId, chatId) => {
+ return window.WWebJS.forwardMessage(chatId, msgId);
+ },
+ this.id._serialized,
+ chatId,
+ );
}
/**
@@ -479,57 +547,84 @@ class Message extends Base {
}
const result = await this.client.pupPage.evaluate(async (msgId) => {
- const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
+ const msg =
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
// REUPLOADING mediaStage means the media is expired and the download button is spinning, cannot be downloaded now
- if (!msg || !msg.mediaData || msg.mediaData.mediaStage === 'REUPLOADING') {
+ if (
+ !msg ||
+ !msg.mediaData ||
+ msg.mediaData.mediaStage === 'REUPLOADING'
+ ) {
return null;
}
if (msg.mediaData.mediaStage != 'RESOLVED') {
// try to resolve media
await msg.downloadMedia({
downloadEvenIfExpensive: true,
- rmrReason: 1
+ rmrReason: 1,
});
}
- if (msg.mediaData.mediaStage.includes('ERROR') || msg.mediaData.mediaStage === 'FETCHING') {
+ if (
+ msg.mediaData.mediaStage.includes('ERROR') ||
+ msg.mediaData.mediaStage === 'FETCHING'
+ ) {
// media could not be downloaded
return undefined;
}
try {
const mockQpl = {
- addAnnotations: function() { return this; },
- addPoint: function() { return this; }
+ addAnnotations: function () {
+ return this;
+ },
+ addPoint: function () {
+ return this;
+ },
};
- const decryptedMedia = await window.Store.DownloadManager.downloadAndMaybeDecrypt({
- directPath: msg.directPath,
- encFilehash: msg.encFilehash,
- filehash: msg.filehash,
- mediaKey: msg.mediaKey,
- mediaKeyTimestamp: msg.mediaKeyTimestamp,
- type: msg.type,
- signal: (new AbortController).signal,
- downloadQpl: mockQpl
- });
+ const decryptedMedia = await window
+ .require('WAWebDownloadManager')
+ .downloadManager.downloadAndMaybeDecrypt({
+ directPath: msg.directPath,
+ encFilehash: msg.encFilehash,
+ filehash: msg.filehash,
+ mediaKey: msg.mediaKey,
+ mediaKeyTimestamp: msg.mediaKeyTimestamp,
+ type: msg.type,
+ signal: new AbortController().signal,
+ downloadQpl: mockQpl,
+ });
- const data = await window.WWebJS.arrayBufferToBase64Async(decryptedMedia);
+ const data =
+ await window.WWebJS.arrayBufferToBase64Async(
+ decryptedMedia,
+ );
return {
data,
mimetype: msg.mimetype,
filename: msg.filename,
- filesize: msg.size
+ filesize: msg.size,
};
} catch (e) {
- if(e.status && e.status === 404) return undefined;
+ if (e.status && e.status === 404) return undefined;
throw e;
}
}, this.id._serialized);
if (!result) return undefined;
- return new MessageMedia(result.mimetype, result.data, result.filename, result.filesize);
+ return new MessageMedia(
+ result.mimetype,
+ result.data,
+ result.filename,
+ result.filesize,
+ );
}
/**
@@ -538,23 +633,66 @@ class Message extends Base {
* @param {?boolean} [clearMedia = true] If true, any associated media will also be deleted from a device.
*/
async delete(everyone, clearMedia = true) {
- await this.client.pupPage.evaluate(async (msgId, everyone, clearMedia) => {
- const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
- const chat = window.Store.Chat.get(msg.id.remote) || (await window.Store.Chat.find(msg.id.remote));
-
- const canRevoke =
- window.Store.MsgActionChecks.canSenderRevokeMsg(msg) || window.Store.MsgActionChecks.canAdminRevokeMsg(msg);
+ await this.client.pupPage.evaluate(
+ async (msgId, everyone, clearMedia) => {
+ const msg =
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
+ const chat =
+ window
+ .require('WAWebCollections')
+ .Chat.get(msg.id.remote) ||
+ (await window
+ .require('WAWebCollections')
+ .Chat.find(msg.id.remote));
- if (everyone && canRevoke) {
- return window.compareWwebVersions(window.Debug.VERSION, '>=', '2.3000.0')
- ? window.Store.Cmd.sendRevokeMsgs(chat, { list: [msg], type: 'message' }, { clearMedia: clearMedia })
- : window.Store.Cmd.sendRevokeMsgs(chat, [msg], { clearMedia: true, type: msg.id.fromMe ? 'Sender' : 'Admin' });
- }
+ const canRevoke =
+ window
+ .require('WAWebMsgActionCapability')
+ .canSenderRevokeMsg(msg) ||
+ window
+ .require('WAWebMsgActionCapability')
+ .canAdminRevokeMsg(msg);
- return window.compareWwebVersions(window.Debug.VERSION, '>=', '2.3000.0')
- ? window.Store.Cmd.sendDeleteMsgs(chat, { list: [msg], type: 'message' }, clearMedia)
- : window.Store.Cmd.sendDeleteMsgs(chat, [msg], clearMedia);
- }, this.id._serialized, everyone, clearMedia);
+ const { Cmd } = window.require('WAWebCmd');
+
+ if (everyone && canRevoke) {
+ return window.WWebJS.compareWwebVersions(
+ window.Debug.VERSION,
+ '>=',
+ '2.3000.0',
+ )
+ ? Cmd.sendRevokeMsgs(
+ chat,
+ { list: [msg], type: 'message' },
+ { clearMedia: clearMedia },
+ )
+ : Cmd.sendRevokeMsgs(chat, [msg], {
+ clearMedia: true,
+ type: msg.id.fromMe ? 'Sender' : 'Admin',
+ });
+ }
+
+ return window.WWebJS.compareWwebVersions(
+ window.Debug.VERSION,
+ '>=',
+ '2.3000.0',
+ )
+ ? Cmd.sendDeleteMsgs(
+ chat,
+ { list: [msg], type: 'message' },
+ clearMedia,
+ )
+ : Cmd.sendDeleteMsgs(chat, [msg], clearMedia);
+ },
+ this.id._serialized,
+ everyone,
+ clearMedia,
+ );
}
/**
@@ -562,10 +700,20 @@ class Message extends Base {
*/
async star() {
await this.client.pupPage.evaluate(async (msgId) => {
- const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
- if (window.Store.MsgActionChecks.canStarMsg(msg)) {
- let chat = await window.Store.Chat.find(msg.id.remote);
- return window.Store.Cmd.sendStarMsgs(chat, [msg], false);
+ const msg =
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
+ if (window.require('WAWebMsgActionCapability').canStarMsg(msg)) {
+ let chat = await window
+ .require('WAWebCollections')
+ .Chat.find(msg.id.remote);
+ return window
+ .require('WAWebCmd')
+ .Cmd.sendStarMsgs(chat, [msg], false);
}
}, this.id._serialized);
}
@@ -575,10 +723,20 @@ class Message extends Base {
*/
async unstar() {
await this.client.pupPage.evaluate(async (msgId) => {
- const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
- if (window.Store.MsgActionChecks.canStarMsg(msg)) {
- let chat = await window.Store.Chat.find(msg.id.remote);
- return window.Store.Cmd.sendUnstarMsgs(chat, [msg], false);
+ const msg =
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
+ if (window.require('WAWebMsgActionCapability').canStarMsg(msg)) {
+ let chat = await window
+ .require('WAWebCollections')
+ .Chat.find(msg.id.remote);
+ return window
+ .require('WAWebCmd')
+ .Cmd.sendUnstarMsgs(chat, [msg], false);
}
}, this.id._serialized);
}
@@ -589,9 +747,17 @@ class Message extends Base {
* @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
*/
async pin(duration) {
- return await this.client.pupPage.evaluate(async (msgId, duration) => {
- return await window.WWebJS.pinUnpinMsgAction(msgId, 1, duration);
- }, this.id._serialized, duration);
+ return await this.client.pupPage.evaluate(
+ async (msgId, duration) => {
+ return await window.WWebJS.pinUnpinMsgAction(
+ msgId,
+ 1,
+ duration,
+ );
+ },
+ this.id._serialized,
+ duration,
+ );
}
/**
@@ -622,13 +788,28 @@ class Message extends Base {
*/
async getInfo() {
const info = await this.client.pupPage.evaluate(async (msgId) => {
- const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
+ const msg =
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
if (!msg || !msg.id.fromMe) return null;
return new Promise((resolve) => {
- setTimeout(async () => {
- resolve(await window.Store.getMsgInfo(msg.id));
- }, (Date.now() - msg.t * 1000 < 1250) && Math.floor(Math.random() * (1200 - 1100 + 1)) + 1100 || 0);
+ setTimeout(
+ async () => {
+ resolve(
+ await window
+ .require('WAWebApiMessageInfoStore')
+ .queryMsgInfo(msg.id),
+ );
+ },
+ (Date.now() - msg.t * 1000 < 1250 &&
+ Math.floor(Math.random() * (1200 - 1100 + 1)) + 1100) ||
+ 0,
+ );
});
}, this.id._serialized);
@@ -641,14 +822,20 @@ class Message extends Base {
*/
async getOrder() {
if (this.type === MessageTypes.ORDER) {
- const result = await this.client.pupPage.evaluate((orderId, token, chatId) => {
- return window.WWebJS.getOrderDetail(orderId, token, chatId);
- }, this.orderId, this.token, this._getChatId());
+ const result = await this.client.pupPage.evaluate(
+ (orderId, token, chatId) => {
+ return window.WWebJS.getOrderDetail(orderId, token, chatId);
+ },
+ this.orderId,
+ this.token,
+ this._getChatId(),
+ );
if (!result) return undefined;
return new Order(this.client, result);
}
return undefined;
}
+
/**
* Gets the payment details associated with a given message
* @return {Promise<Payment>}
@@ -656,8 +843,14 @@ class Message extends Base {
async getPayment() {
if (this.type === MessageTypes.PAYMENT) {
const msg = await this.client.pupPage.evaluate(async (msgId) => {
- const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
- if(!msg) return null;
+ const msg =
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
+ if (!msg) return null;
return msg.serialize();
}, this.id._serialized);
return new Payment(this.client, msg);
@@ -665,7 +858,6 @@ class Message extends Base {
return undefined;
}
-
/**
* Reaction List
* @typedef {Object} ReactionList
@@ -685,7 +877,9 @@ class Message extends Base {
}
const reactions = await this.client.pupPage.evaluate(async (msgId) => {
- const msgReactions = await window.Store.Reactions.find(msgId);
+ const msgReactions = await window
+ .require('WAWebCollections')
+ .Reactions.find(msgId);
if (!msgReactions || !msgReactions.reactions.length) return null;
return msgReactions.reactions.serialize();
}, this.id._serialized);
@@ -694,8 +888,8 @@ class Message extends Base {
return undefined;
}
- return reactions.map(reaction => {
- reaction.senders = reaction.senders.map(sender => {
+ return reactions.map((reaction) => {
+ reaction.senders = reaction.senders.map((sender) => {
sender.timestamp = Math.round(sender.timestamp / 1000);
return new Reaction(this.client, sender);
});
@@ -711,36 +905,68 @@ class Message extends Base {
*/
async edit(content, options = {}) {
if (options.mentions) {
- !Array.isArray(options.mentions) && (options.mentions = [options.mentions]);
- if (options.mentions.some((possiblyContact) => possiblyContact instanceof Contact)) {
- console.warn('Mentions with an array of Contact are now deprecated. See more at https://github.com/pedroslopez/whatsapp-web.js/pull/2166.');
- options.mentions = options.mentions.map((a) => a.id._serialized);
+ !Array.isArray(options.mentions) &&
+ (options.mentions = [options.mentions]);
+ if (
+ options.mentions.some(
+ (possiblyContact) => possiblyContact instanceof Contact,
+ )
+ ) {
+ console.warn(
+ 'Mentions with an array of Contact are now deprecated. See more at https://github.com/wwebjs/whatsapp-web.js/pull/2166.',
+ );
+ options.mentions = options.mentions.map(
+ (a) => a.id._serialized,
+ );
}
}
- options.groupMentions && !Array.isArray(options.groupMentions) && (options.groupMentions = [options.groupMentions]);
+ options.groupMentions &&
+ !Array.isArray(options.groupMentions) &&
+ (options.groupMentions = [options.groupMentions]);
let internalOptions = {
linkPreview: options.linkPreview === false ? undefined : true,
mentionedJidList: options.mentions || [],
groupMentions: options.groupMentions,
- extraOptions: options.extra
+ extraOptions: options.extra,
};
-
+
if (!this.fromMe) {
return null;
}
- const messageEdit = await this.client.pupPage.evaluate(async (msgId, message, options) => {
- const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
- if (!msg) return null;
+ const messageEdit = await this.client.pupPage.evaluate(
+ async (msgId, message, options) => {
+ const msg =
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
+ if (!msg) return null;
- let canEdit = window.Store.MsgActionChecks.canEditText(msg) || window.Store.MsgActionChecks.canEditCaption(msg);
- if (canEdit) {
- const msgEdit = await window.WWebJS.editMessage(msg, message, options);
- return msgEdit.serialize();
- }
- return null;
- }, this.id._serialized, content, internalOptions);
+ let canEdit =
+ window
+ .require('WAWebMsgActionCapability')
+ .canEditText(msg) ||
+ window
+ .require('WAWebMsgActionCapability')
+ .canEditCaption(msg);
+ if (canEdit) {
+ const msgEdit = await window.WWebJS.editMessage(
+ msg,
+ message,
+ options,
+ );
+ return msgEdit.serialize();
+ }
+ return null;
+ },
+ this.id._serialized,
+ content,
+ internalOptions,
+ );
if (messageEdit) {
return new Message(this.client, messageEdit);
}
@@ -758,28 +984,44 @@ class Message extends Base {
return null;
}
- const edittedEventMsg = await this.client.pupPage.evaluate(async (msgId, editedEventObject) => {
- const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
- if (!msg) return null;
+ const edittedEventMsg = await this.client.pupPage.evaluate(
+ async (msgId, editedEventObject) => {
+ const msg =
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
+ if (!msg) return null;
- const { name, startTimeTs, eventSendOptions } = editedEventObject;
- const eventOptions = {
- name: name,
- description: eventSendOptions.description,
- startTime: startTimeTs,
- endTime: eventSendOptions.endTimeTs,
- location: eventSendOptions.location,
- callType: eventSendOptions.callType,
- isEventCanceled: eventSendOptions.isEventCanceled,
- };
+ const { name, startTimeTs, eventSendOptions } =
+ editedEventObject;
+ const eventOptions = {
+ name: name,
+ description: eventSendOptions.description,
+ startTime: startTimeTs,
+ endTime: eventSendOptions.endTimeTs,
+ location: eventSendOptions.location,
+ callType: eventSendOptions.callType,
+ isEventCanceled: eventSendOptions.isEventCanceled,
+ };
- await window.Store.ScheduledEventMsgUtils.sendEventEditMessage(eventOptions, msg);
- const editedMsg = window.Store.Msg.get(msg.id._serialized);
- return editedMsg?.serialize();
- }, this.id._serialized, editedEventObject);
+ await window
+ .require('WAWebSendEventEditMsgAction')
+ .sendEventEditMessage(eventOptions, msg);
+ const editedMsg = window
+ .require('WAWebCollections')
+ .Msg.get(msg.id._serialized);
+ return editedMsg?.serialize();
+ },
+ this.id._serialized,
+ editedEventObject,
+ );
return edittedEventMsg && new Message(this.client, edittedEventMsg);
}
+
/**
* Returns the PollVote this poll message
* @returns {Promise<PollVote[]>}
@@ -794,24 +1036,36 @@ class Message extends Base {
* @returns {Promise}
*/
async vote(selectedOptions) {
- if (this.type != MessageTypes.POLL_CREATION) throw 'Invalid usage! Can only be used with a pollCreation message';
+ if (this.type != MessageTypes.POLL_CREATION)
+ throw 'Invalid usage! Can only be used with a pollCreation message';
- await this.client.pupPage.evaluate(async (messageId, votes) => {
- if (!messageId) return null;
- if (!Array.isArray(votes)) votes = [votes];
- let localIdSet = new Set();
- const msg =
- window.Store.Msg.get(messageId) || (await window.Store.Msg.getMessagesById([messageId]))?.messages?.[0];
- if (!msg) return null;
+ await this.client.pupPage.evaluate(
+ async (messageId, votes) => {
+ if (!messageId) return null;
+ if (!Array.isArray(votes)) votes = [votes];
+ let localIdSet = new Set();
+ const msg =
+ window.require('WAWebCollections').Msg.get(messageId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([messageId])
+ )?.messages?.[0];
+ if (!msg) return null;
- msg.pollOptions.forEach(a => {
- for (const option of votes) {
- if (a.name === option) localIdSet.add(a.localId);
- }
- });
+ msg.pollOptions.forEach((a) => {
+ for (const option of votes) {
+ if (a.name === option) localIdSet.add(a.localId);
+ }
+ });
- await window.Store.PollsSendVote.sendVote(msg, localIdSet);
- }, this.id._serialized, selectedOptions);
+ await window
+ .require('WAWebPollsSendVoteMsgAction')
+ .sendVote(msg, localIdSet);
+ },
+ this.id._serialized,
+ selectedOptions,
+ );
}
}
@@ -826,7 +1080,7 @@ module.exports = Message;
diff --git a/docs/structures_MessageMedia.js.html b/docs/structures_MessageMedia.js.html
index 1bded98..6d600df 100644
--- a/docs/structures_MessageMedia.js.html
+++ b/docs/structures_MessageMedia.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/MessageMedia.js
+ whatsapp-web.js 1.34.7 » Source: structures/MessageMedia.js
@@ -15,7 +15,7 @@
@@ -63,7 +63,7 @@ class MessageMedia {
* @type {?string}
*/
this.filename = filename;
-
+
/**
* Document file size in bytes. Value can be null
* @type {?number}
@@ -73,12 +73,12 @@ class MessageMedia {
/**
* Creates a MessageMedia instance from a local file path
- * @param {string} filePath
+ * @param {string} filePath
* @returns {MessageMedia}
*/
static fromFilePath(filePath) {
- const b64data = fs.readFileSync(filePath, {encoding: 'base64'});
- const mimetype = mime.getType(filePath);
+ const b64data = fs.readFileSync(filePath, { encoding: 'base64' });
+ const mimetype = mime.getType(filePath);
const filename = path.basename(filePath);
return new MessageMedia(mimetype, b64data, filename);
@@ -100,16 +100,25 @@ class MessageMedia {
let mimetype = mime.getType(pUrl.pathname);
if (!mimetype && !options.unsafeMime)
- throw new Error('Unable to determine MIME type using URL. Set unsafeMime to true to download it anyway.');
+ throw new Error(
+ 'Unable to determine MIME type using URL. Set unsafeMime to true to download it anyway.',
+ );
- async function fetchData (url, options) {
- const reqOptions = Object.assign({ headers: { accept: 'image/* video/* text/* audio/*' } }, options);
+ async function fetchData(url, options) {
+ const reqOptions = Object.assign(
+ { headers: { accept: 'image/* video/* text/* audio/*' } },
+ options,
+ );
const response = await fetch(url, reqOptions);
const mime = response.headers.get('Content-Type');
const size = response.headers.get('Content-Length');
- const contentDisposition = response.headers.get('Content-Disposition');
- const name = contentDisposition ? contentDisposition.match(/((?<=filename=")(.*)(?="))/) : null;
+ const contentDisposition = response.headers.get(
+ 'Content-Disposition',
+ );
+ const name = contentDisposition
+ ? contentDisposition.match(/((?<=filename=")(.*)(?="))/)
+ : null;
let data = '';
if (response.buffer) {
@@ -121,19 +130,23 @@ class MessageMedia {
});
data = btoa(data);
}
-
+
return { data, mime, name, size };
}
const res = options.client
- ? (await options.client.pupPage.evaluate(fetchData, url, options.reqOptions))
- : (await fetchData(url, options.reqOptions));
+ ? await options.client.pupPage.evaluate(
+ fetchData,
+ url,
+ options.reqOptions,
+ )
+ : await fetchData(url, options.reqOptions);
- const filename = options.filename ||
- (res.name ? res.name[0] : (pUrl.pathname.split('/').pop() || 'file'));
-
- if (!mimetype)
- mimetype = res.mime;
+ const filename =
+ options.filename ||
+ (res.name ? res.name[0] : pUrl.pathname.split('/').pop() || 'file');
+
+ if (!mimetype) mimetype = res.mime;
return new MessageMedia(mimetype, res.data, filename, res.size || null);
}
@@ -150,7 +163,7 @@ module.exports = MessageMedia;
diff --git a/docs/structures_Order.js.html b/docs/structures_Order.js.html
index ab2ba91..a64fe69 100644
--- a/docs/structures_Order.js.html
+++ b/docs/structures_Order.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/Order.js
+ whatsapp-web.js 1.34.7 » Source: structures/Order.js
@@ -15,7 +15,7 @@
@@ -51,7 +51,9 @@ class Order extends Base {
* @type {Array<Product>}
*/
if (data.products) {
- this.products = data.products.map(product => new Product(this.client, product));
+ this.products = data.products.map(
+ (product) => new Product(this.client, product),
+ );
}
/**
* Order Subtotal
@@ -76,11 +78,10 @@ class Order extends Base {
return super._patch(data);
}
-
-
}
-module.exports = Order;
+module.exports = Order;
+
@@ -90,7 +91,7 @@ module.exports = Order;
diff --git a/docs/structures_Payment.js.html b/docs/structures_Payment.js.html
index ddb93c8..dac7868 100644
--- a/docs/structures_Payment.js.html
+++ b/docs/structures_Payment.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/Payment.js
+ whatsapp-web.js 1.34.7 » Source: structures/Payment.js
@@ -15,7 +15,7 @@
@@ -85,7 +85,7 @@ class Payment extends Base {
* 9:CANCELLED
* 10:WAITING_FOR_PAYER
* 11:WAITING
- *
+ *
* @type {number}
*/
this.paymentStatus = data.paymentStatus;
@@ -100,11 +100,14 @@ class Payment extends Base {
* The note sent with the payment
* @type {string}
*/
- this.paymentNote = !data.paymentNoteMsg ? undefined : data.paymentNoteMsg.body ? data.paymentNoteMsg.body : undefined ;
+ this.paymentNote = !data.paymentNoteMsg
+ ? undefined
+ : data.paymentNoteMsg.body
+ ? data.paymentNoteMsg.body
+ : undefined;
return super._patch(data);
}
-
}
module.exports = Payment;
@@ -118,7 +121,7 @@ module.exports = Payment;
diff --git a/docs/structures_Poll.js.html b/docs/structures_Poll.js.html
index 4a217bf..88dcfda 100644
--- a/docs/structures_Poll.js.html
+++ b/docs/structures_Poll.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/Poll.js
+ whatsapp-web.js 1.34.7 » Source: structures/Poll.js
@@ -15,7 +15,7 @@
@@ -58,7 +58,7 @@ class Poll {
*/
this.pollOptions = pollOptions.map((option, index) => ({
name: option.trim(),
- localId: index
+ localId: index,
}));
/**
@@ -67,7 +67,7 @@ class Poll {
*/
this.options = {
allowMultipleAnswers: options.allowMultipleAnswers === true,
- messageSecret: options.messageSecret
+ messageSecret: options.messageSecret,
};
}
}
@@ -83,7 +83,7 @@ module.exports = Poll;
diff --git a/docs/structures_PollVote.js.html b/docs/structures_PollVote.js.html
index 009933d..d261e7b 100644
--- a/docs/structures_PollVote.js.html
+++ b/docs/structures_PollVote.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/PollVote.js
+ whatsapp-web.js 1.34.7 » Source: structures/PollVote.js
@@ -15,7 +15,7 @@
@@ -66,21 +66,24 @@ class PollVote extends Base {
* @type {SelectedPollOption[]}
*/
if (data.selectedOptionLocalIds.length > 0) {
- if(data.parentMessage) { // temporary failsafe
+ if (data.parentMessage) {
+ // temporary failsafe
this.selectedOptions = data.selectedOptionLocalIds.map((e) => ({
- name: data.parentMessage.pollOptions.find((x) => x.localId === e).name,
- localId: e
+ name: data.parentMessage.pollOptions.find(
+ (x) => x.localId === e,
+ ).name,
+ localId: e,
}));
} else {
this.selectedOptions = data.selectedOptionLocalIds.map((e) => ({
name: undefined,
- localId: e
+ localId: e,
}));
}
} else {
this.selectedOptions = [];
}
-
+
/**
* Timestamp the option was selected or deselected at
* @type {number}
@@ -97,7 +100,7 @@ class PollVote extends Base {
* The poll creation message id
* @type {Object}
*/
- this.parentMsgKey = data.parentMsgKey;
+ this.parentMsgKey = data.parentMsgKey;
return super._patch(data);
}
@@ -114,7 +117,7 @@ module.exports = PollVote;
diff --git a/docs/structures_PrivateChat.js.html b/docs/structures_PrivateChat.js.html
index 64f9e93..808a98f 100644
--- a/docs/structures_PrivateChat.js.html
+++ b/docs/structures_PrivateChat.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/PrivateChat.js
+ whatsapp-web.js 1.34.7 » Source: structures/PrivateChat.js
@@ -15,7 +15,7 @@
@@ -37,11 +37,10 @@ const Chat = require('./Chat');
* Represents a Private Chat on WhatsApp
* @extends {Chat}
*/
-class PrivateChat extends Chat {
+class PrivateChat extends Chat {}
-}
-
-module.exports = PrivateChat;
+module.exports = PrivateChat;
+
@@ -51,7 +50,7 @@ module.exports = PrivateChat;
diff --git a/docs/structures_PrivateContact.js.html b/docs/structures_PrivateContact.js.html
index ec94c28..6e9b557 100644
--- a/docs/structures_PrivateContact.js.html
+++ b/docs/structures_PrivateContact.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/PrivateContact.js
+ whatsapp-web.js 1.34.7 » Source: structures/PrivateContact.js
@@ -15,7 +15,7 @@
@@ -37,11 +37,10 @@ const Contact = require('./Contact');
* Represents a Private Contact on WhatsApp
* @extends {Contact}
*/
-class PrivateContact extends Contact {
+class PrivateContact extends Contact {}
-}
-
-module.exports = PrivateContact;
+module.exports = PrivateContact;
+
@@ -51,7 +50,7 @@ module.exports = PrivateContact;
diff --git a/docs/structures_Product.js.html b/docs/structures_Product.js.html
index c6210fd..edee2d0 100644
--- a/docs/structures_Product.js.html
+++ b/docs/structures_Product.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/Product.js
+ whatsapp-web.js 1.34.7 » Source: structures/Product.js
@@ -15,7 +15,7 @@
@@ -96,7 +96,8 @@ class Product extends Base {
}
}
-module.exports = Product;
+module.exports = Product;
+
@@ -106,7 +107,7 @@ module.exports = Product;
diff --git a/docs/structures_ProductMetadata.js.html b/docs/structures_ProductMetadata.js.html
index e9ce59e..c9e8c8d 100644
--- a/docs/structures_ProductMetadata.js.html
+++ b/docs/structures_ProductMetadata.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/ProductMetadata.js
+ whatsapp-web.js 1.34.7 » Source: structures/ProductMetadata.js
@@ -15,7 +15,7 @@
@@ -50,10 +50,10 @@ class ProductMetadata extends Base {
return super._patch(data);
}
-
}
-module.exports = ProductMetadata;
+module.exports = ProductMetadata;
+
@@ -63,7 +63,7 @@ module.exports = ProductMetadata;
diff --git a/docs/structures_Reaction.js.html b/docs/structures_Reaction.js.html
index a1eed42..5da180d 100644
--- a/docs/structures_Reaction.js.html
+++ b/docs/structures_Reaction.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/Reaction.js
+ whatsapp-web.js 1.34.7 » Source: structures/Reaction.js
@@ -15,7 +15,7 @@
@@ -90,14 +90,13 @@ class Reaction extends Base {
* @type {?number}
*/
this.ack = data.ack;
-
-
+
return super._patch(data);
}
-
}
-module.exports = Reaction;
+module.exports = Reaction;
+
@@ -107,7 +106,7 @@ module.exports = Reaction;
diff --git a/docs/structures_ScheduledEvent.js.html b/docs/structures_ScheduledEvent.js.html
index 35544aa..7b7a9d4 100644
--- a/docs/structures_ScheduledEvent.js.html
+++ b/docs/structures_ScheduledEvent.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: structures/ScheduledEvent.js
+ whatsapp-web.js 1.34.7 » Source: structures/ScheduledEvent.js
@@ -15,7 +15,7 @@
@@ -68,11 +68,13 @@ class ScheduledEvent {
*/
this.eventSendOptions = {
description: options.description?.trim(),
- endTimeTs: options.endTime ? Math.floor(options.endTime.getTime() / 1000) : null,
+ endTimeTs: options.endTime
+ ? Math.floor(options.endTime.getTime() / 1000)
+ : null,
location: options.location?.trim(),
callType: this._validateInputs('callType', options.callType),
isEventCanceled: options.isEventCanceled ?? false,
- messageSecret: options.messageSecret
+ messageSecret: options.messageSecret,
};
}
@@ -84,17 +86,27 @@ class ScheduledEvent {
*/
_validateInputs(propName, propValue) {
if (propName === 'name' && !propValue) {
- throw new class CreateScheduledEventError extends Error {
- constructor(m) { super(m); }
- }(`Empty '${propName}' parameter value is provided.`);
+ throw new (class CreateScheduledEventError extends Error {
+ constructor(m) {
+ super(m);
+ }
+ })(`Empty '${propName}' parameter value is provided.`);
}
- if (propName === 'callType' && propValue && !['video', 'voice', 'none'].includes(propValue)) {
- throw new class CreateScheduledEventError extends Error {
- constructor(m) { super(m); }
- }(`Invalid '${propName}' parameter value is provided. Valid values are: 'voice' | 'video' | 'none'.`);
+ if (
+ propName === 'callType' &&
+ propValue &&
+ !['video', 'voice', 'none'].includes(propValue)
+ ) {
+ throw new (class CreateScheduledEventError extends Error {
+ constructor(m) {
+ super(m);
+ }
+ })(
+ `Invalid '${propName}' parameter value is provided. Valid values are: 'voice' | 'video' | 'none'.`,
+ );
}
-
+
return propValue;
}
}
@@ -110,7 +122,7 @@ module.exports = ScheduledEvent;
diff --git a/docs/util_Constants.js.html b/docs/util_Constants.js.html
index ed92558..b31ac90 100644
--- a/docs/util_Constants.js.html
+++ b/docs/util_Constants.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: util/Constants.js
+ whatsapp-web.js 1.34.7 » Source: util/Constants.js
@@ -15,7 +15,7 @@
@@ -36,7 +36,7 @@ exports.WhatsWebURL = 'https://web.whatsapp.com/';
exports.DefaultOptions = {
puppeteer: {
headless: true,
- defaultViewport: null
+ defaultViewport: null,
},
webVersion: '2.3000.1017054665',
webVersionCache: {
@@ -46,7 +46,8 @@ exports.DefaultOptions = {
qrMaxRetries: 0,
takeoverOnConflict: false,
takeoverTimeoutMs: 0,
- userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36',
+ userAgent:
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36',
ffmpegPath: 'ffmpeg',
bypassCSP: false,
proxyAuthentication: undefined,
@@ -65,7 +66,7 @@ exports.DefaultOptions = {
exports.Status = {
INITIALIZING: 0,
AUTHENTICATING: 1,
- READY: 3
+ READY: 3,
};
/**
@@ -81,6 +82,7 @@ exports.Events = {
CHAT_ARCHIVED: 'chat_archived',
MESSAGE_RECEIVED: 'message',
MESSAGE_CIPHERTEXT: 'message_ciphertext',
+ MESSAGE_CIPHERTEXT_FAILED: 'message_ciphertext_failed',
MESSAGE_CREATE: 'message_create',
MESSAGE_REVOKED_EVERYONE: 'message_revoke_everyone',
MESSAGE_REVOKED_ME: 'message_revoke_me',
@@ -103,7 +105,7 @@ exports.Events = {
BATTERY_CHANGED: 'change_battery',
INCOMING_CALL: 'call',
REMOTE_SESSION_SAVED: 'remote_session_saved',
- VOTE_UPDATE: 'vote_update'
+ VOTE_UPDATE: 'vote_update',
};
/**
@@ -179,7 +181,7 @@ exports.GroupNotificationTypes = {
exports.ChatTypes = {
SOLO: 'solo',
GROUP: 'group',
- UNKNOWN: 'unknown'
+ UNKNOWN: 'unknown',
};
/**
@@ -199,7 +201,7 @@ exports.WAState = {
TOS_BLOCK: 'TOS_BLOCK',
UNLAUNCHED: 'UNLAUNCHED',
UNPAIRED: 'UNPAIRED',
- UNPAIRED_IDLE: 'UNPAIRED_IDLE'
+ UNPAIRED_IDLE: 'UNPAIRED_IDLE',
};
/**
@@ -225,7 +227,7 @@ exports.MessageAck = {
diff --git a/docs/util_Injected_Utils.js.html b/docs/util_Injected_Utils.js.html
index 73e2c99..32fecae 100644
--- a/docs/util_Injected_Utils.js.html
+++ b/docs/util_Injected_Utils.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.28.1-alpha.0 » Source: util/Injected/Utils.js
+ whatsapp-web.js 1.34.7 » Source: util/Injected/Utils.js
@@ -15,7 +15,7 @@
@@ -34,78 +34,209 @@
exports.LoadUtils = () => {
window.WWebJS = {};
- window.WWebJS.forwardMessage = async (chatId, msgId) => {
- const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
- let chat = window.Store.Chat.get(chatId);
-
- if (window.compareWwebVersions(window.Debug.VERSION, '>', '2.3000.0')) {
- return window.Store.ForwardUtils.forwardMessagesToChats([msg], [chat], true);
- } else {
- return chat.forwardMessages([msg]);
+ /**
+ * Helper function that compares between two WWeb versions. Its purpose is to help the developer to choose the correct code implementation depending on the comparison value and the WWeb version.
+ * @param {string} lOperand The left operand for the WWeb version string to compare with
+ * @param {string} operator The comparison operator
+ * @param {string} rOperand The right operand for the WWeb version string to compare with
+ * @returns {boolean} Boolean value that indicates the result of the comparison
+ */
+ window.WWebJS.compareWwebVersions = (lOperand, operator, rOperand) => {
+ if (!['>', '>=', '<', '<=', '='].includes(operator)) {
+ throw new (class _ extends Error {
+ constructor(m) {
+ super(m);
+ this.name = 'CompareWwebVersionsError';
+ }
+ })('Invalid comparison operator is provided');
}
+ if (typeof lOperand !== 'string' || typeof rOperand !== 'string') {
+ throw new (class _ extends Error {
+ constructor(m) {
+ super(m);
+ this.name = 'CompareWwebVersionsError';
+ }
+ })('A non-string WWeb version type is provided');
+ }
+
+ lOperand = lOperand.replace(/-beta$/, '');
+ rOperand = rOperand.replace(/-beta$/, '');
+
+ while (lOperand.length !== rOperand.length) {
+ lOperand.length > rOperand.length
+ ? (rOperand = rOperand.concat('0'))
+ : (lOperand = lOperand.concat('0'));
+ }
+
+ lOperand = Number(lOperand.replace(/\./g, ''));
+ rOperand = Number(rOperand.replace(/\./g, ''));
+
+ return operator === '>'
+ ? lOperand > rOperand
+ : operator === '>='
+ ? lOperand >= rOperand
+ : operator === '<'
+ ? lOperand < rOperand
+ : operator === '<='
+ ? lOperand <= rOperand
+ : operator === '='
+ ? lOperand === rOperand
+ : false;
+ };
+
+ /**
+ * Target options object description
+ * @typedef {Object} TargetOptions
+ * @property {string|number} module The target module
+ * @property {string} function The function name to get from a module
+ */
+ /**
+ * Function to modify functions
+ * @param {TargetOptions} target Options specifying the target function to search for modifying
+ * @param {Function} callback Modified function
+ */
+ window.WWebJS.injectToFunction = (target, callback) => {
+ try {
+ let module = window.require(target.module);
+ if (!module) return;
+
+ const path = target.function.split('.');
+ const funcName = path.pop();
+
+ for (const key of path) {
+ if (!module[key]) return;
+ module = module[key];
+ }
+
+ const originalFunction = module[funcName];
+ if (typeof originalFunction !== 'function') return;
+
+ module[funcName] = ((...args) => {
+ try {
+ return callback(module, originalFunction, ...args);
+ } catch {
+ return originalFunction.apply(module, args);
+ }
+ }).bind(module);
+ } catch {
+ return;
+ }
+ };
+
+ window.WWebJS.injectToFunction(
+ { module: 'WAWebBackendJobsCommon', function: 'mediaTypeFromProtobuf' },
+ (module, func, ...args) => {
+ const [proto] = args;
+ return proto.locationMessage ? null : func(...args);
+ },
+ );
+
+ window.WWebJS.injectToFunction(
+ { module: 'WAWebE2EProtoUtils', function: 'typeAttributeFromProtobuf' },
+ (module, func, ...args) => {
+ const [proto] = args;
+ return proto.locationMessage || proto.groupInviteMessage
+ ? 'text'
+ : func(...args);
+ },
+ );
+
+ window.WWebJS.forwardMessage = async (chatId, msgId) => {
+ const msg =
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
+ const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
+ return await window.require('WAWebChatForwardMessage').forwardMessages({
+ chat: chat,
+ msgs: [msg],
+ multicast: true,
+ includeCaption: true,
+ appendedText: undefined,
+ });
};
window.WWebJS.sendSeen = async (chatId) => {
- let chat = window.Store.Chat.get(chatId);
- if (chat !== undefined) {
- await window.Store.SendSeen.sendSeen(chat, false);
+ const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
+ if (chat) {
+ window.require('WAWebStreamModel').Stream.markAvailable();
+ await window.require('WAWebUpdateUnreadChatAction').sendSeen({
+ chat: chat,
+ threadId: undefined,
+ });
+ window.require('WAWebStreamModel').Stream.markUnavailable();
return true;
}
return false;
-
};
window.WWebJS.sendMessage = async (chat, content, options = {}) => {
- let attOptions = {};
- if (options.attachment) {
- attOptions = options.sendMediaAsSticker
- ? await window.WWebJS.processStickerData(options.attachment)
- : await window.WWebJS.processMediaData(options.attachment, {
- forceVoice: options.sendAudioAsVoice,
- forceDocument: options.sendMediaAsDocument,
- forceGif: options.sendVideoAsGif
- });
-
- attOptions.caption = options.caption;
- content = options.sendMediaAsSticker ? undefined : attOptions.preview;
- attOptions.isViewOnce = options.isViewOnce;
+ const { getIsNewsletter, getIsBroadcast } =
+ window.require('WAWebChatGetters');
+ const isChannel = getIsNewsletter(chat);
+ const isStatus = getIsBroadcast(chat);
- delete options.attachment;
+ const { findLink } = window.require('WALinkify');
+
+ let mediaOptions = {};
+ if (options.media) {
+ mediaOptions =
+ options.sendMediaAsSticker && !isChannel && !isStatus
+ ? await window.WWebJS.processStickerData(options.media)
+ : await window.WWebJS.processMediaData(options.media, {
+ forceSticker: options.sendMediaAsSticker,
+ forceGif: options.sendVideoAsGif,
+ forceVoice: options.sendAudioAsVoice,
+ forceDocument: options.sendMediaAsDocument,
+ forceMediaHd: options.sendMediaAsHd,
+ sendToChannel: isChannel,
+ sendToStatus: isStatus,
+ });
+ mediaOptions.caption = options.caption;
+ content = options.sendMediaAsSticker
+ ? undefined
+ : mediaOptions.preview;
+ mediaOptions.isViewOnce = options.isViewOnce;
+ delete options.media;
delete options.sendMediaAsSticker;
}
+
let quotedMsgOptions = {};
if (options.quotedMessageId) {
- let quotedMessage = await window.Store.Msg.getMessagesById([options.quotedMessageId]);
-
- if (quotedMessage['messages'].length == 1) {
- quotedMessage = quotedMessage['messages'][0];
-
- // TODO remove .canReply() once all clients are updated to >= v2.2241.6
- const canReply = window.Store.ReplyUtils ?
- window.Store.ReplyUtils.canReplyMsg(quotedMessage.unsafe()) :
- quotedMessage.canReply();
+ let quotedMessage = window
+ .require('WAWebCollections')
+ .Msg.get(options.quotedMessageId);
+ !quotedMessage &&
+ (quotedMessage = (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([options.quotedMessageId])
+ )?.messages?.[0]);
+ if (quotedMessage) {
+ const ReplyUtils = window.require('WAWebMsgReply');
+ const canReply = ReplyUtils
+ ? ReplyUtils.canReplyMsg(quotedMessage.unsafe())
+ : quotedMessage.canReply();
if (canReply) {
quotedMsgOptions = quotedMessage.msgContextInfo(chat);
}
- }else{
- if(!options.ignoreQuoteErrors) {
+ } else {
+ if (!options.ignoreQuoteErrors) {
throw new Error('Could not get the quoted message.');
}
}
-
+
delete options.ignoreQuoteErrors;
delete options.quotedMessageId;
}
if (options.mentionedJidList) {
- options.mentionedJidList = await Promise.all(
- options.mentionedJidList.map(async (id) => {
- const wid = window.Store.WidFactory.createWid(id);
- if (await window.Store.QueryExist(wid)) {
- return wid;
- }
- })
+ options.mentionedJidList = options.mentionedJidList.map((id) =>
+ window.require('WAWebWidFactory').createWid(id),
);
options.mentionedJidList = options.mentionedJidList.filter(Boolean);
}
@@ -113,124 +244,189 @@ exports.LoadUtils = () => {
if (options.groupMentions) {
options.groupMentions = options.groupMentions.map((e) => ({
groupSubject: e.subject,
- groupJid: window.Store.WidFactory.createWid(e.id)
+ groupJid: window.require('WAWebWidFactory').createWid(e.id),
}));
}
let locationOptions = {};
if (options.location) {
let { latitude, longitude, description, url } = options.location;
- url = window.Store.Validators.findLink(url)?.href;
+ url = findLink(url)?.href;
url && !description && (description = url);
locationOptions = {
type: 'location',
loc: description,
lat: latitude,
lng: longitude,
- clientUrl: url
+ clientUrl: url,
};
delete options.location;
}
- let _pollOptions = {};
+ let pollOptions = {};
if (options.poll) {
- const { pollName, pollOptions } = options.poll;
- const { allowMultipleAnswers, messageSecret } = options.poll.options;
- _pollOptions = {
+ const { pollName, pollOptions: _pollOptions } = options.poll;
+ const { allowMultipleAnswers, messageSecret } =
+ options.poll.options;
+ pollOptions = {
+ kind: 'pollCreation',
type: 'poll_creation',
pollName: pollName,
- pollOptions: pollOptions,
+ pollOptions: _pollOptions,
pollSelectableOptionsCount: allowMultipleAnswers ? 0 : 1,
messageSecret:
- Array.isArray(messageSecret) && messageSecret.length === 32
- ? new Uint8Array(messageSecret)
- : window.crypto.getRandomValues(new Uint8Array(32))
+ Array.isArray(messageSecret) && messageSecret.length === 32
+ ? new Uint8Array(messageSecret)
+ : window.crypto.getRandomValues(new Uint8Array(32)),
};
delete options.poll;
}
+ let eventOptions = {};
+ if (options.event) {
+ const { name, startTimeTs, eventSendOptions } = options.event;
+ const { messageSecret } = eventSendOptions;
+ eventOptions = {
+ type: 'event_creation',
+ eventName: name,
+ eventDescription: eventSendOptions.description,
+ eventStartTime: startTimeTs,
+ eventEndTime: eventSendOptions.endTimeTs,
+ eventLocation: eventSendOptions.location && {
+ degreesLatitude: 0,
+ degreesLongitude: 0,
+ name: eventSendOptions.location,
+ },
+ eventJoinLink:
+ eventSendOptions.callType === 'none'
+ ? null
+ : await window
+ .require('WAWebGenerateEventCallLink')
+ .createEventCallLink(
+ startTimeTs,
+ eventSendOptions.callType,
+ ),
+ isEventCanceled: eventSendOptions.isEventCanceled,
+ messageSecret:
+ Array.isArray(messageSecret) && messageSecret.length === 32
+ ? new Uint8Array(messageSecret)
+ : window.crypto.getRandomValues(new Uint8Array(32)),
+ };
+ delete options.event;
+ }
+
let vcardOptions = {};
if (options.contactCard) {
- let contact = window.Store.Contact.get(options.contactCard);
+ let contact = await window
+ .require('WAWebCollections')
+ .Contact.find(options.contactCard);
vcardOptions = {
- body: window.Store.VCard.vcardFromContactModel(contact).vcard,
+ body: window
+ .require('WAWebFrontendVcardUtils')
+ .vcardFromContactModel(contact).vcard,
type: 'vcard',
- vcardFormattedName: contact.formattedName
+ vcardFormattedName: contact.formattedName,
};
delete options.contactCard;
} else if (options.contactCardList) {
- let contacts = options.contactCardList.map(c => window.Store.Contact.get(c));
- let vcards = contacts.map(c => window.Store.VCard.vcardFromContactModel(c));
+ let contacts = await Promise.all(
+ options.contactCardList.map((c) =>
+ window.require('WAWebCollections').Contact.find(c),
+ ),
+ );
+ let vcards = contacts.map((c) =>
+ window
+ .require('WAWebFrontendVcardUtils')
+ .vcardFromContactModel(c),
+ );
vcardOptions = {
type: 'multi_vcard',
vcardList: vcards,
- body: undefined
+ body: null,
};
delete options.contactCardList;
- } else if (options.parseVCards && typeof (content) === 'string' && content.startsWith('BEGIN:VCARD')) {
+ } else if (
+ options.parseVCards &&
+ typeof content === 'string' &&
+ content.startsWith('BEGIN:VCARD')
+ ) {
delete options.parseVCards;
+ delete options.linkPreview;
try {
- const parsed = window.Store.VCard.parseVcard(content);
+ const parsed = window
+ .require('WAWebVcardParsingUtils')
+ .parseVcard(content);
if (parsed) {
vcardOptions = {
type: 'vcard',
- vcardFormattedName: window.Store.VCard.vcardGetNameFromParsed(parsed)
+ vcardFormattedName: window
+ .require('WAWebVcardGetNameFromParsed')
+ .vcardGetNameFromParsed(parsed),
};
}
- } catch (_) {
+ } catch (ignoredError) {
// not a vcard
}
}
if (options.linkPreview) {
delete options.linkPreview;
- const link = window.Store.Validators.findLink(content);
+ const link = findLink(content);
if (link) {
- let preview = await window.Store.LinkPreview.getLinkPreview(link);
+ let preview = await window
+ .require('WAWebLinkPreviewChatAction')
+ .getLinkPreview(link);
if (preview && preview.data) {
preview = preview.data;
preview.preview = true;
preview.subtype = 'url';
- options = {...options, ...preview};
+ options = { ...options, ...preview };
}
}
}
-
+
let buttonOptions = {};
- if(options.buttons){
+ if (options.buttons) {
let caption;
if (options.buttons.type === 'chat') {
content = options.buttons.body;
caption = content;
} else {
- caption = options.caption ? options.caption : ' '; //Caption can't be empty
+ caption = options.caption ? options.caption : ' '; // Caption can't be empty
}
buttonOptions = {
productHeaderImageRejected: false,
isFromTemplate: false,
isDynamicReplyButtonsMsg: true,
- title: options.buttons.title ? options.buttons.title : undefined,
- footer: options.buttons.footer ? options.buttons.footer : undefined,
+ title: options.buttons.title
+ ? options.buttons.title
+ : undefined,
+ footer: options.buttons.footer
+ ? options.buttons.footer
+ : undefined,
dynamicReplyButtons: options.buttons.buttons,
replyButtons: options.buttons.buttons,
- caption: caption
+ caption: caption,
};
delete options.buttons;
}
let listOptions = {};
if (options.list) {
- if (window.Store.Conn.platform === 'smba' || window.Store.Conn.platform === 'smbi') {
- throw '[LT01] Whatsapp business can\'t send this yet';
+ if (
+ window.require('WAWebConnModel').Conn.platform === 'smba' ||
+ window.require('WAWebConnModel').Conn.platform === 'smbi'
+ ) {
+ throw "[LT01] Whatsapp business can't send this yet";
}
listOptions = {
type: 'list',
footer: options.list.footer,
list: {
...options.list,
- listType: 1
+ listType: 1,
},
- body: options.list.description
+ body: options.list.description,
};
delete options.list;
delete listOptions.list.footer;
@@ -238,39 +434,66 @@ exports.LoadUtils = () => {
const botOptions = {};
if (options.invokedBotWid) {
- botOptions.messageSecret = window.crypto.getRandomValues(new Uint8Array(32));
- botOptions.botMessageSecret = await window.Store.BotSecret.genBotMsgSecretFromMsgSecret(botOptions.messageSecret);
- botOptions.invokedBotWid = window.Store.WidFactory.createWid(options.invokedBotWid);
- botOptions.botPersonaId = window.Store.BotProfiles.BotProfileCollection.get(options.invokedBotWid).personaId;
+ botOptions.messageSecret = window.crypto.getRandomValues(
+ new Uint8Array(32),
+ );
+ botOptions.botMessageSecret = await window
+ .require('WAWebBotMessageSecret')
+ .genBotMsgSecretFromMsgSecret(botOptions.messageSecret);
+ botOptions.invokedBotWid = window
+ .require('WAWebWidFactory')
+ .createWid(options.invokedBotWid);
+ botOptions.botPersonaId = window
+ .require('WAWebBotProfileCollection')
+ .BotProfileCollection.get(options.invokedBotWid).personaId;
delete options.invokedBotWid;
}
+ const { getMaybeMeLidUser, getMaybeMePnUser } = window.require(
+ 'WAWebUserPrefsMeUser',
+ );
+ const lidUser = getMaybeMeLidUser();
+ const meUser = getMaybeMePnUser();
+ const newId = await window.require('WAWebMsgKey').newId();
+ let from = chat.id.isLid() ? lidUser : meUser;
+ let participant;
- let meUser = window.Store.User.getMaybeMeUser();
- const newId = await window.Store.MsgKey.newId();
-
- if (chat.id.isGroup() && chat.groupMetadata.isLidAddressingMode) {
- meUser = window.Store.User.getMaybeMeLidUser();
+ if (typeof chat.id?.isGroup === 'function' && chat.id.isGroup()) {
+ from =
+ chat.groupMetadata && chat.groupMetadata.isLidAddressingMode
+ ? lidUser
+ : meUser;
+ participant = window
+ .require('WAWebWidFactory')
+ .asUserWidOrThrow(from);
}
-
- const newMsgId = new window.Store.MsgKey({
- from: meUser,
+
+ if (typeof chat.id?.isStatus === 'function' && chat.id.isStatus()) {
+ participant = window
+ .require('WAWebWidFactory')
+ .asUserWidOrThrow(from);
+ }
+
+ const newMsgKey = new (window.require('WAWebMsgKey'))({
+ from: from,
to: chat.id,
id: newId,
- participant: chat.id.isGroup() ? meUser : undefined,
+ participant: participant,
selfDir: 'out',
});
const extraOptions = options.extraOptions || {};
delete options.extraOptions;
- const ephemeralFields = window.Store.EphemeralFields.getEphemeralFields(chat);
+ const ephemeralFields = window
+ .require('WAWebGetEphemeralFieldsMsgActionsUtils')
+ .getEphemeralFields(chat);
const message = {
...options,
- id: newMsgId,
+ id: newMsgKey,
ack: 0,
body: content,
- from: meUser,
+ from: from,
to: chat.id,
local: true,
self: 'out',
@@ -278,40 +501,128 @@ exports.LoadUtils = () => {
isNewMsg: true,
type: 'chat',
...ephemeralFields,
- ...locationOptions,
- ..._pollOptions,
- ...attOptions,
- ...(attOptions.toJSON ? attOptions.toJSON() : {}),
+ ...mediaOptions,
+ ...(mediaOptions.toJSON ? mediaOptions.toJSON() : {}),
...quotedMsgOptions,
+ ...locationOptions,
+ ...pollOptions,
+ ...eventOptions,
...vcardOptions,
...buttonOptions,
...listOptions,
...botOptions,
- ...extraOptions
+ ...extraOptions,
};
-
+
// Bot's won't reply if canonicalUrl is set (linking)
if (botOptions) {
delete message.canonicalUrl;
}
- await window.Store.SendMessage.addAndSendMsgToChat(chat, message);
- return window.Store.Msg.get(newMsgId._serialized);
- };
-
- window.WWebJS.editMessage = async (msg, content, options = {}) => {
+ if (isChannel) {
+ const msg = new (window.require('WAWebCollections').Msg.modelClass)(
+ message,
+ );
+ const msgDataFromMsgModel = window
+ .require('WAWebMsgDataFromModel')
+ .msgDataFromMsgModel(msg);
+ const isMedia = Object.keys(mediaOptions).length > 0;
+ await window
+ .require('WAWebNewsletterUpdateMsgsRecordsJob')
+ .addNewsletterMsgsRecords([msgDataFromMsgModel]);
+ chat.msgs.add(msg);
+ chat.t = msg.t;
+ const sendChannelMsgResponse = await window
+ .require('WAWebNewsletterSendMessageJob')
+ .sendNewsletterMessageJob({
+ msg: msg,
+ type:
+ message.type === 'chat'
+ ? 'text'
+ : isMedia
+ ? 'media'
+ : 'pollCreation',
+ newsletterJid: chat.id.toJid(),
+ ...(isMedia
+ ? {
+ mediaMetadata: msg.avParams(),
+ mediaHandle: isMedia
+ ? mediaOptions.mediaHandle
+ : null,
+ }
+ : {}),
+ });
+
+ if (sendChannelMsgResponse.success) {
+ msg.t = sendChannelMsgResponse.ack.t;
+ msg.serverId = sendChannelMsgResponse.serverId;
+ }
+ msg.updateAck(1, true);
+ await window
+ .require('WAWebNewsletterUpdateMsgsRecordsJob')
+ .updateNewsletterMsgRecord(msg);
+ return msg;
+ }
+
+ if (isStatus) {
+ const { backgroundColor, fontStyle } = extraOptions;
+ const isMedia = Object.keys(mediaOptions).length > 0;
+ const mediaUpdate = (data) =>
+ window.require('WAWebMediaUpdateMsg')(data, mediaOptions);
+ const msg = new (window.require('WAWebCollections').Msg.modelClass)(
+ {
+ ...message,
+ author: participant ? participant : null,
+ messageSecret: window.crypto.getRandomValues(
+ new Uint8Array(32),
+ ),
+ cannotBeRanked: window
+ .require('WAWebStatusGatingUtils')
+ .canCheckStatusRankingPosterGating(),
+ },
+ );
+
+ // for text only
+ const statusOptions = {
+ color:
+ (backgroundColor &&
+ window.WWebJS.assertColor(backgroundColor)) ||
+ 0xff7acca5,
+ font: (fontStyle >= 0 && fontStyle <= 7 && fontStyle) || 0,
+ text: msg.body,
+ };
+
+ await window
+ .require('WAWebSendStatusMsgAction')
+ [
+ isMedia
+ ? 'sendStatusMediaMsgAction'
+ : 'sendStatusTextMsgAction'
+ ](...(isMedia ? [msg, mediaUpdate] : [statusOptions]));
+
+ return msg;
+ }
+
+ const [msgPromise, sendMsgResultPromise] = window
+ .require('WAWebSendMsgChatAction')
+ .addAndSendMsgToChat(chat, message);
+ await msgPromise;
+
+ if (options.waitUntilMsgSent) await sendMsgResultPromise;
+
+ return window
+ .require('WAWebCollections')
+ .Msg.get(newMsgKey._serialized);
+ };
+
+ window.WWebJS.editMessage = async (msg, content, options = {}) => {
const extraOptions = options.extraOptions || {};
delete options.extraOptions;
-
+
if (options.mentionedJidList) {
- options.mentionedJidList = await Promise.all(
- options.mentionedJidList.map(async (id) => {
- const wid = window.Store.WidFactory.createWid(id);
- if (await window.Store.QueryExist(wid)) {
- return wid;
- }
- })
+ options.mentionedJidList = options.mentionedJidList.map((id) =>
+ window.require('WAWebWidFactory').createWid(id),
);
options.mentionedJidList = options.mentionedJidList.filter(Boolean);
}
@@ -319,59 +630,73 @@ exports.LoadUtils = () => {
if (options.groupMentions) {
options.groupMentions = options.groupMentions.map((e) => ({
groupSubject: e.subject,
- groupJid: window.Store.WidFactory.createWid(e.id)
+ groupJid: window.require('WAWebWidFactory').createWid(e.id),
}));
}
if (options.linkPreview) {
+ const { findLink } = window.require('WALinkify');
delete options.linkPreview;
- const link = window.Store.Validators.findLink(content);
+ const link = findLink(content);
if (link) {
- const preview = await window.Store.LinkPreview.getLinkPreview(link);
+ const preview = await window
+ .require('WAWebLinkPreviewChatAction')
+ .getLinkPreview(link);
preview.preview = true;
preview.subtype = 'url';
options = { ...options, ...preview };
}
}
-
const internalOptions = {
...options,
- ...extraOptions
+ ...extraOptions,
};
- await window.Store.EditMessage.sendMessageEdit(msg, content, internalOptions);
- return window.Store.Msg.get(msg.id._serialized);
+ await window
+ .require('WAWebSendMessageEditAction')
+ .sendMessageEdit(msg, content, internalOptions);
+ return window.require('WAWebCollections').Msg.get(msg.id._serialized);
};
window.WWebJS.toStickerData = async (mediaInfo) => {
if (mediaInfo.mimetype == 'image/webp') return mediaInfo;
const file = window.WWebJS.mediaInfoToFile(mediaInfo);
- const webpSticker = await window.Store.StickerTools.toWebpSticker(file);
+ const webpSticker = await window
+ .require('WAWebImageUtils')
+ .toWebpSticker(file);
const webpBuffer = await webpSticker.arrayBuffer();
const data = window.WWebJS.arrayBufferToBase64(webpBuffer);
return {
mimetype: 'image/webp',
- data
+ data,
};
};
window.WWebJS.processStickerData = async (mediaInfo) => {
- if (mediaInfo.mimetype !== 'image/webp') throw new Error('Invalid media type');
+ if (mediaInfo.mimetype !== 'image/webp')
+ throw new Error('Invalid media type');
const file = window.WWebJS.mediaInfoToFile(mediaInfo);
let filehash = await window.WWebJS.getFileHash(file);
let mediaKey = await window.WWebJS.generateHash(32);
const controller = new AbortController();
- const uploadedInfo = await window.Store.UploadUtils.encryptAndUpload({
- blob: file,
- type: 'sticker',
- signal: controller.signal,
- mediaKey
- });
+ const uploadedInfo = await window
+ .require('WAWebUploadManager')
+ .encryptAndUpload({
+ blob: file,
+ type: 'sticker',
+ signal: controller.signal,
+ mediaKey,
+ uploadQpl: window
+ .require('WAWebStartMediaUploadQpl')
+ .startMediaUploadQpl({
+ entryPoint: 'MediaUpload',
+ }),
+ });
const stickerInfo = {
...uploadedInfo,
@@ -380,52 +705,108 @@ exports.LoadUtils = () => {
uploadhash: uploadedInfo.encFilehash,
size: file.size,
type: 'sticker',
- filehash
+ filehash,
};
return stickerInfo;
};
- window.WWebJS.processMediaData = async (mediaInfo, { forceVoice, forceDocument, forceGif }) => {
+ window.WWebJS.processMediaData = async (
+ mediaInfo,
+ {
+ forceSticker,
+ forceGif,
+ forceVoice,
+ forceDocument,
+ forceMediaHd,
+ sendToChannel,
+ sendToStatus,
+ },
+ ) => {
const file = window.WWebJS.mediaInfoToFile(mediaInfo);
- const mData = await window.Store.OpaqueData.createFromData(file, file.type);
- const mediaPrep = window.Store.MediaPrep.prepRawMedia(mData, { asDocument: forceDocument });
- const mediaData = await mediaPrep.waitForPrep();
- const mediaObject = window.Store.MediaObject.getOrCreateMediaObject(mediaData.filehash);
+ const OpaqueData = window.require('WAWebMediaOpaqueData');
+ const opaqueData = await OpaqueData.createFromData(
+ file,
+ mediaInfo.mimetype,
+ );
+ const mediaParams = {
+ asSticker: forceSticker,
+ asGif: forceGif,
+ isPtt: forceVoice,
+ asDocument: forceDocument,
+ };
- const mediaType = window.Store.MediaTypes.msgToMediaType({
+ if (forceMediaHd && file.type.indexOf('image/') === 0) {
+ mediaParams.maxDimension = 2560;
+ }
+
+ const mediaPrep = window
+ .require('WAWebPrepRawMedia')
+ .prepRawMedia(opaqueData, mediaParams);
+ const mediaData = await mediaPrep.waitForPrep();
+ const mediaObject = window
+ .require('WAWebMediaStorage')
+ .getOrCreateMediaObject(mediaData.filehash);
+ const mediaType = window.require('WAWebMmsMediaTypes').msgToMediaType({
type: mediaData.type,
- isGif: mediaData.isGif
+ isGif: mediaData.isGif,
+ isNewsletter: sendToChannel,
});
- if (forceVoice && mediaData.type === 'audio') {
- mediaData.type = 'ptt';
+ if (!mediaData.filehash) {
+ throw new Error('media-fault: sendToChat filehash undefined');
+ }
+
+ if (
+ (forceVoice && mediaData.type === 'ptt') ||
+ (sendToStatus && mediaData.type === 'audio')
+ ) {
const waveform = mediaObject.contentInfo.waveform;
mediaData.waveform =
- waveform ?? await window.WWebJS.generateWaveform(file);
+ waveform || (await window.WWebJS.generateWaveform(file));
}
- if (forceGif && mediaData.type === 'video') {
- mediaData.isGif = true;
- }
-
- if (forceDocument) {
- mediaData.type = 'document';
- }
-
- if (!(mediaData.mediaBlob instanceof window.Store.OpaqueData)) {
- mediaData.mediaBlob = await window.Store.OpaqueData.createFromData(mediaData.mediaBlob, mediaData.mediaBlob.type);
+ if (!(mediaData.mediaBlob instanceof OpaqueData)) {
+ mediaData.mediaBlob = await OpaqueData.createFromData(
+ mediaData.mediaBlob,
+ mediaData.mediaBlob.type,
+ );
}
mediaData.renderableUrl = mediaData.mediaBlob.url();
mediaObject.consolidate(mediaData.toJSON());
- mediaData.mediaBlob.autorelease();
- const uploadedMedia = await window.Store.MediaUpload.uploadMedia({
+ mediaData.mediaBlob.autorelease();
+ const shouldUseMediaCache = window
+ .require('WAWebMediaDataUtils')
+ .shouldUseMediaCache(
+ window.require('WAWebMmsMediaTypes').castToV4(mediaObject.type),
+ );
+ if (shouldUseMediaCache && mediaData.mediaBlob instanceof OpaqueData) {
+ const formData = mediaData.mediaBlob.formData();
+ window
+ .require('WAWebMediaInMemoryBlobCache')
+ .InMemoryMediaBlobCache.put(mediaObject.filehash, formData);
+ }
+
+ const dataToUpload = {
mimetype: mediaData.mimetype,
mediaObject,
- mediaType
- });
+ mediaType,
+ ...(sendToChannel
+ ? {
+ calculateToken: window.require('WAMediaCalculateFilehash')
+ .getRandomFilehash,
+ }
+ : {}),
+ };
+
+ const { uploadMedia, uploadUnencryptedMedia } = window.require(
+ 'WAWebMediaMmsV4Upload',
+ );
+ const uploadedMedia = !sendToChannel
+ ? await uploadMedia(dataToUpload)
+ : await uploadUnencryptedMedia(dataToUpload);
const mediaEntry = uploadedMedia.mediaEntry;
if (!mediaEntry) {
@@ -443,34 +824,45 @@ exports.LoadUtils = () => {
uploadhash: mediaEntry.uploadHash,
size: mediaObject.size,
streamingSidecar: mediaEntry.sidecar,
- firstFrameSidecar: mediaEntry.firstFrameSidecar
+ firstFrameSidecar: mediaEntry.firstFrameSidecar,
+ mediaHandle: sendToChannel ? mediaEntry.handle : null,
});
return mediaData;
};
- window.WWebJS.getMessageModel = message => {
+ window.WWebJS.getMessageModel = (message) => {
const msg = message.serialize();
+ const { findLinks } = window.require('WALinkify');
+
msg.isEphemeral = message.isEphemeral;
msg.isStatusV3 = message.isStatusV3;
- msg.links = (window.Store.Validators.findLinks(message.mediaObject ? message.caption : message.body)).map((link) => ({
+ msg.links = findLinks(
+ message.mediaObject ? message.caption : message.body,
+ ).map((link) => ({
link: link.href,
- isSuspicious: Boolean(link.suspiciousCharacters && link.suspiciousCharacters.size)
+ isSuspicious: Boolean(
+ link.suspiciousCharacters && link.suspiciousCharacters.size,
+ ),
}));
if (msg.buttons) {
msg.buttons = msg.buttons.serialize();
}
if (msg.dynamicReplyButtons) {
- msg.dynamicReplyButtons = JSON.parse(JSON.stringify(msg.dynamicReplyButtons));
+ msg.dynamicReplyButtons = JSON.parse(
+ JSON.stringify(msg.dynamicReplyButtons),
+ );
}
if (msg.replyButtons) {
msg.replyButtons = JSON.parse(JSON.stringify(msg.replyButtons));
}
if (typeof msg.id.remote === 'object') {
- msg.id = Object.assign({}, msg.id, { remote: msg.id.remote._serialized });
+ msg.id = Object.assign({}, msg.id, {
+ remote: msg.id.remote._serialized,
+ });
}
delete msg.pendingAckUpdate;
@@ -478,127 +870,254 @@ exports.LoadUtils = () => {
return msg;
};
- window.WWebJS.getPollVoteModel = async (vote) => {
- const _vote = vote.serialize();
- if (!vote.parentMsgKey) return null;
- const msg =
- window.Store.Msg.get(vote.parentMsgKey) || (await window.Store.Msg.getMessagesById([vote.parentMsgKey]))?.messages?.[0];
- msg && (_vote.parentMessage = window.WWebJS.getMessageModel(msg));
- return _vote;
- };
+ window.WWebJS.getChat = async (chatId, { getAsModel = true } = {}) => {
+ const isChannel = /@\w*newsletter\b/.test(chatId);
+ const chatWid = window.require('WAWebWidFactory').createWid(chatId);
+ let chat;
- window.WWebJS.getChatModel = async chat => {
-
- let res = chat.serialize();
- res.isGroup = false;
- res.formattedTitle = chat.formattedTitle;
- res.isMuted = chat.mute?.expiration !== 0;
-
- if (chat.groupMetadata) {
- res.isGroup = true;
- const chatWid = window.Store.WidFactory.createWid((chat.id._serialized));
- await window.Store.GroupMetadata.update(chatWid);
- res.groupMetadata = chat.groupMetadata.serialize();
- res.isReadOnly = chat.groupMetadata.announce;
- }
-
- res.lastMessage = null;
- if (res.msgs && res.msgs.length) {
- const lastMessage = chat.lastReceivedKey
- ? window.Store.Msg.get(chat.lastReceivedKey._serialized) || (await window.Store.Msg.getMessagesById([chat.lastReceivedKey._serialized]))?.messages?.[0]
- : null;
- if (lastMessage) {
- res.lastMessage = window.WWebJS.getMessageModel(lastMessage);
+ if (isChannel) {
+ try {
+ chat = window
+ .require('WAWebCollections')
+ .WAWebNewsletterCollection.get(chatId);
+ if (!chat) {
+ await window
+ .require('WAWebLoadNewsletterPreviewChatAction')
+ .loadNewsletterPreviewChat(chatId);
+ chat = await window
+ .require('WAWebCollections')
+ .WAWebNewsletterCollection.find(chatWid);
+ }
+ } catch (ignoredError) {
+ chat = null;
}
+ } else {
+ chat =
+ window.require('WAWebCollections').Chat.get(chatWid) ||
+ (
+ await window
+ .require('WAWebFindChatAction')
+ .findOrCreateLatestChat(chatWid)
+ )?.chat;
}
-
- delete res.msgs;
- delete res.msgUnsyncedButtonReplyMsgs;
- delete res.unsyncedButtonReplies;
- return res;
+ return getAsModel && chat
+ ? await window.WWebJS.getChatModel(chat, { isChannel: isChannel })
+ : chat;
};
- window.WWebJS.getChat = async chatId => {
- const chatWid = window.Store.WidFactory.createWid(chatId);
- const chat = await window.Store.Chat.find(chatWid);
- return await window.WWebJS.getChatModel(chat);
+ window.WWebJS.getChannelMetadata = async (inviteCode) => {
+ const role = window
+ .require('WAWebNewsletterModelUtils')
+ .getRoleByIdentifier(inviteCode);
+ const response = await window
+ .require('WAWebNewsletterMetadataQueryJob')
+ .queryNewsletterMetadataByInviteCode(inviteCode, role);
+
+ const picUrl =
+ response.newsletterPictureMetadataMixin?.picture[0]
+ ?.queryPictureDirectPathOrEmptyResponseMixinGroup.value
+ .directPath;
+
+ return {
+ id: response.idJid,
+ createdAtTs:
+ response.newsletterCreationTimeMetadataMixin.creationTimeValue,
+ titleMetadata: {
+ title: response.newsletterNameMetadataMixin.nameElementValue,
+ updatedAtTs:
+ response.newsletterNameMetadataMixin.nameUpdateTime,
+ },
+ descriptionMetadata: {
+ description:
+ response.newsletterDescriptionMetadataMixin
+ .descriptionQueryDescriptionResponseMixin.elementValue,
+ updatedAtTs:
+ response.newsletterDescriptionMetadataMixin
+ .descriptionQueryDescriptionResponseMixin.updateTime,
+ },
+ inviteLink: `https://whatsapp.com/channel/${response.newsletterInviteLinkMetadataMixin.inviteCode}`,
+ membershipType: role,
+ stateType: response.newsletterStateMetadataMixin.stateType,
+ pictureUrl: picUrl ? `https://pps.whatsapp.net${picUrl}` : null,
+ subscribersCount:
+ response.newsletterSubscribersMetadataMixin.subscribersCount,
+ isVerified:
+ response.newsletterVerificationMetadataMixin
+ .verificationState === 'verified',
+ };
};
window.WWebJS.getChats = async () => {
- const chats = window.Store.Chat.getModelsArray();
-
- const chatPromises = chats.map(chat => window.WWebJS.getChatModel(chat));
+ const chats = window.require('WAWebCollections').Chat.getModelsArray();
+ const chatPromises = chats.map((chat) =>
+ window.WWebJS.getChatModel(chat),
+ );
return await Promise.all(chatPromises);
};
- window.WWebJS.getContactModel = contact => {
+ window.WWebJS.getChannels = async () => {
+ const channels = window
+ .require('WAWebCollections')
+ .WAWebNewsletterCollection.getModelsArray();
+ const channelPromises = channels?.map((channel) =>
+ window.WWebJS.getChatModel(channel, { isChannel: true }),
+ );
+ return await Promise.all(channelPromises);
+ };
+
+ window.WWebJS.getChatModel = async (chat, { isChannel = false } = {}) => {
+ if (!chat) return null;
+
+ const model = chat.serialize();
+ model.isGroup = false;
+ model.isMuted = chat.mute?.expiration !== 0;
+ if (isChannel) {
+ model.isChannel = window
+ .require('WAWebChatGetters')
+ .getIsNewsletter(chat);
+ } else {
+ model.formattedTitle = chat.formattedTitle;
+ }
+
+ if (chat.groupMetadata) {
+ model.isGroup = true;
+ const chatWid = window
+ .require('WAWebWidFactory')
+ .createWid(chat.id._serialized);
+ const groupMetadata =
+ window.require('WAWebCollections').GroupMetadata ||
+ window.require('WAWebCollections').WAWebGroupMetadataCollection;
+ await groupMetadata.update(chatWid);
+ const { toPn } = window.require('WAWebLidMigrationUtils');
+ const serializedMetadata = chat.groupMetadata.serialize();
+ for (const p of serializedMetadata.participants || []) {
+ p.id = toPn(p.id) ?? p.id;
+ }
+ model.groupMetadata = serializedMetadata;
+ model.isReadOnly = chat.groupMetadata.announce;
+ }
+
+ if (chat.newsletterMetadata) {
+ const newsletterMetadata =
+ window.require('WAWebCollections')
+ .NewsletterMetadataCollection ||
+ window.require('WAWebCollections')
+ .WAWebNewsletterMetadataCollection;
+ await newsletterMetadata.update(chat.id);
+ model.channelMetadata = chat.newsletterMetadata.serialize();
+ model.channelMetadata.createdAtTs =
+ chat.newsletterMetadata.creationTime;
+ }
+
+ model.lastMessage = null;
+ if (model.msgs && model.msgs.length) {
+ const lastMessage = chat.lastReceivedKey
+ ? window
+ .require('WAWebCollections')
+ .Msg.get(chat.lastReceivedKey._serialized) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([
+ chat.lastReceivedKey._serialized,
+ ])
+ )?.messages?.[0]
+ : null;
+ lastMessage &&
+ (model.lastMessage =
+ window.WWebJS.getMessageModel(lastMessage));
+ }
+
+ delete model.msgs;
+ delete model.msgUnsyncedButtonReplyMsgs;
+ delete model.unsyncedButtonReplies;
+
+ return model;
+ };
+
+ window.WWebJS.getContactModel = (contact) => {
let res = contact.serialize();
- res.isBusiness = contact.isBusiness === undefined ? false : contact.isBusiness;
+
+ const wid = window
+ .require('WAWebWidFactory')
+ .createWidFromWidLike(contact.id);
+ if (wid.isLid() && contact.phoneNumber) {
+ res.id = contact.phoneNumber;
+ }
+
+ res.isBusiness =
+ contact.isBusiness === undefined ? false : contact.isBusiness;
if (contact.businessProfile) {
res.businessProfile = contact.businessProfile.serialize();
}
- // TODO: remove useOldImplementation and its checks once all clients are updated to >= v2.2327.4
- const useOldImplementation
- = window.compareWwebVersions(window.Debug.VERSION, '<', '2.2327.4');
-
- res.isMe = useOldImplementation
- ? contact.isMe
- : window.Store.ContactMethods.getIsMe(contact);
- res.isUser = useOldImplementation
- ? contact.isUser
- : window.Store.ContactMethods.getIsUser(contact);
- res.isGroup = useOldImplementation
- ? contact.isGroup
- : window.Store.ContactMethods.getIsGroup(contact);
- res.isWAContact = useOldImplementation
- ? contact.isWAContact
- : window.Store.ContactMethods.getIsWAContact(contact);
- res.isMyContact = useOldImplementation
- ? contact.isMyContact
- : window.Store.ContactMethods.getIsMyContact(contact);
res.isBlocked = contact.isContactBlocked;
- res.userid = useOldImplementation
- ? contact.userid
- : window.Store.ContactMethods.getUserid(contact);
- res.isEnterprise = useOldImplementation
- ? contact.isEnterprise
- : window.Store.ContactMethods.getIsEnterprise(contact);
- res.verifiedName = useOldImplementation
- ? contact.verifiedName
- : window.Store.ContactMethods.getVerifiedName(contact);
- res.verifiedLevel = useOldImplementation
- ? contact.verifiedLevel
- : window.Store.ContactMethods.getVerifiedLevel(contact);
- res.statusMute = useOldImplementation
- ? contact.statusMute
- : window.Store.ContactMethods.getStatusMute(contact);
- res.name = useOldImplementation
- ? contact.name
- : window.Store.ContactMethods.getName(contact);
- res.shortName = useOldImplementation
- ? contact.shortName
- : window.Store.ContactMethods.getShortName(contact);
- res.pushname = useOldImplementation
- ? contact.pushname
- : window.Store.ContactMethods.getPushname(contact);
+ if (!res.isBlocked) {
+ const alt = window
+ .require('WAWebApiContact')
+ .getAlternateUserWid(wid);
+ if (alt) {
+ res.isBlocked = !!window
+ .require('WAWebCollections')
+ .Blocklist.get(alt);
+ }
+ }
+
+ const ContactMethods = window.require('WAWebContactGetters');
+ res.isMe = ContactMethods.getIsMe(contact);
+ res.isUser = ContactMethods.getIsUser(contact);
+ res.isGroup = ContactMethods.getIsGroup(contact);
+ res.isWAContact = ContactMethods.getIsWAContact(contact);
+ res.userid = ContactMethods.getUserid(contact);
+ res.verifiedName = ContactMethods.getVerifiedName(contact);
+ res.verifiedLevel = ContactMethods.getVerifiedLevel(contact);
+ res.statusMute = ContactMethods.getStatusMute(contact);
+ res.name = ContactMethods.getName(contact);
+ res.shortName = ContactMethods.getShortName(contact);
+ res.pushname = ContactMethods.getPushname(contact);
+
+ const { getIsMyContact } = window.require(
+ 'WAWebFrontendContactGetters',
+ );
+ res.isMyContact = getIsMyContact(contact);
+ res.isEnterprise = ContactMethods.getIsEnterprise(contact);
return res;
};
- window.WWebJS.getContact = async contactId => {
- const wid = window.Store.WidFactory.createWid(contactId);
- const contact = await window.Store.Contact.find(wid);
- const bizProfile = await window.Store.BusinessProfile.fetchBizProfile(wid);
- bizProfile.profileOptions && (contact.businessProfile = bizProfile);
+ window.WWebJS.getContact = async (contactId) => {
+ const contactWid = window
+ .require('WAWebWidFactory')
+ .createWid(contactId);
+ const contact = await window
+ .require('WAWebCollections')
+ .Contact.find(contactWid);
+ if (contact.isBusiness || contact.isEnterprise) {
+ const bizProfile = await window
+ .require('WAWebCollections')
+ .BusinessProfile.find(contactWid);
+ bizProfile.profileOptions && (contact.businessProfile = bizProfile);
+ }
return window.WWebJS.getContactModel(contact);
};
window.WWebJS.getContacts = () => {
- const contacts = window.Store.Contact.getModelsArray();
- return contacts.map(contact => window.WWebJS.getContactModel(contact));
+ const contacts = window
+ .require('WAWebCollections')
+ .Contact.getModelsArray();
+ return Promise.all(
+ contacts.map(async (contact) => {
+ if (contact.isBusiness || contact.isEnterprise) {
+ await window
+ .require('WAWebCollections')
+ .BusinessProfile.find(contact.id)
+ .catch(() => {});
+ }
+ return window.WWebJS.getContactModel(contact);
+ }),
+ );
};
window.WWebJS.mediaInfoToFile = ({ data, mimetype, filename }) => {
@@ -613,7 +1132,7 @@ exports.LoadUtils = () => {
const blob = new Blob([buffer], { type: mimetype });
return new File([blob], filename, {
type: mimetype,
- lastModified: Date.now()
+ lastModified: Date.now(),
});
};
@@ -649,18 +1168,17 @@ exports.LoadUtils = () => {
window.WWebJS.generateHash = async (length) => {
var result = '';
- var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ var characters =
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for (var i = 0; i < length; i++) {
- result += characters.charAt(Math.floor(Math.random() * charactersLength));
+ result += characters.charAt(
+ Math.floor(Math.random() * charactersLength),
+ );
}
return result;
};
- /**
- * Referenced from and modified:
- * @see https://github.com/wppconnect-team/wa-js/commit/290ebfefe6021b3d17f7fdfdda5545bb0473b26f
- */
window.WWebJS.generateWaveform = async (audioFile) => {
try {
const audioData = await audioFile.arrayBuffer();
@@ -684,54 +1202,55 @@ exports.LoadUtils = () => {
const normalizedData = filteredData.map((n) => n * multiplier);
const waveform = new Uint8Array(
- normalizedData.map((n) => Math.floor(100 * n))
+ normalizedData.map((n) => Math.floor(100 * n)),
);
return waveform;
- } catch (e) {
+ } catch (ignoredError) {
return undefined;
}
};
window.WWebJS.sendClearChat = async (chatId) => {
- let chat = window.Store.Chat.get(chatId);
+ let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
if (chat !== undefined) {
- await window.Store.SendClear.sendClear(chat, false);
+ await window.require('WAWebChatClearBridge').sendClear(chat, false);
return true;
}
return false;
};
window.WWebJS.sendDeleteChat = async (chatId) => {
- let chat = window.Store.Chat.get(chatId);
+ let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
if (chat !== undefined) {
- await window.Store.SendDelete.sendDelete(chat);
+ await window.require('WAWebDeleteChatAction').sendDelete(chat);
return true;
}
return false;
};
window.WWebJS.sendChatstate = async (state, chatId) => {
- chatId = window.Store.WidFactory.createWid(chatId);
+ chatId = window.require('WAWebWidFactory').createWid(chatId);
+ const ChatState = window.require('WAWebChatStateBridge');
switch (state) {
- case 'typing':
- await window.Store.ChatState.sendChatStateComposing(chatId);
- break;
- case 'recording':
- await window.Store.ChatState.sendChatStateRecording(chatId);
- break;
- case 'stop':
- await window.Store.ChatState.sendChatStatePaused(chatId);
- break;
- default:
- throw 'Invalid chatstate';
+ case 'typing':
+ await ChatState.sendChatStateComposing(chatId);
+ break;
+ case 'recording':
+ await ChatState.sendChatStateRecording(chatId);
+ break;
+ case 'stop':
+ await ChatState.sendChatStatePaused(chatId);
+ break;
+ default:
+ throw 'Invalid chatstate';
}
return true;
};
- window.WWebJS.getLabelModel = label => {
+ window.WWebJS.getLabelModel = (label) => {
let res = label.serialize();
res.hexColor = label.hexColor;
@@ -739,28 +1258,34 @@ exports.LoadUtils = () => {
};
window.WWebJS.getLabels = () => {
- const labels = window.Store.Label.getModelsArray();
- return labels.map(label => window.WWebJS.getLabelModel(label));
+ const labels = window
+ .require('WAWebCollections')
+ .Label.getModelsArray();
+ return labels.map((label) => window.WWebJS.getLabelModel(label));
};
window.WWebJS.getLabel = (labelId) => {
- const label = window.Store.Label.get(labelId);
+ const label = window.require('WAWebCollections').Label.get(labelId);
return window.WWebJS.getLabelModel(label);
};
window.WWebJS.getChatLabels = async (chatId) => {
const chat = await window.WWebJS.getChat(chatId);
- return (chat.labels || []).map(id => window.WWebJS.getLabel(id));
+ return (chat.labels || []).map((id) => window.WWebJS.getLabel(id));
};
window.WWebJS.getOrderDetail = async (orderId, token, chatId) => {
- const chatWid = window.Store.WidFactory.createWid(chatId);
- return window.Store.QueryOrder.queryOrder(chatWid, orderId, 80, 80, token);
+ const chatWid = window.require('WAWebWidFactory').createWid(chatId);
+ return window
+ .require('WAWebBizOrderBridge')
+ .queryOrder(chatWid, orderId, 80, 80, token);
};
window.WWebJS.getProductMetadata = async (productId) => {
- let sellerId = window.Store.Conn.wid;
- let product = await window.Store.QueryProduct.queryProduct(sellerId, productId);
+ let sellerId = window.require('WAWebConnModel').Conn.wid;
+ let product = await window
+ .require('WAWebBizProductCatalogBridge')
+ .queryProduct(sellerId, productId);
if (product && product.data) {
return product.data;
}
@@ -769,20 +1294,26 @@ exports.LoadUtils = () => {
};
window.WWebJS.rejectCall = async (peerJid, id) => {
- peerJid = peerJid.split('@')[0] + '@s.whatsapp.net';
- let userId = window.Store.User.getMaybeMeUser().user + '@s.whatsapp.net';
- const stanza = window.Store.SocketWap.wap('call', {
- id: window.Store.SocketWap.generateId(),
- from: window.Store.SocketWap.USER_JID(userId),
- to: window.Store.SocketWap.USER_JID(peerJid),
- }, [
- window.Store.SocketWap.wap('reject', {
- 'call-id': id,
- 'call-creator': window.Store.SocketWap.USER_JID(peerJid),
- count: '0',
- })
- ]);
- await window.Store.Socket.deprecatedCastStanza(stanza);
+ let userId = window
+ .require('WAWebUserPrefsMeUser')
+ .getMaybeMePnUser()._serialized;
+
+ const stanza = window.require('WAWap').wap(
+ 'call',
+ {
+ id: window.require('WAWap').generateId(),
+ from: userId,
+ to: peerJid,
+ },
+ [
+ window.require('WAWap').wap('reject', {
+ 'call-id': id,
+ 'call-creator': peerJid,
+ count: '0',
+ }),
+ ],
+ );
+ await window.require('WADeprecatedSendIq').deprecatedCastStanza(stanza);
};
window.WWebJS.cropAndResizeImage = async (media, options = {}) => {
@@ -792,9 +1323,17 @@ exports.LoadUtils = () => {
if (options.mimetype && !options.mimetype.includes('image'))
delete options.mimetype;
- options = Object.assign({ size: 640, mimetype: media.mimetype, quality: .75, asDataUrl: false }, options);
+ options = Object.assign(
+ {
+ size: 640,
+ mimetype: media.mimetype,
+ quality: 0.75,
+ asDataUrl: false,
+ },
+ options,
+ );
- const img = await new Promise ((resolve, reject) => {
+ const img = await new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
@@ -814,48 +1353,69 @@ exports.LoadUtils = () => {
const dataUrl = canvas.toDataURL(options.mimetype, options.quality);
- if (options.asDataUrl)
- return dataUrl;
+ if (options.asDataUrl) return dataUrl;
return Object.assign(media, {
- mimetype: options.mimeType,
- data: dataUrl.replace(`data:${options.mimeType};base64,`, '')
+ mimetype: options.mimetype,
+ data: dataUrl.replace(`data:${options.mimetype};base64,`, ''),
});
};
- window.WWebJS.setPicture = async (chatid, media) => {
- const thumbnail = await window.WWebJS.cropAndResizeImage(media, { asDataUrl: true, mimetype: 'image/jpeg', size: 96 });
- const profilePic = await window.WWebJS.cropAndResizeImage(media, { asDataUrl: true, mimetype: 'image/jpeg', size: 640 });
+ window.WWebJS.setPicture = async (chatId, media) => {
+ const thumbnail = await window.WWebJS.cropAndResizeImage(media, {
+ asDataUrl: true,
+ mimetype: 'image/jpeg',
+ size: 96,
+ });
+ const profilePic = await window.WWebJS.cropAndResizeImage(media, {
+ asDataUrl: true,
+ mimetype: 'image/jpeg',
+ size: 640,
+ });
- const chatWid = window.Store.WidFactory.createWid(chatid);
+ const chatWid = window.require('WAWebWidFactory').createWid(chatId);
try {
- const collection = window.Store.ProfilePicThumb.get(chatid);
- if (!collection.canSet()) return;
+ const collection =
+ window
+ .require('WAWebCollections')
+ .ProfilePicThumb.get(chatId) ||
+ (await window
+ .require('WAWebCollections')
+ .ProfilePicThumb.find(chatId));
+ if (!collection?.canSet()) return false;
- const res = await window.Store.GroupUtils.sendSetPicture(chatWid, thumbnail, profilePic);
+ const res = await window
+ .require('WAWebContactProfilePicThumbBridge')
+ .sendSetPicture(chatWid, thumbnail, profilePic);
return res ? res.status === 200 : false;
} catch (err) {
- if(err.name === 'ServerStatusCodeError') return false;
+ if (err.name === 'ServerStatusCodeError') return false;
throw err;
}
};
window.WWebJS.deletePicture = async (chatid) => {
- const chatWid = window.Store.WidFactory.createWid(chatid);
+ const chatWid = window.require('WAWebWidFactory').createWid(chatid);
try {
- const collection = window.Store.ProfilePicThumb.get(chatid);
+ const collection = window
+ .require('WAWebCollections')
+ .ProfilePicThumb.get(chatid);
if (!collection.canDelete()) return;
- const res = await window.Store.GroupUtils.requestDeletePicture(chatWid);
+ const res = await window
+ .require('WAWebContactProfilePicThumbBridge')
+ .requestDeletePicture(chatWid);
return res ? res.status === 200 : false;
} catch (err) {
- if(err.name === 'ServerStatusCodeError') return false;
+ if (err.name === 'ServerStatusCodeError') return false;
throw err;
}
};
-
+
window.WWebJS.getProfilePicThumbToBase64 = async (chatWid) => {
- const profilePicCollection = await window.Store.ProfilePicThumb.find(chatWid);
+ const profilePicCollection = await window
+ .require('WAWebCollections')
+ .ProfilePicThumb.find(chatWid);
const _readImageAsBase64 = (imageBlob) => {
return new Promise((resolve) => {
@@ -883,69 +1443,60 @@ exports.LoadUtils = () => {
return base64Image;
}
}
- } catch (error) { /* empty */ }
+ } catch (ignoredError) {
+ /* empty */
+ }
}
return undefined;
};
- window.WWebJS.getAddParticipantsRpcResult = async (groupMetadata, groupWid, participantWid) => {
- const participantLidArgs = groupMetadata?.isLidAddressingMode
- ? {
- phoneNumber: participantWid,
- lid: window.Store.LidUtils.getCurrentLid(participantWid)
- }
- : { phoneNumber: participantWid };
+ window.WWebJS.getAddParticipantsRpcResult = async (
+ groupWid,
+ participantWid,
+ ) => {
+ const iqTo = window.require('WAWebWidToJid').widToGroupJid(groupWid);
- const iqTo = window.Store.WidToJid.widToGroupJid(groupWid);
-
- const participantArgs =
- participantLidArgs.lid
- ? [{
- participantJid: window.Store.WidToJid.widToUserJid(participantLidArgs.lid),
- phoneNumberMixinArgs: {
- anyPhoneNumber: window.Store.WidToJid.widToUserJid(participantLidArgs.phoneNumber)
- }
- }]
- : [{
- participantJid: window.Store.WidToJid.widToUserJid(participantLidArgs.phoneNumber)
- }];
+ const participantArgs = [
+ {
+ participantJid: window
+ .require('WAWebWidToJid')
+ .widToUserJid(participantWid),
+ },
+ ];
let rpcResult, resultArgs;
- const isOldImpl = window.compareWwebVersions(window.Debug.VERSION, '<=', '2.2335.9');
const data = {
name: undefined,
code: undefined,
inviteV4Code: undefined,
- inviteV4CodeExp: undefined
+ inviteV4CodeExp: undefined,
};
try {
- rpcResult = await window.Store.GroupParticipants.sendAddParticipantsRPC({ participantArgs, iqTo });
- resultArgs = isOldImpl
- ? rpcResult.value.addParticipant[0].addParticipantsParticipantMixins
- : rpcResult.value.addParticipant[0]
+ rpcResult = await window
+ .require('WASmaxGroupsAddParticipantsRPC')
+ .sendAddParticipantsRPC({ participantArgs, iqTo });
+ resultArgs =
+ rpcResult.value.addParticipant[0]
.addParticipantsParticipantAddedOrNonRegisteredWaUserParticipantErrorLidResponseMixinGroup
- .value
- .addParticipantsParticipantMixins;
- } catch (err) {
+ .value.addParticipantsParticipantMixins;
+ } catch (ignoredError) {
data.code = 400;
return data;
}
if (rpcResult.name === 'AddParticipantsResponseSuccess') {
- const code = resultArgs?.value.error ?? '200';
+ const code = resultArgs?.value.error || '200';
data.name = resultArgs?.name;
data.code = +code;
data.inviteV4Code = resultArgs?.value.addRequestCode;
- data.inviteV4CodeExp = resultArgs?.value.addRequestExpiration?.toString();
- }
-
- else if (rpcResult.name === 'AddParticipantsResponseClientError') {
- const { code: code } = rpcResult.value.errorAddParticipantsClientErrors.value;
+ data.inviteV4CodeExp =
+ resultArgs?.value.addRequestExpiration?.toString();
+ } else if (rpcResult.name === 'AddParticipantsResponseClientError') {
+ const { code: code } =
+ rpcResult.value.errorAddParticipantsClientErrors.value;
data.code = +code;
- }
-
- else if (rpcResult.name === 'AddParticipantsResponseServerError') {
+ } else if (rpcResult.name === 'AddParticipantsResponseServerError') {
const { code: code } = rpcResult.value.errorServerErrors.value;
data.code = +code;
}
@@ -953,44 +1504,69 @@ exports.LoadUtils = () => {
return data;
};
- window.WWebJS.membershipRequestAction = async (groupId, action, requesterIds, sleep) => {
- const groupWid = window.Store.WidFactory.createWid(groupId);
- const group = await window.Store.Chat.find(groupWid);
+ window.WWebJS.membershipRequestAction = async (
+ groupId,
+ action,
+ requesterIds,
+ sleep,
+ ) => {
+ const groupWid = window.require('WAWebWidFactory').createWid(groupId);
+ const group = await window
+ .require('WAWebCollections')
+ .Chat.find(groupWid);
const toApprove = action === 'Approve';
let membershipRequests;
let response;
let result = [];
- await window.Store.GroupQueryAndUpdate({ id: groupId });
+ await window
+ .require('WAWebGroupQueryJob')
+ .queryAndUpdateGroupMetadataById({ id: groupId });
if (!requesterIds?.length) {
- membershipRequests = group.groupMetadata.membershipApprovalRequests._models.map(({ id }) => id);
+ membershipRequests =
+ group.groupMetadata.membershipApprovalRequests._models.map(
+ ({ id }) => id,
+ );
} else {
!Array.isArray(requesterIds) && (requesterIds = [requesterIds]);
- membershipRequests = requesterIds.map(r => window.Store.WidFactory.createWid(r));
+ membershipRequests = requesterIds.map((r) =>
+ window.require('WAWebWidFactory').createWid(r),
+ );
}
if (!membershipRequests.length) return [];
- const participantArgs = membershipRequests.map(m => ({
+ const participantArgs = membershipRequests.map((m) => ({
participantArgs: [
{
- participantJid: window.Store.WidToJid.widToUserJid(m)
- }
- ]
+ participantJid: window
+ .require('WAWebWidToJid')
+ .widToUserJid(m),
+ },
+ ],
}));
- const groupJid = window.Store.WidToJid.widToGroupJid(groupWid);
-
+ const groupJid = window
+ .require('WAWebWidToJid')
+ .widToGroupJid(groupWid);
+
const _getSleepTime = (sleep) => {
- if (!Array.isArray(sleep) || (sleep.length === 2 && sleep[0] === sleep[1])) {
+ if (
+ !Array.isArray(sleep) ||
+ (sleep.length === 2 && sleep[0] === sleep[1])
+ ) {
return sleep;
}
if (sleep.length === 1) {
return sleep[0];
}
- sleep[1] - sleep[0] < 100 && (sleep[0] = sleep[1]) && (sleep[1] += 100);
- return Math.floor(Math.random() * (sleep[1] - sleep[0] + 1)) + sleep[0];
+ sleep[1] - sleep[0] < 100 &&
+ (sleep[0] = sleep[1]) &&
+ (sleep[1] += 100);
+ return (
+ Math.floor(Math.random() * (sleep[1] - sleep[0] + 1)) + sleep[0]
+ );
};
const membReqResCodes = {
@@ -1002,68 +1578,194 @@ exports.LoadUtils = () => {
408: 'ParticipantTemporarilyBlockedError',
409: 'ParticipantConflictError',
412: 'ParticipantParentLinkedGroupsResourceConstraintError',
- 500: 'ParticipantResourceConstraintError'
+ 500: 'ParticipantResourceConstraintError',
};
try {
for (const participant of participantArgs) {
- response = await window.Store.MembershipRequestUtils.sendMembershipRequestsActionRPC({
- iqTo: groupJid,
- [toApprove ? 'approveArgs' : 'rejectArgs']: participant
- });
+ response = await window
+ .require('WASmaxGroupsMembershipRequestsActionRPC')
+ .sendMembershipRequestsActionRPC({
+ iqTo: groupJid,
+ [toApprove ? 'approveArgs' : 'rejectArgs']: participant,
+ });
- if (response.name === 'MembershipRequestsActionResponseSuccess') {
+ if (
+ response.name === 'MembershipRequestsActionResponseSuccess'
+ ) {
const value = toApprove
? response.value.membershipRequestsActionApprove
: response.value.membershipRequestsActionReject;
if (value?.participant) {
- const [_] = value.participant.map(p => {
+ const [_] = value.participant.map((p) => {
const error = toApprove
- ? value.participant[0].membershipRequestsActionAcceptParticipantMixins?.value.error
- : value.participant[0].membershipRequestsActionRejectParticipantMixins?.value.error;
+ ? value.participant[0]
+ .membershipRequestsActionAcceptParticipantMixins
+ ?.value.error
+ : value.participant[0]
+ .membershipRequestsActionRejectParticipantMixins
+ ?.value.error;
return {
- requesterId: window.Store.WidFactory.createWid(p.jid)._serialized,
+ requesterId: window
+ .require('WAWebWidFactory')
+ .createWid(p.jid)._serialized,
...(error
- ? { error: +error, message: membReqResCodes[error] || membReqResCodes.default }
- : { message: `${toApprove ? 'Approved' : 'Rejected'} successfully` })
+ ? {
+ error: +error,
+ message:
+ membReqResCodes[error] ||
+ membReqResCodes.default,
+ }
+ : {
+ message: `${toApprove ? 'Approved' : 'Rejected'} successfully`,
+ }),
};
});
_ && result.push(_);
}
} else {
result.push({
- requesterId: window.Store.JidToWid.userJidToUserWid(participant.participantArgs[0].participantJid)._serialized,
- message: 'ServerStatusCodeError'
+ requesterId: window
+ .require('WAWebJidToWid')
+ .userJidToUserWid(
+ participant.participantArgs[0].participantJid,
+ )._serialized,
+ message: 'ServerStatusCodeError',
});
}
sleep &&
participantArgs.length > 1 &&
- participantArgs.indexOf(participant) !== participantArgs.length - 1 &&
- (await new Promise((resolve) => setTimeout(resolve, _getSleepTime(sleep))));
+ participantArgs.indexOf(participant) !==
+ participantArgs.length - 1 &&
+ (await new Promise((resolve) =>
+ setTimeout(resolve, _getSleepTime(sleep)),
+ ));
}
return result;
- } catch (err) {
+ } catch (ignoredError) {
return [];
}
};
+ window.WWebJS.subscribeToUnsubscribeFromChannel = async (
+ channelId,
+ action,
+ options = {},
+ ) => {
+ const channel = await window.WWebJS.getChat(channelId, {
+ getAsModel: false,
+ });
+
+ if (!channel || channel.newsletterMetadata.membershipType === 'owner')
+ return false;
+ options = {
+ eventSurface: 3,
+ deleteLocalModels: options.deleteLocalModels ?? true,
+ };
+
+ try {
+ if (action === 'Subscribe') {
+ await window
+ .require('WAWebNewsletterSubscribeAction')
+ .subscribeToNewsletterAction(channel, options);
+ } else if (action === 'Unsubscribe') {
+ await window
+ .require('WAWebNewsletterUnsubscribeAction')
+ .unsubscribeFromNewsletterAction(channel, options);
+ } else return false;
+ return true;
+ } catch (err) {
+ if (err.name === 'ServerStatusCodeError') return false;
+ throw err;
+ }
+ };
+
window.WWebJS.pinUnpinMsgAction = async (msgId, action, duration) => {
- const message = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
+ const message =
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
if (!message) return false;
- const response = await window.Store.pinUnpinMsg(message, action, duration);
+
+ if (typeof duration !== 'number') return false;
+
+ const originalFunction = window.require(
+ 'WAWebPinMsgConstants',
+ ).getPinExpiryDuration;
+ window.require('WAWebPinMsgConstants').getPinExpiryDuration = () =>
+ duration;
+
+ const response = await window
+ .require('WAWebSendPinMessageAction')
+ .sendPinInChatMsg(message, action, duration);
+
+ window.require('WAWebPinMsgConstants').getPinExpiryDuration =
+ originalFunction;
+
return response.messageSendResult === 'OK';
};
-
- window.WWebJS.getStatusModel = status => {
+
+ window.WWebJS.getStatusModel = (status) => {
const res = status.serialize();
delete res._msgs;
return res;
};
window.WWebJS.getAllStatuses = () => {
- const statuses = window.Store.Status.getModelsArray();
- return statuses.map(status => window.WWebJS.getStatusModel(status));
+ const statuses = window
+ .require('WAWebCollections')
+ .Status.getModelsArray();
+ return statuses.map((status) => window.WWebJS.getStatusModel(status));
+ };
+
+ window.WWebJS.enforceLidAndPnRetrieval = async (userId) => {
+ const wid = window.require('WAWebWidFactory').createWid(userId);
+ const isLid = wid.server === 'lid';
+
+ let lid = isLid
+ ? wid
+ : window.require('WAWebApiContact').getCurrentLid(wid);
+ let phone = isLid
+ ? window.require('WAWebApiContact').getPhoneNumber(wid)
+ : wid;
+
+ if (!isLid && !lid) {
+ const queryResult = await window
+ .require('WAWebQueryExistsJob')
+ .queryWidExists(wid);
+ if (!queryResult?.wid) return {};
+ lid = window.require('WAWebApiContact').getCurrentLid(wid);
+ }
+
+ if (isLid && !phone) {
+ const queryResult = await window
+ .require('WAWebQueryExistsJob')
+ .queryWidExists(wid);
+ if (!queryResult?.wid) return {};
+ phone = window.require('WAWebApiContact').getPhoneNumber(wid);
+ }
+
+ return { lid, phone };
+ };
+
+ window.WWebJS.assertColor = (hex) => {
+ let color;
+ if (typeof hex === 'number') {
+ color = hex > 0 ? hex : 0xffffffff + parseInt(hex) + 1;
+ } else if (typeof hex === 'string') {
+ let number = hex.trim().replace('#', '');
+ if (number.length <= 6) {
+ number = 'FF' + number.padStart(6, '0');
+ }
+ color = parseInt(number, 16);
+ } else {
+ throw 'Invalid hex color';
+ }
+ return color;
};
};
@@ -1076,7 +1778,7 @@ exports.LoadUtils = () => {
diff --git a/docs/util_InterfaceController.js.html b/docs/util_InterfaceController.js.html
index c7ef9a3..b4e800d 100644
--- a/docs/util_InterfaceController.js.html
+++ b/docs/util_InterfaceController.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: util/InterfaceController.js
+ whatsapp-web.js 1.34.7 » Source: util/InterfaceController.js
@@ -15,7 +15,7 @@
@@ -35,7 +35,6 @@
* Interface Controller
*/
class InterfaceController {
-
constructor(props) {
this.pupPage = props.pupPage;
}
@@ -46,8 +45,12 @@ class InterfaceController {
*/
async openChatWindow(chatId) {
return await this.pupPage.evaluate(async (chatId) => {
- const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
- return await window.Store.Cmd.openChatBottom({'chat':chat});
+ const chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
+ return await window
+ .require('WAWebCmd')
+ .Cmd.openChatBottom({ chat: chat });
}, chatId);
}
@@ -56,9 +59,11 @@ class InterfaceController {
* @param {string} chatId ID of the chat drawer that will be opened
*/
async openChatDrawer(chatId) {
- await this.pupPage.evaluate(async chatId => {
- let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
- await window.Store.Cmd.openDrawerMid(chat);
+ await this.pupPage.evaluate(async (chatId) => {
+ let chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
+ await window.require('WAWebCmd').Cmd.openDrawerMid(chat);
}, chatId);
}
@@ -67,9 +72,11 @@ class InterfaceController {
* @param {string} chatId ID of the chat search that will be opened
*/
async openChatSearch(chatId) {
- await this.pupPage.evaluate(async chatId => {
- let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
- await window.Store.Cmd.chatSearch(chat);
+ await this.pupPage.evaluate(async (chatId) => {
+ let chat = await window.WWebJS.getChat(chatId, {
+ getAsModel: false,
+ });
+ await window.require('WAWebCmd').Cmd.chatSearch(chat);
}, chatId);
}
@@ -79,10 +86,24 @@ class InterfaceController {
*/
async openChatWindowAt(msgId) {
await this.pupPage.evaluate(async (msgId) => {
- const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
- const chat = window.Store.Chat.get(msg.id.remote) ?? await window.Store.Chat.find(msg.id.remote);
- const searchContext = await window.Store.SearchContext.getSearchContext(chat, msg.id);
- await window.Store.Cmd.openChatAt({ chat: chat, msgContext: searchContext });
+ const msg =
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
+ const chat =
+ window.require('WAWebCollections').Chat.get(msg.id.remote) ??
+ (await window
+ .require('WAWebCollections')
+ .Chat.find(msg.id.remote));
+ const searchContext = await window
+ .require('WAWebChatMessageSearch')
+ .getSearchContext(chat, msg.id);
+ await window
+ .require('WAWebCmd')
+ .Cmd.openChatAt({ chat: chat, msgContext: searchContext });
}, msgId);
}
@@ -91,9 +112,15 @@ class InterfaceController {
* @param {string} msgId ID of the message drawer that will be opened
*/
async openMessageDrawer(msgId) {
- await this.pupPage.evaluate(async msgId => {
- const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
- await window.Store.Cmd.msgInfoDrawer(msg);
+ await this.pupPage.evaluate(async (msgId) => {
+ const msg =
+ window.require('WAWebCollections').Msg.get(msgId) ||
+ (
+ await window
+ .require('WAWebCollections')
+ .Msg.getMessagesById([msgId])
+ )?.messages?.[0];
+ await window.require('WAWebCmd').Cmd.msgInfoDrawer(msg);
}, msgId);
}
@@ -102,7 +129,9 @@ class InterfaceController {
*/
async closeRightDrawer() {
await this.pupPage.evaluate(async () => {
- await window.Store.DrawerManager.closeDrawerRight();
+ await window
+ .require('WAWebDrawerManager')
+ .DrawerManager.closeDrawerRight();
});
}
@@ -111,8 +140,11 @@ class InterfaceController {
*/
async getFeatures() {
return await this.pupPage.evaluate(() => {
- if(!window.Store.Features) throw new Error('This version of Whatsapp Web does not support features');
- return window.Store.Features.F;
+ if (!window.require('WAWebCollections').Features)
+ throw new Error(
+ 'This version of Whatsapp Web does not support features',
+ );
+ return window.require('WAWebCollections').Features.F;
});
}
@@ -122,8 +154,13 @@ class InterfaceController {
*/
async checkFeatureStatus(feature) {
return await this.pupPage.evaluate((feature) => {
- if(!window.Store.Features) throw new Error('This version of Whatsapp Web does not support features');
- return window.Store.Features.supportsFeature(feature);
+ if (!window.require('WAWebCollections').Features)
+ throw new Error(
+ 'This version of Whatsapp Web does not support features',
+ );
+ return window
+ .require('WAWebCollections')
+ .Features.supportsFeature(feature);
}, feature);
}
@@ -133,9 +170,14 @@ class InterfaceController {
*/
async enableFeatures(features) {
await this.pupPage.evaluate((features) => {
- if(!window.Store.Features) throw new Error('This version of Whatsapp Web does not support features');
+ if (!window.require('WAWebCollections').Features)
+ throw new Error(
+ 'This version of Whatsapp Web does not support features',
+ );
for (const feature in features) {
- window.Store.Features.setFeature(features[feature], true);
+ window
+ .require('WAWebCollections')
+ .Features.setFeature(features[feature], true);
}
}, features);
}
@@ -146,9 +188,14 @@ class InterfaceController {
*/
async disableFeatures(features) {
await this.pupPage.evaluate((features) => {
- if(!window.Store.Features) throw new Error('This version of Whatsapp Web does not support features');
+ if (!window.require('WAWebCollections').Features)
+ throw new Error(
+ 'This version of Whatsapp Web does not support features',
+ );
for (const feature in features) {
- window.Store.Features.setFeature(features[feature], false);
+ window
+ .require('WAWebCollections')
+ .Features.setFeature(features[feature], false);
}
}, features);
}
@@ -165,7 +212,7 @@ module.exports = InterfaceController;
diff --git a/docs/util_Puppeteer.js.html b/docs/util_Puppeteer.js.html
index 7e54d3f..33497a5 100644
--- a/docs/util_Puppeteer.js.html
+++ b/docs/util_Puppeteer.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: util/Puppeteer.js
+ whatsapp-web.js 1.34.7 » Source: util/Puppeteer.js
@@ -15,7 +15,7 @@
@@ -51,7 +51,7 @@ async function exposeFunctionIfAbsent(page, name, fn) {
await page.exposeFunction(name, fn);
}
-module.exports = {exposeFunctionIfAbsent};
+module.exports = { exposeFunctionIfAbsent };
@@ -62,7 +62,7 @@ module.exports = {exposeFunctionIfAbsent};
diff --git a/docs/util_Util.js.html b/docs/util_Util.js.html
index 8a85f6b..e338ca9 100644
--- a/docs/util_Util.js.html
+++ b/docs/util_Util.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: util/Util.js
+ whatsapp-web.js 1.34.7 » Source: util/Util.js
@@ -15,7 +15,7 @@
@@ -44,15 +44,20 @@ const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
*/
class Util {
constructor() {
- throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
+ throw new Error(
+ `The ${this.constructor.name} class may not be instantiated.`,
+ );
}
static generateHash(length) {
var result = '';
- var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ var characters =
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for (var i = 0; i < length; i++) {
- result += characters.charAt(Math.floor(Math.random() * charactersLength));
+ result += characters.charAt(
+ Math.floor(Math.random() * charactersLength),
+ );
}
return result;
}
@@ -80,7 +85,7 @@ class Util {
/**
* Formats a image to webp
* @param {MessageMedia} media
- *
+ *
* @returns {Promise<MessageMedia>} media in webp format
*/
static async formatImageToWebpSticker(media, pupPage) {
@@ -99,7 +104,7 @@ class Util {
/**
* Formats a video to webp
* @param {MessageMedia} media
- *
+ *
* @returns {Promise<MessageMedia>} media in webp format
*/
static async formatVideoToWebpSticker(media) {
@@ -110,13 +115,13 @@ class Util {
const tempFile = path.join(
tmpdir(),
- `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`
+ `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`,
);
const stream = new (require('stream').Readable)();
const buffer = Buffer.from(
media.data.replace(`data:${media.mimetype};base64,`, ''),
- 'base64'
+ 'base64',
);
stream.push(buffer);
stream.push(null);
@@ -131,7 +136,7 @@ class Util {
'libwebp',
'-vf',
// eslint-disable-next-line no-useless-escape
- 'scale=\'iw*min(300/iw\,300/ih)\':\'ih*min(300/iw\,300/ih)\',format=rgba,pad=300:300:\'(300-iw)/2\':\'(300-ih)/2\':\'#00000000\',setsar=1,fps=10',
+ "scale='iw*min(300/iw\,300/ih)':'ih*min(300/iw\,300/ih)',format=rgba,pad=300:300:'(300-iw)/2':'(300-ih)/2':'#00000000',setsar=1,fps=10",
'-loop',
'0',
'-ss',
@@ -163,8 +168,8 @@ class Util {
/**
* Sticker metadata.
* @typedef {Object} StickerMetadata
- * @property {string} [name]
- * @property {string} [author]
+ * @property {string} [name]
+ * @property {string} [author]
* @property {string[]} [categories]
*/
@@ -172,7 +177,7 @@ class Util {
* Formats a media to webp
* @param {MessageMedia} media
* @param {StickerMetadata} metadata
- *
+ *
* @returns {Promise<MessageMedia>} media in webp format
*/
static async formatToWebpSticker(media, metadata, pupPage) {
@@ -182,8 +187,7 @@ class Util {
webpMedia = await this.formatImageToWebpSticker(media, pupPage);
else if (media.mimetype.includes('video'))
webpMedia = await this.formatVideoToWebpSticker(media);
- else
- throw new Error('Invalid media format');
+ else throw new Error('Invalid media format');
if (metadata.name || metadata.author) {
const img = new webp.Image();
@@ -192,8 +196,17 @@ class Util {
const packname = metadata.name;
const author = metadata.author;
const categories = metadata.categories || [''];
- const json = { 'sticker-pack-id': stickerPackId, 'sticker-pack-name': packname, 'sticker-pack-publisher': author, 'emojis': categories };
- let exifAttr = Buffer.from([0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x41, 0x57, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00]);
+ const json = {
+ 'sticker-pack-id': stickerPackId,
+ 'sticker-pack-name': packname,
+ 'sticker-pack-publisher': author,
+ emojis: categories,
+ };
+ let exifAttr = Buffer.from([
+ 0x49, 0x49, 0x2a, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x41, 0x57, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00,
+ 0x00, 0x00,
+ ]);
let jsonBuffer = Buffer.from(JSON.stringify(json), 'utf8');
let exif = Buffer.concat([exifAttr, jsonBuffer]);
exif.writeUIntLE(jsonBuffer.length, 14, 4);
@@ -225,7 +238,7 @@ module.exports = Util;
diff --git a/docs/webCache_LocalWebCache.js.html b/docs/webCache_LocalWebCache.js.html
index afd8afb..940dcb9 100644
--- a/docs/webCache_LocalWebCache.js.html
+++ b/docs/webCache_LocalWebCache.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: webCache/LocalWebCache.js
+ whatsapp-web.js 1.34.7 » Source: webCache/LocalWebCache.js
@@ -15,7 +15,7 @@
@@ -37,7 +37,7 @@ const { WebCache, VersionResolveError } = require('./WebCache');
/**
* LocalWebCache - Fetches a WhatsApp Web version from a local file store
* @param {object} options - options
- * @param {string} options.path - Path to the directory where cached versions are saved, default is: "./.wwebjs_cache/"
+ * @param {string} options.path - Path to the directory where cached versions are saved, default is: "./.wwebjs_cache/"
* @param {boolean} options.strict - If true, will throw an error if the requested version can't be fetched. If false, will resolve to the latest version.
*/
class LocalWebCache extends WebCache {
@@ -50,12 +50,14 @@ class LocalWebCache extends WebCache {
async resolve(version) {
const filePath = path.join(this.path, `${version}.html`);
-
+
try {
return fs.readFileSync(filePath, 'utf-8');
- }
- catch (err) {
- if (this.strict) throw new VersionResolveError(`Couldn't load version ${version} from the cache`);
+ } catch (ignoredError) {
+ if (this.strict)
+ throw new VersionResolveError(
+ `Couldn't load version ${version} from the cache`,
+ );
return null;
}
}
@@ -79,7 +81,7 @@ module.exports = LocalWebCache;
diff --git a/docs/webCache_RemoteWebCache.js.html b/docs/webCache_RemoteWebCache.js.html
index 96044db..2db3d59 100644
--- a/docs/webCache_RemoteWebCache.js.html
+++ b/docs/webCache_RemoteWebCache.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: webCache/RemoteWebCache.js
+ whatsapp-web.js 1.34.7 » Source: webCache/RemoteWebCache.js
@@ -15,7 +15,7 @@
@@ -42,7 +42,10 @@ class RemoteWebCache extends WebCache {
constructor(options = {}) {
super();
- if (!options.remotePath) throw new Error('webVersionCache.remotePath is required when using the remote cache');
+ if (!options.remotePath)
+ throw new Error(
+ 'webVersionCache.remotePath is required when using the remote cache',
+ );
this.remotePath = options.remotePath;
this.strict = options.strict || false;
}
@@ -59,8 +62,11 @@ class RemoteWebCache extends WebCache {
console.error(`Error fetching version ${version} from remote`, err);
}
- if (this.strict) throw new VersionResolveError(`Couldn't load version ${version} from the archive`);
- return null;
+ if (this.strict)
+ throw new VersionResolveError(
+ `Couldn't load version ${version} from the archive`,
+ );
+ return null;
}
async persist() {
@@ -68,7 +74,8 @@ class RemoteWebCache extends WebCache {
}
}
-module.exports = RemoteWebCache;
+module.exports = RemoteWebCache;
+
@@ -78,7 +85,7 @@ module.exports = RemoteWebCache;
diff --git a/docs/webCache_WebCache.js.html b/docs/webCache_WebCache.js.html
index 7fc1d22..546ed71 100644
--- a/docs/webCache_WebCache.js.html
+++ b/docs/webCache_WebCache.js.html
@@ -4,7 +4,7 @@
- whatsapp-web.js 1.34.6 » Source: webCache/WebCache.js
+ whatsapp-web.js 1.34.7 » Source: webCache/WebCache.js
@@ -15,7 +15,7 @@
@@ -33,16 +33,20 @@
* Default implementation of a web version cache that does nothing.
*/
class WebCache {
- async resolve() { return null; }
- async persist() { }
+ async resolve() {
+ return null;
+ }
+
+ async persist() {}
}
-class VersionResolveError extends Error { }
+class VersionResolveError extends Error {}
module.exports = {
WebCache,
- VersionResolveError
-};
+ VersionResolveError,
+};
+
@@ -52,7 +56,7 @@ module.exports = {
diff --git a/package-lock.json b/package-lock.json
index 47b9332..648ea93 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "whatsapp-web.js",
- "version": "1.34.6",
+ "version": "1.34.7",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "whatsapp-web.js",
- "version": "1.34.6",
+ "version": "1.34.7",
"license": "Apache-2.0",
"dependencies": {
"fluent-ffmpeg": "2.1.3",
@@ -925,7 +925,6 @@
"integrity": "sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw==",
"devOptional": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"undici-types": "~6.21.0"
}
@@ -980,7 +979,6 @@
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -1177,7 +1175,6 @@
"resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz",
"integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==",
"license": "Apache-2.0",
- "peer": true,
"peerDependencies": {
"bare-abort-controller": "*"
},
@@ -1409,7 +1406,6 @@
"integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"assertion-error": "^1.1.0",
"check-error": "^1.0.3",
@@ -1753,7 +1749,6 @@
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz",
"integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==",
"license": "MIT",
- "peer": true,
"dependencies": {
"env-paths": "^2.2.1",
"import-fresh": "^3.3.0",
@@ -1932,8 +1927,7 @@
"version": "0.0.1581282",
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1581282.tgz",
"integrity": "sha512-nv7iKtNZQshSW2hKzYNr46nM/Cfh5SEvE2oV0/SEGgc9XupIY5ggf84Cz8eJIkBce7S3bmTAauFD6aysMpnqsQ==",
- "license": "BSD-3-Clause",
- "peer": true
+ "license": "BSD-3-Clause"
},
"node_modules/diff": {
"version": "7.0.0",
@@ -2102,6 +2096,7 @@
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"dev": true,
"license": "BSD-2-Clause",
+ "peer": true,
"engines": {
"node": ">=0.12"
},
@@ -2238,7 +2233,6 @@
"integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -2299,7 +2293,6 @@
"integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"eslint-config-prettier": "bin/cli.js"
},
@@ -3749,6 +3742,7 @@
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"uc.micro": "^2.0.0"
}
@@ -4174,7 +4168,8 @@
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/meow": {
"version": "13.2.0",
@@ -4722,7 +4717,6 @@
"integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
@@ -4830,6 +4824,7 @@
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=6"
}
@@ -5480,7 +5475,8 @@
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/uglify-js": {
"version": "3.19.3",
diff --git a/package.json b/package.json
index 9835b9e..1785cd5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "whatsapp-web.js",
- "version": "1.34.6",
+ "version": "1.34.7",
"description": "A Node.js library for interacting with WhatsApp Web",
"main": "./index.js",
"typings": "./index.d.ts",