@iflyrpa/playwright 1.0.10 → 1.0.12
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/dist/index.cjs +90 -75
- package/dist/index.d.cts +18 -15
- package/dist/index.d.mts +18 -15
- package/dist/index.d.ts +18 -15
- package/dist/index.mjs +88 -74
- package/package.json +2 -3
package/dist/index.cjs
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const path = require('node:path');
|
|
4
3
|
const fs = require('node:fs');
|
|
4
|
+
const path = require('node:path');
|
|
5
5
|
const https = require('node:https');
|
|
6
6
|
const log = require('loglevel');
|
|
7
|
-
const
|
|
7
|
+
const npminstall = require('npminstall');
|
|
8
8
|
|
|
9
9
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
10
10
|
|
|
11
|
-
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
12
11
|
const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
12
|
+
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
13
13
|
const https__default = /*#__PURE__*/_interopDefaultCompat(https);
|
|
14
14
|
const log__default = /*#__PURE__*/_interopDefaultCompat(log);
|
|
15
|
+
const npminstall__default = /*#__PURE__*/_interopDefaultCompat(npminstall);
|
|
15
16
|
|
|
16
17
|
const name = "@iflyrpa/playwright";
|
|
17
18
|
const type = "module";
|
|
18
|
-
const version$1 = "1.0.
|
|
19
|
-
const description = "";
|
|
19
|
+
const version$1 = "1.0.12";
|
|
20
20
|
const main = "./dist/index.cjs";
|
|
21
21
|
const module$1 = "./dist/index.mjs";
|
|
22
22
|
const types = "./dist/index.d.ts";
|
|
@@ -25,8 +25,6 @@ const scripts = {
|
|
|
25
25
|
dev: "unbuild --stub",
|
|
26
26
|
start: "esno src/index.ts"
|
|
27
27
|
};
|
|
28
|
-
const keywords = [
|
|
29
|
-
];
|
|
30
28
|
const author = "bijinfeng";
|
|
31
29
|
const license = "ISC";
|
|
32
30
|
const files = [
|
|
@@ -34,6 +32,7 @@ const files = [
|
|
|
34
32
|
];
|
|
35
33
|
const dependencies = {
|
|
36
34
|
loglevel: "^1.9.2",
|
|
35
|
+
npminstall: "^7.12.0",
|
|
37
36
|
playwright: "^1.46.1"
|
|
38
37
|
};
|
|
39
38
|
const peerDependencies = {
|
|
@@ -48,12 +47,10 @@ const packageJson = {
|
|
|
48
47
|
name: name,
|
|
49
48
|
type: type,
|
|
50
49
|
version: version$1,
|
|
51
|
-
description: description,
|
|
52
50
|
main: main,
|
|
53
51
|
module: module$1,
|
|
54
52
|
types: types,
|
|
55
53
|
scripts: scripts,
|
|
56
|
-
keywords: keywords,
|
|
57
54
|
author: author,
|
|
58
55
|
license: license,
|
|
59
56
|
files: files,
|
|
@@ -215,13 +212,16 @@ function fetchJSON(url) {
|
|
|
215
212
|
});
|
|
216
213
|
});
|
|
217
214
|
}
|
|
215
|
+
function isNil(value) {
|
|
216
|
+
return value === null || value === void 0;
|
|
217
|
+
}
|
|
218
218
|
|
|
219
219
|
const visibleRangeTexts = {
|
|
220
220
|
public: "\u516C\u5F00",
|
|
221
221
|
private: "\u79C1\u5BC6"
|
|
222
222
|
};
|
|
223
223
|
const xiaohongshuPublishAction = async (props) => {
|
|
224
|
-
const { page,
|
|
224
|
+
const { page, tmpCachePath, params } = props;
|
|
225
225
|
const selectAddress = async (selector, address) => {
|
|
226
226
|
const instance = typeof selector === "string" ? page.locator(selector) : selector;
|
|
227
227
|
await instance.click();
|
|
@@ -244,11 +244,13 @@ const xiaohongshuPublishAction = async (props) => {
|
|
|
244
244
|
await page.locator("#content-area .menu-container .publish-video a").click().catch(() => {
|
|
245
245
|
throw new Error("\u672A\u627E\u5230\u53D1\u5E03\u7B14\u8BB0\u6309\u94AE");
|
|
246
246
|
});
|
|
247
|
-
await page.locator(".creator-container .header .title").filter({ hasText: /^上传图文$/ }).click()
|
|
247
|
+
await page.locator(".creator-container .header .title").filter({ hasText: /^上传图文$/ }).click().catch(() => {
|
|
248
|
+
throw new Error("\u672A\u627E\u5230\u4E0A\u4F20\u56FE\u6587\u6309\u94AE");
|
|
249
|
+
});
|
|
248
250
|
const images = await Promise.all(
|
|
249
251
|
params.banners.map((url) => {
|
|
250
252
|
const fileName = getFilenameFromUrl(url);
|
|
251
|
-
return downloadImage(url, path__default.join(
|
|
253
|
+
return downloadImage(url, path__default.join(tmpCachePath, fileName));
|
|
252
254
|
})
|
|
253
255
|
);
|
|
254
256
|
const fileChooserPromise = page.waitForEvent("filechooser");
|
|
@@ -383,12 +385,11 @@ const _Logger = class _Logger {
|
|
|
383
385
|
log__default.warn(...msg);
|
|
384
386
|
}
|
|
385
387
|
error(prefix, error) {
|
|
386
|
-
|
|
388
|
+
log__default.error(prefix);
|
|
387
389
|
if (error instanceof Error) {
|
|
388
|
-
|
|
389
|
-
Error stack: ${error.stack}
|
|
390
|
+
log__default.error(`${error.message}
|
|
391
|
+
Error stack: ${error.stack}`);
|
|
390
392
|
}
|
|
391
|
-
log__default.error(prefix, errorMessage);
|
|
392
393
|
}
|
|
393
394
|
close() {
|
|
394
395
|
this.stream.end();
|
|
@@ -413,7 +414,7 @@ const generateFile = async (dir) => {
|
|
|
413
414
|
}
|
|
414
415
|
return filePath;
|
|
415
416
|
};
|
|
416
|
-
const createElectronApp = async (cachePath,
|
|
417
|
+
const createElectronApp = async (cachePath, playwright) => {
|
|
417
418
|
const logger = Logger.getInstance(cachePath);
|
|
418
419
|
try {
|
|
419
420
|
const executablePath = path__default.join(
|
|
@@ -422,7 +423,6 @@ const createElectronApp = async (cachePath, playwrightPackage) => {
|
|
|
422
423
|
".bin",
|
|
423
424
|
"electron"
|
|
424
425
|
);
|
|
425
|
-
const playwright = await playwrightPackage;
|
|
426
426
|
const mainPath = await generateFile(cachePath);
|
|
427
427
|
const electronApp = await playwright._electron.launch({
|
|
428
428
|
executablePath,
|
|
@@ -434,6 +434,7 @@ const createElectronApp = async (cachePath, playwrightPackage) => {
|
|
|
434
434
|
return electronApp;
|
|
435
435
|
} catch (error) {
|
|
436
436
|
logger.error("electron \u542F\u52A8\u5931\u8D25\uFF1A", error);
|
|
437
|
+
throw error;
|
|
437
438
|
}
|
|
438
439
|
};
|
|
439
440
|
|
|
@@ -443,6 +444,7 @@ var __publicField$1 = (obj, key, value) => {
|
|
|
443
444
|
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
444
445
|
return value;
|
|
445
446
|
};
|
|
447
|
+
const NPM_REGISTRY = "https://registry.npmmirror.com/";
|
|
446
448
|
class PackageManager {
|
|
447
449
|
constructor(params) {
|
|
448
450
|
__publicField$1(this, "cacheDir");
|
|
@@ -453,41 +455,10 @@ class PackageManager {
|
|
|
453
455
|
__publicField$1(this, "logger");
|
|
454
456
|
this.logger = Logger.getInstance(params.cacheDir);
|
|
455
457
|
this.cacheDir = params.cacheDir;
|
|
456
|
-
this.forceUpdate = params.forceUpdate
|
|
458
|
+
this.forceUpdate = isNil(params.forceUpdate) ? true : params.forceUpdate;
|
|
457
459
|
this.initCacheProject();
|
|
458
460
|
this.initPromise = this.init(params.packageName, params.packageVersion);
|
|
459
461
|
}
|
|
460
|
-
// 在子线程执行 npm 命令
|
|
461
|
-
execCommand(cmd, modules, where = this.cacheDir) {
|
|
462
|
-
return new Promise((resolve) => {
|
|
463
|
-
const args = [cmd].concat(modules).concat("--color=always").concat("--save");
|
|
464
|
-
try {
|
|
465
|
-
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
466
|
-
const npm = node_child_process.spawn(npmCmd, args, { cwd: where });
|
|
467
|
-
let output = "";
|
|
468
|
-
npm.stdout?.on("data", (data) => {
|
|
469
|
-
output += data;
|
|
470
|
-
}).pipe(process.stdout);
|
|
471
|
-
npm.stderr?.on("data", (data) => {
|
|
472
|
-
output += data;
|
|
473
|
-
}).pipe(process.stderr);
|
|
474
|
-
npm.on("close", (code) => {
|
|
475
|
-
if (!code) {
|
|
476
|
-
resolve({ code: 0, data: output });
|
|
477
|
-
} else {
|
|
478
|
-
resolve({ code, data: output });
|
|
479
|
-
}
|
|
480
|
-
});
|
|
481
|
-
npm.on("error", (err) => {
|
|
482
|
-
console.error("NPM is not installed");
|
|
483
|
-
console.error(err);
|
|
484
|
-
});
|
|
485
|
-
} catch (error) {
|
|
486
|
-
this.logger.error(`npm ${args.join(" ")}: `, error);
|
|
487
|
-
console.error(error);
|
|
488
|
-
}
|
|
489
|
-
});
|
|
490
|
-
}
|
|
491
462
|
// 构建 package.json 文件,有了该文件后,依赖可以安装在该目录下,避免污染全局环境
|
|
492
463
|
initCacheProject() {
|
|
493
464
|
const packagePath = path__default.join(this.cacheDir, "package.json");
|
|
@@ -526,28 +497,33 @@ class PackageManager {
|
|
|
526
497
|
return this.getPlugin(module);
|
|
527
498
|
}
|
|
528
499
|
// 安装依赖
|
|
529
|
-
install(
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
return this.execCommand("update", [module]);
|
|
500
|
+
install(name, version) {
|
|
501
|
+
return npminstall__default({
|
|
502
|
+
root: this.cacheDir,
|
|
503
|
+
pkgs: [{ name, version }],
|
|
504
|
+
registry: NPM_REGISTRY
|
|
505
|
+
});
|
|
536
506
|
}
|
|
537
507
|
async init(name, version) {
|
|
538
508
|
const plugin = this.getPlugin(path__default.join(name, "package.json"));
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
if (
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
509
|
+
this.logger.info(`${name} \u662F\u5426\u5DF2\u5B89\u88C5\uFF1A${!!plugin}`);
|
|
510
|
+
try {
|
|
511
|
+
if (!plugin) {
|
|
512
|
+
await this.install(name, version);
|
|
513
|
+
} else if (this.forceUpdate) {
|
|
514
|
+
const pkInfo = await this.getPluginInfo(name);
|
|
515
|
+
if (!pkInfo)
|
|
516
|
+
return;
|
|
517
|
+
const hasNewVersion = semver.gt(pkInfo.version, plugin.version);
|
|
518
|
+
if (hasNewVersion) {
|
|
519
|
+
this.logger.info(`${name} \u68C0\u67E5\u5230\u65B0\u7248\u672C ${pkInfo.version}\uFF0C\u66F4\u65B0\u4F9D\u8D56`);
|
|
520
|
+
await this.install(name, pkInfo.version);
|
|
521
|
+
}
|
|
548
522
|
}
|
|
523
|
+
this.logger.info(`${name} package manager init done!`);
|
|
524
|
+
} catch (error) {
|
|
525
|
+
this.logger.error(`${name} package manager init error`, error);
|
|
549
526
|
}
|
|
550
|
-
this.logger.info(`${name} package manager init done!`);
|
|
551
527
|
}
|
|
552
528
|
}
|
|
553
529
|
|
|
@@ -558,17 +534,20 @@ var __publicField = (obj, key, value) => {
|
|
|
558
534
|
return value;
|
|
559
535
|
};
|
|
560
536
|
const PLAYWRIGHT_VERSION = "1.46.1";
|
|
537
|
+
const ELECTRON_VERSION = "22.3.27";
|
|
561
538
|
class LocalAutomateTask {
|
|
562
539
|
constructor({ cachePath, debug }) {
|
|
540
|
+
__publicField(this, "logger");
|
|
563
541
|
__publicField(this, "cachePath");
|
|
564
542
|
__publicField(this, "debug");
|
|
565
543
|
__publicField(this, "playwrightPackage");
|
|
566
|
-
__publicField(this, "
|
|
544
|
+
__publicField(this, "electronPackage");
|
|
567
545
|
__publicField(this, "_electronApp", null);
|
|
568
546
|
this.cachePath = cachePath;
|
|
569
547
|
this.debug = debug || false;
|
|
570
548
|
this.logger = Logger.getInstance(cachePath);
|
|
571
549
|
this.playwrightPackage = this.installPlaywright();
|
|
550
|
+
this.electronPackage = this.installElectron();
|
|
572
551
|
}
|
|
573
552
|
/**
|
|
574
553
|
* 安装 playwright
|
|
@@ -578,29 +557,65 @@ class LocalAutomateTask {
|
|
|
578
557
|
const playwrightPackageManager = new PackageManager({
|
|
579
558
|
packageName: "playwright",
|
|
580
559
|
packageVersion: PLAYWRIGHT_VERSION,
|
|
581
|
-
cacheDir: this.cachePath
|
|
560
|
+
cacheDir: this.cachePath,
|
|
561
|
+
forceUpdate: false
|
|
582
562
|
});
|
|
583
563
|
return playwrightPackageManager.getPluginAfterInit("playwright");
|
|
584
564
|
}
|
|
565
|
+
/**
|
|
566
|
+
* 安装 electron
|
|
567
|
+
* @returns
|
|
568
|
+
*/
|
|
569
|
+
installElectron() {
|
|
570
|
+
const playwrightPackageManager = new PackageManager({
|
|
571
|
+
packageName: "electron",
|
|
572
|
+
packageVersion: ELECTRON_VERSION,
|
|
573
|
+
cacheDir: this.cachePath,
|
|
574
|
+
forceUpdate: false
|
|
575
|
+
});
|
|
576
|
+
return playwrightPackageManager.getPluginAfterInit("electron");
|
|
577
|
+
}
|
|
585
578
|
/**
|
|
586
579
|
* 启动 Electron
|
|
587
580
|
* @returns
|
|
588
581
|
*/
|
|
589
582
|
async getElectronApp() {
|
|
590
583
|
if (!this._electronApp) {
|
|
591
|
-
|
|
592
|
-
this.
|
|
593
|
-
this.
|
|
594
|
-
);
|
|
584
|
+
const [playwright] = await Promise.all([
|
|
585
|
+
this.playwrightPackage,
|
|
586
|
+
this.electronPackage
|
|
587
|
+
]);
|
|
588
|
+
this._electronApp = await createElectronApp(this.cachePath, playwright);
|
|
595
589
|
}
|
|
596
590
|
return this._electronApp;
|
|
597
591
|
}
|
|
592
|
+
/**
|
|
593
|
+
* 临时文件目录
|
|
594
|
+
* @returns
|
|
595
|
+
*/
|
|
596
|
+
getTmpPath() {
|
|
597
|
+
return path__default.join(this.cachePath, "tmp");
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* 清空临时文件
|
|
601
|
+
*/
|
|
602
|
+
clearTmpPath() {
|
|
603
|
+
const tmpPath = this.getTmpPath();
|
|
604
|
+
return fs__default.rm(tmpPath, { recursive: true, force: true }, (err) => {
|
|
605
|
+
if (err) {
|
|
606
|
+
this.logger.error("\u5220\u9664\u4E34\u65F6\u6587\u4EF6\u5931\u8D25\uFF0C", err);
|
|
607
|
+
} else {
|
|
608
|
+
this.logger.info("\u5220\u9664\u4E34\u65F6\u6587\u4EF6\u6210\u529F");
|
|
609
|
+
}
|
|
610
|
+
});
|
|
611
|
+
}
|
|
598
612
|
/**
|
|
599
613
|
* 关闭 playwright 启动的 electron 客户端
|
|
600
614
|
* @returns
|
|
601
615
|
*/
|
|
602
616
|
async close() {
|
|
603
617
|
this.logger.close();
|
|
618
|
+
this.clearTmpPath();
|
|
604
619
|
const electronApp = await this.getElectronApp();
|
|
605
620
|
return electronApp.close();
|
|
606
621
|
}
|
|
@@ -652,13 +667,13 @@ class LocalAutomateTask {
|
|
|
652
667
|
const res = await xiaohongshuPublishAction({
|
|
653
668
|
page,
|
|
654
669
|
params,
|
|
655
|
-
|
|
670
|
+
tmpCachePath: this.getTmpPath(),
|
|
656
671
|
debug: !!this.debug
|
|
657
672
|
});
|
|
658
673
|
return res;
|
|
659
674
|
} catch (error) {
|
|
660
675
|
this.logger.error("\u5C0F\u7EA2\u4E66\u53D1\u5E03\u5931\u8D25", error);
|
|
661
|
-
|
|
676
|
+
throw error;
|
|
662
677
|
}
|
|
663
678
|
}
|
|
664
679
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
import { CookiesSetDetails } from 'electron';
|
|
2
2
|
|
|
3
|
-
declare class Logger {
|
|
4
|
-
static instance: Logger | null;
|
|
5
|
-
private stream;
|
|
6
|
-
constructor(cachePath: string);
|
|
7
|
-
static getInstance(cachePath: string): Logger;
|
|
8
|
-
debug(...msg: any[]): void;
|
|
9
|
-
info(...msg: any[]): void;
|
|
10
|
-
warn(...msg: any[]): void;
|
|
11
|
-
error(prefix: string, error: unknown): void;
|
|
12
|
-
close(): void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
3
|
type CookieMap = CookiesSetDetails[];
|
|
16
4
|
|
|
17
5
|
interface FictionalRendition {
|
|
@@ -55,10 +43,11 @@ interface TaskParams {
|
|
|
55
43
|
cachePath: string;
|
|
56
44
|
}
|
|
57
45
|
declare class LocalAutomateTask implements TaskParams {
|
|
46
|
+
private logger;
|
|
58
47
|
cachePath: string;
|
|
59
48
|
debug: boolean;
|
|
60
|
-
playwrightPackage
|
|
61
|
-
|
|
49
|
+
private playwrightPackage;
|
|
50
|
+
private electronPackage;
|
|
62
51
|
private _electronApp;
|
|
63
52
|
constructor({ cachePath, debug }: TaskParams);
|
|
64
53
|
/**
|
|
@@ -66,11 +55,25 @@ declare class LocalAutomateTask implements TaskParams {
|
|
|
66
55
|
* @returns
|
|
67
56
|
*/
|
|
68
57
|
private installPlaywright;
|
|
58
|
+
/**
|
|
59
|
+
* 安装 electron
|
|
60
|
+
* @returns
|
|
61
|
+
*/
|
|
62
|
+
private installElectron;
|
|
69
63
|
/**
|
|
70
64
|
* 启动 Electron
|
|
71
65
|
* @returns
|
|
72
66
|
*/
|
|
73
67
|
private getElectronApp;
|
|
68
|
+
/**
|
|
69
|
+
* 临时文件目录
|
|
70
|
+
* @returns
|
|
71
|
+
*/
|
|
72
|
+
private getTmpPath;
|
|
73
|
+
/**
|
|
74
|
+
* 清空临时文件
|
|
75
|
+
*/
|
|
76
|
+
private clearTmpPath;
|
|
74
77
|
/**
|
|
75
78
|
* 关闭 playwright 启动的 electron 客户端
|
|
76
79
|
* @returns
|
|
@@ -79,7 +82,7 @@ declare class LocalAutomateTask implements TaskParams {
|
|
|
79
82
|
/**
|
|
80
83
|
* 小红书自动化发布
|
|
81
84
|
*/
|
|
82
|
-
xiaohongshuPublish(params: XiaohonshuPublishParams): Promise<
|
|
85
|
+
xiaohongshuPublish(params: XiaohonshuPublishParams): Promise<string>;
|
|
83
86
|
}
|
|
84
87
|
declare const RpaTask: (params: TaskParams) => LocalAutomateTask;
|
|
85
88
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
import { CookiesSetDetails } from 'electron';
|
|
2
2
|
|
|
3
|
-
declare class Logger {
|
|
4
|
-
static instance: Logger | null;
|
|
5
|
-
private stream;
|
|
6
|
-
constructor(cachePath: string);
|
|
7
|
-
static getInstance(cachePath: string): Logger;
|
|
8
|
-
debug(...msg: any[]): void;
|
|
9
|
-
info(...msg: any[]): void;
|
|
10
|
-
warn(...msg: any[]): void;
|
|
11
|
-
error(prefix: string, error: unknown): void;
|
|
12
|
-
close(): void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
3
|
type CookieMap = CookiesSetDetails[];
|
|
16
4
|
|
|
17
5
|
interface FictionalRendition {
|
|
@@ -55,10 +43,11 @@ interface TaskParams {
|
|
|
55
43
|
cachePath: string;
|
|
56
44
|
}
|
|
57
45
|
declare class LocalAutomateTask implements TaskParams {
|
|
46
|
+
private logger;
|
|
58
47
|
cachePath: string;
|
|
59
48
|
debug: boolean;
|
|
60
|
-
playwrightPackage
|
|
61
|
-
|
|
49
|
+
private playwrightPackage;
|
|
50
|
+
private electronPackage;
|
|
62
51
|
private _electronApp;
|
|
63
52
|
constructor({ cachePath, debug }: TaskParams);
|
|
64
53
|
/**
|
|
@@ -66,11 +55,25 @@ declare class LocalAutomateTask implements TaskParams {
|
|
|
66
55
|
* @returns
|
|
67
56
|
*/
|
|
68
57
|
private installPlaywright;
|
|
58
|
+
/**
|
|
59
|
+
* 安装 electron
|
|
60
|
+
* @returns
|
|
61
|
+
*/
|
|
62
|
+
private installElectron;
|
|
69
63
|
/**
|
|
70
64
|
* 启动 Electron
|
|
71
65
|
* @returns
|
|
72
66
|
*/
|
|
73
67
|
private getElectronApp;
|
|
68
|
+
/**
|
|
69
|
+
* 临时文件目录
|
|
70
|
+
* @returns
|
|
71
|
+
*/
|
|
72
|
+
private getTmpPath;
|
|
73
|
+
/**
|
|
74
|
+
* 清空临时文件
|
|
75
|
+
*/
|
|
76
|
+
private clearTmpPath;
|
|
74
77
|
/**
|
|
75
78
|
* 关闭 playwright 启动的 electron 客户端
|
|
76
79
|
* @returns
|
|
@@ -79,7 +82,7 @@ declare class LocalAutomateTask implements TaskParams {
|
|
|
79
82
|
/**
|
|
80
83
|
* 小红书自动化发布
|
|
81
84
|
*/
|
|
82
|
-
xiaohongshuPublish(params: XiaohonshuPublishParams): Promise<
|
|
85
|
+
xiaohongshuPublish(params: XiaohonshuPublishParams): Promise<string>;
|
|
83
86
|
}
|
|
84
87
|
declare const RpaTask: (params: TaskParams) => LocalAutomateTask;
|
|
85
88
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
import { CookiesSetDetails } from 'electron';
|
|
2
2
|
|
|
3
|
-
declare class Logger {
|
|
4
|
-
static instance: Logger | null;
|
|
5
|
-
private stream;
|
|
6
|
-
constructor(cachePath: string);
|
|
7
|
-
static getInstance(cachePath: string): Logger;
|
|
8
|
-
debug(...msg: any[]): void;
|
|
9
|
-
info(...msg: any[]): void;
|
|
10
|
-
warn(...msg: any[]): void;
|
|
11
|
-
error(prefix: string, error: unknown): void;
|
|
12
|
-
close(): void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
3
|
type CookieMap = CookiesSetDetails[];
|
|
16
4
|
|
|
17
5
|
interface FictionalRendition {
|
|
@@ -55,10 +43,11 @@ interface TaskParams {
|
|
|
55
43
|
cachePath: string;
|
|
56
44
|
}
|
|
57
45
|
declare class LocalAutomateTask implements TaskParams {
|
|
46
|
+
private logger;
|
|
58
47
|
cachePath: string;
|
|
59
48
|
debug: boolean;
|
|
60
|
-
playwrightPackage
|
|
61
|
-
|
|
49
|
+
private playwrightPackage;
|
|
50
|
+
private electronPackage;
|
|
62
51
|
private _electronApp;
|
|
63
52
|
constructor({ cachePath, debug }: TaskParams);
|
|
64
53
|
/**
|
|
@@ -66,11 +55,25 @@ declare class LocalAutomateTask implements TaskParams {
|
|
|
66
55
|
* @returns
|
|
67
56
|
*/
|
|
68
57
|
private installPlaywright;
|
|
58
|
+
/**
|
|
59
|
+
* 安装 electron
|
|
60
|
+
* @returns
|
|
61
|
+
*/
|
|
62
|
+
private installElectron;
|
|
69
63
|
/**
|
|
70
64
|
* 启动 Electron
|
|
71
65
|
* @returns
|
|
72
66
|
*/
|
|
73
67
|
private getElectronApp;
|
|
68
|
+
/**
|
|
69
|
+
* 临时文件目录
|
|
70
|
+
* @returns
|
|
71
|
+
*/
|
|
72
|
+
private getTmpPath;
|
|
73
|
+
/**
|
|
74
|
+
* 清空临时文件
|
|
75
|
+
*/
|
|
76
|
+
private clearTmpPath;
|
|
74
77
|
/**
|
|
75
78
|
* 关闭 playwright 启动的 electron 客户端
|
|
76
79
|
* @returns
|
|
@@ -79,7 +82,7 @@ declare class LocalAutomateTask implements TaskParams {
|
|
|
79
82
|
/**
|
|
80
83
|
* 小红书自动化发布
|
|
81
84
|
*/
|
|
82
|
-
xiaohongshuPublish(params: XiaohonshuPublishParams): Promise<
|
|
85
|
+
xiaohongshuPublish(params: XiaohonshuPublishParams): Promise<string>;
|
|
83
86
|
}
|
|
84
87
|
declare const RpaTask: (params: TaskParams) => LocalAutomateTask;
|
|
85
88
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
3
|
import https from 'node:https';
|
|
4
4
|
import log from 'loglevel';
|
|
5
|
-
import
|
|
5
|
+
import npminstall from 'npminstall';
|
|
6
6
|
|
|
7
7
|
const name = "@iflyrpa/playwright";
|
|
8
8
|
const type = "module";
|
|
9
|
-
const version$1 = "1.0.
|
|
10
|
-
const description = "";
|
|
9
|
+
const version$1 = "1.0.12";
|
|
11
10
|
const main = "./dist/index.cjs";
|
|
12
11
|
const module = "./dist/index.mjs";
|
|
13
12
|
const types = "./dist/index.d.ts";
|
|
@@ -16,8 +15,6 @@ const scripts = {
|
|
|
16
15
|
dev: "unbuild --stub",
|
|
17
16
|
start: "esno src/index.ts"
|
|
18
17
|
};
|
|
19
|
-
const keywords = [
|
|
20
|
-
];
|
|
21
18
|
const author = "bijinfeng";
|
|
22
19
|
const license = "ISC";
|
|
23
20
|
const files = [
|
|
@@ -25,6 +22,7 @@ const files = [
|
|
|
25
22
|
];
|
|
26
23
|
const dependencies = {
|
|
27
24
|
loglevel: "^1.9.2",
|
|
25
|
+
npminstall: "^7.12.0",
|
|
28
26
|
playwright: "^1.46.1"
|
|
29
27
|
};
|
|
30
28
|
const peerDependencies = {
|
|
@@ -39,12 +37,10 @@ const packageJson = {
|
|
|
39
37
|
name: name,
|
|
40
38
|
type: type,
|
|
41
39
|
version: version$1,
|
|
42
|
-
description: description,
|
|
43
40
|
main: main,
|
|
44
41
|
module: module,
|
|
45
42
|
types: types,
|
|
46
43
|
scripts: scripts,
|
|
47
|
-
keywords: keywords,
|
|
48
44
|
author: author,
|
|
49
45
|
license: license,
|
|
50
46
|
files: files,
|
|
@@ -206,13 +202,16 @@ function fetchJSON(url) {
|
|
|
206
202
|
});
|
|
207
203
|
});
|
|
208
204
|
}
|
|
205
|
+
function isNil(value) {
|
|
206
|
+
return value === null || value === void 0;
|
|
207
|
+
}
|
|
209
208
|
|
|
210
209
|
const visibleRangeTexts = {
|
|
211
210
|
public: "\u516C\u5F00",
|
|
212
211
|
private: "\u79C1\u5BC6"
|
|
213
212
|
};
|
|
214
213
|
const xiaohongshuPublishAction = async (props) => {
|
|
215
|
-
const { page,
|
|
214
|
+
const { page, tmpCachePath, params } = props;
|
|
216
215
|
const selectAddress = async (selector, address) => {
|
|
217
216
|
const instance = typeof selector === "string" ? page.locator(selector) : selector;
|
|
218
217
|
await instance.click();
|
|
@@ -235,11 +234,13 @@ const xiaohongshuPublishAction = async (props) => {
|
|
|
235
234
|
await page.locator("#content-area .menu-container .publish-video a").click().catch(() => {
|
|
236
235
|
throw new Error("\u672A\u627E\u5230\u53D1\u5E03\u7B14\u8BB0\u6309\u94AE");
|
|
237
236
|
});
|
|
238
|
-
await page.locator(".creator-container .header .title").filter({ hasText: /^上传图文$/ }).click()
|
|
237
|
+
await page.locator(".creator-container .header .title").filter({ hasText: /^上传图文$/ }).click().catch(() => {
|
|
238
|
+
throw new Error("\u672A\u627E\u5230\u4E0A\u4F20\u56FE\u6587\u6309\u94AE");
|
|
239
|
+
});
|
|
239
240
|
const images = await Promise.all(
|
|
240
241
|
params.banners.map((url) => {
|
|
241
242
|
const fileName = getFilenameFromUrl(url);
|
|
242
|
-
return downloadImage(url, path.join(
|
|
243
|
+
return downloadImage(url, path.join(tmpCachePath, fileName));
|
|
243
244
|
})
|
|
244
245
|
);
|
|
245
246
|
const fileChooserPromise = page.waitForEvent("filechooser");
|
|
@@ -374,12 +375,11 @@ const _Logger = class _Logger {
|
|
|
374
375
|
log.warn(...msg);
|
|
375
376
|
}
|
|
376
377
|
error(prefix, error) {
|
|
377
|
-
|
|
378
|
+
log.error(prefix);
|
|
378
379
|
if (error instanceof Error) {
|
|
379
|
-
|
|
380
|
-
Error stack: ${error.stack}
|
|
380
|
+
log.error(`${error.message}
|
|
381
|
+
Error stack: ${error.stack}`);
|
|
381
382
|
}
|
|
382
|
-
log.error(prefix, errorMessage);
|
|
383
383
|
}
|
|
384
384
|
close() {
|
|
385
385
|
this.stream.end();
|
|
@@ -404,7 +404,7 @@ const generateFile = async (dir) => {
|
|
|
404
404
|
}
|
|
405
405
|
return filePath;
|
|
406
406
|
};
|
|
407
|
-
const createElectronApp = async (cachePath,
|
|
407
|
+
const createElectronApp = async (cachePath, playwright) => {
|
|
408
408
|
const logger = Logger.getInstance(cachePath);
|
|
409
409
|
try {
|
|
410
410
|
const executablePath = path.join(
|
|
@@ -413,7 +413,6 @@ const createElectronApp = async (cachePath, playwrightPackage) => {
|
|
|
413
413
|
".bin",
|
|
414
414
|
"electron"
|
|
415
415
|
);
|
|
416
|
-
const playwright = await playwrightPackage;
|
|
417
416
|
const mainPath = await generateFile(cachePath);
|
|
418
417
|
const electronApp = await playwright._electron.launch({
|
|
419
418
|
executablePath,
|
|
@@ -425,6 +424,7 @@ const createElectronApp = async (cachePath, playwrightPackage) => {
|
|
|
425
424
|
return electronApp;
|
|
426
425
|
} catch (error) {
|
|
427
426
|
logger.error("electron \u542F\u52A8\u5931\u8D25\uFF1A", error);
|
|
427
|
+
throw error;
|
|
428
428
|
}
|
|
429
429
|
};
|
|
430
430
|
|
|
@@ -434,6 +434,7 @@ var __publicField$1 = (obj, key, value) => {
|
|
|
434
434
|
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
435
435
|
return value;
|
|
436
436
|
};
|
|
437
|
+
const NPM_REGISTRY = "https://registry.npmmirror.com/";
|
|
437
438
|
class PackageManager {
|
|
438
439
|
constructor(params) {
|
|
439
440
|
__publicField$1(this, "cacheDir");
|
|
@@ -444,41 +445,10 @@ class PackageManager {
|
|
|
444
445
|
__publicField$1(this, "logger");
|
|
445
446
|
this.logger = Logger.getInstance(params.cacheDir);
|
|
446
447
|
this.cacheDir = params.cacheDir;
|
|
447
|
-
this.forceUpdate = params.forceUpdate
|
|
448
|
+
this.forceUpdate = isNil(params.forceUpdate) ? true : params.forceUpdate;
|
|
448
449
|
this.initCacheProject();
|
|
449
450
|
this.initPromise = this.init(params.packageName, params.packageVersion);
|
|
450
451
|
}
|
|
451
|
-
// 在子线程执行 npm 命令
|
|
452
|
-
execCommand(cmd, modules, where = this.cacheDir) {
|
|
453
|
-
return new Promise((resolve) => {
|
|
454
|
-
const args = [cmd].concat(modules).concat("--color=always").concat("--save");
|
|
455
|
-
try {
|
|
456
|
-
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
457
|
-
const npm = spawn(npmCmd, args, { cwd: where });
|
|
458
|
-
let output = "";
|
|
459
|
-
npm.stdout?.on("data", (data) => {
|
|
460
|
-
output += data;
|
|
461
|
-
}).pipe(process.stdout);
|
|
462
|
-
npm.stderr?.on("data", (data) => {
|
|
463
|
-
output += data;
|
|
464
|
-
}).pipe(process.stderr);
|
|
465
|
-
npm.on("close", (code) => {
|
|
466
|
-
if (!code) {
|
|
467
|
-
resolve({ code: 0, data: output });
|
|
468
|
-
} else {
|
|
469
|
-
resolve({ code, data: output });
|
|
470
|
-
}
|
|
471
|
-
});
|
|
472
|
-
npm.on("error", (err) => {
|
|
473
|
-
console.error("NPM is not installed");
|
|
474
|
-
console.error(err);
|
|
475
|
-
});
|
|
476
|
-
} catch (error) {
|
|
477
|
-
this.logger.error(`npm ${args.join(" ")}: `, error);
|
|
478
|
-
console.error(error);
|
|
479
|
-
}
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
452
|
// 构建 package.json 文件,有了该文件后,依赖可以安装在该目录下,避免污染全局环境
|
|
483
453
|
initCacheProject() {
|
|
484
454
|
const packagePath = path.join(this.cacheDir, "package.json");
|
|
@@ -517,28 +487,33 @@ class PackageManager {
|
|
|
517
487
|
return this.getPlugin(module);
|
|
518
488
|
}
|
|
519
489
|
// 安装依赖
|
|
520
|
-
install(
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
return this.execCommand("update", [module]);
|
|
490
|
+
install(name, version) {
|
|
491
|
+
return npminstall({
|
|
492
|
+
root: this.cacheDir,
|
|
493
|
+
pkgs: [{ name, version }],
|
|
494
|
+
registry: NPM_REGISTRY
|
|
495
|
+
});
|
|
527
496
|
}
|
|
528
497
|
async init(name, version) {
|
|
529
498
|
const plugin = this.getPlugin(path.join(name, "package.json"));
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
if (
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
499
|
+
this.logger.info(`${name} \u662F\u5426\u5DF2\u5B89\u88C5\uFF1A${!!plugin}`);
|
|
500
|
+
try {
|
|
501
|
+
if (!plugin) {
|
|
502
|
+
await this.install(name, version);
|
|
503
|
+
} else if (this.forceUpdate) {
|
|
504
|
+
const pkInfo = await this.getPluginInfo(name);
|
|
505
|
+
if (!pkInfo)
|
|
506
|
+
return;
|
|
507
|
+
const hasNewVersion = semver.gt(pkInfo.version, plugin.version);
|
|
508
|
+
if (hasNewVersion) {
|
|
509
|
+
this.logger.info(`${name} \u68C0\u67E5\u5230\u65B0\u7248\u672C ${pkInfo.version}\uFF0C\u66F4\u65B0\u4F9D\u8D56`);
|
|
510
|
+
await this.install(name, pkInfo.version);
|
|
511
|
+
}
|
|
539
512
|
}
|
|
513
|
+
this.logger.info(`${name} package manager init done!`);
|
|
514
|
+
} catch (error) {
|
|
515
|
+
this.logger.error(`${name} package manager init error`, error);
|
|
540
516
|
}
|
|
541
|
-
this.logger.info(`${name} package manager init done!`);
|
|
542
517
|
}
|
|
543
518
|
}
|
|
544
519
|
|
|
@@ -549,17 +524,20 @@ var __publicField = (obj, key, value) => {
|
|
|
549
524
|
return value;
|
|
550
525
|
};
|
|
551
526
|
const PLAYWRIGHT_VERSION = "1.46.1";
|
|
527
|
+
const ELECTRON_VERSION = "22.3.27";
|
|
552
528
|
class LocalAutomateTask {
|
|
553
529
|
constructor({ cachePath, debug }) {
|
|
530
|
+
__publicField(this, "logger");
|
|
554
531
|
__publicField(this, "cachePath");
|
|
555
532
|
__publicField(this, "debug");
|
|
556
533
|
__publicField(this, "playwrightPackage");
|
|
557
|
-
__publicField(this, "
|
|
534
|
+
__publicField(this, "electronPackage");
|
|
558
535
|
__publicField(this, "_electronApp", null);
|
|
559
536
|
this.cachePath = cachePath;
|
|
560
537
|
this.debug = debug || false;
|
|
561
538
|
this.logger = Logger.getInstance(cachePath);
|
|
562
539
|
this.playwrightPackage = this.installPlaywright();
|
|
540
|
+
this.electronPackage = this.installElectron();
|
|
563
541
|
}
|
|
564
542
|
/**
|
|
565
543
|
* 安装 playwright
|
|
@@ -569,29 +547,65 @@ class LocalAutomateTask {
|
|
|
569
547
|
const playwrightPackageManager = new PackageManager({
|
|
570
548
|
packageName: "playwright",
|
|
571
549
|
packageVersion: PLAYWRIGHT_VERSION,
|
|
572
|
-
cacheDir: this.cachePath
|
|
550
|
+
cacheDir: this.cachePath,
|
|
551
|
+
forceUpdate: false
|
|
573
552
|
});
|
|
574
553
|
return playwrightPackageManager.getPluginAfterInit("playwright");
|
|
575
554
|
}
|
|
555
|
+
/**
|
|
556
|
+
* 安装 electron
|
|
557
|
+
* @returns
|
|
558
|
+
*/
|
|
559
|
+
installElectron() {
|
|
560
|
+
const playwrightPackageManager = new PackageManager({
|
|
561
|
+
packageName: "electron",
|
|
562
|
+
packageVersion: ELECTRON_VERSION,
|
|
563
|
+
cacheDir: this.cachePath,
|
|
564
|
+
forceUpdate: false
|
|
565
|
+
});
|
|
566
|
+
return playwrightPackageManager.getPluginAfterInit("electron");
|
|
567
|
+
}
|
|
576
568
|
/**
|
|
577
569
|
* 启动 Electron
|
|
578
570
|
* @returns
|
|
579
571
|
*/
|
|
580
572
|
async getElectronApp() {
|
|
581
573
|
if (!this._electronApp) {
|
|
582
|
-
|
|
583
|
-
this.
|
|
584
|
-
this.
|
|
585
|
-
);
|
|
574
|
+
const [playwright] = await Promise.all([
|
|
575
|
+
this.playwrightPackage,
|
|
576
|
+
this.electronPackage
|
|
577
|
+
]);
|
|
578
|
+
this._electronApp = await createElectronApp(this.cachePath, playwright);
|
|
586
579
|
}
|
|
587
580
|
return this._electronApp;
|
|
588
581
|
}
|
|
582
|
+
/**
|
|
583
|
+
* 临时文件目录
|
|
584
|
+
* @returns
|
|
585
|
+
*/
|
|
586
|
+
getTmpPath() {
|
|
587
|
+
return path.join(this.cachePath, "tmp");
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* 清空临时文件
|
|
591
|
+
*/
|
|
592
|
+
clearTmpPath() {
|
|
593
|
+
const tmpPath = this.getTmpPath();
|
|
594
|
+
return fs.rm(tmpPath, { recursive: true, force: true }, (err) => {
|
|
595
|
+
if (err) {
|
|
596
|
+
this.logger.error("\u5220\u9664\u4E34\u65F6\u6587\u4EF6\u5931\u8D25\uFF0C", err);
|
|
597
|
+
} else {
|
|
598
|
+
this.logger.info("\u5220\u9664\u4E34\u65F6\u6587\u4EF6\u6210\u529F");
|
|
599
|
+
}
|
|
600
|
+
});
|
|
601
|
+
}
|
|
589
602
|
/**
|
|
590
603
|
* 关闭 playwright 启动的 electron 客户端
|
|
591
604
|
* @returns
|
|
592
605
|
*/
|
|
593
606
|
async close() {
|
|
594
607
|
this.logger.close();
|
|
608
|
+
this.clearTmpPath();
|
|
595
609
|
const electronApp = await this.getElectronApp();
|
|
596
610
|
return electronApp.close();
|
|
597
611
|
}
|
|
@@ -643,13 +657,13 @@ class LocalAutomateTask {
|
|
|
643
657
|
const res = await xiaohongshuPublishAction({
|
|
644
658
|
page,
|
|
645
659
|
params,
|
|
646
|
-
|
|
660
|
+
tmpCachePath: this.getTmpPath(),
|
|
647
661
|
debug: !!this.debug
|
|
648
662
|
});
|
|
649
663
|
return res;
|
|
650
664
|
} catch (error) {
|
|
651
665
|
this.logger.error("\u5C0F\u7EA2\u4E66\u53D1\u5E03\u5931\u8D25", error);
|
|
652
|
-
|
|
666
|
+
throw error;
|
|
653
667
|
}
|
|
654
668
|
}
|
|
655
669
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iflyrpa/playwright",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
5
|
-
"description": "",
|
|
4
|
+
"version": "1.0.12",
|
|
6
5
|
"main": "./dist/index.cjs",
|
|
7
6
|
"module": "./dist/index.mjs",
|
|
8
7
|
"types": "./dist/index.d.ts",
|
|
@@ -11,12 +10,12 @@
|
|
|
11
10
|
"dev": "unbuild --stub",
|
|
12
11
|
"start": "esno src/index.ts"
|
|
13
12
|
},
|
|
14
|
-
"keywords": [],
|
|
15
13
|
"author": "bijinfeng",
|
|
16
14
|
"license": "ISC",
|
|
17
15
|
"files": ["dist"],
|
|
18
16
|
"dependencies": {
|
|
19
17
|
"loglevel": "^1.9.2",
|
|
18
|
+
"npminstall": "^7.12.0",
|
|
20
19
|
"playwright": "^1.46.1"
|
|
21
20
|
},
|
|
22
21
|
"peerDependencies": {
|