adspower-browser 2.0.6 → 2.0.8
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/cli/index.js +510 -315
- package/package.json +1 -1
package/cli/index.js
CHANGED
|
@@ -93,11 +93,12 @@ var Store = class {
|
|
|
93
93
|
var store = new Store();
|
|
94
94
|
|
|
95
95
|
// src/core/start.ts
|
|
96
|
-
var
|
|
97
|
-
var
|
|
98
|
-
var
|
|
96
|
+
var fs3 = __toESM(require("fs"));
|
|
97
|
+
var path4 = __toESM(require("path"));
|
|
98
|
+
var import_node_child_process3 = require("child_process");
|
|
99
99
|
|
|
100
100
|
// src/tools/index.ts
|
|
101
|
+
var readline = __toESM(require("readline/promises"));
|
|
101
102
|
var os = __toESM(require("os"));
|
|
102
103
|
var path = __toESM(require("path"));
|
|
103
104
|
var fs = __toESM(require("fs"));
|
|
@@ -288,244 +289,188 @@ var initSqlite3 = () => {
|
|
|
288
289
|
logSuccess(`[i] SQLite file initialized successfully!`);
|
|
289
290
|
}
|
|
290
291
|
};
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
return [];
|
|
292
|
+
async function promptYesNo(question) {
|
|
293
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
294
|
+
logWarning("[!] Interactive prompt is unavailable in non-interactive mode.");
|
|
295
|
+
return null;
|
|
296
296
|
}
|
|
297
|
-
const
|
|
298
|
-
|
|
299
|
-
|
|
297
|
+
const rl = readline.createInterface({
|
|
298
|
+
input: process.stdin,
|
|
299
|
+
output: process.stdout
|
|
300
|
+
});
|
|
301
|
+
try {
|
|
302
|
+
while (true) {
|
|
303
|
+
const answer = (await rl.question(`${question} [y/N]: `)).trim().toLowerCase();
|
|
304
|
+
if (answer === "y" || answer === "yes") {
|
|
305
|
+
return "y";
|
|
306
|
+
}
|
|
307
|
+
if (answer === "n" || answer === "no" || answer === "") {
|
|
308
|
+
return "n";
|
|
309
|
+
}
|
|
310
|
+
logWarning("[!] Please enter y or n.");
|
|
311
|
+
}
|
|
312
|
+
} finally {
|
|
313
|
+
rl.close();
|
|
300
314
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// src/core/check.ts
|
|
318
|
+
var import_axios = __toESM(require("axios"));
|
|
319
|
+
var import_fs = __toESM(require("fs"));
|
|
320
|
+
var import_path = __toESM(require("path"));
|
|
321
|
+
var import_node_child_process2 = require("child_process");
|
|
322
|
+
var NPM_PACKAGE_NAME = "adspower-browser";
|
|
323
|
+
var NPM_REGISTRY_URL = `https://registry.npmjs.org/${NPM_PACKAGE_NAME}/latest`;
|
|
324
|
+
var checkUpdates = async (apiKey, baseUrl) => {
|
|
325
|
+
const [js, npm] = await Promise.all([
|
|
326
|
+
checkUpdateJS(apiKey, baseUrl),
|
|
327
|
+
checkUpdateNpmPackage()
|
|
328
|
+
]);
|
|
329
|
+
return {
|
|
330
|
+
js,
|
|
331
|
+
npm: npm.hasUpdate,
|
|
332
|
+
npmLatestVersion: npm.latestVersion
|
|
310
333
|
};
|
|
311
|
-
if (store.getStoreValue("baseUrl")) {
|
|
312
|
-
env.BASE_URL = store.getStoreValue("baseUrl");
|
|
313
|
-
}
|
|
314
|
-
if (store.getStoreValue("nodeEnv")) {
|
|
315
|
-
env.NODE_ENV = store.getStoreValue("nodeEnv");
|
|
316
|
-
}
|
|
317
|
-
return env;
|
|
318
334
|
};
|
|
319
|
-
var
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
const processInstance = readPidFile();
|
|
325
|
-
if (processInstance && processInstance.pid) {
|
|
326
|
-
const isRun = await isRunning(processInstance.pid);
|
|
327
|
-
removePidFile();
|
|
328
|
-
if (isRun) {
|
|
329
|
-
process.kill(Number(processInstance.pid), "SIGKILL");
|
|
330
|
-
await sleepTime(1e3);
|
|
331
|
-
}
|
|
335
|
+
var checkUpdateJS = async (apiKey, baseUrl) => {
|
|
336
|
+
return new Promise(async (resolve) => {
|
|
337
|
+
let system = "";
|
|
338
|
+
if (process.platform === "win32") {
|
|
339
|
+
system = process.arch === "x64" ? "x64" : "x86";
|
|
332
340
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
if (text.indexOf("START_API_SERVER_SUCCESS_$$_") === 0) {
|
|
361
|
-
const port = text.replace("START_API_SERVER_SUCCESS_$$_", "").trim();
|
|
362
|
-
store.setStoreValue("apiPort", port);
|
|
363
|
-
const localUrl = `http://local.adspower.net:${port}`;
|
|
364
|
-
logSuccess(`Server running at:`);
|
|
365
|
-
logSuccess(` - local: ${toTerminalLink(localUrl)}`);
|
|
366
|
-
writePidFile(store.getAllStoreValue());
|
|
367
|
-
if (child) {
|
|
368
|
-
child.disconnect();
|
|
369
|
-
child.unref();
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
if (text.includes("CACHE_FOLDER_$$_")) {
|
|
373
|
-
const cacheFolder = text.replace("CACHE_FOLDER_$$_", "").trim();
|
|
374
|
-
logSuccess(`[i] Cache folder: ${cacheFolder}`);
|
|
375
|
-
}
|
|
376
|
-
if (text.indexOf("START_API_SERVER_FAIL_$$_") === 0) {
|
|
377
|
-
const serverMsg = text.replace("START_API_SERVER_FAIL_$$_", "").split("_").filter(Boolean);
|
|
378
|
-
if (serverMsg[0]) {
|
|
379
|
-
logError(`ERROR - ${serverMsg[0]}`);
|
|
380
|
-
}
|
|
381
|
-
if (serverMsg[1]) {
|
|
382
|
-
logError(`ERROR - ${serverMsg[1]}`);
|
|
383
|
-
}
|
|
384
|
-
process.exit(0);
|
|
385
|
-
}
|
|
386
|
-
if (text === "start") {
|
|
387
|
-
clearTimeout(timer);
|
|
388
|
-
resolve();
|
|
389
|
-
store.setStoreValue("status", "doing");
|
|
390
|
-
writePidFile(store.getAllStoreValue());
|
|
391
|
-
}
|
|
392
|
-
if (text === "restart") {
|
|
393
|
-
child && child.kill("SIGKILL");
|
|
394
|
-
store.setStoreValue("status", "restarting");
|
|
395
|
-
startChild("2").catch(() => {
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
if (text.indexOf("INTRANET_$$_") > -1) {
|
|
399
|
-
const arr = text.split("_$$_");
|
|
400
|
-
if (arr && arr[1]) {
|
|
401
|
-
store.setStoreValue("intranet", arr[1]);
|
|
341
|
+
if (process.platform === "darwin") {
|
|
342
|
+
system = process.arch === "arm64" ? "arm64" : "mac";
|
|
343
|
+
}
|
|
344
|
+
if (process.platform === "linux") {
|
|
345
|
+
system = "linux_x64";
|
|
346
|
+
}
|
|
347
|
+
const curVersion = await getCurVersion();
|
|
348
|
+
if (!curVersion) {
|
|
349
|
+
resolve(false);
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
import_axios.default.get(`${baseUrl || "https://api.adspower.com/"}client/sys-version/list`, {
|
|
353
|
+
headers: {
|
|
354
|
+
"api-key": apiKey
|
|
355
|
+
},
|
|
356
|
+
params: {
|
|
357
|
+
version: `v${curVersion}`,
|
|
358
|
+
system
|
|
359
|
+
}
|
|
360
|
+
}).then(async (res) => {
|
|
361
|
+
const data = res.data.data;
|
|
362
|
+
if (data && data.js) {
|
|
363
|
+
const newVersion = data.js.version;
|
|
364
|
+
if (curVersion) {
|
|
365
|
+
if (greaterThanVersion(newVersion, curVersion)) {
|
|
366
|
+
resolve(true);
|
|
367
|
+
return;
|
|
402
368
|
}
|
|
403
369
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
}
|
|
411
|
-
if (text.indexOf("RPA_PLUS_PROCESS_PID_") > -1) {
|
|
412
|
-
const rpaPlusPid = text.replace("RPA_PLUS_PROCESS_PID_", "");
|
|
413
|
-
store.setStoreValue("rpaPlusPid", rpaPlusPid);
|
|
414
|
-
}
|
|
415
|
-
if (text.indexOf("AI_PROCESS_PID_") > -1) {
|
|
416
|
-
const aiPid = text.replace("AI_PROCESS_PID_", "");
|
|
417
|
-
store.setStoreValue("aiPid", aiPid);
|
|
418
|
-
}
|
|
419
|
-
});
|
|
420
|
-
child.on("error", (err) => {
|
|
421
|
-
logError(`[!] Node\u542F\u52A8\u5931\u8D25: ${err.message}`);
|
|
422
|
-
store.setStoreValue("status", "stop");
|
|
423
|
-
store.clear();
|
|
424
|
-
removePidFile();
|
|
425
|
-
process.exit(0);
|
|
426
|
-
});
|
|
427
|
-
child.on("exit", async (code, signal) => {
|
|
428
|
-
if (signal === "SIGKILL") {
|
|
429
|
-
await browsersKill();
|
|
430
|
-
store.clear();
|
|
431
|
-
removePidFile();
|
|
432
|
-
} else {
|
|
433
|
-
child = null;
|
|
434
|
-
await sleepTime(500);
|
|
435
|
-
startChild("2").then(() => {
|
|
436
|
-
}).catch(() => {
|
|
437
|
-
logError("[!] Restart failed");
|
|
438
|
-
});
|
|
439
|
-
}
|
|
440
|
-
});
|
|
441
|
-
timer = setTimeout(() => {
|
|
442
|
-
child && child.kill("SIGKILL");
|
|
443
|
-
child = null;
|
|
444
|
-
store.setStoreValue("status", "stop");
|
|
445
|
-
logError("[!] Start Timeout");
|
|
446
|
-
reject("Start Timeout");
|
|
447
|
-
}, 30 * 1e3);
|
|
448
|
-
} catch (error) {
|
|
449
|
-
clearTimeout(timer);
|
|
450
|
-
reject(error);
|
|
451
|
-
child = null;
|
|
452
|
-
store.clear();
|
|
453
|
-
logError(`[!] Node\u542F\u52A8\u5931\u8D25: ${error instanceof Error ? error.message : JSON.stringify(error)}`);
|
|
454
|
-
}
|
|
370
|
+
}
|
|
371
|
+
resolve(false);
|
|
372
|
+
}).catch((err) => {
|
|
373
|
+
console.log(err);
|
|
374
|
+
resolve(false);
|
|
375
|
+
});
|
|
455
376
|
});
|
|
456
377
|
};
|
|
457
|
-
var
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
try {
|
|
466
|
-
await sleepTime(2e3);
|
|
467
|
-
process.kill(Number(processInstance.pid), "SIGKILL");
|
|
468
|
-
removePidFile();
|
|
469
|
-
} catch (error2) {
|
|
470
|
-
logError(`[!] Stop child fail: ${error2 instanceof Error ? error2.message : JSON.stringify(error2)}`);
|
|
471
|
-
if (isRun) {
|
|
472
|
-
logWarning(`[!] Please manually close the browser process: ${processInstance.pid}`);
|
|
473
|
-
}
|
|
474
|
-
return;
|
|
475
|
-
}
|
|
378
|
+
var checkUpdateNpmPackage = async () => {
|
|
379
|
+
try {
|
|
380
|
+
const res = await import_axios.default.get(NPM_REGISTRY_URL, {
|
|
381
|
+
timeout: 3e4
|
|
382
|
+
});
|
|
383
|
+
const latestVersion = res.data?.version;
|
|
384
|
+
if (!latestVersion || typeof latestVersion !== "string") {
|
|
385
|
+
return { hasUpdate: false };
|
|
476
386
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
387
|
+
return {
|
|
388
|
+
hasUpdate: greaterThanVersion(latestVersion, VERSION),
|
|
389
|
+
latestVersion
|
|
390
|
+
};
|
|
391
|
+
} catch (err) {
|
|
392
|
+
return { hasUpdate: false };
|
|
480
393
|
}
|
|
481
394
|
};
|
|
482
|
-
var
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
const
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
await stopChild();
|
|
489
|
-
await sleepTime(1e3);
|
|
490
|
-
store.setStoreValue("apiKey", apiKey);
|
|
491
|
-
store.setStoreValue("baseUrl", baseUrl);
|
|
492
|
-
store.setStoreValue("nodeEnv", nodeEnv);
|
|
493
|
-
await startChild().then(() => {
|
|
494
|
-
logSuccess("[i] Adspower program is restarted");
|
|
495
|
-
}).catch((error) => {
|
|
496
|
-
logError(`[!] Restart failed: ${error.message}`);
|
|
395
|
+
var updateNpmPackage = async () => {
|
|
396
|
+
const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
397
|
+
await new Promise((resolve, reject) => {
|
|
398
|
+
const child = (0, import_node_child_process2.spawn)(npmCommand, ["install", "-g", `${NPM_PACKAGE_NAME}@latest`], {
|
|
399
|
+
stdio: "inherit",
|
|
400
|
+
windowsHide: true
|
|
497
401
|
});
|
|
498
|
-
|
|
499
|
-
|
|
402
|
+
child.on("error", reject);
|
|
403
|
+
child.on("close", (code) => {
|
|
404
|
+
if (code === 0) {
|
|
405
|
+
resolve();
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
reject(new Error(`npm install exited with code ${code}`));
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
};
|
|
412
|
+
var getCurVersion = async () => {
|
|
413
|
+
const mainJs = import_path.default.join(__dirname, "../cwd/lib", "main.min.js");
|
|
414
|
+
const curVersion = getVersion(await readFirstLienVersion(mainJs, (msg) => {
|
|
415
|
+
}));
|
|
416
|
+
return curVersion;
|
|
417
|
+
};
|
|
418
|
+
var getVersion = (line) => {
|
|
419
|
+
if (!line) {
|
|
420
|
+
return "";
|
|
500
421
|
}
|
|
422
|
+
return line.split(/\D/).filter((e) => e).join(".");
|
|
501
423
|
};
|
|
502
|
-
var
|
|
503
|
-
const
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
424
|
+
var readFirstLienVersion = (filePath, cb) => new Promise((resolve) => {
|
|
425
|
+
const rs = import_fs.default.createReadStream(filePath, {
|
|
426
|
+
encoding: "utf8",
|
|
427
|
+
start: 0,
|
|
428
|
+
end: 30
|
|
429
|
+
});
|
|
430
|
+
let acc = "";
|
|
431
|
+
let pos = 0;
|
|
432
|
+
let index;
|
|
433
|
+
rs.on("data", (chunk) => {
|
|
434
|
+
index = chunk.indexOf("\n");
|
|
435
|
+
acc += chunk;
|
|
436
|
+
index !== -1 ? rs.close() : pos += chunk.length;
|
|
437
|
+
}).on("close", () => {
|
|
438
|
+
const line = acc.slice(0, pos + index);
|
|
439
|
+
const i = line.indexOf("AdsPower") !== -1 ? line.indexOf("AdsPower") : line.indexOf("RPA");
|
|
440
|
+
if (i > 0 && i < 50) {
|
|
441
|
+
cb(`line-${line}`);
|
|
442
|
+
resolve(line);
|
|
509
443
|
return;
|
|
510
444
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
445
|
+
resolve("");
|
|
446
|
+
}).on("error", (err) => {
|
|
447
|
+
resolve("");
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
var greaterThanVersion = (onlineVersion, localVersion) => {
|
|
451
|
+
if (!onlineVersion) {
|
|
452
|
+
return false;
|
|
453
|
+
}
|
|
454
|
+
if (!localVersion) {
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
const onlineTemp = onlineVersion.replace(/[a-zA-Z]/g, "");
|
|
458
|
+
const localTemp = localVersion.replace(/[a-zA-Z]/g, "");
|
|
459
|
+
if (onlineTemp === localTemp) {
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
const onlineArr = onlineTemp.split(".");
|
|
463
|
+
const localArr = localTemp.split(".");
|
|
464
|
+
for (let i = 0; i < onlineArr.length; i += 1) {
|
|
465
|
+
if (+onlineArr[i] !== +localArr[i]) {
|
|
466
|
+
return +onlineArr[i] > +localArr[i];
|
|
521
467
|
}
|
|
522
|
-
} else {
|
|
523
|
-
logInfo("[i] Adspower program is not running");
|
|
524
468
|
}
|
|
469
|
+
return false;
|
|
525
470
|
};
|
|
526
471
|
|
|
527
472
|
// ../core/src/constants/api.ts
|
|
528
|
-
var
|
|
473
|
+
var import_axios2 = __toESM(require("axios"));
|
|
529
474
|
|
|
530
475
|
// ../core/src/constants/config.ts
|
|
531
476
|
function parseArgs() {
|
|
@@ -962,11 +907,11 @@ var API_ENDPOINTS = {
|
|
|
962
907
|
GET_KERNEL_LIST: LOCAL_API_CONTRACTS["get-kernel-list"].path,
|
|
963
908
|
UPDATE_PATCH: LOCAL_API_CONTRACTS["update-patch"].path
|
|
964
909
|
};
|
|
965
|
-
var apiClient =
|
|
910
|
+
var apiClient = import_axios2.default.create({
|
|
966
911
|
headers: API_KEY ? { "Authorization": `Bearer ${API_KEY}` } : {}
|
|
967
912
|
});
|
|
968
913
|
var getApiClient = () => {
|
|
969
|
-
const client =
|
|
914
|
+
const client = import_axios2.default.create({
|
|
970
915
|
headers: CONFIG.apiKey ? { "Authorization": `Bearer ${CONFIG.apiKey}` } : {}
|
|
971
916
|
});
|
|
972
917
|
client.interceptors.request.use(async (config2) => {
|
|
@@ -1652,7 +1597,7 @@ var tagHandlers = {
|
|
|
1652
1597
|
};
|
|
1653
1598
|
|
|
1654
1599
|
// ../core/src/handlers/automation.ts
|
|
1655
|
-
var
|
|
1600
|
+
var import_path2 = __toESM(require("path"));
|
|
1656
1601
|
var import_os = __toESM(require("os"));
|
|
1657
1602
|
|
|
1658
1603
|
// ../core/src/utils/browserBase.ts
|
|
@@ -1706,7 +1651,7 @@ var BrowserBase = class {
|
|
|
1706
1651
|
var browserBase_default = new BrowserBase();
|
|
1707
1652
|
|
|
1708
1653
|
// ../core/src/handlers/automation.ts
|
|
1709
|
-
var defaultDownloadsPath =
|
|
1654
|
+
var defaultDownloadsPath = import_path2.default.join(import_os.default.homedir(), "Downloads");
|
|
1710
1655
|
|
|
1711
1656
|
// ../core/src/handlers/kernel.ts
|
|
1712
1657
|
var kernelHandlers = {
|
|
@@ -2504,6 +2449,9 @@ var schemas = {
|
|
|
2504
2449
|
}).strict()
|
|
2505
2450
|
};
|
|
2506
2451
|
|
|
2452
|
+
// src/handleAction.ts
|
|
2453
|
+
var import_colors2 = require("colors");
|
|
2454
|
+
|
|
2507
2455
|
// src/cli.ts
|
|
2508
2456
|
function formatJsonValueForHelp(value, indent) {
|
|
2509
2457
|
const pad = " ".repeat(indent);
|
|
@@ -2803,77 +2751,7 @@ function resolveStatelessCommandArgs(commandName, params) {
|
|
|
2803
2751
|
}
|
|
2804
2752
|
}
|
|
2805
2753
|
|
|
2806
|
-
// src/startConfig.ts
|
|
2807
|
-
var MISSING_API_KEY_ERROR = "error: required option '-k, --api-key <apiKey>' not specified";
|
|
2808
|
-
function resolveStartApiKey(optionApiKey, env = process.env) {
|
|
2809
|
-
if (optionApiKey) {
|
|
2810
|
-
return {
|
|
2811
|
-
ok: true,
|
|
2812
|
-
apiKey: optionApiKey
|
|
2813
|
-
};
|
|
2814
|
-
}
|
|
2815
|
-
if (env.ADS_API_KEY) {
|
|
2816
|
-
return {
|
|
2817
|
-
ok: true,
|
|
2818
|
-
apiKey: env.ADS_API_KEY
|
|
2819
|
-
};
|
|
2820
|
-
}
|
|
2821
|
-
return {
|
|
2822
|
-
ok: false,
|
|
2823
|
-
error: MISSING_API_KEY_ERROR
|
|
2824
|
-
};
|
|
2825
|
-
}
|
|
2826
|
-
|
|
2827
|
-
// src/completion.ts
|
|
2828
|
-
var import_commander = __toESM(require("@bomb.sh/tab/commander"));
|
|
2829
|
-
var CLI_BIN_ALIASES = ["ads", "adspower", "adspower-browser"];
|
|
2830
|
-
function patchShellCompletionScript(shell, script) {
|
|
2831
|
-
if (shell === "zsh") {
|
|
2832
|
-
return script.replace(/^#compdef .+$/m, `#compdef ${CLI_BIN_ALIASES.join(" ")}`).replace(/^compdef _ads ads$/m, `compdef _ads ${CLI_BIN_ALIASES.join(" ")}`);
|
|
2833
|
-
}
|
|
2834
|
-
if (shell === "bash") {
|
|
2835
|
-
return script.replace(
|
|
2836
|
-
/^complete -F __ads_complete ads$/m,
|
|
2837
|
-
`complete -F __ads_complete ${CLI_BIN_ALIASES.join(" ")}`
|
|
2838
|
-
);
|
|
2839
|
-
}
|
|
2840
|
-
return script;
|
|
2841
|
-
}
|
|
2842
|
-
function setupShellCompletion(program2) {
|
|
2843
|
-
program2.name("ads");
|
|
2844
|
-
(0, import_commander.default)(program2);
|
|
2845
|
-
}
|
|
2846
|
-
function isShellCompletionRequest(argv = process.argv) {
|
|
2847
|
-
const completionIndex = argv.indexOf("complete");
|
|
2848
|
-
const dashDashIndex = argv.indexOf("--");
|
|
2849
|
-
return completionIndex !== -1 && dashDashIndex !== -1 && dashDashIndex > completionIndex;
|
|
2850
|
-
}
|
|
2851
|
-
function wrapShellScriptOutput(shell) {
|
|
2852
|
-
if (shell !== "zsh" && shell !== "bash") {
|
|
2853
|
-
return () => {
|
|
2854
|
-
};
|
|
2855
|
-
}
|
|
2856
|
-
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
2857
|
-
process.stdout.write = ((chunk, encoding, callback) => {
|
|
2858
|
-
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString(typeof encoding === "string" ? encoding : "utf8");
|
|
2859
|
-
const patched = patchShellCompletionScript(shell, text);
|
|
2860
|
-
if (typeof encoding === "function") {
|
|
2861
|
-
return originalWrite(patched, encoding);
|
|
2862
|
-
}
|
|
2863
|
-
return originalWrite(
|
|
2864
|
-
patched,
|
|
2865
|
-
encoding,
|
|
2866
|
-
callback
|
|
2867
|
-
);
|
|
2868
|
-
});
|
|
2869
|
-
return () => {
|
|
2870
|
-
process.stdout.write = originalWrite;
|
|
2871
|
-
};
|
|
2872
|
-
}
|
|
2873
|
-
|
|
2874
2754
|
// src/handleAction.ts
|
|
2875
|
-
var readline = __toESM(require("readline/promises"));
|
|
2876
|
-
var import_colors2 = require("colors");
|
|
2877
2755
|
var renderKernelProgress = (result) => {
|
|
2878
2756
|
const status = result.status || "pending";
|
|
2879
2757
|
const progress = ["completed", "installing"].includes(status) ? 100 : Math.max(0, Math.min(100, Number(result.progress) || 0));
|
|
@@ -2940,6 +2818,21 @@ var handleAction = async (params, options, command, fnc) => {
|
|
|
2940
2818
|
${out}
|
|
2941
2819
|
|
|
2942
2820
|
`);
|
|
2821
|
+
} else if (commandName === "update-patch") {
|
|
2822
|
+
const result = await fnc(args);
|
|
2823
|
+
const out = typeof result === "string" ? result : JSON.stringify(result, null, 2);
|
|
2824
|
+
if (!out.includes("The client is already on the latest patch version. No update is required")) {
|
|
2825
|
+
await sleepTime(1e3 * 60);
|
|
2826
|
+
loading.stop();
|
|
2827
|
+
await restartChild();
|
|
2828
|
+
} else {
|
|
2829
|
+
loading.stop();
|
|
2830
|
+
}
|
|
2831
|
+
logInfo(`
|
|
2832
|
+
|
|
2833
|
+
${out}
|
|
2834
|
+
`);
|
|
2835
|
+
return out;
|
|
2943
2836
|
} else {
|
|
2944
2837
|
const result = await fnc(args);
|
|
2945
2838
|
const out = typeof result === "string" ? result : JSON.stringify(result, null, 2);
|
|
@@ -2948,10 +2841,6 @@ ${out}
|
|
|
2948
2841
|
|
|
2949
2842
|
${out}
|
|
2950
2843
|
`);
|
|
2951
|
-
if (commandName === "update-patch" && !out.includes("The client is already on the latest patch version. No update is required")) {
|
|
2952
|
-
await sleepTime(1e3 * 60);
|
|
2953
|
-
await restartChild();
|
|
2954
|
-
}
|
|
2955
2844
|
return out;
|
|
2956
2845
|
}
|
|
2957
2846
|
} catch (error) {
|
|
@@ -3031,29 +2920,335 @@ var handleError = async (msg, commandName, params) => {
|
|
|
3031
2920
|
}
|
|
3032
2921
|
}
|
|
3033
2922
|
};
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
2923
|
+
|
|
2924
|
+
// src/core/start.ts
|
|
2925
|
+
var getRuntimeExecArgv = () => {
|
|
2926
|
+
if (process.platform !== "win32") {
|
|
2927
|
+
return [];
|
|
3038
2928
|
}
|
|
3039
|
-
const
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
}
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
2929
|
+
const preload = path4.join(__dirname, "core/winHideChildProcess.js");
|
|
2930
|
+
if (!fs3.existsSync(preload)) {
|
|
2931
|
+
return [];
|
|
2932
|
+
}
|
|
2933
|
+
return ["--require", preload];
|
|
2934
|
+
};
|
|
2935
|
+
var getEnv = () => {
|
|
2936
|
+
const env = {
|
|
2937
|
+
...process.env,
|
|
2938
|
+
// 系统的环境变量信息
|
|
2939
|
+
API_KEY: store.getStoreValue("apiKey"),
|
|
2940
|
+
IS_CLOUD_BROWSER: true
|
|
2941
|
+
// 云浏览器场景预留标识
|
|
2942
|
+
};
|
|
2943
|
+
if (store.getStoreValue("baseUrl")) {
|
|
2944
|
+
env.BASE_URL = store.getStoreValue("baseUrl");
|
|
2945
|
+
}
|
|
2946
|
+
if (store.getStoreValue("nodeEnv")) {
|
|
2947
|
+
env.NODE_ENV = store.getStoreValue("nodeEnv");
|
|
2948
|
+
}
|
|
2949
|
+
return env;
|
|
2950
|
+
};
|
|
2951
|
+
var startChild = (type) => {
|
|
2952
|
+
let timer;
|
|
2953
|
+
let child = null;
|
|
2954
|
+
return new Promise(async (resolve, reject) => {
|
|
2955
|
+
initSqlite3();
|
|
2956
|
+
const processInstance = readPidFile();
|
|
2957
|
+
if (processInstance && processInstance.pid) {
|
|
2958
|
+
const isRun = await isRunning(processInstance.pid);
|
|
2959
|
+
removePidFile();
|
|
2960
|
+
if (isRun) {
|
|
2961
|
+
process.kill(Number(processInstance.pid), "SIGKILL");
|
|
2962
|
+
await sleepTime(1e3);
|
|
3048
2963
|
}
|
|
3049
|
-
|
|
3050
|
-
|
|
2964
|
+
}
|
|
2965
|
+
const env = Object.fromEntries(
|
|
2966
|
+
Object.entries(getEnv()).map(([key, value]) => [key, value == null ? value : String(value)])
|
|
2967
|
+
);
|
|
2968
|
+
try {
|
|
2969
|
+
const mainJs = path4.join(__dirname, "../cwd/lib", "main.min.js");
|
|
2970
|
+
const forkOptions = {
|
|
2971
|
+
env,
|
|
2972
|
+
detached: true,
|
|
2973
|
+
windowsHide: true,
|
|
2974
|
+
// 隐藏子进程的控制台窗口
|
|
2975
|
+
stdio: ["ignore", "ignore", "ignore", "ipc"],
|
|
2976
|
+
execArgv: getRuntimeExecArgv()
|
|
2977
|
+
};
|
|
2978
|
+
child = (0, import_node_child_process3.fork)(mainJs, [], forkOptions);
|
|
2979
|
+
ensureBrowserPath();
|
|
2980
|
+
store.setStoreValue("status", "starting");
|
|
2981
|
+
logSuccess(`[i] Adspower program is starting...`);
|
|
2982
|
+
store.setStoreValue("pid", child?.pid?.toString() || "");
|
|
2983
|
+
let isAppPortOk = false;
|
|
2984
|
+
writePidFile(store.getAllStoreValue());
|
|
2985
|
+
child.on("message", async (msg) => {
|
|
2986
|
+
const text = String(msg);
|
|
2987
|
+
if (text.indexOf("SERVER_PORT_$$_") === 0 && !isAppPortOk) {
|
|
2988
|
+
const port = text.replace("SERVER_PORT_$$_", "").trim();
|
|
2989
|
+
store.setStoreValue("appPort", port);
|
|
2990
|
+
isAppPortOk = true;
|
|
2991
|
+
}
|
|
2992
|
+
if (text.indexOf("START_API_SERVER_SUCCESS_$$_") === 0) {
|
|
2993
|
+
const port = text.replace("START_API_SERVER_SUCCESS_$$_", "").trim();
|
|
2994
|
+
store.setStoreValue("apiPort", port);
|
|
2995
|
+
writePidFile(store.getAllStoreValue());
|
|
2996
|
+
if (child) {
|
|
2997
|
+
child.disconnect();
|
|
2998
|
+
child.unref();
|
|
2999
|
+
}
|
|
3000
|
+
const updates = await checkUpdates(store.getStoreValue("apiKey"), store.getStoreValue("baseUrl"));
|
|
3001
|
+
if (updates.js || updates.npm) {
|
|
3002
|
+
const answer = await promptYesNo(`[?] A new update is available. Update now?`);
|
|
3003
|
+
if (answer === "y") {
|
|
3004
|
+
if (updates.npm) {
|
|
3005
|
+
try {
|
|
3006
|
+
logInfo(`[i] Updating adspower-browser npm package${updates.npmLatestVersion ? ` to ${updates.npmLatestVersion}` : ""}...`);
|
|
3007
|
+
await updateNpmPackage();
|
|
3008
|
+
logSuccess(`[i] adspower-browser npm package updated. Please use the next command execution for the new CLI version.`);
|
|
3009
|
+
if (!updates.js) {
|
|
3010
|
+
await restartChild();
|
|
3011
|
+
}
|
|
3012
|
+
} catch (error) {
|
|
3013
|
+
logWarning(`[!] Failed to update adspower-browser npm package: ${error instanceof Error ? error.message : JSON.stringify(error)}`);
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
3016
|
+
if (updates.js) {
|
|
3017
|
+
await handleAction(
|
|
3018
|
+
JSON.stringify({ "version_type": "beta" }),
|
|
3019
|
+
{},
|
|
3020
|
+
{ name: () => "update-patch" },
|
|
3021
|
+
STATELESS_HANDLERS["update-patch"].fn
|
|
3022
|
+
);
|
|
3023
|
+
}
|
|
3024
|
+
return;
|
|
3025
|
+
}
|
|
3026
|
+
}
|
|
3027
|
+
const localUrl = `http://local.adspower.net:${port}`;
|
|
3028
|
+
logSuccess(`Server running at:`);
|
|
3029
|
+
logSuccess(` - local: ${toTerminalLink(localUrl)}`);
|
|
3030
|
+
}
|
|
3031
|
+
if (text.includes("CACHE_FOLDER_$$_")) {
|
|
3032
|
+
const cacheFolder = text.replace("CACHE_FOLDER_$$_", "").trim();
|
|
3033
|
+
logSuccess(`[i] Cache folder: ${cacheFolder}`);
|
|
3034
|
+
}
|
|
3035
|
+
if (text.indexOf("START_API_SERVER_FAIL_$$_") === 0) {
|
|
3036
|
+
const serverMsg = text.replace("START_API_SERVER_FAIL_$$_", "").split("_").filter(Boolean);
|
|
3037
|
+
if (serverMsg[0]) {
|
|
3038
|
+
logError(`ERROR - ${serverMsg[0]}`);
|
|
3039
|
+
}
|
|
3040
|
+
if (serverMsg[1]) {
|
|
3041
|
+
logError(`ERROR - ${serverMsg[1]}`);
|
|
3042
|
+
}
|
|
3043
|
+
process.exit(0);
|
|
3044
|
+
}
|
|
3045
|
+
if (text === "start") {
|
|
3046
|
+
clearTimeout(timer);
|
|
3047
|
+
resolve();
|
|
3048
|
+
store.setStoreValue("status", "doing");
|
|
3049
|
+
writePidFile(store.getAllStoreValue());
|
|
3050
|
+
}
|
|
3051
|
+
if (text === "restart") {
|
|
3052
|
+
child && child.kill("SIGKILL");
|
|
3053
|
+
store.setStoreValue("status", "restarting");
|
|
3054
|
+
startChild("2").catch(() => {
|
|
3055
|
+
});
|
|
3056
|
+
}
|
|
3057
|
+
if (text.indexOf("INTRANET_$$_") > -1) {
|
|
3058
|
+
const arr = text.split("_$$_");
|
|
3059
|
+
if (arr && arr[1]) {
|
|
3060
|
+
store.setStoreValue("intranet", arr[1]);
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
if (text === "browser-kill") {
|
|
3064
|
+
await browsersKill();
|
|
3065
|
+
}
|
|
3066
|
+
if (text.indexOf("RPA_PROCESS_PID_") > -1) {
|
|
3067
|
+
const rpaPid = text.replace("RPA_PROCESS_PID_", "");
|
|
3068
|
+
store.setStoreValue("rpaPid", rpaPid);
|
|
3069
|
+
}
|
|
3070
|
+
if (text.indexOf("RPA_PLUS_PROCESS_PID_") > -1) {
|
|
3071
|
+
const rpaPlusPid = text.replace("RPA_PLUS_PROCESS_PID_", "");
|
|
3072
|
+
store.setStoreValue("rpaPlusPid", rpaPlusPid);
|
|
3073
|
+
}
|
|
3074
|
+
if (text.indexOf("AI_PROCESS_PID_") > -1) {
|
|
3075
|
+
const aiPid = text.replace("AI_PROCESS_PID_", "");
|
|
3076
|
+
store.setStoreValue("aiPid", aiPid);
|
|
3077
|
+
}
|
|
3078
|
+
});
|
|
3079
|
+
child.on("error", (err) => {
|
|
3080
|
+
logError(`[!] Node\u542F\u52A8\u5931\u8D25: ${err.message}`);
|
|
3081
|
+
store.setStoreValue("status", "stop");
|
|
3082
|
+
store.clear();
|
|
3083
|
+
removePidFile();
|
|
3084
|
+
process.exit(0);
|
|
3085
|
+
});
|
|
3086
|
+
child.on("exit", async (code, signal) => {
|
|
3087
|
+
if (signal === "SIGKILL") {
|
|
3088
|
+
await browsersKill();
|
|
3089
|
+
store.clear();
|
|
3090
|
+
removePidFile();
|
|
3091
|
+
} else {
|
|
3092
|
+
child = null;
|
|
3093
|
+
await sleepTime(500);
|
|
3094
|
+
startChild("2").then(() => {
|
|
3095
|
+
}).catch(() => {
|
|
3096
|
+
logError("[!] Restart failed");
|
|
3097
|
+
});
|
|
3098
|
+
}
|
|
3099
|
+
});
|
|
3100
|
+
timer = setTimeout(() => {
|
|
3101
|
+
child && child.kill("SIGKILL");
|
|
3102
|
+
child = null;
|
|
3103
|
+
store.setStoreValue("status", "stop");
|
|
3104
|
+
logError("[!] Start Timeout");
|
|
3105
|
+
reject("Start Timeout");
|
|
3106
|
+
}, 30 * 1e3);
|
|
3107
|
+
} catch (error) {
|
|
3108
|
+
clearTimeout(timer);
|
|
3109
|
+
reject(error);
|
|
3110
|
+
child = null;
|
|
3111
|
+
store.clear();
|
|
3112
|
+
logError(`[!] Node\u542F\u52A8\u5931\u8D25: ${error instanceof Error ? error.message : JSON.stringify(error)}`);
|
|
3113
|
+
}
|
|
3114
|
+
});
|
|
3115
|
+
};
|
|
3116
|
+
var stopChild = async () => {
|
|
3117
|
+
const processInstance = readPidFile();
|
|
3118
|
+
if (processInstance.pid) {
|
|
3119
|
+
const isRun = await isRunning(processInstance.pid);
|
|
3120
|
+
try {
|
|
3121
|
+
process.kill(Number(processInstance.pid), "SIGKILL");
|
|
3122
|
+
removePidFile();
|
|
3123
|
+
} catch (error) {
|
|
3124
|
+
try {
|
|
3125
|
+
await sleepTime(2e3);
|
|
3126
|
+
process.kill(Number(processInstance.pid), "SIGKILL");
|
|
3127
|
+
removePidFile();
|
|
3128
|
+
} catch (error2) {
|
|
3129
|
+
logError(`[!] Stop child fail: ${error2 instanceof Error ? error2.message : JSON.stringify(error2)}`);
|
|
3130
|
+
if (isRun) {
|
|
3131
|
+
logWarning(`[!] Please manually close the browser process: ${processInstance.pid}`);
|
|
3132
|
+
}
|
|
3133
|
+
return;
|
|
3051
3134
|
}
|
|
3052
|
-
logWarning("[!] Please enter y or n.");
|
|
3053
3135
|
}
|
|
3054
|
-
|
|
3055
|
-
|
|
3136
|
+
logSuccess("[i] Adspower program is stopped");
|
|
3137
|
+
} else {
|
|
3138
|
+
logInfo("[i] No running adspower program");
|
|
3139
|
+
}
|
|
3140
|
+
};
|
|
3141
|
+
var restartChild = async () => {
|
|
3142
|
+
const processInstance = readPidFile();
|
|
3143
|
+
if (processInstance.pid) {
|
|
3144
|
+
const apiKey = processInstance.apiKey;
|
|
3145
|
+
const baseUrl = processInstance.baseUrl;
|
|
3146
|
+
const nodeEnv = processInstance.nodeEnv;
|
|
3147
|
+
await stopChild();
|
|
3148
|
+
await sleepTime(1e3);
|
|
3149
|
+
store.setStoreValue("apiKey", apiKey);
|
|
3150
|
+
store.setStoreValue("baseUrl", baseUrl);
|
|
3151
|
+
store.setStoreValue("nodeEnv", nodeEnv);
|
|
3152
|
+
await startChild().then(() => {
|
|
3153
|
+
logSuccess("[i] Adspower program is restarted");
|
|
3154
|
+
}).catch((error) => {
|
|
3155
|
+
logError(`[!] Restart failed: ${error.message}`);
|
|
3156
|
+
});
|
|
3157
|
+
} else {
|
|
3158
|
+
logInfo("[i] No running adspower program");
|
|
3056
3159
|
}
|
|
3160
|
+
};
|
|
3161
|
+
var getChildStatus = async () => {
|
|
3162
|
+
const processInstance = readPidFile();
|
|
3163
|
+
if (processInstance.pid) {
|
|
3164
|
+
const isRun = await isRunning(processInstance.pid);
|
|
3165
|
+
if (!isRun) {
|
|
3166
|
+
removePidFile();
|
|
3167
|
+
logInfo("[i] Adspower program is not running");
|
|
3168
|
+
return;
|
|
3169
|
+
}
|
|
3170
|
+
const status = processInstance.status;
|
|
3171
|
+
if (status === "starting") {
|
|
3172
|
+
logSuccess("[i] Adspower program is starting...");
|
|
3173
|
+
} else if (status === "doing" && processInstance.apiPort) {
|
|
3174
|
+
logSuccess("[i] Adspower program is running at:");
|
|
3175
|
+
logSuccess(` - http://local.adspower.net:${processInstance.apiPort}`);
|
|
3176
|
+
} else if (status === "stop") {
|
|
3177
|
+
logInfo("[i] Adspower program is stopped");
|
|
3178
|
+
} else {
|
|
3179
|
+
logInfo("[i] Adspower program is not started");
|
|
3180
|
+
}
|
|
3181
|
+
} else {
|
|
3182
|
+
logInfo("[i] Adspower program is not running");
|
|
3183
|
+
}
|
|
3184
|
+
};
|
|
3185
|
+
|
|
3186
|
+
// src/startConfig.ts
|
|
3187
|
+
var MISSING_API_KEY_ERROR = "error: required option '-k, --api-key <apiKey>' not specified";
|
|
3188
|
+
function resolveStartApiKey(optionApiKey, env = process.env) {
|
|
3189
|
+
if (optionApiKey) {
|
|
3190
|
+
return {
|
|
3191
|
+
ok: true,
|
|
3192
|
+
apiKey: optionApiKey
|
|
3193
|
+
};
|
|
3194
|
+
}
|
|
3195
|
+
if (env.ADS_API_KEY) {
|
|
3196
|
+
return {
|
|
3197
|
+
ok: true,
|
|
3198
|
+
apiKey: env.ADS_API_KEY
|
|
3199
|
+
};
|
|
3200
|
+
}
|
|
3201
|
+
return {
|
|
3202
|
+
ok: false,
|
|
3203
|
+
error: MISSING_API_KEY_ERROR
|
|
3204
|
+
};
|
|
3205
|
+
}
|
|
3206
|
+
|
|
3207
|
+
// src/completion.ts
|
|
3208
|
+
var import_commander = __toESM(require("@bomb.sh/tab/commander"));
|
|
3209
|
+
var CLI_BIN_ALIASES = ["ads", "adspower", "adspower-browser"];
|
|
3210
|
+
function patchShellCompletionScript(shell, script) {
|
|
3211
|
+
if (shell === "zsh") {
|
|
3212
|
+
return script.replace(/^#compdef .+$/m, `#compdef ${CLI_BIN_ALIASES.join(" ")}`).replace(/^compdef _ads ads$/m, `compdef _ads ${CLI_BIN_ALIASES.join(" ")}`);
|
|
3213
|
+
}
|
|
3214
|
+
if (shell === "bash") {
|
|
3215
|
+
return script.replace(
|
|
3216
|
+
/^complete -F __ads_complete ads$/m,
|
|
3217
|
+
`complete -F __ads_complete ${CLI_BIN_ALIASES.join(" ")}`
|
|
3218
|
+
);
|
|
3219
|
+
}
|
|
3220
|
+
return script;
|
|
3221
|
+
}
|
|
3222
|
+
function setupShellCompletion(program2) {
|
|
3223
|
+
program2.name("ads");
|
|
3224
|
+
(0, import_commander.default)(program2);
|
|
3225
|
+
}
|
|
3226
|
+
function isShellCompletionRequest(argv = process.argv) {
|
|
3227
|
+
const completionIndex = argv.indexOf("complete");
|
|
3228
|
+
const dashDashIndex = argv.indexOf("--");
|
|
3229
|
+
return completionIndex !== -1 && dashDashIndex !== -1 && dashDashIndex > completionIndex;
|
|
3230
|
+
}
|
|
3231
|
+
function wrapShellScriptOutput(shell) {
|
|
3232
|
+
if (shell !== "zsh" && shell !== "bash") {
|
|
3233
|
+
return () => {
|
|
3234
|
+
};
|
|
3235
|
+
}
|
|
3236
|
+
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
3237
|
+
process.stdout.write = ((chunk, encoding, callback) => {
|
|
3238
|
+
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString(typeof encoding === "string" ? encoding : "utf8");
|
|
3239
|
+
const patched = patchShellCompletionScript(shell, text);
|
|
3240
|
+
if (typeof encoding === "function") {
|
|
3241
|
+
return originalWrite(patched, encoding);
|
|
3242
|
+
}
|
|
3243
|
+
return originalWrite(
|
|
3244
|
+
patched,
|
|
3245
|
+
encoding,
|
|
3246
|
+
callback
|
|
3247
|
+
);
|
|
3248
|
+
});
|
|
3249
|
+
return () => {
|
|
3250
|
+
process.stdout.write = originalWrite;
|
|
3251
|
+
};
|
|
3057
3252
|
}
|
|
3058
3253
|
|
|
3059
3254
|
// src/index.ts
|