@open-wa/wa-automate 4.30.12 → 4.31.2
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/README.md +3 -3
- package/bin/config-schema.json +1 -1
- package/dist/api/Client.d.ts +39 -41
- package/dist/api/Client.js +44 -43
- 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/controllers/auth.d.ts +5 -1
- package/dist/controllers/auth.js +25 -9
- package/dist/controllers/browser.js +74 -12
- package/dist/controllers/initializer.js +1 -1
- 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,29 @@ 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
|
+
if (response.request().url() == "https://web.whatsapp.com/") {
|
136
|
+
const t = yield response.text();
|
137
|
+
if (t.includes(`class="no-js"`) && t.includes(`self.`) && !dumbCache) {
|
138
|
+
//this is a valid response, save it for later
|
139
|
+
dumbCache = t;
|
140
|
+
logging_1.log.info("saving valid page to dumb cache");
|
141
|
+
}
|
142
|
+
}
|
143
|
+
}));
|
110
144
|
const authCompleteEv = new events_1.EvEmitter(sessionId, 'AUTH');
|
111
145
|
waPage.on('request', (request) => __awaiter(this, void 0, void 0, function* () {
|
146
|
+
//local refresh cache:
|
147
|
+
if (request.url() === "https://web.whatsapp.com/" && dumbCache) {
|
148
|
+
//if the dumbCache isn't set and this response includes
|
149
|
+
logging_1.log.info("reviving page from dumb cache");
|
150
|
+
return yield request.respond({
|
151
|
+
status: 200,
|
152
|
+
body: dumbCache
|
153
|
+
});
|
154
|
+
}
|
112
155
|
if (interceptAuthentication &&
|
113
156
|
request.url().includes('_priority_components') &&
|
114
157
|
!quickAuthed) {
|
@@ -184,7 +227,6 @@ function initPage(sessionId, config, customUserAgent, spinner, _page, skipAuth)
|
|
184
227
|
//try twice
|
185
228
|
const WEB_START_TS = new Date().getTime();
|
186
229
|
const webRes = yield waPage.goto(puppeteer_config_1.puppeteerConfig.WAUrl);
|
187
|
-
Promise.all([injectApi(waPage, spinner), auth_1.qrManager.waitFirstQr(waPage, config, spinner)]);
|
188
230
|
const WEB_END_TS = new Date().getTime();
|
189
231
|
if (webRes == null) {
|
190
232
|
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 +304,15 @@ const getSessionDataFilePath = (sessionId, config) => {
|
|
262
304
|
return false;
|
263
305
|
};
|
264
306
|
exports.getSessionDataFilePath = getSessionDataFilePath;
|
265
|
-
const addScript = (page, js) => page.
|
266
|
-
path: require.resolve(path.join(__dirname, '../lib', js))
|
267
|
-
});
|
307
|
+
const addScript = (page, js) => __awaiter(void 0, void 0, void 0, function* () { return page.evaluate(yield script_preloader_1.scriptLoader.getScript(js)); });
|
268
308
|
exports.addScript = addScript;
|
309
|
+
// (page: Page, js : string) : Promise<unknown> => page.addScriptTag({
|
310
|
+
// path: require.resolve(path.join(__dirname, '../lib', js))
|
311
|
+
// })
|
269
312
|
function injectPreApiScripts(page, spinner) {
|
270
313
|
return __awaiter(this, void 0, void 0, function* () {
|
314
|
+
if (yield page.evaluate("!['jsSHA','axios', 'QRCode', 'Base64', 'objectHash'].find(x=>!window[x])"))
|
315
|
+
return;
|
271
316
|
const t1 = yield (0, tools_1.timePromise)(() => Promise.all([
|
272
317
|
'axios.min.js',
|
273
318
|
'jsSha.min.js',
|
@@ -282,17 +327,33 @@ function injectPreApiScripts(page, spinner) {
|
|
282
327
|
exports.injectPreApiScripts = injectPreApiScripts;
|
283
328
|
function injectWapi(page, spinner, force = false) {
|
284
329
|
return __awaiter(this, void 0, void 0, function* () {
|
330
|
+
const bruteInjectionAttempts = 1;
|
331
|
+
yield (0, patch_manager_1.earlyInjectionCheck)(page);
|
332
|
+
const check = `window.WAPI && window.Store ? true : false`;
|
333
|
+
const initCheck = yield page.evaluate(check);
|
334
|
+
if (initCheck)
|
335
|
+
return;
|
336
|
+
logging_1.log.info(`WAPI CHECK: ${initCheck}`);
|
337
|
+
if (!check)
|
338
|
+
force = true;
|
285
339
|
if (wapiInjected && !force)
|
286
340
|
return page;
|
287
|
-
const
|
288
|
-
|
289
|
-
|
341
|
+
const multiScriptInjectPromiseArr = Array(bruteInjectionAttempts).fill("wapi.js").map((_s) => (0, exports.addScript)(page, _s));
|
342
|
+
try {
|
343
|
+
const wapi = yield (0, tools_1.timePromise)(() => Promise.all(multiScriptInjectPromiseArr));
|
344
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.info(`WAPI inject: ${wapi}ms`);
|
345
|
+
}
|
346
|
+
catch (error) {
|
347
|
+
logging_1.log.error("injectWapi ~ error", error.message);
|
348
|
+
//one of the injection attempts failed.
|
349
|
+
return yield injectWapi(page, spinner, force);
|
350
|
+
}
|
290
351
|
spinner === null || spinner === void 0 ? void 0 : spinner.info("Checking session integrity");
|
291
352
|
wapiAttempts++;
|
292
|
-
wapiInjected = !!(yield page.waitForFunction(check, { timeout: 3000, polling:
|
353
|
+
wapiInjected = !!(yield page.waitForFunction(check, { timeout: 3000, polling: 50 }).catch(e => false));
|
293
354
|
if (!wapiInjected) {
|
294
355
|
spinner === null || spinner === void 0 ? void 0 : spinner.info(`Session integrity check failed, trying again... ${wapiAttempts}`);
|
295
|
-
return yield injectWapi(page, spinner);
|
356
|
+
return yield injectWapi(page, spinner, true);
|
296
357
|
}
|
297
358
|
spinner === null || spinner === void 0 ? void 0 : spinner.info("Session integrity check passed");
|
298
359
|
return page;
|
@@ -301,10 +362,11 @@ function injectWapi(page, spinner, force = false) {
|
|
301
362
|
exports.injectWapi = injectWapi;
|
302
363
|
function injectApi(page, spinner, force = false) {
|
303
364
|
return __awaiter(this, void 0, void 0, function* () {
|
365
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.info("Injecting scripts");
|
304
366
|
yield injectPreApiScripts(page, spinner);
|
305
367
|
yield injectWapi(page, spinner, force);
|
306
368
|
const launch = yield (0, tools_1.timePromise)(() => (0, exports.addScript)(page, 'launch.js'));
|
307
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.
|
369
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.succeed(`Launch inject: ${launch}ms`);
|
308
370
|
return page;
|
309
371
|
});
|
310
372
|
}
|
@@ -363,7 +363,7 @@ function create(config = {}) {
|
|
363
363
|
waPage.on('error', error => {
|
364
364
|
if (config === null || config === void 0 ? void 0 : config.logConsoleErrors)
|
365
365
|
console.error(error);
|
366
|
-
logging_1.log.error('Page Console Error:', error.text());
|
366
|
+
logging_1.log.error('Page Console Error:', error.message || (error === null || error === void 0 ? void 0 : error.text()));
|
367
367
|
});
|
368
368
|
if (config === null || config === void 0 ? void 0 : config.restartOnCrash)
|
369
369
|
waPage.on('error', (error) => __awaiter(this, void 0, void 0, function* () {
|
@@ -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;
|