@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.cjs CHANGED
@@ -361,18 +361,18 @@ var fallbackLog = {
361
361
  error: (...args) => console.error(...args),
362
362
  debug: (...args) => console.debug ? console.debug(...args) : console.log(...args)
363
363
  };
364
- var resolveLogMethod = (logger13, name) => {
365
- if (logger13 && typeof logger13[name] === "function") {
366
- return logger13[name].bind(logger13);
364
+ var resolveLogMethod = (logger14, name) => {
365
+ if (logger14 && typeof logger14[name] === "function") {
366
+ return logger14[name].bind(logger14);
367
367
  }
368
- if (name === "warning" && logger13 && typeof logger13.warn === "function") {
369
- return logger13.warn.bind(logger13);
368
+ if (name === "warning" && logger14 && typeof logger14.warn === "function") {
369
+ return logger14.warn.bind(logger14);
370
370
  }
371
371
  return fallbackLog[name];
372
372
  };
373
373
  var defaultLogger = null;
374
- var setDefaultLogger = (logger13) => {
375
- defaultLogger = logger13;
374
+ var setDefaultLogger = (logger14) => {
375
+ defaultLogger = logger14;
376
376
  };
377
377
  var resolveLogger = (explicitLogger) => {
378
378
  if (explicitLogger && typeof explicitLogger.info === "function") {
@@ -399,8 +399,8 @@ var colorize = (text, color) => {
399
399
  var createBaseLogger = (prefix = "", explicitLogger) => {
400
400
  const name = prefix ? String(prefix) : "";
401
401
  const dispatch = (methodName, icon, message, color) => {
402
- const logger13 = resolveLogger(explicitLogger);
403
- const logFn = resolveLogMethod(logger13, methodName);
402
+ const logger14 = resolveLogger(explicitLogger);
403
+ const logFn = resolveLogMethod(logger14, methodName);
404
404
  const timestamp = colorize(`[${formatTimestamp()}]`, ANSI.gray);
405
405
  const line = formatLine(name, icon, message);
406
406
  const coloredLine = colorize(line, color);
@@ -439,7 +439,6 @@ function createInternalLogger(moduleName, explicitLogger) {
439
439
  },
440
440
  warning(message) {
441
441
  baseLogger.warning(message);
442
- a;
443
442
  },
444
443
  info(message) {
445
444
  baseLogger.info(message);
@@ -686,9 +685,9 @@ var resolveResourceTypeMeta = (domain) => {
686
685
  if (!byType || byType.size === 0) {
687
686
  return { resourceType: "", resourceTypeCounts: void 0 };
688
687
  }
689
- const entries = Array.from(byType.entries()).filter(([type, count]) => type && Number(count) > 0).sort((a2, b) => {
690
- if (Number(b[1]) !== Number(a2[1])) return Number(b[1]) - Number(a2[1]);
691
- return String(a2[0]).localeCompare(String(b[0]));
688
+ const entries = Array.from(byType.entries()).filter(([type, count]) => type && Number(count) > 0).sort((a, b) => {
689
+ if (Number(b[1]) !== Number(a[1])) return Number(b[1]) - Number(a[1]);
690
+ return String(a[0]).localeCompare(String(b[0]));
692
691
  });
693
692
  if (entries.length === 0) {
694
693
  return { resourceType: "", resourceTypeCounts: void 0 };
@@ -778,10 +777,10 @@ var normalizeDomainRows = (hosts) => {
778
777
  resourceTypeCounts: resourceTypeMeta.resourceTypeCounts || void 0
779
778
  });
780
779
  }
781
- rows.sort((a2, b) => {
782
- if (b.totalBytes !== a2.totalBytes) return b.totalBytes - a2.totalBytes;
783
- if (b.requests !== a2.requests) return b.requests - a2.requests;
784
- return String(a2.domain).localeCompare(String(b.domain));
780
+ rows.sort((a, b) => {
781
+ if (b.totalBytes !== a.totalBytes) return b.totalBytes - a.totalBytes;
782
+ if (b.requests !== a.requests) return b.requests - a.requests;
783
+ return String(a.domain).localeCompare(String(b.domain));
785
784
  });
786
785
  return {
787
786
  topDomains: rows.slice(0, MAX_TOP_DOMAINS),
@@ -2976,13 +2975,91 @@ var LiveView = {
2976
2975
  useLiveView
2977
2976
  };
2978
2977
 
2979
- // src/captcha-monitor.js
2978
+ // src/chaptcha.js
2980
2979
  var import_uuid = require("uuid");
2980
+
2981
+ // src/internals/captcha/shared.js
2982
+ var waitForVisible = async (locator, timeout) => {
2983
+ try {
2984
+ await locator.waitFor({
2985
+ state: "visible",
2986
+ timeout
2987
+ });
2988
+ return true;
2989
+ } catch {
2990
+ return false;
2991
+ }
2992
+ };
2993
+ var isAnyCaptchaTextVisible = async (frame, texts, timeout) => {
2994
+ for (const text of texts || []) {
2995
+ if (!text) {
2996
+ continue;
2997
+ }
2998
+ const candidates = [
2999
+ frame.getByText(text, { exact: false }).first(),
3000
+ frame.locator(`text=${text}`).first()
3001
+ ];
3002
+ for (const candidate of candidates) {
3003
+ const isVisible = await candidate.isVisible({ timeout }).catch(() => false);
3004
+ if (isVisible) {
3005
+ return true;
3006
+ }
3007
+ }
3008
+ }
3009
+ return false;
3010
+ };
3011
+ var clickCaptchaAction = async (frame, texts, options) => {
3012
+ for (const text of texts || []) {
3013
+ const candidates = [
3014
+ frame.getByText(text, { exact: false }).first(),
3015
+ frame.locator(`text=${text}`).first()
3016
+ ];
3017
+ for (const candidate of candidates) {
3018
+ const isVisible = await waitForVisible(candidate, options.actionVisibleTimeoutMs);
3019
+ if (!isVisible) {
3020
+ continue;
3021
+ }
3022
+ await candidate.click();
3023
+ return true;
3024
+ }
3025
+ }
3026
+ return false;
3027
+ };
3028
+ var dragCaptchaWithMouse = async (page, sourceLocator, targetLocator) => {
3029
+ const sourceBox = await sourceLocator.boundingBox();
3030
+ const targetBox = await targetLocator.boundingBox();
3031
+ if (!sourceBox || !targetBox) {
3032
+ throw new Error("Unable to resolve captcha drag coordinates.");
3033
+ }
3034
+ const startX = sourceBox.x + sourceBox.width / 2;
3035
+ const startY = sourceBox.y + sourceBox.height / 2;
3036
+ const endX = targetBox.x + targetBox.width / 2;
3037
+ const endY = targetBox.y + targetBox.height / 2;
3038
+ const steps = 10;
3039
+ const liftOffsetX = Math.min(18, Math.max(8, sourceBox.width * 0.12));
3040
+ const liftOffsetY = Math.min(12, Math.max(4, sourceBox.height * 0.08));
3041
+ await page.mouse.move(startX, startY, { steps: 8 });
3042
+ await page.waitForTimeout(250);
3043
+ await page.mouse.down();
3044
+ await page.waitForTimeout(350);
3045
+ await page.mouse.move(startX + liftOffsetX, startY + liftOffsetY, { steps: 6 });
3046
+ await page.waitForTimeout(250);
3047
+ for (let step = 1; step <= steps; step++) {
3048
+ const progress = step / steps;
3049
+ const easedProgress = 1 - (1 - progress) * (1 - progress);
3050
+ const currentX = startX + liftOffsetX + (endX - startX - liftOffsetX) * easedProgress;
3051
+ const currentY = startY + liftOffsetY + (endY - startY - liftOffsetY) * easedProgress;
3052
+ await page.mouse.move(currentX, currentY, { steps: 2 });
3053
+ await page.waitForTimeout(90);
3054
+ }
3055
+ await page.waitForTimeout(100);
3056
+ await page.mouse.up();
3057
+ await page.waitForTimeout(100);
3058
+ };
3059
+
3060
+ // src/internals/captcha/bytedance.js
2981
3061
  var logger9 = createInternalLogger("Captcha");
2982
- var DEFAULT_BYTEDANCE_CAPTCHA_TOKEN = "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI";
2983
3062
  var DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS = Object.freeze({
2984
- token: DEFAULT_BYTEDANCE_CAPTCHA_TOKEN,
2985
- apiUrl: "https://api.jfbym.com/api/YmServer/customApi",
2986
3063
  apiType: "31234",
2987
3064
  maxRetries: 3,
2988
3065
  containerSelector: "#captcha_container",
@@ -3019,128 +3096,6 @@ var DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS = Object.freeze({
3019
3096
  retryDelayBaseMs: 2e3,
3020
3097
  retryDelayStepMs: 1e3
3021
3098
  });
3022
- function useCaptchaMonitor(page, options) {
3023
- const { domSelector, urlPattern, onDetected } = options;
3024
- if (!domSelector && !urlPattern) {
3025
- throw new Error("[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector \u6216 urlPattern\u3002");
3026
- }
3027
- if (!onDetected || typeof onDetected !== "function") {
3028
- throw new Error("[CaptchaMonitor] onDetected \u5FC5\u987B\u662F\u51FD\u6570\u3002");
3029
- }
3030
- let isStopped = false;
3031
- let isHandling = false;
3032
- let frameHandler = null;
3033
- let exposedFunctionName = null;
3034
- const triggerDetected = async () => {
3035
- if (isStopped || isHandling) return;
3036
- isHandling = true;
3037
- try {
3038
- await onDetected();
3039
- } finally {
3040
- isHandling = false;
3041
- }
3042
- };
3043
- const cleanupFns = [];
3044
- if (domSelector) {
3045
- exposedFunctionName = `__c_d_${(0, import_uuid.v4)().replace(/-/g, "_")}`;
3046
- const cleanerName = `__c_cleaner_${(0, import_uuid.v4)().replace(/-/g, "_")}`;
3047
- page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {
3048
- });
3049
- page.addInitScript(({ selector, callbackName, cleanerName: cleanupName }) => {
3050
- (() => {
3051
- let observer = null;
3052
- const checkAndReport = () => {
3053
- const element = document.querySelector(selector);
3054
- if (!element) {
3055
- return false;
3056
- }
3057
- if (window[callbackName]) {
3058
- window[callbackName]();
3059
- }
3060
- return true;
3061
- };
3062
- checkAndReport();
3063
- observer = new MutationObserver((mutations) => {
3064
- const shouldCheck = mutations.some((mutation) => mutation.addedNodes.length > 0);
3065
- if (shouldCheck && observer) {
3066
- checkAndReport();
3067
- }
3068
- });
3069
- const mountObserver = () => {
3070
- const target = document.documentElement;
3071
- if (target && observer) {
3072
- observer.observe(target, { childList: true, subtree: true });
3073
- }
3074
- };
3075
- if (document.readyState === "loading") {
3076
- window.addEventListener("DOMContentLoaded", mountObserver);
3077
- } else {
3078
- mountObserver();
3079
- }
3080
- window[cleanupName] = () => {
3081
- if (observer) {
3082
- observer.disconnect();
3083
- observer = null;
3084
- }
3085
- };
3086
- })();
3087
- }, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
3088
- logger9.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
3089
- cleanupFns.push(async () => {
3090
- try {
3091
- await page.evaluate((name) => {
3092
- if (window[name]) {
3093
- window[name]();
3094
- delete window[name];
3095
- }
3096
- }, cleanerName);
3097
- } catch {
3098
- }
3099
- });
3100
- }
3101
- if (urlPattern) {
3102
- frameHandler = async (frame) => {
3103
- if (frame !== page.mainFrame()) {
3104
- return;
3105
- }
3106
- const currentUrl = page.url();
3107
- if (currentUrl.includes(urlPattern)) {
3108
- await triggerDetected();
3109
- }
3110
- };
3111
- page.on("framenavigated", frameHandler);
3112
- logger9.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
3113
- cleanupFns.push(async () => {
3114
- page.off("framenavigated", frameHandler);
3115
- });
3116
- }
3117
- return {
3118
- stop: async () => {
3119
- logger9.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
3120
- for (const fn of cleanupFns) {
3121
- await fn();
3122
- }
3123
- isStopped = true;
3124
- }
3125
- };
3126
- }
3127
- var callCaptchaRecognitionApi = async (imageBase64, { apiUrl, apiType, token }) => {
3128
- const response = await fetch(apiUrl, {
3129
- method: "POST",
3130
- headers: {
3131
- "Content-Type": "application/json"
3132
- },
3133
- body: JSON.stringify({
3134
- type: apiType,
3135
- image: imageBase64,
3136
- token
3137
- })
3138
- });
3139
- if (!response.ok) {
3140
- throw new Error(`Captcha API request failed with status ${response.status}`);
3141
- }
3142
- return await response.json();
3143
- };
3144
3099
  var extractCaptchaSerialNumbers = (apiResponse) => {
3145
3100
  const serialNumbers = apiResponse?.data?.data?.serial_number;
3146
3101
  if (!Array.isArray(serialNumbers)) {
@@ -3148,76 +3103,6 @@ var extractCaptchaSerialNumbers = (apiResponse) => {
3148
3103
  }
3149
3104
  return serialNumbers.map((value) => Number(value)).filter((value) => Number.isInteger(value) && value >= 0);
3150
3105
  };
3151
- var waitForVisible = async (locator, timeout) => {
3152
- try {
3153
- await locator.waitFor({
3154
- state: "visible",
3155
- timeout
3156
- });
3157
- return true;
3158
- } catch {
3159
- return false;
3160
- }
3161
- };
3162
- var isAnyCaptchaTextVisible = async (frame, texts, timeout) => {
3163
- for (const text of texts || []) {
3164
- if (!text) {
3165
- continue;
3166
- }
3167
- const candidates = [
3168
- frame.getByText(text, { exact: false }).first(),
3169
- frame.locator(`text=${text}`).first()
3170
- ];
3171
- for (const candidate of candidates) {
3172
- const isVisible = await candidate.isVisible({ timeout }).catch(() => false);
3173
- if (isVisible) {
3174
- return true;
3175
- }
3176
- }
3177
- }
3178
- return false;
3179
- };
3180
- var waitForCaptchaChallengeReady = async (page, frame, options) => {
3181
- const deadline = Date.now() + options.challengeReadyTimeoutMs;
3182
- let refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3183
- let hasSeenLoading = false;
3184
- while (Date.now() < deadline) {
3185
- const isLoadingVisible = await isAnyCaptchaTextVisible(
3186
- frame,
3187
- options.loadingTexts,
3188
- options.loadingIndicatorVisibleTimeoutMs
3189
- );
3190
- const hasErrorTextVisible = await isAnyCaptchaTextVisible(
3191
- frame,
3192
- options.errorTexts,
3193
- options.loadingIndicatorVisibleTimeoutMs
3194
- );
3195
- hasSeenLoading = hasSeenLoading || isLoadingVisible;
3196
- const sourceImages = frame.locator(options.sourceImageSelector);
3197
- const imageCount = await sourceImages.count().catch(() => 0);
3198
- const hasVisibleSourceImage = imageCount > 0 ? await sourceImages.first().isVisible({ timeout: options.loadingIndicatorVisibleTimeoutMs }).catch(() => false) : false;
3199
- if (!isLoadingVisible && hasVisibleSourceImage) {
3200
- logger9.info(hasSeenLoading ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u52A0\u8F7D\u5B8C\u6210\u3002" : "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u5C31\u7EEA\u3002");
3201
- return;
3202
- }
3203
- if (hasErrorTextVisible) {
3204
- 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");
3205
- await refreshCaptcha(page, frame, options);
3206
- refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3207
- hasSeenLoading = false;
3208
- continue;
3209
- }
3210
- if (!hasVisibleSourceImage && Date.now() >= refreshDeadline) {
3211
- logger9.warn(`\u9A8C\u8BC1\u7801\u56FE\u7247\u8D85\u8FC7 ${options.challengeReadyRefreshTimeoutMs}ms \u4ECD\u672A\u51FA\u73B0\uFF0C\u5C1D\u8BD5\u5237\u65B0\u9898\u76EE\u3002`);
3212
- await refreshCaptcha(page, frame, options);
3213
- refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3214
- hasSeenLoading = false;
3215
- continue;
3216
- }
3217
- await page.waitForTimeout(options.challengeReadyPollMs);
3218
- }
3219
- throw new Error("Captcha challenge is still loading and did not become ready in time.");
3220
- };
3221
3106
  var resolveContentFrame = async (page, iframeLocator, options) => {
3222
3107
  for (let attempt = 1; attempt <= options.contentFrameResolveRetries; attempt++) {
3223
3108
  const iframeHandle = await iframeLocator.elementHandle();
@@ -3264,22 +3149,14 @@ var getVerifycenterCaptchaContext = async (page, options) => {
3264
3149
  }
3265
3150
  return { iframeLocator, frame };
3266
3151
  };
3267
- var clickCaptchaAction = async (frame, texts, options) => {
3268
- for (const text of texts) {
3269
- const candidates = [
3270
- frame.getByText(text, { exact: false }).first(),
3271
- frame.locator(`text=${text}`).first()
3272
- ];
3273
- for (const candidate of candidates) {
3274
- const isVisible = await waitForVisible(candidate, options.actionVisibleTimeoutMs);
3275
- if (!isVisible) {
3276
- continue;
3277
- }
3278
- await candidate.click();
3279
- return true;
3280
- }
3152
+ var refreshCaptcha = async (page, frame, options) => {
3153
+ const clicked = await clickCaptchaAction(frame, options.refreshTexts, options).catch(() => false);
3154
+ if (!clicked) {
3155
+ logger9.warn("Refresh button not found.");
3156
+ return false;
3281
3157
  }
3282
- return false;
3158
+ await page.waitForTimeout(options.refreshWaitMs);
3159
+ return true;
3283
3160
  };
3284
3161
  var findCaptchaDropTarget = async (frame, options) => {
3285
3162
  for (const text of options.dropTargetTexts) {
@@ -3296,47 +3173,52 @@ var findCaptchaDropTarget = async (frame, options) => {
3296
3173
  }
3297
3174
  return null;
3298
3175
  };
3299
- var dragCaptchaWithMouse = async (page, sourceLocator, targetLocator) => {
3300
- const sourceBox = await sourceLocator.boundingBox();
3301
- const targetBox = await targetLocator.boundingBox();
3302
- if (!sourceBox || !targetBox) {
3303
- throw new Error("Unable to resolve captcha drag coordinates.");
3304
- }
3305
- const startX = sourceBox.x + sourceBox.width / 2;
3306
- const startY = sourceBox.y + sourceBox.height / 2;
3307
- const endX = targetBox.x + targetBox.width / 2;
3308
- const endY = targetBox.y + targetBox.height / 2;
3309
- const steps = 10;
3310
- const liftOffsetX = Math.min(18, Math.max(8, sourceBox.width * 0.12));
3311
- const liftOffsetY = Math.min(12, Math.max(4, sourceBox.height * 0.08));
3312
- await page.mouse.move(startX, startY, { steps: 8 });
3313
- await page.waitForTimeout(250);
3314
- await page.mouse.down();
3315
- await page.waitForTimeout(350);
3316
- await page.mouse.move(startX + liftOffsetX, startY + liftOffsetY, { steps: 6 });
3317
- await page.waitForTimeout(250);
3318
- for (let step = 1; step <= steps; step++) {
3319
- const progress = step / steps;
3320
- const easedProgress = 1 - (1 - progress) * (1 - progress);
3321
- const currentX = startX + liftOffsetX + (endX - startX - liftOffsetX) * easedProgress;
3322
- const currentY = startY + liftOffsetY + (endY - startY - liftOffsetY) * easedProgress;
3323
- await page.mouse.move(currentX, currentY, { steps: 2 });
3324
- await page.waitForTimeout(90);
3176
+ var waitForCaptchaChallengeReady = async (page, frame, options) => {
3177
+ const deadline = Date.now() + options.challengeReadyTimeoutMs;
3178
+ let refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3179
+ let hasSeenLoading = false;
3180
+ while (Date.now() < deadline) {
3181
+ const isLoadingVisible = await isAnyCaptchaTextVisible(
3182
+ frame,
3183
+ options.loadingTexts,
3184
+ options.loadingIndicatorVisibleTimeoutMs
3185
+ );
3186
+ const hasErrorTextVisible = await isAnyCaptchaTextVisible(
3187
+ frame,
3188
+ options.errorTexts,
3189
+ options.loadingIndicatorVisibleTimeoutMs
3190
+ );
3191
+ hasSeenLoading = hasSeenLoading || isLoadingVisible;
3192
+ const sourceImages = frame.locator(options.sourceImageSelector);
3193
+ const imageCount = await sourceImages.count().catch(() => 0);
3194
+ const hasVisibleSourceImage = imageCount > 0 ? await sourceImages.first().isVisible({ timeout: options.loadingIndicatorVisibleTimeoutMs }).catch(() => false) : false;
3195
+ if (!isLoadingVisible && hasVisibleSourceImage) {
3196
+ logger9.info(hasSeenLoading ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u52A0\u8F7D\u5B8C\u6210\u3002" : "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u5C31\u7EEA\u3002");
3197
+ return;
3198
+ }
3199
+ if (hasErrorTextVisible) {
3200
+ 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");
3201
+ await refreshCaptcha(page, frame, options);
3202
+ refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3203
+ hasSeenLoading = false;
3204
+ continue;
3205
+ }
3206
+ if (!hasVisibleSourceImage && Date.now() >= refreshDeadline) {
3207
+ logger9.warn(`\u9A8C\u8BC1\u7801\u56FE\u7247\u8D85\u8FC7 ${options.challengeReadyRefreshTimeoutMs}ms \u4ECD\u672A\u51FA\u73B0\uFF0C\u5C1D\u8BD5\u5237\u65B0\u9898\u76EE\u3002`);
3208
+ await refreshCaptcha(page, frame, options);
3209
+ refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3210
+ hasSeenLoading = false;
3211
+ continue;
3212
+ }
3213
+ await page.waitForTimeout(options.challengeReadyPollMs);
3325
3214
  }
3326
- await page.waitForTimeout(100);
3327
- await page.mouse.up();
3328
- await page.waitForTimeout(100);
3215
+ throw new Error("Captcha challenge is still loading and did not become ready in time.");
3329
3216
  };
3330
- var refreshCaptcha = async (page, frame, options) => {
3331
- const clicked = await clickCaptchaAction(frame, options.refreshTexts, options).catch(() => false);
3332
- if (!clicked) {
3333
- logger9.warn("Refresh button not found.");
3334
- return false;
3217
+ async function solveCaptcha(page, options = {}, dependencies = {}) {
3218
+ const { callCaptchaRecognitionApi: callCaptchaRecognitionApi2 } = dependencies;
3219
+ if (typeof callCaptchaRecognitionApi2 !== "function") {
3220
+ throw new Error("[Captcha] \u7F3A\u5C11\u901A\u7528\u8BC6\u522B\u8BF7\u6C42\u51FD\u6570 callCaptchaRecognitionApi\u3002");
3335
3221
  }
3336
- await page.waitForTimeout(options.refreshWaitMs);
3337
- return true;
3338
- };
3339
- async function solveBytedanceCaptcha(page, options = {}) {
3340
3222
  const config = {
3341
3223
  ...DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS,
3342
3224
  ...options
@@ -3345,6 +3227,7 @@ async function solveBytedanceCaptcha(page, options = {}) {
3345
3227
  logger9.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
3346
3228
  return false;
3347
3229
  }
3230
+ logger9.info("\u5F53\u524D\u4F7F\u7528\u672Ctool\u2014\u2014\u6D4B\u8BD5\u7248\u672C");
3348
3231
  for (let attempt = 1; attempt <= config.maxRetries; attempt++) {
3349
3232
  logger9.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
3350
3233
  try {
@@ -3357,10 +3240,12 @@ async function solveBytedanceCaptcha(page, options = {}) {
3357
3240
  await waitForCaptchaChallengeReady(page, frame, config);
3358
3241
  await page.waitForTimeout(config.recognitionDelayMs);
3359
3242
  const screenshotBuffer = await iframeLocator.screenshot();
3360
- const apiResponse = await callCaptchaRecognitionApi(
3361
- screenshotBuffer.toString("base64"),
3362
- config
3363
- );
3243
+ const apiResponse = await callCaptchaRecognitionApi2({
3244
+ apiUrl: config.apiUrl,
3245
+ type: config.apiType,
3246
+ image: screenshotBuffer.toString("base64"),
3247
+ token: config.token
3248
+ });
3364
3249
  const serialNumbers = extractCaptchaSerialNumbers(apiResponse);
3365
3250
  if (apiResponse?.code !== config.recognitionSuccessCode || serialNumbers.length === 0) {
3366
3251
  logger9.warn(
@@ -3416,15 +3301,178 @@ async function solveBytedanceCaptcha(page, options = {}) {
3416
3301
  logger9.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
3417
3302
  return false;
3418
3303
  }
3304
+ var sloveCaptcha = solveCaptcha;
3305
+
3306
+ // src/chaptcha.js
3307
+ var logger10 = createInternalLogger("Captcha");
3308
+ var DEFAULT_CAPTCHA_RECOGNITION_OPTIONS = Object.freeze({
3309
+ token: "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI",
3310
+ apiUrl: "https://api.jfbym.com/api/YmServer/customApi"
3311
+ });
3312
+ var CAPTCHA_STRATEGIES = Object.freeze({
3313
+ bytedance: {
3314
+ sloveCaptcha
3315
+ }
3316
+ });
3317
+ var mergeDefinedOptions = (...sources) => {
3318
+ const merged = {};
3319
+ for (const source of sources) {
3320
+ for (const [key, value] of Object.entries(source || {})) {
3321
+ if (value !== void 0) {
3322
+ merged[key] = value;
3323
+ }
3324
+ }
3325
+ }
3326
+ return merged;
3327
+ };
3328
+ function useCaptchaMonitor(page, options) {
3329
+ const { domSelector, urlPattern, onDetected } = options;
3330
+ if (!domSelector && !urlPattern) {
3331
+ throw new Error("[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector \u6216 urlPattern\u3002");
3332
+ }
3333
+ if (!onDetected || typeof onDetected !== "function") {
3334
+ throw new Error("[CaptchaMonitor] onDetected \u5FC5\u987B\u662F\u51FD\u6570\u3002");
3335
+ }
3336
+ let isStopped = false;
3337
+ let isHandling = false;
3338
+ let frameHandler = null;
3339
+ let exposedFunctionName = null;
3340
+ const triggerDetected = async () => {
3341
+ if (isStopped || isHandling) return;
3342
+ isHandling = true;
3343
+ try {
3344
+ await onDetected();
3345
+ } finally {
3346
+ isHandling = false;
3347
+ }
3348
+ };
3349
+ const cleanupFns = [];
3350
+ if (domSelector) {
3351
+ exposedFunctionName = `__c_d_${(0, import_uuid.v4)().replace(/-/g, "_")}`;
3352
+ const cleanerName = `__c_cleaner_${(0, import_uuid.v4)().replace(/-/g, "_")}`;
3353
+ page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {
3354
+ });
3355
+ page.addInitScript(({ selector, callbackName, cleanerName: cleanupName }) => {
3356
+ (() => {
3357
+ let observer = null;
3358
+ const checkAndReport = () => {
3359
+ const element = document.querySelector(selector);
3360
+ if (!element) {
3361
+ return false;
3362
+ }
3363
+ if (window[callbackName]) {
3364
+ window[callbackName]();
3365
+ }
3366
+ return true;
3367
+ };
3368
+ checkAndReport();
3369
+ observer = new MutationObserver((mutations) => {
3370
+ const shouldCheck = mutations.some((mutation) => mutation.addedNodes.length > 0);
3371
+ if (shouldCheck && observer) {
3372
+ checkAndReport();
3373
+ }
3374
+ });
3375
+ const mountObserver = () => {
3376
+ const target = document.documentElement;
3377
+ if (target && observer) {
3378
+ observer.observe(target, { childList: true, subtree: true });
3379
+ }
3380
+ };
3381
+ if (document.readyState === "loading") {
3382
+ window.addEventListener("DOMContentLoaded", mountObserver);
3383
+ } else {
3384
+ mountObserver();
3385
+ }
3386
+ window[cleanupName] = () => {
3387
+ if (observer) {
3388
+ observer.disconnect();
3389
+ observer = null;
3390
+ }
3391
+ };
3392
+ })();
3393
+ }, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
3394
+ logger10.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
3395
+ cleanupFns.push(async () => {
3396
+ try {
3397
+ await page.evaluate((name) => {
3398
+ if (window[name]) {
3399
+ window[name]();
3400
+ delete window[name];
3401
+ }
3402
+ }, cleanerName);
3403
+ } catch {
3404
+ }
3405
+ });
3406
+ }
3407
+ if (urlPattern) {
3408
+ frameHandler = async (frame) => {
3409
+ if (frame !== page.mainFrame()) {
3410
+ return;
3411
+ }
3412
+ const currentUrl = page.url();
3413
+ if (currentUrl.includes(urlPattern)) {
3414
+ await triggerDetected();
3415
+ }
3416
+ };
3417
+ page.on("framenavigated", frameHandler);
3418
+ logger10.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
3419
+ cleanupFns.push(async () => {
3420
+ page.off("framenavigated", frameHandler);
3421
+ });
3422
+ }
3423
+ return {
3424
+ stop: async () => {
3425
+ logger10.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
3426
+ for (const fn of cleanupFns) {
3427
+ await fn();
3428
+ }
3429
+ isStopped = true;
3430
+ }
3431
+ };
3432
+ }
3433
+ var callCaptchaRecognitionApi = async (requestParams = {}) => {
3434
+ const { apiUrl, ...payload } = mergeDefinedOptions(
3435
+ DEFAULT_CAPTCHA_RECOGNITION_OPTIONS,
3436
+ requestParams
3437
+ );
3438
+ if (!apiUrl) {
3439
+ throw new Error("[Captcha] \u7F3A\u5C11\u9A8C\u8BC1\u7801\u8BC6\u522B\u63A5\u53E3\u5730\u5740 apiUrl\u3002");
3440
+ }
3441
+ const response = await fetch(apiUrl, {
3442
+ method: "POST",
3443
+ headers: {
3444
+ "Content-Type": "application/json"
3445
+ },
3446
+ body: JSON.stringify(payload)
3447
+ });
3448
+ if (!response.ok) {
3449
+ throw new Error(`Captcha API request failed with status ${response.status}`);
3450
+ }
3451
+ return await response.json();
3452
+ };
3453
+ async function solveCaptchaWithStrategy(strategyName, page, options = {}) {
3454
+ const strategy = CAPTCHA_STRATEGIES[strategyName];
3455
+ if (!strategy?.sloveCaptcha) {
3456
+ throw new Error(`[Captcha] \u672A\u627E\u5230\u9A8C\u8BC1\u7801\u7B56\u7565\uFF1A${strategyName}`);
3457
+ }
3458
+ const resolvedOptions = mergeDefinedOptions(
3459
+ DEFAULT_CAPTCHA_RECOGNITION_OPTIONS,
3460
+ options
3461
+ );
3462
+ return strategy.sloveCaptcha(page, resolvedOptions, {
3463
+ callCaptchaRecognitionApi,
3464
+ logger: logger10
3465
+ });
3466
+ }
3419
3467
  var Captcha = {
3420
3468
  useCaptchaMonitor,
3421
- solveBytedanceCaptcha
3469
+ solveCaptchaWithStrategy
3422
3470
  };
3423
3471
 
3424
3472
  // src/mutation.js
3425
3473
  var import_node_crypto = require("node:crypto");
3426
3474
  var import_uuid2 = require("uuid");
3427
- var logger10 = createInternalLogger("Mutation");
3475
+ var logger11 = createInternalLogger("Mutation");
3428
3476
  var MUTATION_MONITOR_MODE = Object.freeze({
3429
3477
  Added: "added",
3430
3478
  Changed: "changed",
@@ -3457,14 +3505,14 @@ var Mutation = {
3457
3505
  const stableTime = options.stableTime ?? 5 * 1e3;
3458
3506
  const timeout = options.timeout ?? 120 * 1e3;
3459
3507
  const onMutation = options.onMutation;
3460
- logger10.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
3508
+ logger11.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
3461
3509
  if (initialTimeout > 0) {
3462
3510
  const selectorQuery = selectorList.join(",");
3463
3511
  try {
3464
3512
  await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
3465
- logger10.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3513
+ logger11.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3466
3514
  } catch (e) {
3467
- logger10.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3515
+ logger11.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3468
3516
  throw e;
3469
3517
  }
3470
3518
  }
@@ -3480,7 +3528,7 @@ var Mutation = {
3480
3528
  return "__CONTINUE__";
3481
3529
  }
3482
3530
  });
3483
- logger10.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
3531
+ logger11.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
3484
3532
  } catch (e) {
3485
3533
  }
3486
3534
  }
@@ -3595,9 +3643,9 @@ var Mutation = {
3595
3643
  { selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }
3596
3644
  );
3597
3645
  if (result.mutationCount === 0 && result.stableTime === 0) {
3598
- logger10.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3646
+ logger11.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3599
3647
  }
3600
- logger10.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3648
+ logger11.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3601
3649
  return result;
3602
3650
  },
3603
3651
  /**
@@ -3769,22 +3817,22 @@ var Mutation = {
3769
3817
  return "__CONTINUE__";
3770
3818
  }
3771
3819
  };
3772
- logger10.start(
3820
+ logger11.start(
3773
3821
  "waitForStableAcrossRoots",
3774
3822
  `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668(\u8DE8 root), \u7A33\u5B9A\u65F6\u95F4=${waitForStableTime}ms`
3775
3823
  );
3776
3824
  if (initialTimeout > 0) {
3777
3825
  try {
3778
3826
  await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
3779
- logger10.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3827
+ logger11.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3780
3828
  } catch (e) {
3781
- logger10.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3829
+ logger11.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3782
3830
  throw e;
3783
3831
  }
3784
3832
  }
3785
3833
  let state = await buildState();
3786
3834
  if (!state?.hasMatched) {
3787
- logger10.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3835
+ logger11.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3788
3836
  return { mutationCount: 0, stableTime: 0, wasPaused: false };
3789
3837
  }
3790
3838
  let mutationCount = 0;
@@ -3821,7 +3869,7 @@ var Mutation = {
3821
3869
  if (lastState.snapshotKey !== lastSnapshotKey) {
3822
3870
  lastSnapshotKey = lastState.snapshotKey;
3823
3871
  mutationCount += 1;
3824
- logger10.info(
3872
+ logger11.info(
3825
3873
  `waitForStableAcrossRoots \u53D8\u5316#${mutationCount}, len=${lastState.snapshotLength}, path=${lastState.primaryPath || "unknown"}, preview="${truncate(lastState.text, 120)}"`
3826
3874
  );
3827
3875
  const signal = await invokeMutationCallback({
@@ -3834,7 +3882,7 @@ var Mutation = {
3834
3882
  continue;
3835
3883
  }
3836
3884
  if (!isPaused && stableSince > 0 && Date.now() - stableSince >= waitForStableTime) {
3837
- logger10.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3885
+ logger11.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3838
3886
  return {
3839
3887
  mutationCount,
3840
3888
  stableTime: waitForStableTime,
@@ -3861,7 +3909,7 @@ var Mutation = {
3861
3909
  const onMutation = options.onMutation;
3862
3910
  const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();
3863
3911
  const mode = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode) ? rawMode : MUTATION_MONITOR_MODE.Added;
3864
- logger10.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
3912
+ logger11.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
3865
3913
  const monitorKey = generateKey("pk_mon");
3866
3914
  const callbackName = generateKey("pk_mon_cb");
3867
3915
  const cleanerName = generateKey("pk_mon_clean");
@@ -4004,7 +4052,7 @@ var Mutation = {
4004
4052
  return total;
4005
4053
  };
4006
4054
  }, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });
4007
- logger10.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
4055
+ logger11.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
4008
4056
  return {
4009
4057
  stop: async () => {
4010
4058
  let totalMutations = 0;
@@ -4017,7 +4065,7 @@ var Mutation = {
4017
4065
  }, cleanerName);
4018
4066
  } catch (e) {
4019
4067
  }
4020
- logger10.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
4068
+ logger11.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
4021
4069
  return { totalMutations };
4022
4070
  }
4023
4071
  };
@@ -4886,7 +4934,7 @@ var createTemplateLogger = (baseLogger = createBaseLogger()) => {
4886
4934
  };
4887
4935
  var getDefaultBaseLogger = () => createBaseLogger("");
4888
4936
  var Logger = {
4889
- setLogger: (logger13) => setDefaultLogger(logger13),
4937
+ setLogger: (logger14) => setDefaultLogger(logger14),
4890
4938
  info: (message) => getDefaultBaseLogger().info(message),
4891
4939
  success: (message) => getDefaultBaseLogger().success(message),
4892
4940
  warning: (message) => getDefaultBaseLogger().warning(message),
@@ -4894,8 +4942,8 @@ var Logger = {
4894
4942
  error: (message) => getDefaultBaseLogger().error(message),
4895
4943
  debug: (message) => getDefaultBaseLogger().debug(message),
4896
4944
  start: (message) => getDefaultBaseLogger().start(message),
4897
- useTemplate: (logger13) => {
4898
- if (logger13) return createTemplateLogger(createBaseLogger("", logger13));
4945
+ useTemplate: (logger14) => {
4946
+ if (logger14) return createTemplateLogger(createBaseLogger("", logger14));
4899
4947
  return createTemplateLogger();
4900
4948
  }
4901
4949
  };
@@ -4960,7 +5008,7 @@ var LOCATION_NETWORK_SUFFIX_PATTERNS = [
4960
5008
  ];
4961
5009
  var cachedStripLogoSrcPromise = null;
4962
5010
  var cachedEnrichmentByContext = /* @__PURE__ */ new WeakMap();
4963
- var logger11 = createInternalLogger("Watermarkify");
5011
+ var logger12 = createInternalLogger("Watermarkify");
4964
5012
  var normalizeText = (value) => String(value || "").trim();
4965
5013
  var toInline = (value, maxLen = 200) => {
4966
5014
  const text = normalizeText(value);
@@ -5202,9 +5250,9 @@ var resolveWithCustomResolver = async (page, baseMeta, options = {}) => {
5202
5250
  location: toInline(resolved.location, 80)
5203
5251
  };
5204
5252
  if (enrichment.ip || enrichment.location) {
5205
- logger11.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
5253
+ logger12.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
5206
5254
  } else {
5207
- logger11.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
5255
+ logger12.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
5208
5256
  }
5209
5257
  return enrichment;
5210
5258
  } finally {
@@ -5388,12 +5436,12 @@ var buildWatermarkifyRenderHtml = ({ imageSrc, overlaySvg, width, height }) => {
5388
5436
  };
5389
5437
  var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageInfo = {}) => {
5390
5438
  if (!page || typeof page.context !== "function") {
5391
- logger11.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
5439
+ logger12.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
5392
5440
  return buffer;
5393
5441
  }
5394
5442
  const renderScope = await openProbePage(page);
5395
5443
  if (!renderScope?.page) {
5396
- logger11.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
5444
+ logger12.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
5397
5445
  return buffer;
5398
5446
  }
5399
5447
  try {
@@ -5436,13 +5484,13 @@ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageI
5436
5484
  fullPage: true,
5437
5485
  animations: "disabled"
5438
5486
  }).catch((error) => {
5439
- logger11.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
5487
+ logger12.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
5440
5488
  return null;
5441
5489
  });
5442
5490
  if (Buffer.isBuffer(composed) && composed.length > 0) {
5443
5491
  return composed;
5444
5492
  }
5445
- logger11.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
5493
+ logger12.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
5446
5494
  return buffer;
5447
5495
  } finally {
5448
5496
  await renderScope.close().catch(() => {
@@ -5455,7 +5503,7 @@ var resolveWithIpLookup = async (page, options = {}) => {
5455
5503
  }
5456
5504
  const probeScope = await openProbePage(page);
5457
5505
  if (!probeScope?.page) {
5458
- logger11.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
5506
+ logger12.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
5459
5507
  return null;
5460
5508
  }
5461
5509
  const timeoutMs = Math.max(
@@ -5464,12 +5512,12 @@ var resolveWithIpLookup = async (page, options = {}) => {
5464
5512
  );
5465
5513
  try {
5466
5514
  const probePage = probeScope.page;
5467
- logger11.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
5515
+ logger12.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
5468
5516
  const response = await probePage.goto(DEFAULT_IP_LOOKUP_URL, {
5469
5517
  waitUntil: "commit",
5470
5518
  timeout: timeoutMs
5471
5519
  }).catch((error) => {
5472
- logger11.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
5520
+ logger12.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
5473
5521
  return null;
5474
5522
  });
5475
5523
  const status = response && typeof response.status === "function" ? response.status() : 0;
@@ -5491,13 +5539,13 @@ var resolveWithIpLookup = async (page, options = {}) => {
5491
5539
  }
5492
5540
  const parsed = parseIpIpJsonResponse(rawText);
5493
5541
  if (parsed?.ip || parsed?.location) {
5494
- logger11.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
5542
+ logger12.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
5495
5543
  return parsed;
5496
5544
  }
5497
- logger11.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
5545
+ logger12.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
5498
5546
  return null;
5499
5547
  } catch (error) {
5500
- logger11.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
5548
+ logger12.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
5501
5549
  return null;
5502
5550
  } finally {
5503
5551
  await probeScope.close().catch(() => {
@@ -5511,10 +5559,10 @@ var resolveEnrichment = async (page, baseMeta, options) => {
5511
5559
  ip: toInline(options.ip, 80),
5512
5560
  location: toInline(options.location, 80)
5513
5561
  };
5514
- logger11.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
5562
+ logger12.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
5515
5563
  if (!merged.ip || !merged.location) {
5516
5564
  if (cached?.ip || cached?.location) {
5517
- logger11.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
5565
+ logger12.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
5518
5566
  }
5519
5567
  fillEnrichment(merged, cached);
5520
5568
  }
@@ -5538,15 +5586,15 @@ var resolveEnrichment = async (page, baseMeta, options) => {
5538
5586
  "x-geo-country"
5539
5587
  ]), 80);
5540
5588
  if (!merged.location || isWeakLocationValue(merged.location) && headerLocation) {
5541
- logger11.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
5589
+ logger12.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
5542
5590
  merged.location = headerLocation || merged.location;
5543
5591
  }
5544
5592
  }
5545
5593
  writeCachedEnrichment(page, merged);
5546
5594
  if (merged.ip || merged.location) {
5547
- logger11.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
5595
+ logger12.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
5548
5596
  } else {
5549
- logger11.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
5597
+ logger12.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
5550
5598
  }
5551
5599
  return merged;
5552
5600
  };
@@ -6214,7 +6262,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
6214
6262
  }
6215
6263
  const imageInfo = readImageInfo(buffer);
6216
6264
  if (!imageInfo.width || !imageInfo.height || !imageInfo.mimeType) {
6217
- logger11.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
6265
+ logger12.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
6218
6266
  return buffer;
6219
6267
  }
6220
6268
  const overlaySvg = buildWatermarkifySvg(meta, imageInfo.width, imageInfo.height);
@@ -6225,7 +6273,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
6225
6273
  };
6226
6274
 
6227
6275
  // src/share.js
6228
- var logger12 = createInternalLogger("Share");
6276
+ var logger13 = createInternalLogger("Share");
6229
6277
  var DEFAULT_TIMEOUT_MS2 = 50 * 1e3;
6230
6278
  var DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;
6231
6279
  var DEFAULT_POLL_INTERVAL_MS = 120;
@@ -6362,7 +6410,7 @@ var createDomShareMonitor = async (page, options = {}) => {
6362
6410
  const onMatch = typeof options.onMatch === "function" ? options.onMatch : null;
6363
6411
  const onTelemetry = typeof options.onTelemetry === "function" ? options.onTelemetry : null;
6364
6412
  let matched = false;
6365
- logger12.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
6413
+ logger13.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
6366
6414
  const monitor = await Mutation.useMonitor(page, selectors, {
6367
6415
  mode,
6368
6416
  onMutation: (context = {}) => {
@@ -6380,12 +6428,12 @@ ${text}`;
6380
6428
  });
6381
6429
  }
6382
6430
  if (mutationCount <= 5 || mutationCount % 50 === 0) {
6383
- logger12.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
6431
+ logger13.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
6384
6432
  }
6385
6433
  const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];
6386
6434
  if (!candidate) return;
6387
6435
  matched = true;
6388
- logger12.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
6436
+ logger13.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
6389
6437
  if (onMatch) {
6390
6438
  onMatch({
6391
6439
  link: candidate,
@@ -6401,7 +6449,7 @@ ${text}`;
6401
6449
  return {
6402
6450
  stop: async () => {
6403
6451
  const result = await monitor.stop();
6404
- logger12.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
6452
+ logger13.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
6405
6453
  return result;
6406
6454
  }
6407
6455
  };
@@ -6441,8 +6489,8 @@ var Share = {
6441
6489
  if (share.mode === "response" && apiMatchers.length === 0) {
6442
6490
  throw new Error("Share.captureLink requires share.xurl[0] api matcher when mode=response");
6443
6491
  }
6444
- logger12.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);
6445
- logger12.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
6492
+ logger13.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);
6493
+ logger13.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
6446
6494
  const stats = {
6447
6495
  actionTimedOut: false,
6448
6496
  domMutationCount: 0,
@@ -6467,7 +6515,7 @@ var Share = {
6467
6515
  link: validated,
6468
6516
  payloadText: String(payloadText || "")
6469
6517
  };
6470
- logger12.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
6518
+ logger13.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
6471
6519
  return true;
6472
6520
  };
6473
6521
  const resolveResponseCandidate = (responseText) => {
@@ -6502,7 +6550,7 @@ var Share = {
6502
6550
  try {
6503
6551
  await monitor.stop();
6504
6552
  } catch (error) {
6505
- logger12.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
6553
+ logger13.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
6506
6554
  }
6507
6555
  };
6508
6556
  const onResponse = async (response) => {
@@ -6515,29 +6563,29 @@ var Share = {
6515
6563
  stats.responseSampleUrls.push(url);
6516
6564
  }
6517
6565
  if (stats.responseObserved <= 5) {
6518
- logger12.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
6566
+ logger13.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
6519
6567
  }
6520
6568
  if (!apiMatchers.some((matcher) => url.includes(matcher))) return;
6521
6569
  stats.responseMatched += 1;
6522
6570
  stats.lastMatchedUrl = url;
6523
- logger12.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
6571
+ logger13.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
6524
6572
  const text = await response.text();
6525
6573
  const hit = resolveResponseCandidate(text);
6526
6574
  if (!hit?.link) {
6527
6575
  if (stats.responseMatched <= 3) {
6528
- logger12.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
6576
+ logger13.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
6529
6577
  }
6530
6578
  return;
6531
6579
  }
6532
6580
  stats.responseResolved += 1;
6533
- logger12.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
6581
+ logger13.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
6534
6582
  setCandidate("response", hit.link, hit.payloadText);
6535
6583
  } catch (error) {
6536
- logger12.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
6584
+ logger13.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
6537
6585
  }
6538
6586
  };
6539
6587
  if (share.mode === "dom") {
6540
- logger12.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
6588
+ logger13.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
6541
6589
  domMonitor = await createDomShareMonitor(page, {
6542
6590
  prefix: share.prefix,
6543
6591
  selectors: domSelectors,
@@ -6552,14 +6600,14 @@ var Share = {
6552
6600
  });
6553
6601
  }
6554
6602
  if (share.mode === "response") {
6555
- logger12.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
6603
+ logger13.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
6556
6604
  page.on("response", onResponse);
6557
6605
  }
6558
6606
  const deadline = Date.now() + timeoutMs;
6559
6607
  const getRemainingMs = () => Math.max(0, deadline - Date.now());
6560
6608
  try {
6561
6609
  const actionTimeout = getRemainingMs();
6562
- logger12.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);
6610
+ logger13.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);
6563
6611
  if (actionTimeout > 0) {
6564
6612
  let timer = null;
6565
6613
  let actionError = null;
@@ -6573,21 +6621,21 @@ var Share = {
6573
6621
  const actionResult = await Promise.race([actionPromise, timeoutPromise]);
6574
6622
  if (timer) clearTimeout(timer);
6575
6623
  if (actionResult === "__ACTION_ERROR__") {
6576
- logger12.fail("captureLink.performActions", actionError);
6624
+ logger13.fail("captureLink.performActions", actionError);
6577
6625
  throw actionError;
6578
6626
  }
6579
6627
  if (actionResult === "__ACTION_TIMEOUT__") {
6580
6628
  stats.actionTimedOut = true;
6581
- logger12.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
6629
+ logger13.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
6582
6630
  } else {
6583
- logger12.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
6631
+ logger13.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
6584
6632
  }
6585
6633
  }
6586
6634
  let nextProgressLogTs = Date.now() + 3e3;
6587
6635
  while (true) {
6588
6636
  const selected = share.mode === "dom" ? candidates.dom : candidates.response;
6589
6637
  if (selected?.link) {
6590
- logger12.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
6638
+ logger13.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
6591
6639
  return {
6592
6640
  link: selected.link,
6593
6641
  payloadText: selected.payloadText,
@@ -6599,7 +6647,7 @@ var Share = {
6599
6647
  if (remaining <= 0) break;
6600
6648
  const now = Date.now();
6601
6649
  if (now >= nextProgressLogTs) {
6602
- logger12.info(
6650
+ logger13.info(
6603
6651
  `captureLink \u7B49\u5F85\u4E2D: remaining=${remaining}ms, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`
6604
6652
  );
6605
6653
  nextProgressLogTs = now + 5e3;
@@ -6607,11 +6655,11 @@ var Share = {
6607
6655
  await (0, import_delay2.default)(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
6608
6656
  }
6609
6657
  if (share.mode === "response" && stats.responseMatched === 0) {
6610
- logger12.warning(
6658
+ logger13.warning(
6611
6659
  `\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`
6612
6660
  );
6613
6661
  }
6614
- logger12.warning(
6662
+ logger13.warning(
6615
6663
  `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"}`
6616
6664
  );
6617
6665
  return {
@@ -6623,7 +6671,7 @@ var Share = {
6623
6671
  } finally {
6624
6672
  if (share.mode === "response") {
6625
6673
  page.off("response", onResponse);
6626
- logger12.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
6674
+ logger13.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
6627
6675
  }
6628
6676
  await stopDomMonitor();
6629
6677
  }