@skrillex1224/playwright-toolkit 2.1.133 → 2.1.134

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 CHANGED
@@ -182,6 +182,12 @@ Captcha.useCaptchaMonitor(page, {
182
182
  urlPattern: '/captcha',
183
183
  onDetected: async () => { await Actor.fail('检测到验证码'); }
184
184
  });
185
+
186
+ // Title 监控模式
187
+ Captcha.useCaptchaMonitor(page, {
188
+ titlePattern: /human verification|access denied/i,
189
+ onDetected: async () => { await Actor.fail('检测到风控标题'); }
190
+ });
185
191
  ```
186
192
 
187
193
  ### Constants
package/dist/index.cjs CHANGED
@@ -1345,15 +1345,19 @@ var LiveView = {
1345
1345
  var import_uuid = require("uuid");
1346
1346
  var logger7 = createInternalLogger("Captcha");
1347
1347
  function useCaptchaMonitor(page, options) {
1348
- const { domSelector, urlPattern, onDetected } = options;
1349
- if (!domSelector && !urlPattern) {
1350
- throw new Error("[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector \u6216 urlPattern \u81F3\u5C11\u4E00\u4E2A");
1348
+ const { domSelector, urlPattern, titlePattern, onDetected } = options;
1349
+ if (!domSelector && !urlPattern && !titlePattern) {
1350
+ throw new Error("[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector / urlPattern / titlePattern \u81F3\u5C11\u4E00\u4E2A");
1351
1351
  }
1352
1352
  if (!onDetected || typeof onDetected !== "function") {
1353
1353
  throw new Error("[CaptchaMonitor] onDetected \u5FC5\u987B\u662F\u4E00\u4E2A\u51FD\u6570");
1354
1354
  }
1355
+ if (titlePattern && typeof titlePattern !== "string" && !(titlePattern instanceof RegExp)) {
1356
+ throw new Error("[CaptchaMonitor] titlePattern \u5FC5\u987B\u662F string \u6216 RegExp");
1357
+ }
1355
1358
  let isHandled = false;
1356
1359
  let frameHandler = null;
1360
+ let titleFrameHandler = null;
1357
1361
  let exposedFunctionName = null;
1358
1362
  const triggerDetected = async () => {
1359
1363
  if (isHandled) return;
@@ -1443,6 +1447,51 @@ function useCaptchaMonitor(page, options) {
1443
1447
  page.off("framenavigated", frameHandler);
1444
1448
  });
1445
1449
  }
1450
+ if (titlePattern) {
1451
+ let titleTimer = null;
1452
+ let lastTitle = null;
1453
+ const matchTitle = (title) => {
1454
+ if (!titlePattern) return false;
1455
+ const normalized = String(title || "");
1456
+ if (titlePattern instanceof RegExp) {
1457
+ titlePattern.lastIndex = 0;
1458
+ return titlePattern.test(normalized);
1459
+ }
1460
+ return normalized.includes(String(titlePattern));
1461
+ };
1462
+ const checkCurrentTitle = async (force = false) => {
1463
+ try {
1464
+ const currentTitle = await page.title();
1465
+ if (!force && currentTitle === lastTitle) return;
1466
+ lastTitle = currentTitle;
1467
+ if (!matchTitle(currentTitle)) return;
1468
+ await triggerDetected();
1469
+ } catch {
1470
+ }
1471
+ };
1472
+ titleFrameHandler = async (frame) => {
1473
+ if (frame !== page.mainFrame()) return;
1474
+ await checkCurrentTitle();
1475
+ };
1476
+ page.on("framenavigated", titleFrameHandler);
1477
+ checkCurrentTitle(true).catch(() => {
1478
+ });
1479
+ titleTimer = setInterval(() => {
1480
+ if (isHandled) return;
1481
+ checkCurrentTitle(false).catch(() => {
1482
+ });
1483
+ }, 1e3);
1484
+ logger7.success("useCaptchaMonitor", `Title \u76D1\u63A7\u5DF2\u542F\u7528: ${String(titlePattern)}`);
1485
+ cleanupFns.push(async () => {
1486
+ if (titleTimer) {
1487
+ clearInterval(titleTimer);
1488
+ titleTimer = null;
1489
+ }
1490
+ if (titleFrameHandler) {
1491
+ page.off("framenavigated", titleFrameHandler);
1492
+ }
1493
+ });
1494
+ }
1446
1495
  return {
1447
1496
  stop: async () => {
1448
1497
  logger7.info("useCaptchaMonitor", "\u6B63\u5728\u505C\u6B62\u76D1\u63A7...");