@skrillex1224/playwright-toolkit 2.1.220 → 2.1.222

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.js CHANGED
@@ -334,18 +334,18 @@ var fallbackLog = {
334
334
  error: (...args) => console.error(...args),
335
335
  debug: (...args) => console.debug ? console.debug(...args) : console.log(...args)
336
336
  };
337
- var resolveLogMethod = (logger13, name) => {
338
- if (logger13 && typeof logger13[name] === "function") {
339
- return logger13[name].bind(logger13);
337
+ var resolveLogMethod = (logger14, name) => {
338
+ if (logger14 && typeof logger14[name] === "function") {
339
+ return logger14[name].bind(logger14);
340
340
  }
341
- if (name === "warning" && logger13 && typeof logger13.warn === "function") {
342
- return logger13.warn.bind(logger13);
341
+ if (name === "warning" && logger14 && typeof logger14.warn === "function") {
342
+ return logger14.warn.bind(logger14);
343
343
  }
344
344
  return fallbackLog[name];
345
345
  };
346
346
  var defaultLogger = null;
347
- var setDefaultLogger = (logger13) => {
348
- defaultLogger = logger13;
347
+ var setDefaultLogger = (logger14) => {
348
+ defaultLogger = logger14;
349
349
  };
350
350
  var resolveLogger = (explicitLogger) => {
351
351
  if (explicitLogger && typeof explicitLogger.info === "function") {
@@ -372,8 +372,8 @@ var colorize = (text, color) => {
372
372
  var createBaseLogger = (prefix = "", explicitLogger) => {
373
373
  const name = prefix ? String(prefix) : "";
374
374
  const dispatch = (methodName, icon, message, color) => {
375
- const logger13 = resolveLogger(explicitLogger);
376
- const logFn = resolveLogMethod(logger13, methodName);
375
+ const logger14 = resolveLogger(explicitLogger);
376
+ const logFn = resolveLogMethod(logger14, methodName);
377
377
  const timestamp = colorize(`[${formatTimestamp()}]`, ANSI.gray);
378
378
  const line = formatLine(name, icon, message);
379
379
  const coloredLine = colorize(line, color);
@@ -412,7 +412,6 @@ function createInternalLogger(moduleName, explicitLogger) {
412
412
  },
413
413
  warning(message) {
414
414
  baseLogger.warning(message);
415
- a;
416
415
  },
417
416
  info(message) {
418
417
  baseLogger.info(message);
@@ -658,9 +657,9 @@ var resolveResourceTypeMeta = (domain) => {
658
657
  if (!byType || byType.size === 0) {
659
658
  return { resourceType: "", resourceTypeCounts: void 0 };
660
659
  }
661
- const entries = Array.from(byType.entries()).filter(([type, count]) => type && Number(count) > 0).sort((a2, b) => {
662
- if (Number(b[1]) !== Number(a2[1])) return Number(b[1]) - Number(a2[1]);
663
- return String(a2[0]).localeCompare(String(b[0]));
660
+ const entries = Array.from(byType.entries()).filter(([type, count]) => type && Number(count) > 0).sort((a, b) => {
661
+ if (Number(b[1]) !== Number(a[1])) return Number(b[1]) - Number(a[1]);
662
+ return String(a[0]).localeCompare(String(b[0]));
664
663
  });
665
664
  if (entries.length === 0) {
666
665
  return { resourceType: "", resourceTypeCounts: void 0 };
@@ -750,10 +749,10 @@ var normalizeDomainRows = (hosts) => {
750
749
  resourceTypeCounts: resourceTypeMeta.resourceTypeCounts || void 0
751
750
  });
752
751
  }
753
- rows.sort((a2, b) => {
754
- if (b.totalBytes !== a2.totalBytes) return b.totalBytes - a2.totalBytes;
755
- if (b.requests !== a2.requests) return b.requests - a2.requests;
756
- return String(a2.domain).localeCompare(String(b.domain));
752
+ rows.sort((a, b) => {
753
+ if (b.totalBytes !== a.totalBytes) return b.totalBytes - a.totalBytes;
754
+ if (b.requests !== a.requests) return b.requests - a.requests;
755
+ return String(a.domain).localeCompare(String(b.domain));
757
756
  });
758
757
  return {
759
758
  topDomains: rows.slice(0, MAX_TOP_DOMAINS),
@@ -2948,13 +2947,91 @@ var LiveView = {
2948
2947
  useLiveView
2949
2948
  };
2950
2949
 
2951
- // src/captcha-monitor.js
2950
+ // src/chaptcha.js
2952
2951
  import { v4 as uuidv4 } from "uuid";
2952
+
2953
+ // src/internals/captcha/shared.js
2954
+ var waitForVisible = async (locator, timeout) => {
2955
+ try {
2956
+ await locator.waitFor({
2957
+ state: "visible",
2958
+ timeout
2959
+ });
2960
+ return true;
2961
+ } catch {
2962
+ return false;
2963
+ }
2964
+ };
2965
+ var isAnyCaptchaTextVisible = async (frame, texts, timeout) => {
2966
+ for (const text of texts || []) {
2967
+ if (!text) {
2968
+ continue;
2969
+ }
2970
+ const candidates = [
2971
+ frame.getByText(text, { exact: false }).first(),
2972
+ frame.locator(`text=${text}`).first()
2973
+ ];
2974
+ for (const candidate of candidates) {
2975
+ const isVisible = await candidate.isVisible({ timeout }).catch(() => false);
2976
+ if (isVisible) {
2977
+ return true;
2978
+ }
2979
+ }
2980
+ }
2981
+ return false;
2982
+ };
2983
+ var clickCaptchaAction = async (frame, texts, options) => {
2984
+ for (const text of texts || []) {
2985
+ const candidates = [
2986
+ frame.getByText(text, { exact: false }).first(),
2987
+ frame.locator(`text=${text}`).first()
2988
+ ];
2989
+ for (const candidate of candidates) {
2990
+ const isVisible = await waitForVisible(candidate, options.actionVisibleTimeoutMs);
2991
+ if (!isVisible) {
2992
+ continue;
2993
+ }
2994
+ await candidate.click();
2995
+ return true;
2996
+ }
2997
+ }
2998
+ return false;
2999
+ };
3000
+ var dragCaptchaWithMouse = async (page, sourceLocator, targetLocator) => {
3001
+ const sourceBox = await sourceLocator.boundingBox();
3002
+ const targetBox = await targetLocator.boundingBox();
3003
+ if (!sourceBox || !targetBox) {
3004
+ throw new Error("Unable to resolve captcha drag coordinates.");
3005
+ }
3006
+ const startX = sourceBox.x + sourceBox.width / 2;
3007
+ const startY = sourceBox.y + sourceBox.height / 2;
3008
+ const endX = targetBox.x + targetBox.width / 2;
3009
+ const endY = targetBox.y + targetBox.height / 2;
3010
+ const steps = 10;
3011
+ const liftOffsetX = Math.min(18, Math.max(8, sourceBox.width * 0.12));
3012
+ const liftOffsetY = Math.min(12, Math.max(4, sourceBox.height * 0.08));
3013
+ await page.mouse.move(startX, startY, { steps: 8 });
3014
+ await page.waitForTimeout(250);
3015
+ await page.mouse.down();
3016
+ await page.waitForTimeout(350);
3017
+ await page.mouse.move(startX + liftOffsetX, startY + liftOffsetY, { steps: 6 });
3018
+ await page.waitForTimeout(250);
3019
+ for (let step = 1; step <= steps; step++) {
3020
+ const progress = step / steps;
3021
+ const easedProgress = 1 - (1 - progress) * (1 - progress);
3022
+ const currentX = startX + liftOffsetX + (endX - startX - liftOffsetX) * easedProgress;
3023
+ const currentY = startY + liftOffsetY + (endY - startY - liftOffsetY) * easedProgress;
3024
+ await page.mouse.move(currentX, currentY, { steps: 2 });
3025
+ await page.waitForTimeout(90);
3026
+ }
3027
+ await page.waitForTimeout(100);
3028
+ await page.mouse.up();
3029
+ await page.waitForTimeout(100);
3030
+ };
3031
+
3032
+ // src/internals/captcha/bytedance.js
2953
3033
  var logger9 = createInternalLogger("Captcha");
2954
- var DEFAULT_BYTEDANCE_CAPTCHA_TOKEN = "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI";
2955
3034
  var DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS = Object.freeze({
2956
- token: DEFAULT_BYTEDANCE_CAPTCHA_TOKEN,
2957
- apiUrl: "https://api.jfbym.com/api/YmServer/customApi",
2958
3035
  apiType: "31234",
2959
3036
  maxRetries: 3,
2960
3037
  containerSelector: "#captcha_container",
@@ -2991,128 +3068,6 @@ var DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS = Object.freeze({
2991
3068
  retryDelayBaseMs: 2e3,
2992
3069
  retryDelayStepMs: 1e3
2993
3070
  });
2994
- function useCaptchaMonitor(page, options) {
2995
- const { domSelector, urlPattern, onDetected } = options;
2996
- if (!domSelector && !urlPattern) {
2997
- throw new Error("[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector \u6216 urlPattern\u3002");
2998
- }
2999
- if (!onDetected || typeof onDetected !== "function") {
3000
- throw new Error("[CaptchaMonitor] onDetected \u5FC5\u987B\u662F\u51FD\u6570\u3002");
3001
- }
3002
- let isStopped = false;
3003
- let isHandling = false;
3004
- let frameHandler = null;
3005
- let exposedFunctionName = null;
3006
- const triggerDetected = async () => {
3007
- if (isStopped || isHandling) return;
3008
- isHandling = true;
3009
- try {
3010
- await onDetected();
3011
- } finally {
3012
- isHandling = false;
3013
- }
3014
- };
3015
- const cleanupFns = [];
3016
- if (domSelector) {
3017
- exposedFunctionName = `__c_d_${uuidv4().replace(/-/g, "_")}`;
3018
- const cleanerName = `__c_cleaner_${uuidv4().replace(/-/g, "_")}`;
3019
- page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {
3020
- });
3021
- page.addInitScript(({ selector, callbackName, cleanerName: cleanupName }) => {
3022
- (() => {
3023
- let observer = null;
3024
- const checkAndReport = () => {
3025
- const element = document.querySelector(selector);
3026
- if (!element) {
3027
- return false;
3028
- }
3029
- if (window[callbackName]) {
3030
- window[callbackName]();
3031
- }
3032
- return true;
3033
- };
3034
- checkAndReport();
3035
- observer = new MutationObserver((mutations) => {
3036
- const shouldCheck = mutations.some((mutation) => mutation.addedNodes.length > 0);
3037
- if (shouldCheck && observer) {
3038
- checkAndReport();
3039
- }
3040
- });
3041
- const mountObserver = () => {
3042
- const target = document.documentElement;
3043
- if (target && observer) {
3044
- observer.observe(target, { childList: true, subtree: true });
3045
- }
3046
- };
3047
- if (document.readyState === "loading") {
3048
- window.addEventListener("DOMContentLoaded", mountObserver);
3049
- } else {
3050
- mountObserver();
3051
- }
3052
- window[cleanupName] = () => {
3053
- if (observer) {
3054
- observer.disconnect();
3055
- observer = null;
3056
- }
3057
- };
3058
- })();
3059
- }, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
3060
- logger9.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
3061
- cleanupFns.push(async () => {
3062
- try {
3063
- await page.evaluate((name) => {
3064
- if (window[name]) {
3065
- window[name]();
3066
- delete window[name];
3067
- }
3068
- }, cleanerName);
3069
- } catch {
3070
- }
3071
- });
3072
- }
3073
- if (urlPattern) {
3074
- frameHandler = async (frame) => {
3075
- if (frame !== page.mainFrame()) {
3076
- return;
3077
- }
3078
- const currentUrl = page.url();
3079
- if (currentUrl.includes(urlPattern)) {
3080
- await triggerDetected();
3081
- }
3082
- };
3083
- page.on("framenavigated", frameHandler);
3084
- logger9.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
3085
- cleanupFns.push(async () => {
3086
- page.off("framenavigated", frameHandler);
3087
- });
3088
- }
3089
- return {
3090
- stop: async () => {
3091
- logger9.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
3092
- for (const fn of cleanupFns) {
3093
- await fn();
3094
- }
3095
- isStopped = true;
3096
- }
3097
- };
3098
- }
3099
- var callCaptchaRecognitionApi = async (imageBase64, { apiUrl, apiType, token }) => {
3100
- const response = await fetch(apiUrl, {
3101
- method: "POST",
3102
- headers: {
3103
- "Content-Type": "application/json"
3104
- },
3105
- body: JSON.stringify({
3106
- type: apiType,
3107
- image: imageBase64,
3108
- token
3109
- })
3110
- });
3111
- if (!response.ok) {
3112
- throw new Error(`Captcha API request failed with status ${response.status}`);
3113
- }
3114
- return await response.json();
3115
- };
3116
3071
  var extractCaptchaSerialNumbers = (apiResponse) => {
3117
3072
  const serialNumbers = apiResponse?.data?.data?.serial_number;
3118
3073
  if (!Array.isArray(serialNumbers)) {
@@ -3120,76 +3075,6 @@ var extractCaptchaSerialNumbers = (apiResponse) => {
3120
3075
  }
3121
3076
  return serialNumbers.map((value) => Number(value)).filter((value) => Number.isInteger(value) && value >= 0);
3122
3077
  };
3123
- var waitForVisible = async (locator, timeout) => {
3124
- try {
3125
- await locator.waitFor({
3126
- state: "visible",
3127
- timeout
3128
- });
3129
- return true;
3130
- } catch {
3131
- return false;
3132
- }
3133
- };
3134
- var isAnyCaptchaTextVisible = async (frame, texts, timeout) => {
3135
- for (const text of texts || []) {
3136
- if (!text) {
3137
- continue;
3138
- }
3139
- const candidates = [
3140
- frame.getByText(text, { exact: false }).first(),
3141
- frame.locator(`text=${text}`).first()
3142
- ];
3143
- for (const candidate of candidates) {
3144
- const isVisible = await candidate.isVisible({ timeout }).catch(() => false);
3145
- if (isVisible) {
3146
- return true;
3147
- }
3148
- }
3149
- }
3150
- return false;
3151
- };
3152
- var waitForCaptchaChallengeReady = async (page, frame, options) => {
3153
- const deadline = Date.now() + options.challengeReadyTimeoutMs;
3154
- let refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3155
- let hasSeenLoading = false;
3156
- while (Date.now() < deadline) {
3157
- const isLoadingVisible = await isAnyCaptchaTextVisible(
3158
- frame,
3159
- options.loadingTexts,
3160
- options.loadingIndicatorVisibleTimeoutMs
3161
- );
3162
- const hasErrorTextVisible = await isAnyCaptchaTextVisible(
3163
- frame,
3164
- options.errorTexts,
3165
- options.loadingIndicatorVisibleTimeoutMs
3166
- );
3167
- hasSeenLoading = hasSeenLoading || isLoadingVisible;
3168
- const sourceImages = frame.locator(options.sourceImageSelector);
3169
- const imageCount = await sourceImages.count().catch(() => 0);
3170
- const hasVisibleSourceImage = imageCount > 0 ? await sourceImages.first().isVisible({ timeout: options.loadingIndicatorVisibleTimeoutMs }).catch(() => false) : false;
3171
- if (!isLoadingVisible && hasVisibleSourceImage) {
3172
- logger9.info(hasSeenLoading ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u52A0\u8F7D\u5B8C\u6210\u3002" : "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u5C31\u7EEA\u3002");
3173
- return;
3174
- }
3175
- if (hasErrorTextVisible) {
3176
- logger9.warn("\u9A8C\u8BC1\u7801\u9762\u677F\u51FA\u73B0\u7F51\u7EDC\u5F02\u5E38\u6587\u6848\uFF0C\u5C1D\u8BD5\u7ACB\u5373\u5237\u65B0\u9898\u76EE\u3002");
3177
- await refreshCaptcha(page, frame, options);
3178
- refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3179
- hasSeenLoading = false;
3180
- continue;
3181
- }
3182
- if (!hasVisibleSourceImage && Date.now() >= refreshDeadline) {
3183
- logger9.warn(`\u9A8C\u8BC1\u7801\u56FE\u7247\u8D85\u8FC7 ${options.challengeReadyRefreshTimeoutMs}ms \u4ECD\u672A\u51FA\u73B0\uFF0C\u5C1D\u8BD5\u5237\u65B0\u9898\u76EE\u3002`);
3184
- await refreshCaptcha(page, frame, options);
3185
- refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3186
- hasSeenLoading = false;
3187
- continue;
3188
- }
3189
- await page.waitForTimeout(options.challengeReadyPollMs);
3190
- }
3191
- throw new Error("Captcha challenge is still loading and did not become ready in time.");
3192
- };
3193
3078
  var resolveContentFrame = async (page, iframeLocator, options) => {
3194
3079
  for (let attempt = 1; attempt <= options.contentFrameResolveRetries; attempt++) {
3195
3080
  const iframeHandle = await iframeLocator.elementHandle();
@@ -3236,22 +3121,14 @@ var getVerifycenterCaptchaContext = async (page, options) => {
3236
3121
  }
3237
3122
  return { iframeLocator, frame };
3238
3123
  };
3239
- var clickCaptchaAction = async (frame, texts, options) => {
3240
- for (const text of texts) {
3241
- const candidates = [
3242
- frame.getByText(text, { exact: false }).first(),
3243
- frame.locator(`text=${text}`).first()
3244
- ];
3245
- for (const candidate of candidates) {
3246
- const isVisible = await waitForVisible(candidate, options.actionVisibleTimeoutMs);
3247
- if (!isVisible) {
3248
- continue;
3249
- }
3250
- await candidate.click();
3251
- return true;
3252
- }
3124
+ var refreshCaptcha = async (page, frame, options) => {
3125
+ const clicked = await clickCaptchaAction(frame, options.refreshTexts, options).catch(() => false);
3126
+ if (!clicked) {
3127
+ logger9.warn("Refresh button not found.");
3128
+ return false;
3253
3129
  }
3254
- return false;
3130
+ await page.waitForTimeout(options.refreshWaitMs);
3131
+ return true;
3255
3132
  };
3256
3133
  var findCaptchaDropTarget = async (frame, options) => {
3257
3134
  for (const text of options.dropTargetTexts) {
@@ -3268,47 +3145,52 @@ var findCaptchaDropTarget = async (frame, options) => {
3268
3145
  }
3269
3146
  return null;
3270
3147
  };
3271
- var dragCaptchaWithMouse = async (page, sourceLocator, targetLocator) => {
3272
- const sourceBox = await sourceLocator.boundingBox();
3273
- const targetBox = await targetLocator.boundingBox();
3274
- if (!sourceBox || !targetBox) {
3275
- throw new Error("Unable to resolve captcha drag coordinates.");
3276
- }
3277
- const startX = sourceBox.x + sourceBox.width / 2;
3278
- const startY = sourceBox.y + sourceBox.height / 2;
3279
- const endX = targetBox.x + targetBox.width / 2;
3280
- const endY = targetBox.y + targetBox.height / 2;
3281
- const steps = 10;
3282
- const liftOffsetX = Math.min(18, Math.max(8, sourceBox.width * 0.12));
3283
- const liftOffsetY = Math.min(12, Math.max(4, sourceBox.height * 0.08));
3284
- await page.mouse.move(startX, startY, { steps: 8 });
3285
- await page.waitForTimeout(250);
3286
- await page.mouse.down();
3287
- await page.waitForTimeout(350);
3288
- await page.mouse.move(startX + liftOffsetX, startY + liftOffsetY, { steps: 6 });
3289
- await page.waitForTimeout(250);
3290
- for (let step = 1; step <= steps; step++) {
3291
- const progress = step / steps;
3292
- const easedProgress = 1 - (1 - progress) * (1 - progress);
3293
- const currentX = startX + liftOffsetX + (endX - startX - liftOffsetX) * easedProgress;
3294
- const currentY = startY + liftOffsetY + (endY - startY - liftOffsetY) * easedProgress;
3295
- await page.mouse.move(currentX, currentY, { steps: 2 });
3296
- await page.waitForTimeout(90);
3148
+ var waitForCaptchaChallengeReady = async (page, frame, options) => {
3149
+ const deadline = Date.now() + options.challengeReadyTimeoutMs;
3150
+ let refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3151
+ let hasSeenLoading = false;
3152
+ while (Date.now() < deadline) {
3153
+ const isLoadingVisible = await isAnyCaptchaTextVisible(
3154
+ frame,
3155
+ options.loadingTexts,
3156
+ options.loadingIndicatorVisibleTimeoutMs
3157
+ );
3158
+ const hasErrorTextVisible = await isAnyCaptchaTextVisible(
3159
+ frame,
3160
+ options.errorTexts,
3161
+ options.loadingIndicatorVisibleTimeoutMs
3162
+ );
3163
+ hasSeenLoading = hasSeenLoading || isLoadingVisible;
3164
+ const sourceImages = frame.locator(options.sourceImageSelector);
3165
+ const imageCount = await sourceImages.count().catch(() => 0);
3166
+ const hasVisibleSourceImage = imageCount > 0 ? await sourceImages.first().isVisible({ timeout: options.loadingIndicatorVisibleTimeoutMs }).catch(() => false) : false;
3167
+ if (!isLoadingVisible && hasVisibleSourceImage) {
3168
+ logger9.info(hasSeenLoading ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u52A0\u8F7D\u5B8C\u6210\u3002" : "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u5C31\u7EEA\u3002");
3169
+ return;
3170
+ }
3171
+ if (hasErrorTextVisible) {
3172
+ logger9.warn("\u9A8C\u8BC1\u7801\u9762\u677F\u51FA\u73B0\u7F51\u7EDC\u5F02\u5E38\u6587\u6848\uFF0C\u5C1D\u8BD5\u7ACB\u5373\u5237\u65B0\u9898\u76EE\u3002");
3173
+ await refreshCaptcha(page, frame, options);
3174
+ refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3175
+ hasSeenLoading = false;
3176
+ continue;
3177
+ }
3178
+ if (!hasVisibleSourceImage && Date.now() >= refreshDeadline) {
3179
+ logger9.warn(`\u9A8C\u8BC1\u7801\u56FE\u7247\u8D85\u8FC7 ${options.challengeReadyRefreshTimeoutMs}ms \u4ECD\u672A\u51FA\u73B0\uFF0C\u5C1D\u8BD5\u5237\u65B0\u9898\u76EE\u3002`);
3180
+ await refreshCaptcha(page, frame, options);
3181
+ refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3182
+ hasSeenLoading = false;
3183
+ continue;
3184
+ }
3185
+ await page.waitForTimeout(options.challengeReadyPollMs);
3297
3186
  }
3298
- await page.waitForTimeout(100);
3299
- await page.mouse.up();
3300
- await page.waitForTimeout(100);
3187
+ throw new Error("Captcha challenge is still loading and did not become ready in time.");
3301
3188
  };
3302
- var refreshCaptcha = async (page, frame, options) => {
3303
- const clicked = await clickCaptchaAction(frame, options.refreshTexts, options).catch(() => false);
3304
- if (!clicked) {
3305
- logger9.warn("Refresh button not found.");
3306
- return false;
3189
+ async function solveCaptcha(page, options = {}, dependencies = {}) {
3190
+ const { callCaptchaRecognitionApi: callCaptchaRecognitionApi2 } = dependencies;
3191
+ if (typeof callCaptchaRecognitionApi2 !== "function") {
3192
+ throw new Error("[Captcha] \u7F3A\u5C11\u901A\u7528\u8BC6\u522B\u8BF7\u6C42\u51FD\u6570 callCaptchaRecognitionApi\u3002");
3307
3193
  }
3308
- await page.waitForTimeout(options.refreshWaitMs);
3309
- return true;
3310
- };
3311
- async function solveBytedanceCaptcha(page, options = {}) {
3312
3194
  const config = {
3313
3195
  ...DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS,
3314
3196
  ...options
@@ -3317,6 +3199,7 @@ async function solveBytedanceCaptcha(page, options = {}) {
3317
3199
  logger9.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
3318
3200
  return false;
3319
3201
  }
3202
+ logger9.info("\u5F53\u524D\u4F7F\u7528\u672Ctool\u2014\u2014\u6D4B\u8BD5\u7248\u672C");
3320
3203
  for (let attempt = 1; attempt <= config.maxRetries; attempt++) {
3321
3204
  logger9.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
3322
3205
  try {
@@ -3329,10 +3212,12 @@ async function solveBytedanceCaptcha(page, options = {}) {
3329
3212
  await waitForCaptchaChallengeReady(page, frame, config);
3330
3213
  await page.waitForTimeout(config.recognitionDelayMs);
3331
3214
  const screenshotBuffer = await iframeLocator.screenshot();
3332
- const apiResponse = await callCaptchaRecognitionApi(
3333
- screenshotBuffer.toString("base64"),
3334
- config
3335
- );
3215
+ const apiResponse = await callCaptchaRecognitionApi2({
3216
+ apiUrl: config.apiUrl,
3217
+ type: config.apiType,
3218
+ image: screenshotBuffer.toString("base64"),
3219
+ token: config.token
3220
+ });
3336
3221
  const serialNumbers = extractCaptchaSerialNumbers(apiResponse);
3337
3222
  if (apiResponse?.code !== config.recognitionSuccessCode || serialNumbers.length === 0) {
3338
3223
  logger9.warn(
@@ -3388,15 +3273,178 @@ async function solveBytedanceCaptcha(page, options = {}) {
3388
3273
  logger9.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
3389
3274
  return false;
3390
3275
  }
3276
+ var sloveCaptcha = solveCaptcha;
3277
+
3278
+ // src/chaptcha.js
3279
+ var logger10 = createInternalLogger("Captcha");
3280
+ var DEFAULT_CAPTCHA_RECOGNITION_OPTIONS = Object.freeze({
3281
+ token: "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI",
3282
+ apiUrl: "https://api.jfbym.com/api/YmServer/customApi"
3283
+ });
3284
+ var CAPTCHA_STRATEGIES = Object.freeze({
3285
+ bytedance: {
3286
+ sloveCaptcha
3287
+ }
3288
+ });
3289
+ var mergeDefinedOptions = (...sources) => {
3290
+ const merged = {};
3291
+ for (const source of sources) {
3292
+ for (const [key, value] of Object.entries(source || {})) {
3293
+ if (value !== void 0) {
3294
+ merged[key] = value;
3295
+ }
3296
+ }
3297
+ }
3298
+ return merged;
3299
+ };
3300
+ function useCaptchaMonitor(page, options) {
3301
+ const { domSelector, urlPattern, onDetected } = options;
3302
+ if (!domSelector && !urlPattern) {
3303
+ throw new Error("[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector \u6216 urlPattern\u3002");
3304
+ }
3305
+ if (!onDetected || typeof onDetected !== "function") {
3306
+ throw new Error("[CaptchaMonitor] onDetected \u5FC5\u987B\u662F\u51FD\u6570\u3002");
3307
+ }
3308
+ let isStopped = false;
3309
+ let isHandling = false;
3310
+ let frameHandler = null;
3311
+ let exposedFunctionName = null;
3312
+ const triggerDetected = async () => {
3313
+ if (isStopped || isHandling) return;
3314
+ isHandling = true;
3315
+ try {
3316
+ await onDetected();
3317
+ } finally {
3318
+ isHandling = false;
3319
+ }
3320
+ };
3321
+ const cleanupFns = [];
3322
+ if (domSelector) {
3323
+ exposedFunctionName = `__c_d_${uuidv4().replace(/-/g, "_")}`;
3324
+ const cleanerName = `__c_cleaner_${uuidv4().replace(/-/g, "_")}`;
3325
+ page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {
3326
+ });
3327
+ page.addInitScript(({ selector, callbackName, cleanerName: cleanupName }) => {
3328
+ (() => {
3329
+ let observer = null;
3330
+ const checkAndReport = () => {
3331
+ const element = document.querySelector(selector);
3332
+ if (!element) {
3333
+ return false;
3334
+ }
3335
+ if (window[callbackName]) {
3336
+ window[callbackName]();
3337
+ }
3338
+ return true;
3339
+ };
3340
+ checkAndReport();
3341
+ observer = new MutationObserver((mutations) => {
3342
+ const shouldCheck = mutations.some((mutation) => mutation.addedNodes.length > 0);
3343
+ if (shouldCheck && observer) {
3344
+ checkAndReport();
3345
+ }
3346
+ });
3347
+ const mountObserver = () => {
3348
+ const target = document.documentElement;
3349
+ if (target && observer) {
3350
+ observer.observe(target, { childList: true, subtree: true });
3351
+ }
3352
+ };
3353
+ if (document.readyState === "loading") {
3354
+ window.addEventListener("DOMContentLoaded", mountObserver);
3355
+ } else {
3356
+ mountObserver();
3357
+ }
3358
+ window[cleanupName] = () => {
3359
+ if (observer) {
3360
+ observer.disconnect();
3361
+ observer = null;
3362
+ }
3363
+ };
3364
+ })();
3365
+ }, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
3366
+ logger10.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
3367
+ cleanupFns.push(async () => {
3368
+ try {
3369
+ await page.evaluate((name) => {
3370
+ if (window[name]) {
3371
+ window[name]();
3372
+ delete window[name];
3373
+ }
3374
+ }, cleanerName);
3375
+ } catch {
3376
+ }
3377
+ });
3378
+ }
3379
+ if (urlPattern) {
3380
+ frameHandler = async (frame) => {
3381
+ if (frame !== page.mainFrame()) {
3382
+ return;
3383
+ }
3384
+ const currentUrl = page.url();
3385
+ if (currentUrl.includes(urlPattern)) {
3386
+ await triggerDetected();
3387
+ }
3388
+ };
3389
+ page.on("framenavigated", frameHandler);
3390
+ logger10.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
3391
+ cleanupFns.push(async () => {
3392
+ page.off("framenavigated", frameHandler);
3393
+ });
3394
+ }
3395
+ return {
3396
+ stop: async () => {
3397
+ logger10.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
3398
+ for (const fn of cleanupFns) {
3399
+ await fn();
3400
+ }
3401
+ isStopped = true;
3402
+ }
3403
+ };
3404
+ }
3405
+ var callCaptchaRecognitionApi = async (requestParams = {}) => {
3406
+ const { apiUrl, ...payload } = mergeDefinedOptions(
3407
+ DEFAULT_CAPTCHA_RECOGNITION_OPTIONS,
3408
+ requestParams
3409
+ );
3410
+ if (!apiUrl) {
3411
+ throw new Error("[Captcha] \u7F3A\u5C11\u9A8C\u8BC1\u7801\u8BC6\u522B\u63A5\u53E3\u5730\u5740 apiUrl\u3002");
3412
+ }
3413
+ const response = await fetch(apiUrl, {
3414
+ method: "POST",
3415
+ headers: {
3416
+ "Content-Type": "application/json"
3417
+ },
3418
+ body: JSON.stringify(payload)
3419
+ });
3420
+ if (!response.ok) {
3421
+ throw new Error(`Captcha API request failed with status ${response.status}`);
3422
+ }
3423
+ return await response.json();
3424
+ };
3425
+ async function solveCaptchaWithStrategy(strategyName, page, options = {}) {
3426
+ const strategy = CAPTCHA_STRATEGIES[strategyName];
3427
+ if (!strategy?.sloveCaptcha) {
3428
+ throw new Error(`[Captcha] \u672A\u627E\u5230\u9A8C\u8BC1\u7801\u7B56\u7565\uFF1A${strategyName}`);
3429
+ }
3430
+ const resolvedOptions = mergeDefinedOptions(
3431
+ DEFAULT_CAPTCHA_RECOGNITION_OPTIONS,
3432
+ options
3433
+ );
3434
+ return strategy.sloveCaptcha(page, resolvedOptions, {
3435
+ callCaptchaRecognitionApi,
3436
+ logger: logger10
3437
+ });
3438
+ }
3391
3439
  var Captcha = {
3392
3440
  useCaptchaMonitor,
3393
- solveBytedanceCaptcha
3441
+ solveCaptchaWithStrategy
3394
3442
  };
3395
3443
 
3396
3444
  // src/mutation.js
3397
3445
  import { createHash } from "node:crypto";
3398
3446
  import { v4 as uuidv42 } from "uuid";
3399
- var logger10 = createInternalLogger("Mutation");
3447
+ var logger11 = createInternalLogger("Mutation");
3400
3448
  var MUTATION_MONITOR_MODE = Object.freeze({
3401
3449
  Added: "added",
3402
3450
  Changed: "changed",
@@ -3429,14 +3477,14 @@ var Mutation = {
3429
3477
  const stableTime = options.stableTime ?? 5 * 1e3;
3430
3478
  const timeout = options.timeout ?? 120 * 1e3;
3431
3479
  const onMutation = options.onMutation;
3432
- logger10.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
3480
+ logger11.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
3433
3481
  if (initialTimeout > 0) {
3434
3482
  const selectorQuery = selectorList.join(",");
3435
3483
  try {
3436
3484
  await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
3437
- logger10.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3485
+ logger11.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3438
3486
  } catch (e) {
3439
- logger10.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3487
+ logger11.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3440
3488
  throw e;
3441
3489
  }
3442
3490
  }
@@ -3452,7 +3500,7 @@ var Mutation = {
3452
3500
  return "__CONTINUE__";
3453
3501
  }
3454
3502
  });
3455
- logger10.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
3503
+ logger11.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
3456
3504
  } catch (e) {
3457
3505
  }
3458
3506
  }
@@ -3567,9 +3615,9 @@ var Mutation = {
3567
3615
  { selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }
3568
3616
  );
3569
3617
  if (result.mutationCount === 0 && result.stableTime === 0) {
3570
- logger10.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3618
+ logger11.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3571
3619
  }
3572
- logger10.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3620
+ logger11.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3573
3621
  return result;
3574
3622
  },
3575
3623
  /**
@@ -3741,22 +3789,22 @@ var Mutation = {
3741
3789
  return "__CONTINUE__";
3742
3790
  }
3743
3791
  };
3744
- logger10.start(
3792
+ logger11.start(
3745
3793
  "waitForStableAcrossRoots",
3746
3794
  `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668(\u8DE8 root), \u7A33\u5B9A\u65F6\u95F4=${waitForStableTime}ms`
3747
3795
  );
3748
3796
  if (initialTimeout > 0) {
3749
3797
  try {
3750
3798
  await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
3751
- logger10.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3799
+ logger11.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3752
3800
  } catch (e) {
3753
- logger10.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3801
+ logger11.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3754
3802
  throw e;
3755
3803
  }
3756
3804
  }
3757
3805
  let state = await buildState();
3758
3806
  if (!state?.hasMatched) {
3759
- logger10.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3807
+ logger11.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3760
3808
  return { mutationCount: 0, stableTime: 0, wasPaused: false };
3761
3809
  }
3762
3810
  let mutationCount = 0;
@@ -3793,7 +3841,7 @@ var Mutation = {
3793
3841
  if (lastState.snapshotKey !== lastSnapshotKey) {
3794
3842
  lastSnapshotKey = lastState.snapshotKey;
3795
3843
  mutationCount += 1;
3796
- logger10.info(
3844
+ logger11.info(
3797
3845
  `waitForStableAcrossRoots \u53D8\u5316#${mutationCount}, len=${lastState.snapshotLength}, path=${lastState.primaryPath || "unknown"}, preview="${truncate(lastState.text, 120)}"`
3798
3846
  );
3799
3847
  const signal = await invokeMutationCallback({
@@ -3806,7 +3854,7 @@ var Mutation = {
3806
3854
  continue;
3807
3855
  }
3808
3856
  if (!isPaused && stableSince > 0 && Date.now() - stableSince >= waitForStableTime) {
3809
- logger10.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3857
+ logger11.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3810
3858
  return {
3811
3859
  mutationCount,
3812
3860
  stableTime: waitForStableTime,
@@ -3833,7 +3881,7 @@ var Mutation = {
3833
3881
  const onMutation = options.onMutation;
3834
3882
  const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();
3835
3883
  const mode = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode) ? rawMode : MUTATION_MONITOR_MODE.Added;
3836
- logger10.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
3884
+ logger11.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
3837
3885
  const monitorKey = generateKey("pk_mon");
3838
3886
  const callbackName = generateKey("pk_mon_cb");
3839
3887
  const cleanerName = generateKey("pk_mon_clean");
@@ -3976,7 +4024,7 @@ var Mutation = {
3976
4024
  return total;
3977
4025
  };
3978
4026
  }, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });
3979
- logger10.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
4027
+ logger11.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
3980
4028
  return {
3981
4029
  stop: async () => {
3982
4030
  let totalMutations = 0;
@@ -3989,7 +4037,7 @@ var Mutation = {
3989
4037
  }, cleanerName);
3990
4038
  } catch (e) {
3991
4039
  }
3992
- logger10.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
4040
+ logger11.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
3993
4041
  return { totalMutations };
3994
4042
  }
3995
4043
  };
@@ -4858,7 +4906,7 @@ var createTemplateLogger = (baseLogger = createBaseLogger()) => {
4858
4906
  };
4859
4907
  var getDefaultBaseLogger = () => createBaseLogger("");
4860
4908
  var Logger = {
4861
- setLogger: (logger13) => setDefaultLogger(logger13),
4909
+ setLogger: (logger14) => setDefaultLogger(logger14),
4862
4910
  info: (message) => getDefaultBaseLogger().info(message),
4863
4911
  success: (message) => getDefaultBaseLogger().success(message),
4864
4912
  warning: (message) => getDefaultBaseLogger().warning(message),
@@ -4866,8 +4914,8 @@ var Logger = {
4866
4914
  error: (message) => getDefaultBaseLogger().error(message),
4867
4915
  debug: (message) => getDefaultBaseLogger().debug(message),
4868
4916
  start: (message) => getDefaultBaseLogger().start(message),
4869
- useTemplate: (logger13) => {
4870
- if (logger13) return createTemplateLogger(createBaseLogger("", logger13));
4917
+ useTemplate: (logger14) => {
4918
+ if (logger14) return createTemplateLogger(createBaseLogger("", logger14));
4871
4919
  return createTemplateLogger();
4872
4920
  }
4873
4921
  };
@@ -4932,7 +4980,7 @@ var LOCATION_NETWORK_SUFFIX_PATTERNS = [
4932
4980
  ];
4933
4981
  var cachedStripLogoSrcPromise = null;
4934
4982
  var cachedEnrichmentByContext = /* @__PURE__ */ new WeakMap();
4935
- var logger11 = createInternalLogger("Watermarkify");
4983
+ var logger12 = createInternalLogger("Watermarkify");
4936
4984
  var normalizeText = (value) => String(value || "").trim();
4937
4985
  var toInline = (value, maxLen = 200) => {
4938
4986
  const text = normalizeText(value);
@@ -5174,9 +5222,9 @@ var resolveWithCustomResolver = async (page, baseMeta, options = {}) => {
5174
5222
  location: toInline(resolved.location, 80)
5175
5223
  };
5176
5224
  if (enrichment.ip || enrichment.location) {
5177
- logger11.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
5225
+ logger12.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
5178
5226
  } else {
5179
- logger11.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
5227
+ logger12.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
5180
5228
  }
5181
5229
  return enrichment;
5182
5230
  } finally {
@@ -5360,12 +5408,12 @@ var buildWatermarkifyRenderHtml = ({ imageSrc, overlaySvg, width, height }) => {
5360
5408
  };
5361
5409
  var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageInfo = {}) => {
5362
5410
  if (!page || typeof page.context !== "function") {
5363
- logger11.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
5411
+ logger12.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
5364
5412
  return buffer;
5365
5413
  }
5366
5414
  const renderScope = await openProbePage(page);
5367
5415
  if (!renderScope?.page) {
5368
- logger11.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
5416
+ logger12.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
5369
5417
  return buffer;
5370
5418
  }
5371
5419
  try {
@@ -5408,13 +5456,13 @@ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageI
5408
5456
  fullPage: true,
5409
5457
  animations: "disabled"
5410
5458
  }).catch((error) => {
5411
- logger11.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
5459
+ logger12.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
5412
5460
  return null;
5413
5461
  });
5414
5462
  if (Buffer.isBuffer(composed) && composed.length > 0) {
5415
5463
  return composed;
5416
5464
  }
5417
- logger11.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
5465
+ logger12.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
5418
5466
  return buffer;
5419
5467
  } finally {
5420
5468
  await renderScope.close().catch(() => {
@@ -5427,7 +5475,7 @@ var resolveWithIpLookup = async (page, options = {}) => {
5427
5475
  }
5428
5476
  const probeScope = await openProbePage(page);
5429
5477
  if (!probeScope?.page) {
5430
- logger11.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
5478
+ logger12.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
5431
5479
  return null;
5432
5480
  }
5433
5481
  const timeoutMs = Math.max(
@@ -5436,12 +5484,12 @@ var resolveWithIpLookup = async (page, options = {}) => {
5436
5484
  );
5437
5485
  try {
5438
5486
  const probePage = probeScope.page;
5439
- logger11.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
5487
+ logger12.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
5440
5488
  const response = await probePage.goto(DEFAULT_IP_LOOKUP_URL, {
5441
5489
  waitUntil: "commit",
5442
5490
  timeout: timeoutMs
5443
5491
  }).catch((error) => {
5444
- logger11.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
5492
+ logger12.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
5445
5493
  return null;
5446
5494
  });
5447
5495
  const status = response && typeof response.status === "function" ? response.status() : 0;
@@ -5463,13 +5511,13 @@ var resolveWithIpLookup = async (page, options = {}) => {
5463
5511
  }
5464
5512
  const parsed = parseIpIpJsonResponse(rawText);
5465
5513
  if (parsed?.ip || parsed?.location) {
5466
- logger11.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
5514
+ logger12.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
5467
5515
  return parsed;
5468
5516
  }
5469
- logger11.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
5517
+ logger12.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
5470
5518
  return null;
5471
5519
  } catch (error) {
5472
- logger11.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
5520
+ logger12.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
5473
5521
  return null;
5474
5522
  } finally {
5475
5523
  await probeScope.close().catch(() => {
@@ -5483,10 +5531,10 @@ var resolveEnrichment = async (page, baseMeta, options) => {
5483
5531
  ip: toInline(options.ip, 80),
5484
5532
  location: toInline(options.location, 80)
5485
5533
  };
5486
- logger11.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
5534
+ logger12.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
5487
5535
  if (!merged.ip || !merged.location) {
5488
5536
  if (cached?.ip || cached?.location) {
5489
- logger11.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
5537
+ logger12.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
5490
5538
  }
5491
5539
  fillEnrichment(merged, cached);
5492
5540
  }
@@ -5510,15 +5558,15 @@ var resolveEnrichment = async (page, baseMeta, options) => {
5510
5558
  "x-geo-country"
5511
5559
  ]), 80);
5512
5560
  if (!merged.location || isWeakLocationValue(merged.location) && headerLocation) {
5513
- logger11.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
5561
+ logger12.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
5514
5562
  merged.location = headerLocation || merged.location;
5515
5563
  }
5516
5564
  }
5517
5565
  writeCachedEnrichment(page, merged);
5518
5566
  if (merged.ip || merged.location) {
5519
- logger11.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
5567
+ logger12.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
5520
5568
  } else {
5521
- logger11.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
5569
+ logger12.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
5522
5570
  }
5523
5571
  return merged;
5524
5572
  };
@@ -6186,7 +6234,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
6186
6234
  }
6187
6235
  const imageInfo = readImageInfo(buffer);
6188
6236
  if (!imageInfo.width || !imageInfo.height || !imageInfo.mimeType) {
6189
- logger11.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
6237
+ logger12.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
6190
6238
  return buffer;
6191
6239
  }
6192
6240
  const overlaySvg = buildWatermarkifySvg(meta, imageInfo.width, imageInfo.height);
@@ -6197,7 +6245,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
6197
6245
  };
6198
6246
 
6199
6247
  // src/share.js
6200
- var logger12 = createInternalLogger("Share");
6248
+ var logger13 = createInternalLogger("Share");
6201
6249
  var DEFAULT_TIMEOUT_MS2 = 50 * 1e3;
6202
6250
  var DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;
6203
6251
  var DEFAULT_POLL_INTERVAL_MS = 120;
@@ -6334,7 +6382,7 @@ var createDomShareMonitor = async (page, options = {}) => {
6334
6382
  const onMatch = typeof options.onMatch === "function" ? options.onMatch : null;
6335
6383
  const onTelemetry = typeof options.onTelemetry === "function" ? options.onTelemetry : null;
6336
6384
  let matched = false;
6337
- logger12.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
6385
+ logger13.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
6338
6386
  const monitor = await Mutation.useMonitor(page, selectors, {
6339
6387
  mode,
6340
6388
  onMutation: (context = {}) => {
@@ -6352,12 +6400,12 @@ ${text}`;
6352
6400
  });
6353
6401
  }
6354
6402
  if (mutationCount <= 5 || mutationCount % 50 === 0) {
6355
- logger12.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
6403
+ logger13.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
6356
6404
  }
6357
6405
  const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];
6358
6406
  if (!candidate) return;
6359
6407
  matched = true;
6360
- logger12.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
6408
+ logger13.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
6361
6409
  if (onMatch) {
6362
6410
  onMatch({
6363
6411
  link: candidate,
@@ -6373,7 +6421,7 @@ ${text}`;
6373
6421
  return {
6374
6422
  stop: async () => {
6375
6423
  const result = await monitor.stop();
6376
- logger12.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
6424
+ logger13.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
6377
6425
  return result;
6378
6426
  }
6379
6427
  };
@@ -6413,8 +6461,8 @@ var Share = {
6413
6461
  if (share.mode === "response" && apiMatchers.length === 0) {
6414
6462
  throw new Error("Share.captureLink requires share.xurl[0] api matcher when mode=response");
6415
6463
  }
6416
- logger12.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);
6417
- logger12.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
6464
+ logger13.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);
6465
+ logger13.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
6418
6466
  const stats = {
6419
6467
  actionTimedOut: false,
6420
6468
  domMutationCount: 0,
@@ -6439,7 +6487,7 @@ var Share = {
6439
6487
  link: validated,
6440
6488
  payloadText: String(payloadText || "")
6441
6489
  };
6442
- logger12.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
6490
+ logger13.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
6443
6491
  return true;
6444
6492
  };
6445
6493
  const resolveResponseCandidate = (responseText) => {
@@ -6474,7 +6522,7 @@ var Share = {
6474
6522
  try {
6475
6523
  await monitor.stop();
6476
6524
  } catch (error) {
6477
- logger12.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
6525
+ logger13.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
6478
6526
  }
6479
6527
  };
6480
6528
  const onResponse = async (response) => {
@@ -6487,29 +6535,29 @@ var Share = {
6487
6535
  stats.responseSampleUrls.push(url);
6488
6536
  }
6489
6537
  if (stats.responseObserved <= 5) {
6490
- logger12.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
6538
+ logger13.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
6491
6539
  }
6492
6540
  if (!apiMatchers.some((matcher) => url.includes(matcher))) return;
6493
6541
  stats.responseMatched += 1;
6494
6542
  stats.lastMatchedUrl = url;
6495
- logger12.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
6543
+ logger13.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
6496
6544
  const text = await response.text();
6497
6545
  const hit = resolveResponseCandidate(text);
6498
6546
  if (!hit?.link) {
6499
6547
  if (stats.responseMatched <= 3) {
6500
- logger12.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
6548
+ logger13.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
6501
6549
  }
6502
6550
  return;
6503
6551
  }
6504
6552
  stats.responseResolved += 1;
6505
- logger12.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
6553
+ logger13.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
6506
6554
  setCandidate("response", hit.link, hit.payloadText);
6507
6555
  } catch (error) {
6508
- logger12.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
6556
+ logger13.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
6509
6557
  }
6510
6558
  };
6511
6559
  if (share.mode === "dom") {
6512
- logger12.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
6560
+ logger13.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
6513
6561
  domMonitor = await createDomShareMonitor(page, {
6514
6562
  prefix: share.prefix,
6515
6563
  selectors: domSelectors,
@@ -6524,14 +6572,14 @@ var Share = {
6524
6572
  });
6525
6573
  }
6526
6574
  if (share.mode === "response") {
6527
- logger12.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
6575
+ logger13.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
6528
6576
  page.on("response", onResponse);
6529
6577
  }
6530
6578
  const deadline = Date.now() + timeoutMs;
6531
6579
  const getRemainingMs = () => Math.max(0, deadline - Date.now());
6532
6580
  try {
6533
6581
  const actionTimeout = getRemainingMs();
6534
- logger12.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);
6582
+ logger13.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);
6535
6583
  if (actionTimeout > 0) {
6536
6584
  let timer = null;
6537
6585
  let actionError = null;
@@ -6545,21 +6593,21 @@ var Share = {
6545
6593
  const actionResult = await Promise.race([actionPromise, timeoutPromise]);
6546
6594
  if (timer) clearTimeout(timer);
6547
6595
  if (actionResult === "__ACTION_ERROR__") {
6548
- logger12.fail("captureLink.performActions", actionError);
6596
+ logger13.fail("captureLink.performActions", actionError);
6549
6597
  throw actionError;
6550
6598
  }
6551
6599
  if (actionResult === "__ACTION_TIMEOUT__") {
6552
6600
  stats.actionTimedOut = true;
6553
- logger12.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
6601
+ logger13.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
6554
6602
  } else {
6555
- logger12.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
6603
+ logger13.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
6556
6604
  }
6557
6605
  }
6558
6606
  let nextProgressLogTs = Date.now() + 3e3;
6559
6607
  while (true) {
6560
6608
  const selected = share.mode === "dom" ? candidates.dom : candidates.response;
6561
6609
  if (selected?.link) {
6562
- logger12.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
6610
+ logger13.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
6563
6611
  return {
6564
6612
  link: selected.link,
6565
6613
  payloadText: selected.payloadText,
@@ -6571,7 +6619,7 @@ var Share = {
6571
6619
  if (remaining <= 0) break;
6572
6620
  const now = Date.now();
6573
6621
  if (now >= nextProgressLogTs) {
6574
- logger12.info(
6622
+ logger13.info(
6575
6623
  `captureLink \u7B49\u5F85\u4E2D: remaining=${remaining}ms, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`
6576
6624
  );
6577
6625
  nextProgressLogTs = now + 5e3;
@@ -6579,11 +6627,11 @@ var Share = {
6579
6627
  await delay2(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
6580
6628
  }
6581
6629
  if (share.mode === "response" && stats.responseMatched === 0) {
6582
- logger12.warning(
6630
+ logger13.warning(
6583
6631
  `\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`
6584
6632
  );
6585
6633
  }
6586
- logger12.warning(
6634
+ logger13.warning(
6587
6635
  `captureLink \u8D85\u65F6\u672A\u62FF\u5230\u94FE\u63A5: mode=${share.mode}, actionTimedOut=${stats.actionTimedOut}, domMutationCount=${stats.domMutationCount}, responseObserved=${stats.responseObserved}, responseMatched=${stats.responseMatched}, lastMatchedUrl=${stats.lastMatchedUrl || "none"}`
6588
6636
  );
6589
6637
  return {
@@ -6595,7 +6643,7 @@ var Share = {
6595
6643
  } finally {
6596
6644
  if (share.mode === "response") {
6597
6645
  page.off("response", onResponse);
6598
- logger12.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
6646
+ logger13.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
6599
6647
  }
6600
6648
  await stopDomMonitor();
6601
6649
  }