mirror of
https://github.com/cheveguerra/whatsapp-web.js.git
synced 2026-04-18 03:29:14 +00:00
Compare commits
1 Commits
v1.18.3-al
...
pedroslope
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d846611cc4 |
19
index.d.ts
vendored
19
index.d.ts
vendored
@@ -322,14 +322,6 @@ declare namespace WAWebJS {
|
||||
/** How many times should the qrcode be refreshed before giving up
|
||||
* @default 0 (disabled) */
|
||||
qrMaxRetries?: number,
|
||||
/**
|
||||
* @deprecated This option should be set directly on the LegacySessionAuth
|
||||
*/
|
||||
restartOnAuthFail?: boolean
|
||||
/**
|
||||
* @deprecated Only here for backwards-compatibility. You should move to using LocalAuth, or set the authStrategy to LegacySessionAuth explicitly.
|
||||
*/
|
||||
session?: ClientSession
|
||||
/** If another whatsapp web session is detected (another browser), take over the session in the current browser
|
||||
* @default false */
|
||||
takeoverOnConflict?: boolean,
|
||||
@@ -405,17 +397,6 @@ declare namespace WAWebJS {
|
||||
extract: (options: { session: string, path: string }) => Promise<any> | any,
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy session auth strategy
|
||||
* Not compatible with multi-device accounts.
|
||||
*/
|
||||
export class LegacySessionAuth extends AuthStrategy {
|
||||
constructor(options?: {
|
||||
session?: ClientSession,
|
||||
restartOnAuthFail?: boolean,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a WhatsApp client session
|
||||
*/
|
||||
|
||||
@@ -11,7 +11,6 @@ const { ExposeStore, LoadUtils } = require('./util/Injected');
|
||||
const ChatFactory = require('./factories/ChatFactory');
|
||||
const ContactFactory = require('./factories/ContactFactory');
|
||||
const { ClientInfo, Message, MessageMedia, Contact, Location, GroupNotification, Label, Call, Buttons, List, Reaction } = require('./structures');
|
||||
const LegacySessionAuth = require('./authStrategies/LegacySessionAuth');
|
||||
const NoAuth = require('./authStrategies/NoAuth');
|
||||
|
||||
/**
|
||||
@@ -22,8 +21,6 @@ const NoAuth = require('./authStrategies/NoAuth');
|
||||
* @param {number} options.authTimeoutMs - Timeout for authentication selector in puppeteer
|
||||
* @param {object} options.puppeteer - Puppeteer launch options. View docs here: https://github.com/puppeteer/puppeteer/
|
||||
* @param {number} options.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
|
||||
@@ -52,23 +49,10 @@ class Client extends EventEmitter {
|
||||
|
||||
this.options = Util.mergeDefault(DefaultOptions, options);
|
||||
|
||||
if(!this.options.authStrategy) {
|
||||
if(Object.prototype.hasOwnProperty.call(this.options, 'session')) {
|
||||
process.emitWarning(
|
||||
'options.session is deprecated and will be removed in a future release due to incompatibility with multi-device. ' +
|
||||
'Use the LocalAuth authStrategy, don\'t pass in a session as an option, or suppress this warning by using the LegacySessionAuth strategy explicitly (see https://wwebjs.dev/guide/authentication.html#legacysessionauth-strategy).',
|
||||
'DeprecationWarning'
|
||||
);
|
||||
|
||||
this.authStrategy = new LegacySessionAuth({
|
||||
session: this.options.session,
|
||||
restartOnAuthFail: this.options.restartOnAuthFail
|
||||
});
|
||||
} else {
|
||||
this.authStrategy = new NoAuth();
|
||||
}
|
||||
} else {
|
||||
if(this.options.authStrategy) {
|
||||
this.authStrategy = this.options.authStrategy;
|
||||
} else {
|
||||
this.authStrategy = new NoAuth();
|
||||
}
|
||||
|
||||
this.authStrategy.setup(this);
|
||||
@@ -822,16 +806,11 @@ class Client extends EventEmitter {
|
||||
* @returns {Promise<Boolean>}
|
||||
*/
|
||||
async setDisplayName(displayName) {
|
||||
const couldSet = await this.pupPage.evaluate(async displayName => {
|
||||
const couldSet = await this.pupPage.evaluate(async () => {
|
||||
if(!window.Store.Conn.canSetMyPushname()) return false;
|
||||
|
||||
if(window.Store.MDBackend) {
|
||||
// TODO
|
||||
return false;
|
||||
} else {
|
||||
const res = await window.Store.Wap.setPushname(displayName);
|
||||
return !res.status || res.status === 200;
|
||||
}
|
||||
// TODO for MD
|
||||
return false;
|
||||
}, displayName);
|
||||
|
||||
return couldSet;
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const BaseAuthStrategy = require('./BaseAuthStrategy');
|
||||
|
||||
/**
|
||||
* Legacy session auth strategy
|
||||
* Not compatible with multi-device accounts.
|
||||
* @param {object} options - options
|
||||
* @param {string} options.restartOnAuthFail - Restart client with a new session (i.e. use null 'session' var) if authentication fails
|
||||
* @param {object} options.session - Whatsapp session to restore. If not set, will start a new session
|
||||
* @param {string} options.session.WABrowserId
|
||||
* @param {string} options.session.WASecretBundle
|
||||
* @param {string} options.session.WAToken1
|
||||
* @param {string} options.session.WAToken2
|
||||
*/
|
||||
class LegacySessionAuth extends BaseAuthStrategy {
|
||||
constructor({ session, restartOnAuthFail }={}) {
|
||||
super();
|
||||
this.session = session;
|
||||
this.restartOnAuthFail = restartOnAuthFail;
|
||||
}
|
||||
|
||||
async afterBrowserInitialized() {
|
||||
if(this.session) {
|
||||
await this.client.pupPage.evaluateOnNewDocument(session => {
|
||||
if (document.referrer === 'https://whatsapp.com/') {
|
||||
localStorage.clear();
|
||||
localStorage.setItem('WABrowserId', session.WABrowserId);
|
||||
localStorage.setItem('WASecretBundle', session.WASecretBundle);
|
||||
localStorage.setItem('WAToken1', session.WAToken1);
|
||||
localStorage.setItem('WAToken2', session.WAToken2);
|
||||
}
|
||||
|
||||
localStorage.setItem('remember-me', 'true');
|
||||
}, this.session);
|
||||
}
|
||||
}
|
||||
|
||||
async onAuthenticationNeeded() {
|
||||
if(this.session) {
|
||||
this.session = null;
|
||||
return {
|
||||
failed: true,
|
||||
restart: this.restartOnAuthFail,
|
||||
failureEventPayload: 'Unable to log in. Are the session details valid?'
|
||||
};
|
||||
}
|
||||
|
||||
return { failed: false };
|
||||
}
|
||||
|
||||
async getAuthEventPayload() {
|
||||
const isMD = await this.client.pupPage.evaluate(() => {
|
||||
return window.Store.MDBackend;
|
||||
});
|
||||
|
||||
if(isMD) throw new Error('Authenticating via JSON session is not supported for MultiDevice-enabled WhatsApp accounts.');
|
||||
|
||||
const localStorage = JSON.parse(await this.client.pupPage.evaluate(() => {
|
||||
return JSON.stringify(window.localStorage);
|
||||
}));
|
||||
|
||||
return {
|
||||
WABrowserId: localStorage.WABrowserId,
|
||||
WASecretBundle: localStorage.WASecretBundle,
|
||||
WAToken1: localStorage.WAToken1,
|
||||
WAToken2: localStorage.WAToken2
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = LegacySessionAuth;
|
||||
@@ -13,7 +13,6 @@ exports.ExposeStore = (moduleRaidStr) => {
|
||||
window.Store.Cmd = window.mR.findModule('Cmd')[0].Cmd;
|
||||
window.Store.CryptoLib = window.mR.findModule('decryptE2EMedia')[0];
|
||||
window.Store.DownloadManager = window.mR.findModule('downloadManager')[0].downloadManager;
|
||||
window.Store.MDBackend = window.mR.findModule('isMDBackend')[0].isMDBackend();
|
||||
window.Store.Features = window.mR.findModule('FEATURE_CHANGE_EVENT')[0].LegacyPhoneFeatures;
|
||||
window.Store.GroupMetadata = window.mR.findModule((module) => module.default && module.default.handlePendingInvite)[0].default;
|
||||
window.Store.Invite = window.mR.findModule('sendJoinGroupViaInvite')[0];
|
||||
@@ -162,16 +161,7 @@ exports.LoadUtils = () => {
|
||||
if (options.linkPreview) {
|
||||
delete options.linkPreview;
|
||||
|
||||
// Not supported yet by WhatsApp Web on MD
|
||||
if(!window.Store.MDBackend) {
|
||||
const link = window.Store.Validators.findLink(content);
|
||||
if (link) {
|
||||
const preview = await window.Store.Wap.queryLinkPreview(link.url);
|
||||
preview.preview = true;
|
||||
preview.subtype = 'url';
|
||||
options = { ...options, ...preview };
|
||||
}
|
||||
}
|
||||
// TODO Not supported yet by WhatsApp Web on MD
|
||||
}
|
||||
|
||||
let buttonOptions = {};
|
||||
@@ -215,13 +205,12 @@ exports.LoadUtils = () => {
|
||||
}
|
||||
|
||||
const meUser = window.Store.User.getMaybeMeUser();
|
||||
const isMD = window.Store.MDBackend;
|
||||
|
||||
const newMsgId = new window.Store.MsgKey({
|
||||
from: meUser,
|
||||
to: chat.id,
|
||||
id: window.Store.MsgKey.newId(),
|
||||
participant: isMD && chat.id.isGroup() ? meUser : undefined,
|
||||
participant: chat.id.isGroup() ? meUser : undefined,
|
||||
selfDir: 'out',
|
||||
});
|
||||
|
||||
@@ -526,9 +515,8 @@ exports.LoadUtils = () => {
|
||||
};
|
||||
|
||||
window.WWebJS.sendChatstate = async (state, chatId) => {
|
||||
if (window.Store.MDBackend) {
|
||||
chatId = window.Store.WidFactory.createWid(chatId);
|
||||
}
|
||||
chatId = window.Store.WidFactory.createWid(chatId);
|
||||
|
||||
switch (state) {
|
||||
case 'typing':
|
||||
await window.Store.ChatState.sendChatStateComposing(chatId);
|
||||
|
||||
121
tests/client.js
121
tests/client.js
@@ -8,14 +8,12 @@ const Contact = require('../src/structures/Contact');
|
||||
const Message = require('../src/structures/Message');
|
||||
const MessageMedia = require('../src/structures/MessageMedia');
|
||||
const Location = require('../src/structures/Location');
|
||||
const LegacySessionAuth = require('../src/authStrategies/LegacySessionAuth');
|
||||
const { MessageTypes, WAState, DefaultOptions } = require('../src/util/Constants');
|
||||
const { MessageTypes, DefaultOptions } = require('../src/util/Constants');
|
||||
|
||||
const expect = chai.expect;
|
||||
chai.use(chaiAsPromised);
|
||||
|
||||
const remoteId = helper.remoteId;
|
||||
const isMD = helper.isMD();
|
||||
|
||||
describe('Client', function() {
|
||||
describe('User Agent', function () {
|
||||
@@ -155,123 +153,6 @@ describe('Client', function() {
|
||||
|
||||
await client.destroy();
|
||||
});
|
||||
|
||||
describe('LegacySessionAuth', function () {
|
||||
it('should fail auth if session is invalid', async function() {
|
||||
this.timeout(40000);
|
||||
|
||||
const authFailCallback = sinon.spy();
|
||||
const qrCallback = sinon.spy();
|
||||
const readyCallback = sinon.spy();
|
||||
|
||||
const client = helper.createClient({
|
||||
options: {
|
||||
authStrategy: new LegacySessionAuth({
|
||||
session: {
|
||||
WABrowserId: 'invalid',
|
||||
WASecretBundle: 'invalid',
|
||||
WAToken1: 'invalid',
|
||||
WAToken2: 'invalid'
|
||||
},
|
||||
restartOnAuthFail: false,
|
||||
}),
|
||||
}
|
||||
});
|
||||
|
||||
client.on('qr', qrCallback);
|
||||
client.on('auth_failure', authFailCallback);
|
||||
client.on('ready', readyCallback);
|
||||
|
||||
client.initialize();
|
||||
|
||||
await helper.sleep(25000);
|
||||
|
||||
expect(authFailCallback.called).to.equal(true);
|
||||
expect(authFailCallback.args[0][0]).to.equal('Unable to log in. Are the session details valid?');
|
||||
|
||||
expect(readyCallback.called).to.equal(false);
|
||||
expect(qrCallback.called).to.equal(false);
|
||||
|
||||
await client.destroy();
|
||||
});
|
||||
|
||||
it('can restart without a session if session was invalid and restartOnAuthFail=true', async function() {
|
||||
this.timeout(40000);
|
||||
|
||||
const authFailCallback = sinon.spy();
|
||||
const qrCallback = sinon.spy();
|
||||
|
||||
const client = helper.createClient({
|
||||
options: {
|
||||
authStrategy: new LegacySessionAuth({
|
||||
session: {
|
||||
WABrowserId: 'invalid',
|
||||
WASecretBundle: 'invalid',
|
||||
WAToken1: 'invalid',
|
||||
WAToken2: 'invalid'
|
||||
},
|
||||
restartOnAuthFail: true,
|
||||
}),
|
||||
}
|
||||
});
|
||||
|
||||
client.on('auth_failure', authFailCallback);
|
||||
client.on('qr', qrCallback);
|
||||
|
||||
client.initialize();
|
||||
|
||||
await helper.sleep(35000);
|
||||
|
||||
expect(authFailCallback.called).to.equal(true);
|
||||
expect(qrCallback.called).to.equal(true);
|
||||
expect(qrCallback.args[0][0]).to.have.lengthOf(152);
|
||||
|
||||
await client.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Non-MD only', function () {
|
||||
if(!isMD) {
|
||||
it('can take over if client was logged in somewhere else with takeoverOnConflict=true', async function() {
|
||||
this.timeout(40000);
|
||||
|
||||
const readyCallback1 = sinon.spy();
|
||||
const readyCallback2 = sinon.spy();
|
||||
const disconnectedCallback1 = sinon.spy();
|
||||
const disconnectedCallback2 = sinon.spy();
|
||||
|
||||
const client1 = helper.createClient({
|
||||
authenticated: true,
|
||||
options: { takeoverOnConflict: true, takeoverTimeoutMs: 5000 }
|
||||
});
|
||||
const client2 = helper.createClient({authenticated: true});
|
||||
|
||||
client1.on('ready', readyCallback1);
|
||||
client2.on('ready', readyCallback2);
|
||||
client1.on('disconnected', disconnectedCallback1);
|
||||
client2.on('disconnected', disconnectedCallback2);
|
||||
|
||||
await client1.initialize();
|
||||
expect(readyCallback1.called).to.equal(true);
|
||||
expect(readyCallback2.called).to.equal(false);
|
||||
expect(disconnectedCallback1.called).to.equal(false);
|
||||
expect(disconnectedCallback2.called).to.equal(false);
|
||||
|
||||
await client2.initialize();
|
||||
expect(readyCallback2.called).to.equal(true);
|
||||
expect(disconnectedCallback1.called).to.equal(false);
|
||||
expect(disconnectedCallback2.called).to.equal(false);
|
||||
|
||||
// wait for takeoverTimeoutMs to kick in
|
||||
await helper.sleep(5200);
|
||||
expect(disconnectedCallback1.called).to.equal(false);
|
||||
expect(disconnectedCallback2.called).to.equal(true);
|
||||
expect(disconnectedCallback2.calledWith(WAState.CONFLICT)).to.equal(true);
|
||||
|
||||
await client1.destroy();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('Authenticated', function() {
|
||||
|
||||
Reference in New Issue
Block a user