@open-wa/wa-automate 4.30.13 → 4.31.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/config-schema.json +1 -1
- package/dist/api/Client.d.ts +39 -41
- package/dist/api/Client.js +43 -42
- package/dist/api/model/aliases.d.ts +10 -6
- package/dist/api/model/aliases.js +1 -0
- package/dist/api/model/config.d.ts +4 -1
- package/dist/api/model/index.d.ts +1 -0
- package/dist/api/model/index.js +1 -0
- package/dist/api/model/product.d.ts +1 -1
- package/dist/cli/cli-options.js +7 -0
- package/dist/cli/setup.js +5 -1
- package/dist/controllers/auth.d.ts +5 -1
- package/dist/controllers/auth.js +24 -9
- package/dist/controllers/browser.js +79 -12
- package/dist/controllers/patch_manager.js +3 -1
- package/dist/controllers/script_preloader.d.ts +17 -0
- package/dist/controllers/script_preloader.js +83 -0
- package/dist/lib/launch.js +1 -1
- package/dist/lib/wapi.js +3 -3
- package/package.json +3 -3
@@ -45,12 +45,15 @@ const promise_1 = __importDefault(require("terminate/promise"));
|
|
45
45
|
const logging_1 = require("../logging/logging");
|
46
46
|
const tools_1 = require("../utils/tools");
|
47
47
|
const auth_1 = require("./auth");
|
48
|
-
|
48
|
+
const script_preloader_1 = require("./script_preloader");
|
49
|
+
const patch_manager_1 = require("./patch_manager");
|
50
|
+
let browser, wapiInjected = false, dumbCache = undefined, wapiAttempts = 1;
|
49
51
|
exports.BROWSER_START_TS = 0;
|
50
52
|
function initPage(sessionId, config, customUserAgent, spinner, _page, skipAuth) {
|
51
53
|
var _a, _b, _c, _d, _e;
|
52
54
|
return __awaiter(this, void 0, void 0, function* () {
|
53
55
|
const setupPromises = [];
|
56
|
+
script_preloader_1.scriptLoader.loadScripts();
|
54
57
|
if ((config === null || config === void 0 ? void 0 : config.resizable) === undefined || !(config === null || config === void 0 ? void 0 : config.resizable) == false)
|
55
58
|
config.defaultViewport = null;
|
56
59
|
if (config === null || config === void 0 ? void 0 : config.useStealth) {
|
@@ -65,7 +68,28 @@ function initPage(sessionId, config, customUserAgent, spinner, _page, skipAuth)
|
|
65
68
|
spinner === null || spinner === void 0 ? void 0 : spinner.info(`Browser launched: ${((0, tools_1.now)() - startBrowser).toFixed(0)}ms`);
|
66
69
|
waPage = yield getWAPage(browser);
|
67
70
|
}
|
71
|
+
//@ts-ignore
|
72
|
+
waPage._client.send('Network.setBypassServiceWorker', { bypass: true });
|
68
73
|
const postBrowserLaunchTs = (0, tools_1.now)();
|
74
|
+
waPage.on("framenavigated", (frame) => __awaiter(this, void 0, void 0, function* () {
|
75
|
+
try {
|
76
|
+
const frameNavPromises = [];
|
77
|
+
const content = yield frame.content();
|
78
|
+
const webpPackKey = (((content.match(/self.(?:.*)=self.*\|\|\[\]/g) || [])[0] || "").match(/self.*\w?=/g) || [""])[0].replace("=", "").replace("self.", "") || false;
|
79
|
+
logging_1.log.info(`FRAME NAV, ${frame.url()}, ${webpPackKey}`);
|
80
|
+
if (webpPackKey) {
|
81
|
+
frameNavPromises.push(injectApi(waPage, spinner, true));
|
82
|
+
frameNavPromises.push(auth_1.qrManager.waitFirstQr(waPage, config, spinner));
|
83
|
+
}
|
84
|
+
if (frame.url().includes('post_logout=1')) {
|
85
|
+
console.log("Session most likely logged out");
|
86
|
+
}
|
87
|
+
yield Promise.all(frameNavPromises);
|
88
|
+
}
|
89
|
+
catch (error) {
|
90
|
+
logging_1.log.error('framenaverr', error);
|
91
|
+
}
|
92
|
+
}));
|
69
93
|
spinner === null || spinner === void 0 ? void 0 : spinner.info('Setting Up Page');
|
70
94
|
if (config === null || config === void 0 ? void 0 : config.proxyServerCredentials) {
|
71
95
|
yield waPage.authenticate(config.proxyServerCredentials);
|
@@ -105,10 +129,34 @@ function initPage(sessionId, config, customUserAgent, spinner, _page, skipAuth)
|
|
105
129
|
if (proxyAddr) {
|
106
130
|
proxy = (yield Promise.resolve().then(() => __importStar(require('puppeteer-page-proxy')))).default;
|
107
131
|
}
|
108
|
-
if (interceptAuthentication || proxyAddr || blockCrashLogs) {
|
132
|
+
if (interceptAuthentication || proxyAddr || blockCrashLogs || true) {
|
109
133
|
yield waPage.setRequestInterception(true);
|
134
|
+
waPage.on('response', (response) => __awaiter(this, void 0, void 0, function* () {
|
135
|
+
try {
|
136
|
+
if (response.request().url() == "https://web.whatsapp.com/") {
|
137
|
+
const t = yield response.text();
|
138
|
+
if (t.includes(`class="no-js"`) && t.includes(`self.`) && !dumbCache) {
|
139
|
+
//this is a valid response, save it for later
|
140
|
+
dumbCache = t;
|
141
|
+
logging_1.log.info("saving valid page to dumb cache");
|
142
|
+
}
|
143
|
+
}
|
144
|
+
}
|
145
|
+
catch (error) {
|
146
|
+
logging_1.log.error("dumb cache error", error);
|
147
|
+
}
|
148
|
+
}));
|
110
149
|
const authCompleteEv = new events_1.EvEmitter(sessionId, 'AUTH');
|
111
150
|
waPage.on('request', (request) => __awaiter(this, void 0, void 0, function* () {
|
151
|
+
//local refresh cache:
|
152
|
+
if (request.url() === "https://web.whatsapp.com/" && dumbCache) {
|
153
|
+
//if the dumbCache isn't set and this response includes
|
154
|
+
logging_1.log.info("reviving page from dumb cache");
|
155
|
+
return yield request.respond({
|
156
|
+
status: 200,
|
157
|
+
body: dumbCache
|
158
|
+
});
|
159
|
+
}
|
112
160
|
if (interceptAuthentication &&
|
113
161
|
request.url().includes('_priority_components') &&
|
114
162
|
!quickAuthed) {
|
@@ -184,7 +232,6 @@ function initPage(sessionId, config, customUserAgent, spinner, _page, skipAuth)
|
|
184
232
|
//try twice
|
185
233
|
const WEB_START_TS = new Date().getTime();
|
186
234
|
const webRes = yield waPage.goto(puppeteer_config_1.puppeteerConfig.WAUrl);
|
187
|
-
Promise.all([injectApi(waPage, spinner), auth_1.qrManager.waitFirstQr(waPage, config, spinner)]);
|
188
235
|
const WEB_END_TS = new Date().getTime();
|
189
236
|
if (webRes == null) {
|
190
237
|
spinner === null || spinner === void 0 ? void 0 : spinner.info(`Page loaded but something may have gone wrong: ${WEB_END_TS - WEB_START_TS}ms`);
|
@@ -262,12 +309,15 @@ const getSessionDataFilePath = (sessionId, config) => {
|
|
262
309
|
return false;
|
263
310
|
};
|
264
311
|
exports.getSessionDataFilePath = getSessionDataFilePath;
|
265
|
-
const addScript = (page, js) => page.
|
266
|
-
path: require.resolve(path.join(__dirname, '../lib', js))
|
267
|
-
});
|
312
|
+
const addScript = (page, js) => __awaiter(void 0, void 0, void 0, function* () { return page.evaluate(yield script_preloader_1.scriptLoader.getScript(js)); });
|
268
313
|
exports.addScript = addScript;
|
314
|
+
// (page: Page, js : string) : Promise<unknown> => page.addScriptTag({
|
315
|
+
// path: require.resolve(path.join(__dirname, '../lib', js))
|
316
|
+
// })
|
269
317
|
function injectPreApiScripts(page, spinner) {
|
270
318
|
return __awaiter(this, void 0, void 0, function* () {
|
319
|
+
if (yield page.evaluate("!['jsSHA','axios', 'QRCode', 'Base64', 'objectHash'].find(x=>!window[x])"))
|
320
|
+
return;
|
271
321
|
const t1 = yield (0, tools_1.timePromise)(() => Promise.all([
|
272
322
|
'axios.min.js',
|
273
323
|
'jsSha.min.js',
|
@@ -282,17 +332,33 @@ function injectPreApiScripts(page, spinner) {
|
|
282
332
|
exports.injectPreApiScripts = injectPreApiScripts;
|
283
333
|
function injectWapi(page, spinner, force = false) {
|
284
334
|
return __awaiter(this, void 0, void 0, function* () {
|
335
|
+
const bruteInjectionAttempts = 1;
|
336
|
+
yield (0, patch_manager_1.earlyInjectionCheck)(page);
|
337
|
+
const check = `window.WAPI && window.Store ? true : false`;
|
338
|
+
const initCheck = yield page.evaluate(check);
|
339
|
+
if (initCheck)
|
340
|
+
return;
|
341
|
+
logging_1.log.info(`WAPI CHECK: ${initCheck}`);
|
342
|
+
if (!check)
|
343
|
+
force = true;
|
285
344
|
if (wapiInjected && !force)
|
286
345
|
return page;
|
287
|
-
const
|
288
|
-
|
289
|
-
|
346
|
+
const multiScriptInjectPromiseArr = Array(bruteInjectionAttempts).fill("wapi.js").map((_s) => (0, exports.addScript)(page, _s));
|
347
|
+
try {
|
348
|
+
const wapi = yield (0, tools_1.timePromise)(() => Promise.all(multiScriptInjectPromiseArr));
|
349
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.info(`WAPI inject: ${wapi}ms`);
|
350
|
+
}
|
351
|
+
catch (error) {
|
352
|
+
logging_1.log.error("injectWapi ~ error", error.message);
|
353
|
+
//one of the injection attempts failed.
|
354
|
+
return yield injectWapi(page, spinner, force);
|
355
|
+
}
|
290
356
|
spinner === null || spinner === void 0 ? void 0 : spinner.info("Checking session integrity");
|
291
357
|
wapiAttempts++;
|
292
|
-
wapiInjected = !!(yield page.waitForFunction(check, { timeout: 3000, polling:
|
358
|
+
wapiInjected = !!(yield page.waitForFunction(check, { timeout: 3000, polling: 50 }).catch(e => false));
|
293
359
|
if (!wapiInjected) {
|
294
360
|
spinner === null || spinner === void 0 ? void 0 : spinner.info(`Session integrity check failed, trying again... ${wapiAttempts}`);
|
295
|
-
return yield injectWapi(page, spinner);
|
361
|
+
return yield injectWapi(page, spinner, true);
|
296
362
|
}
|
297
363
|
spinner === null || spinner === void 0 ? void 0 : spinner.info("Session integrity check passed");
|
298
364
|
return page;
|
@@ -301,10 +367,11 @@ function injectWapi(page, spinner, force = false) {
|
|
301
367
|
exports.injectWapi = injectWapi;
|
302
368
|
function injectApi(page, spinner, force = false) {
|
303
369
|
return __awaiter(this, void 0, void 0, function* () {
|
370
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.info("Injecting scripts");
|
304
371
|
yield injectPreApiScripts(page, spinner);
|
305
372
|
yield injectWapi(page, spinner, force);
|
306
373
|
const launch = yield (0, tools_1.timePromise)(() => (0, exports.addScript)(page, 'launch.js'));
|
307
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.
|
374
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.succeed(`Launch inject: ${launch}ms`);
|
308
375
|
return page;
|
309
376
|
});
|
310
377
|
}
|
@@ -164,6 +164,8 @@ function getLicense(config, me, debugInfo, spinner) {
|
|
164
164
|
exports.getLicense = getLicense;
|
165
165
|
function earlyInjectionCheck(page) {
|
166
166
|
return __awaiter(this, void 0, void 0, function* () {
|
167
|
+
//@ts-ignore
|
168
|
+
yield page.waitForFunction(() => Object.entries(window).filter(([, o]) => o && o.push && (o.push != [].push))[0] ? true : false, { timeout: 10, polling: 500 }).catch(() => { });
|
167
169
|
//@ts-ignore
|
168
170
|
return yield page.evaluate(() => { if (window.webpackChunkwhatsapp_web_client) {
|
169
171
|
window.webpackChunkbuild = window.webpackChunkwhatsapp_web_client;
|
@@ -172,7 +174,7 @@ function earlyInjectionCheck(page) {
|
|
172
174
|
(function () { const f = Object.entries(window).filter(([, o]) => o && o.push && (o.push != [].push)); if (f[0]) {
|
173
175
|
window.webpackChunkbuild = window[f[0][0]];
|
174
176
|
} })();
|
175
|
-
} return (typeof webpackChunkbuild !== "undefined"); });
|
177
|
+
} return (typeof window.webpackChunkbuild !== "undefined"); });
|
176
178
|
});
|
177
179
|
}
|
178
180
|
exports.earlyInjectionCheck = earlyInjectionCheck;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
export declare class ScriptLoader {
|
2
|
+
scripts: string[];
|
3
|
+
contentRegistry: {
|
4
|
+
[key: string]: string;
|
5
|
+
};
|
6
|
+
constructor();
|
7
|
+
loadScripts(): Promise<{
|
8
|
+
[key: string]: string;
|
9
|
+
}>;
|
10
|
+
getScript(scriptName: string): Promise<string>;
|
11
|
+
flush(): void;
|
12
|
+
getScripts(): {
|
13
|
+
[key: string]: string;
|
14
|
+
};
|
15
|
+
}
|
16
|
+
declare const scriptLoader: ScriptLoader;
|
17
|
+
export { scriptLoader };
|
@@ -0,0 +1,83 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
5
|
+
}) : (function(o, m, k, k2) {
|
6
|
+
if (k2 === undefined) k2 = k;
|
7
|
+
o[k2] = m[k];
|
8
|
+
}));
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
11
|
+
}) : function(o, v) {
|
12
|
+
o["default"] = v;
|
13
|
+
});
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
15
|
+
if (mod && mod.__esModule) return mod;
|
16
|
+
var result = {};
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
18
|
+
__setModuleDefault(result, mod);
|
19
|
+
return result;
|
20
|
+
};
|
21
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
22
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
23
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
24
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
25
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
26
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
27
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
28
|
+
});
|
29
|
+
};
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
31
|
+
exports.scriptLoader = exports.ScriptLoader = void 0;
|
32
|
+
const path = __importStar(require("path"));
|
33
|
+
const fs = __importStar(require("fs"));
|
34
|
+
const logging_1 = require("../logging/logging");
|
35
|
+
const read = (_path) => new Promise((resolve, reject) => {
|
36
|
+
fs.readFile(require.resolve(path.join(__dirname, '../lib', _path)), 'utf8', (err, file) => {
|
37
|
+
if (err)
|
38
|
+
reject(err);
|
39
|
+
resolve(file);
|
40
|
+
});
|
41
|
+
});
|
42
|
+
class ScriptLoader {
|
43
|
+
constructor() {
|
44
|
+
this.scripts = [
|
45
|
+
// stage 1
|
46
|
+
'axios.min.js',
|
47
|
+
'jsSha.min.js',
|
48
|
+
'qr.min.js',
|
49
|
+
'base64.js',
|
50
|
+
'hash.js',
|
51
|
+
//stage 2
|
52
|
+
'wapi.js',
|
53
|
+
//stage 3,
|
54
|
+
'launch.js'
|
55
|
+
];
|
56
|
+
this.contentRegistry = {};
|
57
|
+
this.contentRegistry = {};
|
58
|
+
}
|
59
|
+
loadScripts() {
|
60
|
+
return __awaiter(this, void 0, void 0, function* () {
|
61
|
+
yield Promise.all(this.scripts.map(this.getScript.bind(this)));
|
62
|
+
return this.contentRegistry;
|
63
|
+
});
|
64
|
+
}
|
65
|
+
getScript(scriptName) {
|
66
|
+
return __awaiter(this, void 0, void 0, function* () {
|
67
|
+
if (!this.contentRegistry[scriptName]) {
|
68
|
+
this.contentRegistry[scriptName] = yield read(scriptName);
|
69
|
+
logging_1.log.info("SCRIPT READY: " + scriptName);
|
70
|
+
}
|
71
|
+
return this.contentRegistry[scriptName];
|
72
|
+
});
|
73
|
+
}
|
74
|
+
flush() {
|
75
|
+
this.contentRegistry = {};
|
76
|
+
}
|
77
|
+
getScripts() {
|
78
|
+
return this.contentRegistry;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
exports.ScriptLoader = ScriptLoader;
|
82
|
+
const scriptLoader = new ScriptLoader();
|
83
|
+
exports.scriptLoader = scriptLoader;
|