@xbrowser/cli 1.23.0 → 1.24.0
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 +13 -0
- package/dist/chunk-A7RZYSWM.js +8778 -0
- package/dist/chunk-BROEUPL3.js +9122 -0
- package/dist/{chunk-LPW6QS4M.js → chunk-FNXA6FDM.js} +39 -1
- package/dist/{chunk-FBQZ3PVD.js → chunk-PGKV24QN.js} +39 -1
- package/dist/{chunk-XTUAUFL3.js → chunk-SOPN4XDK.js} +41 -96
- package/dist/cli.js +255 -8918
- package/dist/daemon-main.js +50 -4
- package/dist/{human-interaction-MXST5ZQM.js → human-interaction-CTZ4IWXJ.js} +1 -1
- package/dist/{human-interaction-67K43B4O.js → human-interaction-HJCK45SL.js} +1 -1
- package/dist/{human-interaction-57VYIR56.js → human-interaction-V3VDGHHI.js} +2 -1
- package/dist/index.d.ts +16 -0
- package/dist/index.js +439 -9395
- package/dist/{recovery-LGY25LIM.js → recovery-5C4FBA5O.js} +1 -1
- package/dist/{recovery-6RI2FE3E.js → recovery-EBKORYEU.js} +1 -1
- package/dist/{recovery-LMJW537X.js → recovery-IMZUGWSS.js} +2 -1
- package/dist/server-NPINOVJS.js +243 -0
- package/dist/server-YVMWMNHD.js +240 -0
- package/package.json +2 -2
|
@@ -251,6 +251,7 @@ var CaptchaDetector = class {
|
|
|
251
251
|
};
|
|
252
252
|
|
|
253
253
|
// src/webhook.ts
|
|
254
|
+
import * as os from "os";
|
|
254
255
|
var WebhookNotifier = class {
|
|
255
256
|
url;
|
|
256
257
|
constructor(url) {
|
|
@@ -264,11 +265,15 @@ var WebhookNotifier = class {
|
|
|
264
265
|
*/
|
|
265
266
|
async notify(payload) {
|
|
266
267
|
if (!this.url) return false;
|
|
268
|
+
if (this.isDrelEndpoint(this.url)) {
|
|
269
|
+
payload = { ...payload, previewUrl: this.lanify(payload.previewUrl) };
|
|
270
|
+
}
|
|
267
271
|
try {
|
|
272
|
+
const body = this.isDrelEndpoint(this.url) ? JSON.stringify(this.toDrelPayload(payload)) : JSON.stringify(payload);
|
|
268
273
|
const response = await fetch(this.url, {
|
|
269
274
|
method: "POST",
|
|
270
275
|
headers: { "Content-Type": "application/json" },
|
|
271
|
-
body
|
|
276
|
+
body,
|
|
272
277
|
signal: AbortSignal.timeout(5e3)
|
|
273
278
|
});
|
|
274
279
|
return response.ok;
|
|
@@ -276,6 +281,39 @@ var WebhookNotifier = class {
|
|
|
276
281
|
return false;
|
|
277
282
|
}
|
|
278
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* previewUrl 里的 localhost/127.0.0.1 替换为本机局域网 IPv4——
|
|
286
|
+
* 推送目标是手机,localhost 在手机上不可达;同一 Wi-Fi 下局域网 IP 可达。
|
|
287
|
+
*/
|
|
288
|
+
lanify(url) {
|
|
289
|
+
if (!url) return url;
|
|
290
|
+
if (!url.includes("localhost") && !url.includes("127.0.0.1")) return url;
|
|
291
|
+
const ips = Object.values(os.networkInterfaces()).flat().filter((i) => !!i && i.family === "IPv4" && !i.internal);
|
|
292
|
+
if (!ips.length) return url;
|
|
293
|
+
return url.replace("localhost", ips[0].address).replace("127.0.0.1", ips[0].address);
|
|
294
|
+
}
|
|
295
|
+
/** Drel 推送端点识别(api.drel.app/<token>) */
|
|
296
|
+
isDrelEndpoint(url) {
|
|
297
|
+
return url.includes("api.drel.app") || url.includes("drel.app");
|
|
298
|
+
}
|
|
299
|
+
toDrelPayload(payload) {
|
|
300
|
+
const eventLabel = {
|
|
301
|
+
"captcha-detected": "\u26A0\uFE0F \u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801",
|
|
302
|
+
"captcha-resolved": "\u2705 \u9A8C\u8BC1\u7801\u5DF2\u89E3\u51B3",
|
|
303
|
+
"session-started": "\u25B6\uFE0F \u4F1A\u8BDD\u5F00\u59CB",
|
|
304
|
+
"session-ended": "\u23F9 \u4F1A\u8BDD\u7ED3\u675F"
|
|
305
|
+
};
|
|
306
|
+
const parts = [];
|
|
307
|
+
if (payload.reason) parts.push(payload.reason);
|
|
308
|
+
if (payload.targetUrl) parts.push(`\u76EE\u6807: ${payload.targetUrl}`);
|
|
309
|
+
if (payload.sessionId) parts.push(`\u4F1A\u8BDD: ${payload.sessionId}`);
|
|
310
|
+
if (payload.timeout) parts.push(`\u8D85\u65F6: ${payload.timeout}s`);
|
|
311
|
+
return {
|
|
312
|
+
title: payload.title || `${eventLabel[payload.event] || payload.event} \u2014 \u9700\u8981\u4F60\u4ECB\u5165`,
|
|
313
|
+
body: payload.body || parts.join("\n") || payload.event,
|
|
314
|
+
...payload.previewUrl ? { url: payload.previewUrl } : {}
|
|
315
|
+
};
|
|
316
|
+
}
|
|
279
317
|
};
|
|
280
318
|
|
|
281
319
|
// src/human-interaction.ts
|
|
@@ -111,6 +111,7 @@ var CaptchaDetector = class {
|
|
|
111
111
|
};
|
|
112
112
|
|
|
113
113
|
// src/webhook.ts
|
|
114
|
+
import * as os from "os";
|
|
114
115
|
var WebhookNotifier = class {
|
|
115
116
|
url;
|
|
116
117
|
constructor(url) {
|
|
@@ -124,11 +125,15 @@ var WebhookNotifier = class {
|
|
|
124
125
|
*/
|
|
125
126
|
async notify(payload) {
|
|
126
127
|
if (!this.url) return false;
|
|
128
|
+
if (this.isDrelEndpoint(this.url)) {
|
|
129
|
+
payload = { ...payload, previewUrl: this.lanify(payload.previewUrl) };
|
|
130
|
+
}
|
|
127
131
|
try {
|
|
132
|
+
const body = this.isDrelEndpoint(this.url) ? JSON.stringify(this.toDrelPayload(payload)) : JSON.stringify(payload);
|
|
128
133
|
const response = await fetch(this.url, {
|
|
129
134
|
method: "POST",
|
|
130
135
|
headers: { "Content-Type": "application/json" },
|
|
131
|
-
body
|
|
136
|
+
body,
|
|
132
137
|
signal: AbortSignal.timeout(5e3)
|
|
133
138
|
});
|
|
134
139
|
return response.ok;
|
|
@@ -136,6 +141,39 @@ var WebhookNotifier = class {
|
|
|
136
141
|
return false;
|
|
137
142
|
}
|
|
138
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* previewUrl 里的 localhost/127.0.0.1 替换为本机局域网 IPv4——
|
|
146
|
+
* 推送目标是手机,localhost 在手机上不可达;同一 Wi-Fi 下局域网 IP 可达。
|
|
147
|
+
*/
|
|
148
|
+
lanify(url) {
|
|
149
|
+
if (!url) return url;
|
|
150
|
+
if (!url.includes("localhost") && !url.includes("127.0.0.1")) return url;
|
|
151
|
+
const ips = Object.values(os.networkInterfaces()).flat().filter((i) => !!i && i.family === "IPv4" && !i.internal);
|
|
152
|
+
if (!ips.length) return url;
|
|
153
|
+
return url.replace("localhost", ips[0].address).replace("127.0.0.1", ips[0].address);
|
|
154
|
+
}
|
|
155
|
+
/** Drel 推送端点识别(api.drel.app/<token>) */
|
|
156
|
+
isDrelEndpoint(url) {
|
|
157
|
+
return url.includes("api.drel.app") || url.includes("drel.app");
|
|
158
|
+
}
|
|
159
|
+
toDrelPayload(payload) {
|
|
160
|
+
const eventLabel = {
|
|
161
|
+
"captcha-detected": "\u26A0\uFE0F \u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801",
|
|
162
|
+
"captcha-resolved": "\u2705 \u9A8C\u8BC1\u7801\u5DF2\u89E3\u51B3",
|
|
163
|
+
"session-started": "\u25B6\uFE0F \u4F1A\u8BDD\u5F00\u59CB",
|
|
164
|
+
"session-ended": "\u23F9 \u4F1A\u8BDD\u7ED3\u675F"
|
|
165
|
+
};
|
|
166
|
+
const parts = [];
|
|
167
|
+
if (payload.reason) parts.push(payload.reason);
|
|
168
|
+
if (payload.targetUrl) parts.push(`\u76EE\u6807: ${payload.targetUrl}`);
|
|
169
|
+
if (payload.sessionId) parts.push(`\u4F1A\u8BDD: ${payload.sessionId}`);
|
|
170
|
+
if (payload.timeout) parts.push(`\u8D85\u65F6: ${payload.timeout}s`);
|
|
171
|
+
return {
|
|
172
|
+
title: payload.title || `${eventLabel[payload.event] || payload.event} \u2014 \u9700\u8981\u4F60\u4ECB\u5165`,
|
|
173
|
+
body: payload.body || parts.join("\n") || payload.event,
|
|
174
|
+
...payload.previewUrl ? { url: payload.previewUrl } : {}
|
|
175
|
+
};
|
|
176
|
+
}
|
|
139
177
|
};
|
|
140
178
|
|
|
141
179
|
// src/human-interaction.ts
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getCaptchaConfig
|
|
3
|
+
} from "./chunk-ZTHE5RBZ.js";
|
|
4
|
+
|
|
1
5
|
// src/human-interaction.ts
|
|
2
6
|
import { execFile } from "child_process";
|
|
3
7
|
|
|
@@ -247,6 +251,7 @@ var CaptchaDetector = class {
|
|
|
247
251
|
};
|
|
248
252
|
|
|
249
253
|
// src/webhook.ts
|
|
254
|
+
import * as os from "os";
|
|
250
255
|
var WebhookNotifier = class {
|
|
251
256
|
url;
|
|
252
257
|
constructor(url) {
|
|
@@ -260,11 +265,15 @@ var WebhookNotifier = class {
|
|
|
260
265
|
*/
|
|
261
266
|
async notify(payload) {
|
|
262
267
|
if (!this.url) return false;
|
|
268
|
+
if (this.isDrelEndpoint(this.url)) {
|
|
269
|
+
payload = { ...payload, previewUrl: this.lanify(payload.previewUrl) };
|
|
270
|
+
}
|
|
263
271
|
try {
|
|
272
|
+
const body = this.isDrelEndpoint(this.url) ? JSON.stringify(this.toDrelPayload(payload)) : JSON.stringify(payload);
|
|
264
273
|
const response = await fetch(this.url, {
|
|
265
274
|
method: "POST",
|
|
266
275
|
headers: { "Content-Type": "application/json" },
|
|
267
|
-
body
|
|
276
|
+
body,
|
|
268
277
|
signal: AbortSignal.timeout(5e3)
|
|
269
278
|
});
|
|
270
279
|
return response.ok;
|
|
@@ -272,95 +281,40 @@ var WebhookNotifier = class {
|
|
|
272
281
|
return false;
|
|
273
282
|
}
|
|
274
283
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
return coreLoadConfig(getConfigSource());
|
|
286
|
-
}
|
|
287
|
-
function saveConfig(config) {
|
|
288
|
-
coreSaveConfig(getConfigSource(), config);
|
|
289
|
-
}
|
|
290
|
-
function getConfigValue(key) {
|
|
291
|
-
const parts = key.split(".");
|
|
292
|
-
let obj = loadConfig();
|
|
293
|
-
for (const part of parts) {
|
|
294
|
-
if (obj && typeof obj === "object") {
|
|
295
|
-
obj = obj[part];
|
|
296
|
-
} else {
|
|
297
|
-
return void 0;
|
|
298
|
-
}
|
|
284
|
+
/**
|
|
285
|
+
* previewUrl 里的 localhost/127.0.0.1 替换为本机局域网 IPv4——
|
|
286
|
+
* 推送目标是手机,localhost 在手机上不可达;同一 Wi-Fi 下局域网 IP 可达。
|
|
287
|
+
*/
|
|
288
|
+
lanify(url) {
|
|
289
|
+
if (!url) return url;
|
|
290
|
+
if (!url.includes("localhost") && !url.includes("127.0.0.1")) return url;
|
|
291
|
+
const ips = Object.values(os.networkInterfaces()).flat().filter((i) => !!i && i.family === "IPv4" && !i.internal);
|
|
292
|
+
if (!ips.length) return url;
|
|
293
|
+
return url.replace("localhost", ips[0].address).replace("127.0.0.1", ips[0].address);
|
|
299
294
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
const config = loadConfig();
|
|
304
|
-
const parts = key.split(".");
|
|
305
|
-
let obj = config;
|
|
306
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
307
|
-
if (!obj[parts[i]] || typeof obj[parts[i]] !== "object") {
|
|
308
|
-
obj[parts[i]] = {};
|
|
309
|
-
}
|
|
310
|
-
obj = obj[parts[i]];
|
|
295
|
+
/** Drel 推送端点识别(api.drel.app/<token>) */
|
|
296
|
+
isDrelEndpoint(url) {
|
|
297
|
+
return url.includes("api.drel.app") || url.includes("drel.app");
|
|
311
298
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
if (name.startsWith("@")) return [name];
|
|
330
|
-
const resolved = NPM_NAME_ALIASES[name] ?? name;
|
|
331
|
-
return [
|
|
332
|
-
`${NPM_SCOPE}xbrowser-plugin-${resolved}`,
|
|
333
|
-
`${NPM_SCOPE}${resolved}`,
|
|
334
|
-
`xbrowser-plugin-${resolved}`
|
|
335
|
-
];
|
|
336
|
-
}
|
|
337
|
-
async function resolveNpmPackageWithFallback(name) {
|
|
338
|
-
const candidates = generateNpmCandidates(name);
|
|
339
|
-
for (const candidate of candidates) {
|
|
340
|
-
try {
|
|
341
|
-
const encoded = encodeURIComponent(candidate);
|
|
342
|
-
const res = await fetch(`${NPM_REGISTRY_URL}/${encoded}`);
|
|
343
|
-
if (res.ok) return candidate;
|
|
344
|
-
} catch {
|
|
345
|
-
continue;
|
|
346
|
-
}
|
|
299
|
+
toDrelPayload(payload) {
|
|
300
|
+
const eventLabel = {
|
|
301
|
+
"captcha-detected": "\u26A0\uFE0F \u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801",
|
|
302
|
+
"captcha-resolved": "\u2705 \u9A8C\u8BC1\u7801\u5DF2\u89E3\u51B3",
|
|
303
|
+
"session-started": "\u25B6\uFE0F \u4F1A\u8BDD\u5F00\u59CB",
|
|
304
|
+
"session-ended": "\u23F9 \u4F1A\u8BDD\u7ED3\u675F"
|
|
305
|
+
};
|
|
306
|
+
const parts = [];
|
|
307
|
+
if (payload.reason) parts.push(payload.reason);
|
|
308
|
+
if (payload.targetUrl) parts.push(`\u76EE\u6807: ${payload.targetUrl}`);
|
|
309
|
+
if (payload.sessionId) parts.push(`\u4F1A\u8BDD: ${payload.sessionId}`);
|
|
310
|
+
if (payload.timeout) parts.push(`\u8D85\u65F6: ${payload.timeout}s`);
|
|
311
|
+
return {
|
|
312
|
+
title: payload.title || `${eventLabel[payload.event] || payload.event} \u2014 \u9700\u8981\u4F60\u4ECB\u5165`,
|
|
313
|
+
body: payload.body || parts.join("\n") || payload.event,
|
|
314
|
+
...payload.previewUrl ? { url: payload.previewUrl } : {}
|
|
315
|
+
};
|
|
347
316
|
}
|
|
348
|
-
|
|
349
|
-
}
|
|
350
|
-
function getCaptchaConfig() {
|
|
351
|
-
const config = loadConfig();
|
|
352
|
-
return {
|
|
353
|
-
notifyUrl: process.env.XBROWSER_NOTIFY_URL || config.captcha?.notifyUrl,
|
|
354
|
-
autoOpen: process.env.XBROWSER_AUTO_OPEN === "true" || config.captcha?.autoOpen === true,
|
|
355
|
-
timeout: parseInt(process.env.XBROWSER_CAPTCHA_TIMEOUT || "") || config.captcha?.timeout || 120,
|
|
356
|
-
previewPort: parseInt(process.env.XBROWSER_PREVIEW_PORT || "") || config.preview?.port || 9223
|
|
357
|
-
};
|
|
358
|
-
}
|
|
359
|
-
function resolveScreenshotsDir() {
|
|
360
|
-
const configured = getConfigValue("screenshots.dir");
|
|
361
|
-
if (typeof configured === "string" && configured.trim()) return configured.trim();
|
|
362
|
-
return join(tmpdir(), "xbrowser", "screenshots");
|
|
363
|
-
}
|
|
317
|
+
};
|
|
364
318
|
|
|
365
319
|
// src/human-interaction.ts
|
|
366
320
|
var HumanInteractionManager = class {
|
|
@@ -510,15 +464,6 @@ var HumanInteractionManager = class {
|
|
|
510
464
|
};
|
|
511
465
|
|
|
512
466
|
export {
|
|
513
|
-
loadConfig,
|
|
514
|
-
getConfigValue,
|
|
515
|
-
setConfigValue,
|
|
516
|
-
NPM_REGISTRY_URL,
|
|
517
|
-
NPM_SCOPE,
|
|
518
|
-
getMarketplaceUrl,
|
|
519
|
-
resolveNpmPackageWithFallback,
|
|
520
|
-
getCaptchaConfig,
|
|
521
|
-
resolveScreenshotsDir,
|
|
522
467
|
ScreencastCapturer,
|
|
523
468
|
CaptchaDetector,
|
|
524
469
|
WebhookNotifier,
|