diff --git a/index.d.ts b/index.d.ts index ae31dc4b07..f7473cdaa9 100644 --- a/index.d.ts +++ b/index.d.ts @@ -323,10 +323,6 @@ declare namespace WAWebJS { /** Emitted when authentication is successful */ on(event: 'authenticated', listener: ( - /** - * Object containing session information, when using LegacySessionAuth. Can be used to restore the session - */ - session?: ClientSession ) => void): this /** @@ -567,7 +563,7 @@ declare namespace WAWebJS { evalOnNewDoc?: Function, /** Puppeteer launch options. View docs here: https://github.com/puppeteer/puppeteer/ */ puppeteer?: puppeteer.PuppeteerNodeLaunchOptions & puppeteer.ConnectOptions - /** Determines how to save and restore sessions. Will use LegacySessionAuth if options.session is set. Otherwise, NoAuth will be used. */ + /** Determines how to save and restore sessions. Otherwise, NoAuth will be used. */ authStrategy?: AuthStrategy, /** The version of WhatsApp Web to use. Use options.webVersionCache to configure how the version is retrieved. */ webVersion?: string, @@ -575,15 +571,7 @@ declare namespace WAWebJS { webVersionCache?: WebCacheOptions, /** 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 + qrMaxRetries?: number /** If another whatsapp web session is detected (another browser), take over the session in the current browser * @default false */ takeoverOnConflict?: boolean, @@ -700,17 +688,6 @@ declare namespace WAWebJS { extract: (options: { session: string, path: string }) => Promise | 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 */ @@ -1717,6 +1694,8 @@ declare namespace WAWebJS { lastMessage: Message, /** Indicates if the Chat is pinned */ pinned: boolean, + /** Indicates if the Chat is locked */ + isLocked: boolean, /** Archives this chat */ archive: () => Promise, diff --git a/package.json b/package.json index 9b1e05da48..87716808e2 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ }, "homepage": "https://wwebjs.dev/", "dependencies": { - "@pedroslopez/moduleraid": "^5.0.2", "fluent-ffmpeg": "2.1.3", "mime": "^3.0.0", "node-fetch": "^2.6.9", diff --git a/src/Client.js b/src/Client.js index 3ab22186d0..dacc3d9275 100644 --- a/src/Client.js +++ b/src/Client.js @@ -2,15 +2,12 @@ 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 { 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'); @@ -23,15 +20,13 @@ 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. Otherwise, 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 @@ -96,30 +91,16 @@ class Client extends EventEmitter { * Private function */ async inject() { - 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)); - } - if(!res){ - throw 'auth timeout'; - } + const authTimeout = this.options.authTimeoutMs || 30000; + await this.pupPage.waitForFunction( + 'window.Debug?.VERSION != undefined', + { timeout: authTimeout } + ).catch(() => { throw 'auth timeout'; }); 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; @@ -231,25 +212,13 @@ class Client extends EventEmitter { await webCache.persist(this.currentIndexHtml, version); } - 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 this.pupPage.evaluate(ExposeStore); + + // Check window.Store Injection + await this.pupPage.waitForFunction( + 'window.Store != undefined', + { timeout: 30000 } + ).catch(() => { throw 'ready timeout'; }); /** * Current connection information @@ -287,12 +256,15 @@ class Client extends EventEmitter { 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.AuthStore.Cmd.on('offline_progress_update_from_bridge', () => { window.onOfflineProgressUpdateEvent(window.AuthStore.OfflineMessageHandler.getOfflineDeliveryProgress()); }); window.AuthStore.Cmd.on('logout', async () => { await window.onLogoutEvent(); }); + window.AuthStore.Cmd.on('logout_from_bridge', async () => { + await window.onLogoutEvent(); + }); }); } @@ -350,28 +322,12 @@ class Client extends EventEmitter { 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/' }); - await this.inject(); - this.pupPage.on('framenavigated', async (frame) => { if(frame.url().includes('post_logout=1') || this.lastLoggedOut) { this.emit(Events.DISCONNECTED, 'LOGOUT'); @@ -382,6 +338,8 @@ class Client extends EventEmitter { } await this.inject(); }); + + await this.inject(); } /** @@ -775,70 +733,54 @@ class Client extends EventEmitter { }); window.Store.Chat.on('change:unreadCount', (chat) => {window.onChatUnreadCountEvent(chat);}); - 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; - - return {...reaction, msgKey, parentMsgKey, senderUserJid, timestamp }; - })); - - return ogMethod(...args); - }).bind(module); - - const pollVoteModule = window.Store.AddonPollVoteTable; - const ogPollVoteMethod = pollVoteModule.bulkUpsert; - - 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; - - let parentMessage = window.Store.Msg.get(parentMsgKey._serialized); - if (!parentMessage) { - const fetched = await window.Store.Msg.getMessagesById([parentMsgKey._serialized]); - parentMessage = fetched?.messages?.[0] || null; - } + 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; + + return {...reaction, msgKey, parentMsgKey, senderUserJid, timestamp }; + })); - 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 ogMethod(...args); + }).bind(module); + + const pollVoteModule = window.Store.AddonPollVoteTable; + const ogPollVoteMethod = pollVoteModule.bulkUpsert; + + 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; + + let parentMessage = window.Store.Msg.get(parentMsgKey._serialized); + if (!parentMessage) { + const fetched = await window.Store.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); }); } @@ -1023,6 +965,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 || [], @@ -1560,9 +1503,7 @@ class Client extends EventEmitter { 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); + return await window.Store.ProfilePic.requestProfilePicFromServer(chatWid); } catch (err) { if(err.name === 'ServerStatusCodeError') return undefined; throw err; diff --git a/src/structures/Chat.js b/src/structures/Chat.js index 93d9a0c8dc..9cd76790c2 100644 --- a/src/structures/Chat.js +++ b/src/structures/Chat.js @@ -63,6 +63,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} diff --git a/src/structures/GroupChat.js b/src/structures/GroupChat.js index ae4c95de5d..63f8832c9a 100644 --- a/src/structures/GroupChat.js +++ b/src/structures/GroupChat.js @@ -389,11 +389,8 @@ class GroupChat extends Chat { */ async getInviteCode() { const codeRes = await this.client.pupPage.evaluate(async chatId => { - const chatWid = window.Store.WidFactory.createWid(chatId); try { - return window.compareWwebVersions(window.Debug.VERSION, '>=', '2.3000.1020730154') - ? await window.Store.GroupInvite.fetchMexGroupInviteCode(chatId) - : await window.Store.GroupInvite.queryGroupInviteCode(chatWid, true); + return await window.Store.GroupInvite.fetchMexGroupInviteCode(chatId); } catch (err) { if(err.name === 'ServerStatusCodeError') return undefined; diff --git a/src/structures/Message.js b/src/structures/Message.js index f563c1aeb0..62bb7dceef 100644 --- a/src/structures/Message.js +++ b/src/structures/Message.js @@ -515,14 +515,10 @@ class Message extends Base { window.Store.MsgActionChecks.canSenderRevokeMsg(msg) || window.Store.MsgActionChecks.canAdminRevokeMsg(msg); 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' }); + return window.Store.Cmd.sendRevokeMsgs(chat, { list: [msg], type: 'message' }, { clearMedia: clearMedia }); } - 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); + return window.Store.Cmd.sendDeleteMsgs(chat, { list: [msg], type: 'message' }, clearMedia); }, this.id._serialized, everyone, clearMedia); } diff --git a/src/util/Constants.js b/src/util/Constants.js index 053acd34e6..12624245ad 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -7,7 +7,7 @@ exports.DefaultOptions = { headless: true, defaultViewport: null }, - webVersion: '2.3000.1017054665', + webVersion: '2.3000.1030947950', webVersionCache: { type: 'local', }, diff --git a/src/util/Injected/AuthStore/LegacyAuthStore.js b/src/util/Injected/AuthStore/LegacyAuthStore.js deleted file mode 100644 index c3016f7d17..0000000000 --- a/src/util/Injected/AuthStore/LegacyAuthStore.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -//TODO: To be removed by version 2.3000.x hard release - -exports.ExposeLegacyAuthStore = (moduleRaidStr) => { - eval('var moduleRaid = ' + moduleRaidStr); - // eslint-disable-next-line no-undef - window.mR = moduleRaid(); - window.AuthStore = {}; - window.AuthStore.AppState = window.mR.findModule('Socket')[0].Socket; - window.AuthStore.Cmd = window.mR.findModule('Cmd')[0].Cmd; - window.AuthStore.Conn = window.mR.findModule('Conn')[0].Conn; - window.AuthStore.OfflineMessageHandler = window.mR.findModule('OfflineMessageHandler')[0].OfflineMessageHandler; - window.AuthStore.PairingCodeLinkUtils = window.mR.findModule('initializeAltDeviceLinking')[0]; - window.AuthStore.Base64Tools = window.mR.findModule('encodeB64')[0]; - window.AuthStore.RegistrationUtils = { - ...window.mR.findModule('getCompanionWebClientFromBrowser')[0], - ...window.mR.findModule('verifyKeyIndexListAccountSignature')[0], - ...window.mR.findModule('waNoiseInfo')[0], - ...window.mR.findModule('waSignalStore')[0], - }; -}; \ No newline at end of file diff --git a/src/util/Injected/LegacyStore.js b/src/util/Injected/LegacyStore.js deleted file mode 100644 index e9584d9b7a..0000000000 --- a/src/util/Injected/LegacyStore.js +++ /dev/null @@ -1,146 +0,0 @@ -'use strict'; - -//TODO: To be removed by version 2.3000.x hard release - -// Exposes the internal Store to the WhatsApp Web client -exports.ExposeLegacyStore = () => { - window.Store = Object.assign({}, window.mR.findModule(m => m.default && m.default.Chat)[0].default); - window.Store.AppState = window.mR.findModule('Socket')[0].Socket; - window.Store.Conn = window.mR.findModule('Conn')[0].Conn; - window.Store.BlockContact = window.mR.findModule('blockContact')[0]; - window.Store.Call = window.mR.findModule((module) => module.default && module.default.Call)[0].default.Call; - 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.GroupMetadata = window.mR.findModule('GroupMetadata')[0].default.GroupMetadata; - window.Store.GroupQueryAndUpdate = window.mR.findModule('queryAndUpdateGroupMetadataById')[0].queryAndUpdateGroupMetadataById; - window.Store.Label = window.mR.findModule('LabelCollection')[0].LabelCollection; - window.Store.MediaPrep = window.mR.findModule('prepRawMedia')[0]; - window.Store.MediaObject = window.mR.findModule('getOrCreateMediaObject')[0]; - window.Store.NumberInfo = window.mR.findModule('formattedPhoneNumber')[0]; - window.Store.MediaTypes = window.mR.findModule('msgToMediaType')[0]; - window.Store.MediaUpload = window.mR.findModule('uploadMedia')[0]; - window.Store.MsgKey = window.mR.findModule((module) => module.default && module.default.fromString)[0].default; - window.Store.OpaqueData = window.mR.findModule(module => module.default && module.default.createFromData)[0].default; - window.Store.QueryProduct = window.mR.findModule('queryProduct')[0]; - window.Store.QueryOrder = window.mR.findModule('queryOrder')[0]; - window.Store.SendClear = window.mR.findModule('sendClear')[0]; - window.Store.SendDelete = window.mR.findModule('sendDelete')[0]; - window.Store.SendMessage = window.mR.findModule('addAndSendMsgToChat')[0]; - window.Store.EditMessage = window.mR.findModule('addAndSendMessageEdit')[0]; - window.Store.SendSeen = window.mR.findModule('sendSeen')[0]; - window.Store.User = window.mR.findModule('getMaybeMeUser')[0]; - window.Store.ContactMethods = window.mR.findModule('getUserid')[0]; - window.Store.UploadUtils = window.mR.findModule((module) => (module.default && module.default.encryptAndUpload) ? module.default : null)[0].default; - window.Store.UserConstructor = window.mR.findModule((module) => (module.default && module.default.prototype && module.default.prototype.isServer && module.default.prototype.isUser) ? module.default : null)[0].default; - window.Store.Validators = window.mR.findModule('findLinks')[0]; - window.Store.VCard = window.mR.findModule('vcardFromContactModel')[0]; - window.Store.WidFactory = window.mR.findModule('createWid')[0]; - window.Store.ProfilePic = window.mR.findModule('profilePicResync')[0]; - window.Store.PresenceUtils = window.mR.findModule('sendPresenceAvailable')[0]; - window.Store.ChatState = window.mR.findModule('sendChatStateComposing')[0]; - window.Store.findCommonGroups = window.mR.findModule('findCommonGroups')[0].findCommonGroups; - window.Store.StatusUtils = window.mR.findModule('setMyStatus')[0]; - window.Store.ConversationMsgs = window.mR.findModule('loadEarlierMsgs')[0]; - window.Store.sendReactionToMsg = window.mR.findModule('sendReactionToMsg')[0].sendReactionToMsg; - window.Store.createOrUpdateReactionsModule = window.mR.findModule('createOrUpdateReactions')[0]; - window.Store.EphemeralFields = window.mR.findModule('getEphemeralFields')[0]; - window.Store.MsgActionChecks = window.mR.findModule('canSenderRevokeMsg')[0]; - window.Store.QuotedMsg = window.mR.findModule('getQuotedMsgObj')[0]; - window.Store.LinkPreview = window.mR.findModule('getLinkPreview')[0]; - window.Store.Socket = window.mR.findModule('deprecatedSendIq')[0]; - window.Store.SocketWap = window.mR.findModule('wap')[0]; - window.Store.SearchContext = window.mR.findModule('getSearchContext')[0].getSearchContext; - window.Store.DrawerManager = window.mR.findModule('DrawerManager')[0].DrawerManager; - window.Store.LidUtils = window.mR.findModule('getCurrentLid')[0]; - window.Store.WidToJid = window.mR.findModule('widToUserJid')[0]; - window.Store.JidToWid = window.mR.findModule('userJidToUserWid')[0]; - window.Store.getMsgInfo = (window.mR.findModule('sendQueryMsgInfo')[0] || {}).sendQueryMsgInfo || window.mR.findModule('queryMsgInfo')[0].queryMsgInfo; - window.Store.pinUnpinMsg = window.mR.findModule('sendPinInChatMsg')[0].sendPinInChatMsg; - - /* eslint-disable no-undef, no-cond-assign */ - window.Store.QueryExist = ((m = window.mR.findModule('queryExists')[0]) ? m.queryExists : window.mR.findModule('queryExist')[0].queryWidExists); - window.Store.ReplyUtils = (m = window.mR.findModule('canReplyMsg')).length > 0 && m[0]; - /* eslint-enable no-undef, no-cond-assign */ - - window.Store.Settings = { - ...window.mR.findModule('ChatlistPanelState')[0], - setPushname: window.mR.findModule((m) => m.setPushname && !m.ChatlistPanelState)[0].setPushname - }; - window.Store.StickerTools = { - ...window.mR.findModule('toWebpSticker')[0], - ...window.mR.findModule('addWebpMetadata')[0] - }; - window.Store.GroupUtils = { - ...window.mR.findModule('createGroup')[0], - ...window.mR.findModule('setGroupDescription')[0], - ...window.mR.findModule('sendExitGroup')[0], - ...window.mR.findModule('sendSetPicture')[0] - }; - window.Store.GroupParticipants = { - ...window.mR.findModule('promoteParticipants')[0], - ...window.mR.findModule('sendAddParticipantsRPC')[0] - }; - window.Store.GroupInvite = { - ...window.mR.findModule('resetGroupInviteCode')[0], - ...window.mR.findModule('queryGroupInvite')[0] - }; - window.Store.GroupInviteV4 = { - ...window.mR.findModule('queryGroupInviteV4')[0], - ...window.mR.findModule('sendGroupInviteMessage')[0] - }; - window.Store.MembershipRequestUtils = { - ...window.mR.findModule('getMembershipApprovalRequests')[0], - ...window.mR.findModule('sendMembershipRequestsActionRPC')[0] - }; - - if (!window.Store.Chat._find) { - window.Store.Chat._find = e => { - const target = window.Store.Chat.get(e); - return target ? Promise.resolve(target) : Promise.resolve({ - id: e - }); - }; - } - - // eslint-disable-next-line no-undef - if ((m = window.mR.findModule('ChatCollection')[0]) && m.ChatCollection && typeof m.ChatCollection.findImpl === 'undefined' && typeof m.ChatCollection._find !== 'undefined') m.ChatCollection.findImpl = m.ChatCollection._find; - - const _isMDBackend = window.mR.findModule('isMDBackend'); - if(_isMDBackend && _isMDBackend[0] && _isMDBackend[0].isMDBackend) { - window.Store.MDBackend = _isMDBackend[0].isMDBackend(); - } else { - window.Store.MDBackend = true; - } - - const _features = window.mR.findModule('FEATURE_CHANGE_EVENT')[0]; - if(_features) { - window.Store.Features = _features.LegacyPhoneFeatures; - } - - /** - * Target options object description - * @typedef {Object} TargetOptions - * @property {string|number} module The name or a key of the target module to search - * @property {number} index The index value of 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.injectToFunction = (target, callback) => { - const module = typeof target.module === 'string' - ? window.mR.findModule(target.module) - : window.mR.modules[target.module]; - const originalFunction = module[target.index][target.function]; - const modifiedFunction = (...args) => callback(originalFunction, ...args); - module[target.index][target.function] = modifiedFunction; - }; - - window.injectToFunction({ module: 'mediaTypeFromProtobuf', index: 0, function: 'mediaTypeFromProtobuf' }, (func, ...args) => { const [proto] = args; return proto.locationMessage ? null : func(...args); }); - - window.injectToFunction({ module: 'typeAttributeFromProtobuf', index: 0, function: 'typeAttributeFromProtobuf' }, (func, ...args) => { const [proto] = args; return proto.locationMessage || proto.groupInviteMessage ? 'text' : func(...args); }); -}; \ No newline at end of file diff --git a/src/util/Injected/Store.js b/src/util/Injected/Store.js index 8f56a56ba6..1b9a8cd876 100644 --- a/src/util/Injected/Store.js +++ b/src/util/Injected/Store.js @@ -121,7 +121,8 @@ exports.ExposeStore = () => { }; window.Store.NumberInfo = { ...window.require('WAPhoneUtils'), - ...window.require('WAPhoneFindCC') + ...window.require('WAPhoneFindCC'), + ...window.require('WAWebPhoneUtils') }; window.Store.ForwardUtils = { ...window.require('WAWebChatForwardMessage') diff --git a/tests/client.js b/tests/client.js index 0118c2010e..ac2883d9cc 100644 --- a/tests/client.js +++ b/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 () { @@ -139,139 +137,11 @@ describe('Client', function() { await client.initialize(); expect(authenticatedCallback.called).to.equal(true); - - if(helper.isUsingLegacySession()) { - const newSession = authenticatedCallback.args[0][0]; - expect(newSession).to.have.key([ - 'WABrowserId', - 'WASecretBundle', - 'WAToken1', - 'WAToken2' - ]); - } - expect(readyCallback.called).to.equal(true); expect(qrCallback.called).to.equal(false); 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.length.greaterThanOrEqual(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() { diff --git a/tests/helper.js b/tests/helper.js index fc9ddae556..8a60d97dd7 100644 --- a/tests/helper.js +++ b/tests/helper.js @@ -1,50 +1,19 @@ -const path = require('path'); -const { Client, LegacySessionAuth, LocalAuth } = require('..'); +const { Client, LocalAuth } = require('..'); require('dotenv').config(); const remoteId = process.env.WWEBJS_TEST_REMOTE_ID; if(!remoteId) throw new Error('The WWEBJS_TEST_REMOTE_ID environment variable has not been set.'); -function isUsingLegacySession() { - return Boolean(process.env.WWEBJS_TEST_SESSION || process.env.WWEBJS_TEST_SESSION_PATH); -} - -function isMD() { - return Boolean(process.env.WWEBJS_TEST_MD); -} - -if(isUsingLegacySession() && isMD()) throw 'Cannot use legacy sessions with WWEBJS_TEST_MD=true'; - -function getSessionFromEnv() { - if (!isUsingLegacySession()) return null; - - const envSession = process.env.WWEBJS_TEST_SESSION; - if(envSession) return JSON.parse(envSession); - - const envSessionPath = process.env.WWEBJS_TEST_SESSION_PATH; - if(envSessionPath) { - const absPath = path.resolve(process.cwd(), envSessionPath); - return require(absPath); - } -} - function createClient({authenticated, options: additionalOpts}={}) { const options = {}; if(authenticated) { - const legacySession = getSessionFromEnv(); - if(legacySession) { - options.authStrategy = new LegacySessionAuth({ - session: legacySession - }); - } else { - const clientId = process.env.WWEBJS_TEST_CLIENT_ID; - if(!clientId) throw new Error('No session found in environment.'); - options.authStrategy = new LocalAuth({ - clientId - }); - } + const clientId = process.env.WWEBJS_TEST_CLIENT_ID; + if(!clientId) throw new Error('No session found in environment.'); + options.authStrategy = new LocalAuth({ + clientId + }); } const allOpts = {...options, ...(additionalOpts || {})}; @@ -58,7 +27,5 @@ function sleep(ms) { module.exports = { sleep, createClient, - isUsingLegacySession, - isMD, remoteId, }; \ No newline at end of file