@iflyrpa/playwright 1.0.15 → 1.1.1
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 +77 -1
- package/dist/index.cjs +169 -472
- package/dist/index.d.cts +38 -89
- package/dist/index.d.mts +38 -89
- package/dist/index.d.ts +38 -89
- package/dist/index.mjs +166 -468
- package/package.json +37 -30
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
import { Action } from '@iflyrpa/actions';
|
|
1
2
|
import fs from 'node:fs';
|
|
2
3
|
import path from 'node:path';
|
|
3
|
-
import https from 'node:https';
|
|
4
4
|
import childProcess from 'node:child_process';
|
|
5
5
|
import os from 'node:os';
|
|
6
6
|
import { downloadArtifact } from '@electron/get';
|
|
7
7
|
import extract from 'extract-zip';
|
|
8
|
+
import { ensureFileSync, pathExists, ensureFile, writeFile } from '@iflyrpa/share';
|
|
8
9
|
import log from 'loglevel';
|
|
9
|
-
import {
|
|
10
|
+
import { NodeClient } from '@sentry/node';
|
|
11
|
+
import pacote from 'pacote';
|
|
10
12
|
|
|
11
13
|
const name = "@iflyrpa/playwright";
|
|
12
14
|
const type = "module";
|
|
13
|
-
const version$1 = "1.
|
|
15
|
+
const version$1 = "1.1.1";
|
|
14
16
|
const main = "./dist/index.cjs";
|
|
15
17
|
const module = "./dist/index.mjs";
|
|
16
18
|
const types = "./dist/index.d.ts";
|
|
@@ -24,21 +26,26 @@ const license = "ISC";
|
|
|
24
26
|
const files = [
|
|
25
27
|
"dist"
|
|
26
28
|
];
|
|
27
|
-
const dependencies = {
|
|
28
|
-
"@electron/get": "^2.0.0",
|
|
29
|
-
"extract-zip": "^2.0.1",
|
|
30
|
-
"live-plugin-manager": "^1.0.0",
|
|
31
|
-
loglevel: "^1.9.2"
|
|
32
|
-
};
|
|
33
29
|
const peerDependencies = {
|
|
34
30
|
playwright: "^1.46.1"
|
|
35
31
|
};
|
|
36
32
|
const devDependencies = {
|
|
33
|
+
"@iflyrpa/share": "workspace:*",
|
|
34
|
+
"@types/pacote": "^11.1.8",
|
|
37
35
|
esno: "^4.7.0",
|
|
38
36
|
playwright: "^1.46.1",
|
|
39
37
|
typescript: "^5.5.2",
|
|
40
38
|
unbuild: "^2.0.0"
|
|
41
39
|
};
|
|
40
|
+
const dependencies = {
|
|
41
|
+
"@iflyrpa/actions": "workspace:*",
|
|
42
|
+
"@iflyrpa/share": "workspace:*",
|
|
43
|
+
"@electron/get": "^2.0.0",
|
|
44
|
+
"@sentry/node": "^5.5.0",
|
|
45
|
+
"extract-zip": "^2.0.1",
|
|
46
|
+
loglevel: "^1.9.2",
|
|
47
|
+
pacote: "^20.0.0"
|
|
48
|
+
};
|
|
42
49
|
const packageJson = {
|
|
43
50
|
name: name,
|
|
44
51
|
type: type,
|
|
@@ -50,307 +57,29 @@ const packageJson = {
|
|
|
50
57
|
author: author,
|
|
51
58
|
license: license,
|
|
52
59
|
files: files,
|
|
53
|
-
dependencies: dependencies,
|
|
54
60
|
peerDependencies: peerDependencies,
|
|
55
|
-
devDependencies: devDependencies
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
async function downloadImage(url, savePath) {
|
|
59
|
-
await ensureFile(savePath);
|
|
60
|
-
return new Promise((resolve, reject) => {
|
|
61
|
-
https.get(url, (response) => {
|
|
62
|
-
if (response.statusCode === 200) {
|
|
63
|
-
const fileStream = fs.createWriteStream(savePath);
|
|
64
|
-
response.pipe(fileStream);
|
|
65
|
-
fileStream.on("finish", () => {
|
|
66
|
-
fileStream.close();
|
|
67
|
-
console.log("\u4E0B\u8F7D\u5B8C\u6210\uFF0C\u6587\u4EF6\u5DF2\u4FDD\u5B58\u81F3:", savePath);
|
|
68
|
-
resolve(savePath);
|
|
69
|
-
});
|
|
70
|
-
} else {
|
|
71
|
-
console.log("\u56FE\u7247\u4E0B\u8F7D\u5931\u8D25:", response.statusCode);
|
|
72
|
-
response.resume();
|
|
73
|
-
reject();
|
|
74
|
-
}
|
|
75
|
-
}).on("error", (error) => {
|
|
76
|
-
console.error("\u8BF7\u6C42\u56FE\u7247\u65F6\u53D1\u751F\u9519\u8BEF:", error.message);
|
|
77
|
-
reject();
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
function getFilenameFromUrl(imageUrl) {
|
|
82
|
-
const parsedUrl = new URL(imageUrl);
|
|
83
|
-
return path.basename(parsedUrl.pathname);
|
|
84
|
-
}
|
|
85
|
-
function pathExists(path2) {
|
|
86
|
-
return new Promise((resolve) => {
|
|
87
|
-
fs.stat(path2, (err) => {
|
|
88
|
-
resolve(!err);
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
function ensureFile(filePath) {
|
|
93
|
-
return new Promise((resolve, reject) => {
|
|
94
|
-
const dirPath = path.dirname(filePath);
|
|
95
|
-
fs.stat(dirPath, (err, stats) => {
|
|
96
|
-
if (err) {
|
|
97
|
-
if (err.code === "ENOENT") {
|
|
98
|
-
fs.mkdir(dirPath, { recursive: true }, (err2) => {
|
|
99
|
-
if (err2) {
|
|
100
|
-
return reject(err2);
|
|
101
|
-
}
|
|
102
|
-
createFile();
|
|
103
|
-
});
|
|
104
|
-
} else {
|
|
105
|
-
return reject(err);
|
|
106
|
-
}
|
|
107
|
-
} else if (stats.isDirectory()) {
|
|
108
|
-
checkFile();
|
|
109
|
-
} else {
|
|
110
|
-
reject(new Error(`${dirPath} is not a directory`));
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
function checkFile() {
|
|
114
|
-
fs.stat(filePath, (err, stats) => {
|
|
115
|
-
if (err) {
|
|
116
|
-
if (err.code === "ENOENT") {
|
|
117
|
-
createFile();
|
|
118
|
-
} else {
|
|
119
|
-
reject(err);
|
|
120
|
-
}
|
|
121
|
-
} else if (stats.isFile()) {
|
|
122
|
-
resolve();
|
|
123
|
-
} else {
|
|
124
|
-
reject(new Error(`${filePath} is not a file`));
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
function createFile() {
|
|
129
|
-
fs.writeFile(filePath, "", (err) => {
|
|
130
|
-
if (err) {
|
|
131
|
-
reject(err);
|
|
132
|
-
} else {
|
|
133
|
-
resolve();
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
function ensureFileSync(filePath) {
|
|
140
|
-
const dirPath = path.dirname(filePath);
|
|
141
|
-
try {
|
|
142
|
-
if (!fs.existsSync(dirPath)) {
|
|
143
|
-
fs.mkdirSync(dirPath, { recursive: true });
|
|
144
|
-
}
|
|
145
|
-
} catch (err) {
|
|
146
|
-
if (err instanceof Error) {
|
|
147
|
-
throw new Error(`Error creating directory: ${err.message}`);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
try {
|
|
151
|
-
if (!fs.existsSync(filePath)) {
|
|
152
|
-
fs.writeFileSync(filePath, "");
|
|
153
|
-
}
|
|
154
|
-
} catch (err) {
|
|
155
|
-
if (err instanceof Error) {
|
|
156
|
-
throw new Error(`Error creating file: ${err.message}`);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
function writeFile(filePath, data) {
|
|
161
|
-
return new Promise((resolve, reject) => {
|
|
162
|
-
fs.writeFile(filePath, data, (err) => {
|
|
163
|
-
if (err) {
|
|
164
|
-
console.error("Error writing file:", err);
|
|
165
|
-
reject();
|
|
166
|
-
} else {
|
|
167
|
-
console.log("File written successfully");
|
|
168
|
-
resolve();
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
function compareVersions(v1, v2) {
|
|
174
|
-
const parts1 = v1.split(".").map(Number);
|
|
175
|
-
const parts2 = v2.split(".").map(Number);
|
|
176
|
-
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
177
|
-
const num1 = i < parts1.length ? parts1[i] : 0;
|
|
178
|
-
const num2 = i < parts2.length ? parts2[i] : 0;
|
|
179
|
-
if (num1 > num2)
|
|
180
|
-
return 1;
|
|
181
|
-
if (num1 < num2)
|
|
182
|
-
return -1;
|
|
183
|
-
}
|
|
184
|
-
return 0;
|
|
185
|
-
}
|
|
186
|
-
const semver = {
|
|
187
|
-
gt: (v1, v2) => compareVersions(v1, v2) === 1
|
|
188
|
-
};
|
|
189
|
-
function fetchJSON(url) {
|
|
190
|
-
return new Promise((resolve, reject) => {
|
|
191
|
-
https.get(url, (res) => {
|
|
192
|
-
let data = "";
|
|
193
|
-
res.on("data", (chunk) => {
|
|
194
|
-
data += chunk;
|
|
195
|
-
});
|
|
196
|
-
res.on("end", () => {
|
|
197
|
-
try {
|
|
198
|
-
const parsedData = JSON.parse(data);
|
|
199
|
-
resolve(parsedData);
|
|
200
|
-
} catch (e) {
|
|
201
|
-
if (e instanceof Error) {
|
|
202
|
-
reject(new Error(`Error parsing JSON: ${e.message}`));
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
}).on("error", (err) => {
|
|
207
|
-
reject(new Error(`Request failed: ${err.message}`));
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
function isNil(value) {
|
|
212
|
-
return value === null || value === void 0;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
const visibleRangeTexts = {
|
|
216
|
-
public: "\u516C\u5F00",
|
|
217
|
-
private: "\u79C1\u5BC6"
|
|
218
|
-
};
|
|
219
|
-
const xiaohongshuPublishAction = async (props) => {
|
|
220
|
-
const { page, tmpCachePath, params } = props;
|
|
221
|
-
const selectAddress = async (selector, address) => {
|
|
222
|
-
const instance = typeof selector === "string" ? page.locator(selector) : selector;
|
|
223
|
-
await instance.click();
|
|
224
|
-
await instance.locator("input").fill(address);
|
|
225
|
-
const poperInstance = page.locator(
|
|
226
|
-
'.d-popover:not([style*="display: none"]) .d-options .d-grid-item'
|
|
227
|
-
);
|
|
228
|
-
await poperInstance.first().waitFor();
|
|
229
|
-
await poperInstance.first().click();
|
|
230
|
-
};
|
|
231
|
-
const selectDate = async (selector, date) => {
|
|
232
|
-
const instance = typeof selector === "string" ? page.locator(selector) : selector;
|
|
233
|
-
await instance.click();
|
|
234
|
-
await instance.fill(date);
|
|
235
|
-
await instance.blur();
|
|
236
|
-
};
|
|
237
|
-
await page.waitForSelector("#CreatorPlatform", { state: "visible" }).catch(() => {
|
|
238
|
-
throw new Error("\u767B\u5F55\u5931\u8D25");
|
|
239
|
-
});
|
|
240
|
-
await page.locator("#content-area .menu-container .publish-video a").click().catch(() => {
|
|
241
|
-
throw new Error("\u672A\u627E\u5230\u53D1\u5E03\u7B14\u8BB0\u6309\u94AE");
|
|
242
|
-
});
|
|
243
|
-
await page.locator(".creator-container .header .title").filter({ hasText: /^上传图文$/ }).click().catch(() => {
|
|
244
|
-
throw new Error("\u672A\u627E\u5230\u4E0A\u4F20\u56FE\u6587\u6309\u94AE");
|
|
245
|
-
});
|
|
246
|
-
const images = await Promise.all(
|
|
247
|
-
params.banners.map((url) => {
|
|
248
|
-
const fileName = getFilenameFromUrl(url);
|
|
249
|
-
return downloadImage(url, path.join(tmpCachePath, fileName));
|
|
250
|
-
})
|
|
251
|
-
);
|
|
252
|
-
const fileChooserPromise = page.waitForEvent("filechooser");
|
|
253
|
-
await page.getByRole("textbox").click();
|
|
254
|
-
const fileChooser = await fileChooserPromise;
|
|
255
|
-
await fileChooser.setFiles(images);
|
|
256
|
-
const titleInstance = page.locator(".titleInput input");
|
|
257
|
-
await titleInstance.click();
|
|
258
|
-
await titleInstance.fill(params.title);
|
|
259
|
-
const descInstance = page.locator("#post-textarea");
|
|
260
|
-
await descInstance.click();
|
|
261
|
-
await descInstance.fill(params.content);
|
|
262
|
-
const container = page.locator(".creator-container .content .scroll-content");
|
|
263
|
-
await container.focus();
|
|
264
|
-
await page.mouse.wheel(0, 500);
|
|
265
|
-
if (params.address) {
|
|
266
|
-
await selectAddress(
|
|
267
|
-
page.locator(".media-extension .address-input").filter({ hasText: "\u6DFB\u52A0\u5730\u70B9" }),
|
|
268
|
-
params.address
|
|
269
|
-
);
|
|
270
|
-
}
|
|
271
|
-
if (params.selfDeclaration) {
|
|
272
|
-
await page.locator(".declaration-wrapper").click();
|
|
273
|
-
const selfDeclarationInstance = page.locator(
|
|
274
|
-
".el-popper[aria-hidden=false] ul li[role=menuitem]"
|
|
275
|
-
);
|
|
276
|
-
if (params.selfDeclaration.type === "fictional-rendition") {
|
|
277
|
-
await selfDeclarationInstance.filter({ hasText: "\u865A\u6784\u6F14\u7ECE\uFF0C\u4EC5\u4F9B\u5A31\u4E50" }).click();
|
|
278
|
-
} else if (params.selfDeclaration.type === "ai-generated") {
|
|
279
|
-
await selfDeclarationInstance.filter({ hasText: "\u7B14\u8BB0\u542BAI\u5408\u6210\u5185\u5BB9" }).click();
|
|
280
|
-
} else if (params.selfDeclaration.type === "source-statement") {
|
|
281
|
-
await selfDeclarationInstance.filter({ hasText: "\u5185\u5BB9\u6765\u6E90\u58F0\u660E" }).click();
|
|
282
|
-
const selfDeclarationSecondaryMenuInstance = page.locator(".el-popper[aria-hidden=false] .el-cascader-menu").nth(1).locator("ul li[role=menuitem]");
|
|
283
|
-
await selfDeclarationSecondaryMenuInstance.first().waitFor();
|
|
284
|
-
if (params.selfDeclaration.childType === "self-labeling") {
|
|
285
|
-
await selfDeclarationSecondaryMenuInstance.filter({ hasText: "\u5DF2\u81EA\u4E3B\u6807\u6CE8" }).click();
|
|
286
|
-
} else if (params.selfDeclaration.childType === "self-shooting") {
|
|
287
|
-
const { shootingDate, shootingLocation } = params.selfDeclaration;
|
|
288
|
-
await selfDeclarationSecondaryMenuInstance.filter({ hasText: "\u81EA\u4E3B\u62CD\u6444" }).click();
|
|
289
|
-
const selfShootingPopup = page.locator(".el-overlay-dialog[aria-modal=true][role=dialog]").filter({ hasText: "\u81EA\u4E3B\u62CD\u6444" });
|
|
290
|
-
await selfShootingPopup.waitFor();
|
|
291
|
-
const hasCustomContent = shootingDate || shootingLocation;
|
|
292
|
-
if (shootingLocation) {
|
|
293
|
-
await selectAddress(
|
|
294
|
-
selfShootingPopup.locator(".address-input"),
|
|
295
|
-
shootingLocation
|
|
296
|
-
);
|
|
297
|
-
}
|
|
298
|
-
if (shootingDate) {
|
|
299
|
-
await selectDate(
|
|
300
|
-
selfShootingPopup.locator(".date-picker input"),
|
|
301
|
-
shootingDate
|
|
302
|
-
);
|
|
303
|
-
}
|
|
304
|
-
await selfShootingPopup.locator("footer button").filter({ hasText: hasCustomContent ? "\u786E\u8BA4" : "\u53D6\u6D88" }).click();
|
|
305
|
-
} else if (params.selfDeclaration.childType === "transshipment") {
|
|
306
|
-
await selfDeclarationSecondaryMenuInstance.filter({ hasText: "\u6765\u6E90\u8F6C\u8F7D" }).click();
|
|
307
|
-
const selfShootingPopup = page.locator(".el-overlay-dialog[aria-modal=true][role=dialog]").filter({ hasText: "\u6765\u6E90\u5A92\u4F53" });
|
|
308
|
-
await selfShootingPopup.waitFor();
|
|
309
|
-
const sourceMedia = params.selfDeclaration.sourceMedia;
|
|
310
|
-
if (sourceMedia) {
|
|
311
|
-
await selfShootingPopup.locator(".el-input input").fill(sourceMedia);
|
|
312
|
-
}
|
|
313
|
-
await selfShootingPopup.locator("footer button").filter({ hasText: sourceMedia ? "\u786E\u8BA4" : "\u53D6\u6D88" }).click();
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
const publicLabelInstance = page.locator("label").filter({ hasText: visibleRangeTexts[params.visibleRange] });
|
|
318
|
-
await publicLabelInstance.click();
|
|
319
|
-
const releaseTimeInstance = page.locator("label").filter({ hasText: params.isImmediatelyPublish ? "\u7ACB\u5373\u53D1\u5E03" : "\u5B9A\u65F6\u53D1\u5E03" });
|
|
320
|
-
await releaseTimeInstance.click();
|
|
321
|
-
if (params.scheduledPublish) {
|
|
322
|
-
await selectDate(".date-picker input", params.scheduledPublish);
|
|
323
|
-
}
|
|
324
|
-
const response = await new Promise((resolve) => {
|
|
325
|
-
const handleResponse = async (response2) => {
|
|
326
|
-
if (response2.url().includes("/web_api/sns/v2/note")) {
|
|
327
|
-
const jsonResponse = await response2.json();
|
|
328
|
-
page.off("response", handleResponse);
|
|
329
|
-
resolve(jsonResponse?.data?.id);
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
|
-
page.on("response", handleResponse);
|
|
333
|
-
page.locator(".submit .publishBtn").click();
|
|
334
|
-
});
|
|
335
|
-
await page.close();
|
|
336
|
-
return response;
|
|
61
|
+
devDependencies: devDependencies,
|
|
62
|
+
dependencies: dependencies
|
|
337
63
|
};
|
|
338
64
|
|
|
339
|
-
var __defProp$
|
|
340
|
-
var __defNormalProp$
|
|
341
|
-
var __publicField$
|
|
342
|
-
__defNormalProp$
|
|
65
|
+
var __defProp$4 = Object.defineProperty;
|
|
66
|
+
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
67
|
+
var __publicField$4 = (obj, key, value) => {
|
|
68
|
+
__defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
343
69
|
return value;
|
|
344
70
|
};
|
|
71
|
+
const ELECTRON_MIRROR = "http://npmmirror.com/mirrors/electron/";
|
|
72
|
+
const ELECTRON_VERSION = "22.3.27";
|
|
345
73
|
class ElectronInstall {
|
|
346
|
-
constructor(
|
|
347
|
-
this.
|
|
348
|
-
this
|
|
349
|
-
this
|
|
350
|
-
__publicField$
|
|
351
|
-
__publicField$
|
|
74
|
+
constructor(task) {
|
|
75
|
+
this.task = task;
|
|
76
|
+
__publicField$4(this, "rootDir");
|
|
77
|
+
__publicField$4(this, "electronPath");
|
|
78
|
+
__publicField$4(this, "platformPath");
|
|
79
|
+
__publicField$4(this, "version", ELECTRON_VERSION);
|
|
352
80
|
this.platformPath = this.getPlatformPath();
|
|
353
|
-
this.
|
|
81
|
+
this.rootDir = path.join(task.packagesDir, `electron@${this.version}`);
|
|
82
|
+
this.electronPath = path.join(this.rootDir, this.platformPath);
|
|
354
83
|
}
|
|
355
84
|
isInstalled() {
|
|
356
85
|
try {
|
|
@@ -383,7 +112,7 @@ class ElectronInstall {
|
|
|
383
112
|
}
|
|
384
113
|
async install() {
|
|
385
114
|
const installed = this.isInstalled();
|
|
386
|
-
this.logger.info(`electron@${this.version} \u662F\u5426\u5DF2\u5B89\u88C5\uFF1A${installed}`);
|
|
115
|
+
this.task.logger.info(`electron@${this.version} \u662F\u5426\u5DF2\u5B89\u88C5\uFF1A${installed}`);
|
|
387
116
|
if (installed)
|
|
388
117
|
return this.electronPath;
|
|
389
118
|
const platform = process.env.npm_config_platform || process.platform;
|
|
@@ -400,28 +129,52 @@ class ElectronInstall {
|
|
|
400
129
|
}
|
|
401
130
|
}
|
|
402
131
|
try {
|
|
403
|
-
this.logger.info(`electron@${this.version} \u5F00\u59CB\u4E0B\u8F7D\u8D44\u6E90`);
|
|
132
|
+
this.task.logger.info(`electron@${this.version} \u5F00\u59CB\u4E0B\u8F7D\u8D44\u6E90`);
|
|
404
133
|
const zipPath = await downloadArtifact({
|
|
405
134
|
version: this.version,
|
|
406
135
|
artifactName: "electron",
|
|
407
136
|
force: process.env.force_no_cache === "true",
|
|
408
137
|
cacheRoot: process.env.electron_config_cache,
|
|
409
138
|
checksums: void 0,
|
|
139
|
+
mirrorOptions: { mirror: ELECTRON_MIRROR },
|
|
140
|
+
// 使用国内镜像下载
|
|
410
141
|
platform,
|
|
411
142
|
arch
|
|
412
143
|
});
|
|
413
|
-
this.logger.info(`electron@${this.version} \u5F00\u59CB\u89E3\u538B\u8D44\u6E90`);
|
|
144
|
+
this.task.logger.info(`electron@${this.version} \u5F00\u59CB\u89E3\u538B\u8D44\u6E90`);
|
|
414
145
|
process.noAsar = true;
|
|
415
146
|
await extract(zipPath, { dir: this.rootDir });
|
|
416
|
-
this.logger.info(`electron@${this.version} \u4E0B\u8F7D\u6210\u529F`);
|
|
147
|
+
this.task.logger.info(`electron@${this.version} \u4E0B\u8F7D\u6210\u529F`);
|
|
417
148
|
return this.electronPath;
|
|
418
149
|
} catch (error) {
|
|
419
|
-
this.logger.error(`electron@${this.version} \u4E0B\u8F7D\u5931\u8D25`, error);
|
|
150
|
+
this.task.logger.error(`electron@${this.version} \u4E0B\u8F7D\u5931\u8D25`, error);
|
|
420
151
|
throw error;
|
|
421
152
|
}
|
|
422
153
|
}
|
|
423
154
|
}
|
|
424
155
|
|
|
156
|
+
var __defProp$3 = Object.defineProperty;
|
|
157
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
158
|
+
var __publicField$3 = (obj, key, value) => {
|
|
159
|
+
__defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
160
|
+
return value;
|
|
161
|
+
};
|
|
162
|
+
class SentryInstance {
|
|
163
|
+
constructor(dsn) {
|
|
164
|
+
__publicField$3(this, "sentry");
|
|
165
|
+
if (!dsn)
|
|
166
|
+
return;
|
|
167
|
+
this.sentry = new NodeClient({
|
|
168
|
+
dsn,
|
|
169
|
+
defaultIntegrations: false
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
captureException(error) {
|
|
173
|
+
this.sentry?.captureException(error);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const sentry = new SentryInstance(process.env.RPA_SENTRY_DSN);
|
|
177
|
+
|
|
425
178
|
var __defProp$2 = Object.defineProperty;
|
|
426
179
|
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
427
180
|
var __publicField$2 = (obj, key, value) => {
|
|
@@ -435,12 +188,13 @@ const _Logger = class _Logger {
|
|
|
435
188
|
return _Logger.instance;
|
|
436
189
|
}
|
|
437
190
|
const logFile = path.join(cachePath, "rpa.log");
|
|
191
|
+
ensureFileSync(logFile);
|
|
438
192
|
this.stream = fs.createWriteStream(logFile, { flags: "a" });
|
|
439
193
|
log.setLevel("debug");
|
|
440
194
|
log.methodFactory = (methodName) => {
|
|
441
195
|
return (message) => {
|
|
442
196
|
this.stream.write(
|
|
443
|
-
`[${( new Date()).
|
|
197
|
+
`[${( new Date()).toLocaleString()}] ${methodName.toUpperCase()}: ${message}
|
|
444
198
|
`
|
|
445
199
|
);
|
|
446
200
|
};
|
|
@@ -466,12 +220,14 @@ const _Logger = class _Logger {
|
|
|
466
220
|
warn(...msg) {
|
|
467
221
|
log.warn(...msg);
|
|
468
222
|
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
223
|
+
// error 级别的日志上报 sentry
|
|
224
|
+
error(prefix, err) {
|
|
225
|
+
const error = err || prefix;
|
|
226
|
+
if (err instanceof Error) {
|
|
227
|
+
err.message = `${prefix}\uFF1A${err.message}`;
|
|
474
228
|
}
|
|
229
|
+
log.error(error);
|
|
230
|
+
sentry.captureException(error);
|
|
475
231
|
}
|
|
476
232
|
close() {
|
|
477
233
|
this.stream.end();
|
|
@@ -488,7 +244,7 @@ app.whenReady().then(() => {});
|
|
|
488
244
|
app.on("window-all-closed", (e) => e.preventDefault());
|
|
489
245
|
`;
|
|
490
246
|
const generateFile = async (dir) => {
|
|
491
|
-
const filePath = path.join(dir, "
|
|
247
|
+
const filePath = path.join(dir, "main.js");
|
|
492
248
|
const isPathExists = await pathExists(filePath);
|
|
493
249
|
if (!isPathExists) {
|
|
494
250
|
await ensureFile(filePath);
|
|
@@ -514,121 +270,92 @@ const launchElectronApp = async (cachePath, playwright, electronPath) => {
|
|
|
514
270
|
}
|
|
515
271
|
};
|
|
516
272
|
|
|
517
|
-
var __defProp$1 = Object.defineProperty;
|
|
518
|
-
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
519
|
-
var __publicField$1 = (obj, key, value) => {
|
|
520
|
-
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
521
|
-
return value;
|
|
522
|
-
};
|
|
523
273
|
const NPM_REGISTRY = "https://registry.npmmirror.com/";
|
|
524
|
-
class PackageManager
|
|
525
|
-
constructor(
|
|
526
|
-
|
|
527
|
-
cwd: params.cacheDir,
|
|
528
|
-
pluginsPath: path.join(params.cacheDir, "node_modules"),
|
|
529
|
-
npmRegistryUrl: NPM_REGISTRY
|
|
530
|
-
});
|
|
531
|
-
__publicField$1(this, "cacheDir");
|
|
532
|
-
// 依赖安装目录
|
|
533
|
-
__publicField$1(this, "forceUpdate");
|
|
534
|
-
// 是否强制更新
|
|
535
|
-
__publicField$1(this, "initPromise");
|
|
536
|
-
__publicField$1(this, "logger");
|
|
537
|
-
this.logger = Logger.getInstance(params.cacheDir);
|
|
538
|
-
this.cacheDir = params.cacheDir;
|
|
539
|
-
this.forceUpdate = isNil(params.forceUpdate) ? true : params.forceUpdate;
|
|
540
|
-
this.initCacheProject();
|
|
541
|
-
this.initPromise = this.init(params.packageName, params.packageVersion);
|
|
542
|
-
}
|
|
543
|
-
// 构建 package.json 文件,有了该文件后,依赖可以安装在该目录下,避免污染全局环境
|
|
544
|
-
initCacheProject() {
|
|
545
|
-
const packagePath = path.join(this.cacheDir, "package.json");
|
|
546
|
-
if (!fs.existsSync(packagePath)) {
|
|
547
|
-
this.logger.info("package.json \u4E0D\u5B58\u5728\uFF0C\u6DFB\u52A0\u8BE5\u6587\u4EF6");
|
|
548
|
-
const pkg = {
|
|
549
|
-
name: "rpa-plugins",
|
|
550
|
-
description: "rpa-plugins",
|
|
551
|
-
license: "MIT",
|
|
552
|
-
main: "./src/main.js"
|
|
553
|
-
};
|
|
554
|
-
ensureFileSync(packagePath);
|
|
555
|
-
fs.writeFileSync(packagePath, JSON.stringify(pkg), "utf8");
|
|
556
|
-
}
|
|
274
|
+
class PackageManager {
|
|
275
|
+
constructor(task) {
|
|
276
|
+
this.task = task;
|
|
557
277
|
}
|
|
558
278
|
// 获取依赖信息
|
|
559
|
-
async
|
|
560
|
-
const res = await fetchJSON(
|
|
561
|
-
`https://registry.npmjs.com/-/v1/search?text=${module}`
|
|
562
|
-
);
|
|
563
|
-
const packages = res.objects;
|
|
564
|
-
return packages.find((it) => it.package.name === module)?.package;
|
|
565
|
-
}
|
|
566
|
-
// 查询本地安装的依赖
|
|
567
|
-
getPlugin(module) {
|
|
568
|
-
const pluginDir = path.join(this.cacheDir, "node_modules");
|
|
279
|
+
async getManifest(module) {
|
|
569
280
|
try {
|
|
570
|
-
return
|
|
281
|
+
return pacote.manifest(module, { registry: NPM_REGISTRY });
|
|
571
282
|
} catch (error) {
|
|
572
|
-
|
|
283
|
+
this.task.logger.error("\u83B7\u53D6\u4F9D\u8D56\u4FE1\u606F\u5931\u8D25", error);
|
|
284
|
+
throw error;
|
|
573
285
|
}
|
|
574
286
|
}
|
|
575
|
-
async getPluginAfterInit(module) {
|
|
576
|
-
await this.initPromise;
|
|
577
|
-
return this.getPlugin(module);
|
|
578
|
-
}
|
|
579
287
|
// 安装依赖
|
|
580
|
-
async
|
|
288
|
+
async extract(name, version = "latest") {
|
|
289
|
+
const packageName = `${name}@${version}`;
|
|
581
290
|
try {
|
|
582
|
-
this.logger.info(`${
|
|
583
|
-
await
|
|
584
|
-
|
|
291
|
+
this.task.logger.info(`${packageName} \u5F00\u59CB\u5B89\u88C5`);
|
|
292
|
+
await pacote.extract(
|
|
293
|
+
packageName,
|
|
294
|
+
path.join(this.task.packagesDir, packageName),
|
|
295
|
+
{ registry: NPM_REGISTRY }
|
|
296
|
+
);
|
|
297
|
+
this.task.logger.info(`${packageName} \u5B89\u88C5\u6210\u529F`);
|
|
585
298
|
} catch (error) {
|
|
586
|
-
this.logger.error(`${
|
|
299
|
+
this.task.logger.error(`${packageName} \u5B89\u88C5\u5931\u8D25`, error);
|
|
587
300
|
}
|
|
588
301
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
this.logger.info(`${name} \u662F\u5426\u5DF2\u5B89\u88C5\uFF1A${!!plugin}`);
|
|
302
|
+
// 查询本地安装的依赖
|
|
303
|
+
require(module) {
|
|
592
304
|
try {
|
|
593
|
-
|
|
594
|
-
await this.installPackage(name, version);
|
|
595
|
-
} else if (this.forceUpdate) {
|
|
596
|
-
const pkInfo = await this.getPluginInfo(name);
|
|
597
|
-
if (!pkInfo)
|
|
598
|
-
return;
|
|
599
|
-
const hasNewVersion = semver.gt(pkInfo.version, plugin.version);
|
|
600
|
-
if (hasNewVersion) {
|
|
601
|
-
this.logger.info(`${name} \u68C0\u67E5\u5230\u65B0\u7248\u672C ${pkInfo.version}`);
|
|
602
|
-
await this.installPackage(name, pkInfo.version);
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
this.logger.info(`${name} package manager init done!`);
|
|
305
|
+
return require(path.join(this.task.packagesDir, module));
|
|
606
306
|
} catch (error) {
|
|
607
|
-
|
|
307
|
+
return null;
|
|
608
308
|
}
|
|
609
309
|
}
|
|
310
|
+
// 安装依赖
|
|
311
|
+
async install(name, version) {
|
|
312
|
+
const packageName = `${name}@${version}`;
|
|
313
|
+
const plugin = this.require(packageName);
|
|
314
|
+
this.task.logger.info(`${packageName} \u662F\u5426\u5DF2\u5B89\u88C5\uFF1A${!!plugin}`);
|
|
315
|
+
if (!plugin) {
|
|
316
|
+
await this.extract(name, version);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
// 更新依赖
|
|
320
|
+
async update(name) {
|
|
321
|
+
const manifest = await this.getManifest(`${name}@latest`);
|
|
322
|
+
const version = manifest.version;
|
|
323
|
+
const plugin = this.require(`${name}@${version}`);
|
|
324
|
+
if (!plugin) {
|
|
325
|
+
await this.extract(name, version);
|
|
326
|
+
}
|
|
327
|
+
return version;
|
|
328
|
+
}
|
|
610
329
|
}
|
|
611
330
|
|
|
612
|
-
var __defProp = Object.defineProperty;
|
|
613
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
614
|
-
var __publicField = (obj, key, value) => {
|
|
615
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
331
|
+
var __defProp$1 = Object.defineProperty;
|
|
332
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
333
|
+
var __publicField$1 = (obj, key, value) => {
|
|
334
|
+
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
616
335
|
return value;
|
|
617
336
|
};
|
|
618
337
|
const PLAYWRIGHT_VERSION = "1.46.1";
|
|
619
338
|
const PLAYWRIGHT_NAME = "playwright-core";
|
|
620
|
-
|
|
621
|
-
class LocalAutomateTask {
|
|
339
|
+
class Task {
|
|
622
340
|
constructor({ cachePath, debug }) {
|
|
623
|
-
__publicField(this, "logger");
|
|
624
|
-
__publicField(this, "cachePath");
|
|
625
|
-
__publicField(this, "debug");
|
|
626
|
-
__publicField(this, "
|
|
627
|
-
|
|
628
|
-
__publicField(this, "
|
|
341
|
+
__publicField$1(this, "logger");
|
|
342
|
+
__publicField$1(this, "cachePath");
|
|
343
|
+
__publicField$1(this, "debug");
|
|
344
|
+
__publicField$1(this, "packagesDir");
|
|
345
|
+
// 依赖安装目录
|
|
346
|
+
__publicField$1(this, "packageManager");
|
|
347
|
+
__publicField$1(this, "playwrightPackage");
|
|
348
|
+
__publicField$1(this, "electronPackage");
|
|
349
|
+
__publicField$1(this, "_electronApp", null);
|
|
350
|
+
/**
|
|
351
|
+
* 应用是否已关闭
|
|
352
|
+
*/
|
|
353
|
+
__publicField$1(this, "isClosed", false);
|
|
629
354
|
this.cachePath = cachePath;
|
|
355
|
+
this.packagesDir = path.join(cachePath, "packages");
|
|
630
356
|
this.debug = debug || false;
|
|
631
357
|
this.logger = Logger.getInstance(cachePath);
|
|
358
|
+
this.packageManager = new PackageManager(this);
|
|
632
359
|
this.playwrightPackage = this.installPlaywright();
|
|
633
360
|
this.electronPackage = this.installElectron();
|
|
634
361
|
}
|
|
@@ -636,26 +363,17 @@ class LocalAutomateTask {
|
|
|
636
363
|
* 安装 playwright
|
|
637
364
|
* @returns
|
|
638
365
|
*/
|
|
639
|
-
installPlaywright() {
|
|
640
|
-
const
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
cacheDir: this.cachePath,
|
|
644
|
-
forceUpdate: false
|
|
645
|
-
});
|
|
646
|
-
return playwrightPackageManager.getPluginAfterInit(PLAYWRIGHT_NAME);
|
|
366
|
+
async installPlaywright() {
|
|
367
|
+
const packageName = `${PLAYWRIGHT_NAME}@${PLAYWRIGHT_VERSION}`;
|
|
368
|
+
await this.packageManager.install(PLAYWRIGHT_NAME, PLAYWRIGHT_VERSION);
|
|
369
|
+
return this.packageManager.require(packageName);
|
|
647
370
|
}
|
|
648
371
|
/**
|
|
649
372
|
* 安装 electron
|
|
650
373
|
* @returns
|
|
651
374
|
*/
|
|
652
375
|
installElectron() {
|
|
653
|
-
|
|
654
|
-
path.join(this.cachePath, "electron"),
|
|
655
|
-
ELECTRON_VERSION,
|
|
656
|
-
this.logger
|
|
657
|
-
);
|
|
658
|
-
return electronInstall.install();
|
|
376
|
+
return new ElectronInstall(this).install();
|
|
659
377
|
}
|
|
660
378
|
/**
|
|
661
379
|
* 启动 Electron
|
|
@@ -700,31 +418,15 @@ class LocalAutomateTask {
|
|
|
700
418
|
* @returns
|
|
701
419
|
*/
|
|
702
420
|
async close() {
|
|
703
|
-
this.logger.
|
|
421
|
+
this.logger.info("\u5173\u95ED\u5E94\u7528");
|
|
704
422
|
this.clearTmpPath();
|
|
705
|
-
|
|
706
|
-
|
|
423
|
+
this.logger.close();
|
|
424
|
+
await this._electronApp?.close();
|
|
425
|
+
this.isClosed = true;
|
|
426
|
+
this._electronApp = null;
|
|
707
427
|
}
|
|
708
|
-
|
|
709
|
-
* 小红书自动化发布
|
|
710
|
-
*/
|
|
711
|
-
async xiaohongshuPublish(params) {
|
|
712
|
-
this.logger.info("\u5F00\u59CB\u5C0F\u7EA2\u4E66\u53D1\u5E03");
|
|
428
|
+
async createPage(pageParams) {
|
|
713
429
|
const electronApp = await this.launchApp();
|
|
714
|
-
this.logger.info("\u5C0F\u7EA2\u4E66\u53D1\u5E03\u4E13\u7528\u5BA2\u6237\u7AEF\u5DF2\u542F\u52A8");
|
|
715
|
-
const commonCookies = {
|
|
716
|
-
path: "/",
|
|
717
|
-
sameSite: "lax",
|
|
718
|
-
secure: false,
|
|
719
|
-
domain: "xiaohongshu.com",
|
|
720
|
-
url: "https://creator.xiaohongshu.com",
|
|
721
|
-
httpOnly: true
|
|
722
|
-
};
|
|
723
|
-
const pageParams = {
|
|
724
|
-
show: this.debug,
|
|
725
|
-
url: params.url || "https://creator.xiaohongshu.com/publish/publish",
|
|
726
|
-
cookies: params.cookies?.map((it) => Object.assign(commonCookies, it)) || []
|
|
727
|
-
};
|
|
728
430
|
const [page] = await Promise.all([
|
|
729
431
|
electronApp.waitForEvent("window"),
|
|
730
432
|
electronApp.evaluate(
|
|
@@ -751,38 +453,34 @@ class LocalAutomateTask {
|
|
|
751
453
|
{ pageParams }
|
|
752
454
|
)
|
|
753
455
|
]);
|
|
754
|
-
|
|
456
|
+
return page;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
var __defProp = Object.defineProperty;
|
|
461
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
462
|
+
var __publicField = (obj, key, value) => {
|
|
463
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
464
|
+
return value;
|
|
465
|
+
};
|
|
466
|
+
class RpaTask extends Task {
|
|
467
|
+
constructor(params) {
|
|
468
|
+
super(params);
|
|
469
|
+
__publicField(this, "actions");
|
|
470
|
+
this.actions = new Action(this);
|
|
471
|
+
params.forceUpdate && this.update();
|
|
472
|
+
}
|
|
473
|
+
async update() {
|
|
755
474
|
try {
|
|
756
|
-
const
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
debug: !!this.debug
|
|
761
|
-
});
|
|
762
|
-
this.logger.info(`\u5C0F\u7EA2\u4E66\u53D1\u5E03\u6210\u529F\uFF1A${res}`);
|
|
763
|
-
return res;
|
|
475
|
+
const name = "@iflyrpa/actions";
|
|
476
|
+
const version2 = await this.packageManager.update(name);
|
|
477
|
+
const actionPackage = this.packageManager.require(`${name}@${version2}`);
|
|
478
|
+
actionPackage?.actions && (this.actions = actionPackage.actions);
|
|
764
479
|
} catch (error) {
|
|
765
|
-
this.logger.error("\
|
|
766
|
-
throw error;
|
|
480
|
+
this.logger.error("\u66F4\u65B0\u4F9D\u8D56\u5931\u8D25", error);
|
|
767
481
|
}
|
|
768
482
|
}
|
|
769
483
|
}
|
|
770
|
-
const RpaTask = (params) => {
|
|
771
|
-
const logger = Logger.getInstance(params.cachePath);
|
|
772
|
-
if (params.forceUpdate) {
|
|
773
|
-
logger.info("\u5C1D\u8BD5\u4F7F\u7528\u8FDC\u7A0B\u6700\u65B0\u7248\u672C");
|
|
774
|
-
const packageManager = new PackageManager({
|
|
775
|
-
packageName: packageJson.name,
|
|
776
|
-
cacheDir: params.cachePath
|
|
777
|
-
});
|
|
778
|
-
const localPackge = packageManager.getPlugin(packageJson.name);
|
|
779
|
-
if (localPackge?.LocalAutomateTask && localPackge?.version && semver.gt(localPackge.version, packageJson.version)) {
|
|
780
|
-
logger.info(`\u4F7F\u7528\u8FDC\u7A0B\u7684\u65B0\u7248\u672C\uFF0C\u7248\u672C\u53F7\u4E3A\uFF1A${localPackge.version}`);
|
|
781
|
-
return new localPackge.LocalAutomateTask(params);
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
return new LocalAutomateTask(params);
|
|
785
|
-
};
|
|
786
484
|
const version = packageJson.version;
|
|
787
485
|
|
|
788
|
-
export {
|
|
486
|
+
export { RpaTask, version };
|