@skrillex1224/playwright-toolkit 2.1.219 → 2.1.221

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,6 +439,7 @@ function createInternalLogger(moduleName, explicitLogger) {
439
439
  },
440
440
  warning(message) {
441
441
  baseLogger.warning(message);
442
+ a;
442
443
  },
443
444
  info(message) {
444
445
  baseLogger.info(message);
@@ -685,9 +686,9 @@ var resolveResourceTypeMeta = (domain) => {
685
686
  if (!byType || byType.size === 0) {
686
687
  return { resourceType: "", resourceTypeCounts: void 0 };
687
688
  }
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]));
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]));
691
692
  });
692
693
  if (entries.length === 0) {
693
694
  return { resourceType: "", resourceTypeCounts: void 0 };
@@ -777,10 +778,10 @@ var normalizeDomainRows = (hosts) => {
777
778
  resourceTypeCounts: resourceTypeMeta.resourceTypeCounts || void 0
778
779
  });
779
780
  }
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));
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));
784
785
  });
785
786
  return {
786
787
  topDomains: rows.slice(0, MAX_TOP_DOMAINS),
@@ -2975,13 +2976,91 @@ var LiveView = {
2975
2976
  useLiveView
2976
2977
  };
2977
2978
 
2978
- // src/captcha-monitor.js
2979
+ // src/chaptcha.js
2979
2980
  var import_uuid = require("uuid");
2981
+
2982
+ // src/internals/captcha/shared.js
2983
+ var waitForVisible = async (locator, timeout) => {
2984
+ try {
2985
+ await locator.waitFor({
2986
+ state: "visible",
2987
+ timeout
2988
+ });
2989
+ return true;
2990
+ } catch {
2991
+ return false;
2992
+ }
2993
+ };
2994
+ var isAnyCaptchaTextVisible = async (frame, texts, timeout) => {
2995
+ for (const text of texts || []) {
2996
+ if (!text) {
2997
+ continue;
2998
+ }
2999
+ const candidates = [
3000
+ frame.getByText(text, { exact: false }).first(),
3001
+ frame.locator(`text=${text}`).first()
3002
+ ];
3003
+ for (const candidate of candidates) {
3004
+ const isVisible = await candidate.isVisible({ timeout }).catch(() => false);
3005
+ if (isVisible) {
3006
+ return true;
3007
+ }
3008
+ }
3009
+ }
3010
+ return false;
3011
+ };
3012
+ var clickCaptchaAction = async (frame, texts, options) => {
3013
+ for (const text of texts || []) {
3014
+ const candidates = [
3015
+ frame.getByText(text, { exact: false }).first(),
3016
+ frame.locator(`text=${text}`).first()
3017
+ ];
3018
+ for (const candidate of candidates) {
3019
+ const isVisible = await waitForVisible(candidate, options.actionVisibleTimeoutMs);
3020
+ if (!isVisible) {
3021
+ continue;
3022
+ }
3023
+ await candidate.click();
3024
+ return true;
3025
+ }
3026
+ }
3027
+ return false;
3028
+ };
3029
+ var dragCaptchaWithMouse = async (page, sourceLocator, targetLocator) => {
3030
+ const sourceBox = await sourceLocator.boundingBox();
3031
+ const targetBox = await targetLocator.boundingBox();
3032
+ if (!sourceBox || !targetBox) {
3033
+ throw new Error("Unable to resolve captcha drag coordinates.");
3034
+ }
3035
+ const startX = sourceBox.x + sourceBox.width / 2;
3036
+ const startY = sourceBox.y + sourceBox.height / 2;
3037
+ const endX = targetBox.x + targetBox.width / 2;
3038
+ const endY = targetBox.y + targetBox.height / 2;
3039
+ const steps = 10;
3040
+ const liftOffsetX = Math.min(18, Math.max(8, sourceBox.width * 0.12));
3041
+ const liftOffsetY = Math.min(12, Math.max(4, sourceBox.height * 0.08));
3042
+ await page.mouse.move(startX, startY, { steps: 8 });
3043
+ await page.waitForTimeout(250);
3044
+ await page.mouse.down();
3045
+ await page.waitForTimeout(350);
3046
+ await page.mouse.move(startX + liftOffsetX, startY + liftOffsetY, { steps: 6 });
3047
+ await page.waitForTimeout(250);
3048
+ for (let step = 1; step <= steps; step++) {
3049
+ const progress = step / steps;
3050
+ const easedProgress = 1 - (1 - progress) * (1 - progress);
3051
+ const currentX = startX + liftOffsetX + (endX - startX - liftOffsetX) * easedProgress;
3052
+ const currentY = startY + liftOffsetY + (endY - startY - liftOffsetY) * easedProgress;
3053
+ await page.mouse.move(currentX, currentY, { steps: 2 });
3054
+ await page.waitForTimeout(90);
3055
+ }
3056
+ await page.waitForTimeout(100);
3057
+ await page.mouse.up();
3058
+ await page.waitForTimeout(100);
3059
+ };
3060
+
3061
+ // src/internals/captcha/bytedance.js
2980
3062
  var logger9 = createInternalLogger("Captcha");
2981
- var DEFAULT_BYTEDANCE_CAPTCHA_TOKEN = "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI";
2982
3063
  var DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS = Object.freeze({
2983
- token: DEFAULT_BYTEDANCE_CAPTCHA_TOKEN,
2984
- apiUrl: "https://api.jfbym.com/api/YmServer/customApi",
2985
3064
  apiType: "31234",
2986
3065
  maxRetries: 3,
2987
3066
  containerSelector: "#captcha_container",
@@ -3001,137 +3080,23 @@ var DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS = Object.freeze({
3001
3080
  actionVisibleTimeoutMs: 1500,
3002
3081
  sourceImageVisibleTimeoutMs: 3e3,
3003
3082
  challengeReadyTimeoutMs: 15e3,
3083
+ challengeReadyRefreshTimeoutMs: 2e4,
3004
3084
  challengeReadyPollMs: 300,
3005
3085
  loadingIndicatorVisibleTimeoutMs: 200,
3006
3086
  loadingTexts: ["\u52A0\u8F7D\u4E2D", "\u52A0\u8F7D\u4E2D..."],
3087
+ errorTexts: [
3088
+ "\u68C0\u6D4B\u5230\u60A8\u7684\u7F51\u7EDC\u73AF\u5883\u8F83\u5DEE",
3089
+ "\u7F51\u7EDC\u73AF\u5883\u8F83\u5DEE",
3090
+ "\u8BF7\u66F4\u6362\u7F51\u7EDC\u6216\u8005\u7A0D\u540E\u518D\u8BD5",
3091
+ "\u8BF7\u66F4\u6362\u7F51\u7EDC\u6216\u7A0D\u540E\u518D\u8BD5",
3092
+ "\u7A0D\u540E\u518D\u8BD5"
3093
+ ],
3007
3094
  recognitionDelayMs: 2e3,
3008
3095
  refreshWaitMs: 3e3,
3009
3096
  submitWaitMs: 3e3,
3010
3097
  retryDelayBaseMs: 2e3,
3011
3098
  retryDelayStepMs: 1e3
3012
3099
  });
3013
- function useCaptchaMonitor(page, options) {
3014
- const { domSelector, urlPattern, onDetected } = options;
3015
- if (!domSelector && !urlPattern) {
3016
- throw new Error("[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector \u6216 urlPattern\u3002");
3017
- }
3018
- if (!onDetected || typeof onDetected !== "function") {
3019
- throw new Error("[CaptchaMonitor] onDetected \u5FC5\u987B\u662F\u51FD\u6570\u3002");
3020
- }
3021
- let isStopped = false;
3022
- let isHandling = false;
3023
- let frameHandler = null;
3024
- let exposedFunctionName = null;
3025
- const triggerDetected = async () => {
3026
- if (isStopped || isHandling) return;
3027
- isHandling = true;
3028
- try {
3029
- await onDetected();
3030
- } finally {
3031
- isHandling = false;
3032
- }
3033
- };
3034
- const cleanupFns = [];
3035
- if (domSelector) {
3036
- exposedFunctionName = `__c_d_${(0, import_uuid.v4)().replace(/-/g, "_")}`;
3037
- const cleanerName = `__c_cleaner_${(0, import_uuid.v4)().replace(/-/g, "_")}`;
3038
- page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {
3039
- });
3040
- page.addInitScript(({ selector, callbackName, cleanerName: cleanupName }) => {
3041
- (() => {
3042
- let observer = null;
3043
- const checkAndReport = () => {
3044
- const element = document.querySelector(selector);
3045
- if (!element) {
3046
- return false;
3047
- }
3048
- if (window[callbackName]) {
3049
- window[callbackName]();
3050
- }
3051
- return true;
3052
- };
3053
- checkAndReport();
3054
- observer = new MutationObserver((mutations) => {
3055
- const shouldCheck = mutations.some((mutation) => mutation.addedNodes.length > 0);
3056
- if (shouldCheck && observer) {
3057
- checkAndReport();
3058
- }
3059
- });
3060
- const mountObserver = () => {
3061
- const target = document.documentElement;
3062
- if (target && observer) {
3063
- observer.observe(target, { childList: true, subtree: true });
3064
- }
3065
- };
3066
- if (document.readyState === "loading") {
3067
- window.addEventListener("DOMContentLoaded", mountObserver);
3068
- } else {
3069
- mountObserver();
3070
- }
3071
- window[cleanupName] = () => {
3072
- if (observer) {
3073
- observer.disconnect();
3074
- observer = null;
3075
- }
3076
- };
3077
- })();
3078
- }, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
3079
- logger9.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
3080
- cleanupFns.push(async () => {
3081
- try {
3082
- await page.evaluate((name) => {
3083
- if (window[name]) {
3084
- window[name]();
3085
- delete window[name];
3086
- }
3087
- }, cleanerName);
3088
- } catch {
3089
- }
3090
- });
3091
- }
3092
- if (urlPattern) {
3093
- frameHandler = async (frame) => {
3094
- if (frame !== page.mainFrame()) {
3095
- return;
3096
- }
3097
- const currentUrl = page.url();
3098
- if (currentUrl.includes(urlPattern)) {
3099
- await triggerDetected();
3100
- }
3101
- };
3102
- page.on("framenavigated", frameHandler);
3103
- logger9.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
3104
- cleanupFns.push(async () => {
3105
- page.off("framenavigated", frameHandler);
3106
- });
3107
- }
3108
- return {
3109
- stop: async () => {
3110
- logger9.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
3111
- for (const fn of cleanupFns) {
3112
- await fn();
3113
- }
3114
- isStopped = true;
3115
- }
3116
- };
3117
- }
3118
- var callCaptchaRecognitionApi = async (imageBase64, { apiUrl, apiType, token }) => {
3119
- const response = await fetch(apiUrl, {
3120
- method: "POST",
3121
- headers: {
3122
- "Content-Type": "application/json"
3123
- },
3124
- body: JSON.stringify({
3125
- type: apiType,
3126
- image: imageBase64,
3127
- token
3128
- })
3129
- });
3130
- if (!response.ok) {
3131
- throw new Error(`Captcha API request failed with status ${response.status}`);
3132
- }
3133
- return await response.json();
3134
- };
3135
3100
  var extractCaptchaSerialNumbers = (apiResponse) => {
3136
3101
  const serialNumbers = apiResponse?.data?.data?.serial_number;
3137
3102
  if (!Array.isArray(serialNumbers)) {
@@ -3139,56 +3104,6 @@ var extractCaptchaSerialNumbers = (apiResponse) => {
3139
3104
  }
3140
3105
  return serialNumbers.map((value) => Number(value)).filter((value) => Number.isInteger(value) && value >= 0);
3141
3106
  };
3142
- var waitForVisible = async (locator, timeout) => {
3143
- try {
3144
- await locator.waitFor({
3145
- state: "visible",
3146
- timeout
3147
- });
3148
- return true;
3149
- } catch {
3150
- return false;
3151
- }
3152
- };
3153
- var isAnyCaptchaTextVisible = async (frame, texts, timeout) => {
3154
- for (const text of texts || []) {
3155
- if (!text) {
3156
- continue;
3157
- }
3158
- const candidates = [
3159
- frame.getByText(text, { exact: false }).first(),
3160
- frame.locator(`text=${text}`).first()
3161
- ];
3162
- for (const candidate of candidates) {
3163
- const isVisible = await candidate.isVisible({ timeout }).catch(() => false);
3164
- if (isVisible) {
3165
- return true;
3166
- }
3167
- }
3168
- }
3169
- return false;
3170
- };
3171
- var waitForCaptchaChallengeReady = async (page, frame, options) => {
3172
- const deadline = Date.now() + options.challengeReadyTimeoutMs;
3173
- let hasSeenLoading = false;
3174
- while (Date.now() < deadline) {
3175
- const isLoadingVisible = await isAnyCaptchaTextVisible(
3176
- frame,
3177
- options.loadingTexts,
3178
- options.loadingIndicatorVisibleTimeoutMs
3179
- );
3180
- hasSeenLoading = hasSeenLoading || isLoadingVisible;
3181
- const sourceImages = frame.locator(options.sourceImageSelector);
3182
- const imageCount = await sourceImages.count().catch(() => 0);
3183
- const hasVisibleSourceImage = imageCount > 0 ? await sourceImages.first().isVisible({ timeout: options.loadingIndicatorVisibleTimeoutMs }).catch(() => false) : false;
3184
- if (!isLoadingVisible && hasVisibleSourceImage) {
3185
- logger9.info(hasSeenLoading ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u52A0\u8F7D\u5B8C\u6210\u3002" : "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u5C31\u7EEA\u3002");
3186
- return;
3187
- }
3188
- await page.waitForTimeout(options.challengeReadyPollMs);
3189
- }
3190
- throw new Error("Captcha challenge is still loading and did not become ready in time.");
3191
- };
3192
3107
  var resolveContentFrame = async (page, iframeLocator, options) => {
3193
3108
  for (let attempt = 1; attempt <= options.contentFrameResolveRetries; attempt++) {
3194
3109
  const iframeHandle = await iframeLocator.elementHandle();
@@ -3235,22 +3150,14 @@ var getVerifycenterCaptchaContext = async (page, options) => {
3235
3150
  }
3236
3151
  return { iframeLocator, frame };
3237
3152
  };
3238
- var clickCaptchaAction = async (frame, texts, options) => {
3239
- for (const text of texts) {
3240
- const candidates = [
3241
- frame.getByText(text, { exact: false }).first(),
3242
- frame.locator(`text=${text}`).first()
3243
- ];
3244
- for (const candidate of candidates) {
3245
- const isVisible = await waitForVisible(candidate, options.actionVisibleTimeoutMs);
3246
- if (!isVisible) {
3247
- continue;
3248
- }
3249
- await candidate.click();
3250
- return true;
3251
- }
3153
+ var refreshCaptcha = async (page, frame, options) => {
3154
+ const clicked = await clickCaptchaAction(frame, options.refreshTexts, options).catch(() => false);
3155
+ if (!clicked) {
3156
+ logger9.warn("Refresh button not found.");
3157
+ return false;
3252
3158
  }
3253
- return false;
3159
+ await page.waitForTimeout(options.refreshWaitMs);
3160
+ return true;
3254
3161
  };
3255
3162
  var findCaptchaDropTarget = async (frame, options) => {
3256
3163
  for (const text of options.dropTargetTexts) {
@@ -3267,47 +3174,52 @@ var findCaptchaDropTarget = async (frame, options) => {
3267
3174
  }
3268
3175
  return null;
3269
3176
  };
3270
- var dragCaptchaWithMouse = async (page, sourceLocator, targetLocator) => {
3271
- const sourceBox = await sourceLocator.boundingBox();
3272
- const targetBox = await targetLocator.boundingBox();
3273
- if (!sourceBox || !targetBox) {
3274
- throw new Error("Unable to resolve captcha drag coordinates.");
3275
- }
3276
- const startX = sourceBox.x + sourceBox.width / 2;
3277
- const startY = sourceBox.y + sourceBox.height / 2;
3278
- const endX = targetBox.x + targetBox.width / 2;
3279
- const endY = targetBox.y + targetBox.height / 2;
3280
- const steps = 10;
3281
- const liftOffsetX = Math.min(18, Math.max(8, sourceBox.width * 0.12));
3282
- const liftOffsetY = Math.min(12, Math.max(4, sourceBox.height * 0.08));
3283
- await page.mouse.move(startX, startY, { steps: 8 });
3284
- await page.waitForTimeout(250);
3285
- await page.mouse.down();
3286
- await page.waitForTimeout(350);
3287
- await page.mouse.move(startX + liftOffsetX, startY + liftOffsetY, { steps: 6 });
3288
- await page.waitForTimeout(250);
3289
- for (let step = 1; step <= steps; step++) {
3290
- const progress = step / steps;
3291
- const easedProgress = 1 - (1 - progress) * (1 - progress);
3292
- const currentX = startX + liftOffsetX + (endX - startX - liftOffsetX) * easedProgress;
3293
- const currentY = startY + liftOffsetY + (endY - startY - liftOffsetY) * easedProgress;
3294
- await page.mouse.move(currentX, currentY, { steps: 2 });
3295
- await page.waitForTimeout(90);
3177
+ var waitForCaptchaChallengeReady = async (page, frame, options) => {
3178
+ const deadline = Date.now() + options.challengeReadyTimeoutMs;
3179
+ let refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3180
+ let hasSeenLoading = false;
3181
+ while (Date.now() < deadline) {
3182
+ const isLoadingVisible = await isAnyCaptchaTextVisible(
3183
+ frame,
3184
+ options.loadingTexts,
3185
+ options.loadingIndicatorVisibleTimeoutMs
3186
+ );
3187
+ const hasErrorTextVisible = await isAnyCaptchaTextVisible(
3188
+ frame,
3189
+ options.errorTexts,
3190
+ options.loadingIndicatorVisibleTimeoutMs
3191
+ );
3192
+ hasSeenLoading = hasSeenLoading || isLoadingVisible;
3193
+ const sourceImages = frame.locator(options.sourceImageSelector);
3194
+ const imageCount = await sourceImages.count().catch(() => 0);
3195
+ const hasVisibleSourceImage = imageCount > 0 ? await sourceImages.first().isVisible({ timeout: options.loadingIndicatorVisibleTimeoutMs }).catch(() => false) : false;
3196
+ if (!isLoadingVisible && hasVisibleSourceImage) {
3197
+ logger9.info(hasSeenLoading ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u52A0\u8F7D\u5B8C\u6210\u3002" : "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u5C31\u7EEA\u3002");
3198
+ return;
3199
+ }
3200
+ if (hasErrorTextVisible) {
3201
+ 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");
3202
+ await refreshCaptcha(page, frame, options);
3203
+ refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3204
+ hasSeenLoading = false;
3205
+ continue;
3206
+ }
3207
+ if (!hasVisibleSourceImage && Date.now() >= refreshDeadline) {
3208
+ logger9.warn(`\u9A8C\u8BC1\u7801\u56FE\u7247\u8D85\u8FC7 ${options.challengeReadyRefreshTimeoutMs}ms \u4ECD\u672A\u51FA\u73B0\uFF0C\u5C1D\u8BD5\u5237\u65B0\u9898\u76EE\u3002`);
3209
+ await refreshCaptcha(page, frame, options);
3210
+ refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3211
+ hasSeenLoading = false;
3212
+ continue;
3213
+ }
3214
+ await page.waitForTimeout(options.challengeReadyPollMs);
3296
3215
  }
3297
- await page.waitForTimeout(100);
3298
- await page.mouse.up();
3299
- await page.waitForTimeout(100);
3216
+ throw new Error("Captcha challenge is still loading and did not become ready in time.");
3300
3217
  };
3301
- var refreshCaptcha = async (page, frame, options) => {
3302
- const clicked = await clickCaptchaAction(frame, options.refreshTexts, options).catch(() => false);
3303
- if (!clicked) {
3304
- logger9.warn("Refresh button not found.");
3305
- return false;
3218
+ async function solveCaptcha(page, options = {}, dependencies = {}) {
3219
+ const { callCaptchaRecognitionApi: callCaptchaRecognitionApi2 } = dependencies;
3220
+ if (typeof callCaptchaRecognitionApi2 !== "function") {
3221
+ throw new Error("[Captcha] \u7F3A\u5C11\u901A\u7528\u8BC6\u522B\u8BF7\u6C42\u51FD\u6570 callCaptchaRecognitionApi\u3002");
3306
3222
  }
3307
- await page.waitForTimeout(options.refreshWaitMs);
3308
- return true;
3309
- };
3310
- async function solveBytedanceCaptcha(page, options = {}) {
3311
3223
  const config = {
3312
3224
  ...DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS,
3313
3225
  ...options
@@ -3316,6 +3228,7 @@ async function solveBytedanceCaptcha(page, options = {}) {
3316
3228
  logger9.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
3317
3229
  return false;
3318
3230
  }
3231
+ logger9.info("\u5F53\u524D\u4F7F\u7528\u672Ctool\u2014\u2014\u6D4B\u8BD5\u7248\u672C");
3319
3232
  for (let attempt = 1; attempt <= config.maxRetries; attempt++) {
3320
3233
  logger9.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
3321
3234
  try {
@@ -3328,10 +3241,12 @@ async function solveBytedanceCaptcha(page, options = {}) {
3328
3241
  await waitForCaptchaChallengeReady(page, frame, config);
3329
3242
  await page.waitForTimeout(config.recognitionDelayMs);
3330
3243
  const screenshotBuffer = await iframeLocator.screenshot();
3331
- const apiResponse = await callCaptchaRecognitionApi(
3332
- screenshotBuffer.toString("base64"),
3333
- config
3334
- );
3244
+ const apiResponse = await callCaptchaRecognitionApi2({
3245
+ apiUrl: config.apiUrl,
3246
+ type: config.apiType,
3247
+ image: screenshotBuffer.toString("base64"),
3248
+ token: config.token
3249
+ });
3335
3250
  const serialNumbers = extractCaptchaSerialNumbers(apiResponse);
3336
3251
  if (apiResponse?.code !== config.recognitionSuccessCode || serialNumbers.length === 0) {
3337
3252
  logger9.warn(
@@ -3387,15 +3302,178 @@ async function solveBytedanceCaptcha(page, options = {}) {
3387
3302
  logger9.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
3388
3303
  return false;
3389
3304
  }
3305
+ var sloveCaptcha = solveCaptcha;
3306
+
3307
+ // src/chaptcha.js
3308
+ var logger10 = createInternalLogger("Captcha");
3309
+ var DEFAULT_CAPTCHA_RECOGNITION_OPTIONS = Object.freeze({
3310
+ token: "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI",
3311
+ apiUrl: "https://api.jfbym.com/api/YmServer/customApi"
3312
+ });
3313
+ var CAPTCHA_STRATEGIES = Object.freeze({
3314
+ bytedance: {
3315
+ sloveCaptcha
3316
+ }
3317
+ });
3318
+ var mergeDefinedOptions = (...sources) => {
3319
+ const merged = {};
3320
+ for (const source of sources) {
3321
+ for (const [key, value] of Object.entries(source || {})) {
3322
+ if (value !== void 0) {
3323
+ merged[key] = value;
3324
+ }
3325
+ }
3326
+ }
3327
+ return merged;
3328
+ };
3329
+ function useCaptchaMonitor(page, options) {
3330
+ const { domSelector, urlPattern, onDetected } = options;
3331
+ if (!domSelector && !urlPattern) {
3332
+ throw new Error("[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector \u6216 urlPattern\u3002");
3333
+ }
3334
+ if (!onDetected || typeof onDetected !== "function") {
3335
+ throw new Error("[CaptchaMonitor] onDetected \u5FC5\u987B\u662F\u51FD\u6570\u3002");
3336
+ }
3337
+ let isStopped = false;
3338
+ let isHandling = false;
3339
+ let frameHandler = null;
3340
+ let exposedFunctionName = null;
3341
+ const triggerDetected = async () => {
3342
+ if (isStopped || isHandling) return;
3343
+ isHandling = true;
3344
+ try {
3345
+ await onDetected();
3346
+ } finally {
3347
+ isHandling = false;
3348
+ }
3349
+ };
3350
+ const cleanupFns = [];
3351
+ if (domSelector) {
3352
+ exposedFunctionName = `__c_d_${(0, import_uuid.v4)().replace(/-/g, "_")}`;
3353
+ const cleanerName = `__c_cleaner_${(0, import_uuid.v4)().replace(/-/g, "_")}`;
3354
+ page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {
3355
+ });
3356
+ page.addInitScript(({ selector, callbackName, cleanerName: cleanupName }) => {
3357
+ (() => {
3358
+ let observer = null;
3359
+ const checkAndReport = () => {
3360
+ const element = document.querySelector(selector);
3361
+ if (!element) {
3362
+ return false;
3363
+ }
3364
+ if (window[callbackName]) {
3365
+ window[callbackName]();
3366
+ }
3367
+ return true;
3368
+ };
3369
+ checkAndReport();
3370
+ observer = new MutationObserver((mutations) => {
3371
+ const shouldCheck = mutations.some((mutation) => mutation.addedNodes.length > 0);
3372
+ if (shouldCheck && observer) {
3373
+ checkAndReport();
3374
+ }
3375
+ });
3376
+ const mountObserver = () => {
3377
+ const target = document.documentElement;
3378
+ if (target && observer) {
3379
+ observer.observe(target, { childList: true, subtree: true });
3380
+ }
3381
+ };
3382
+ if (document.readyState === "loading") {
3383
+ window.addEventListener("DOMContentLoaded", mountObserver);
3384
+ } else {
3385
+ mountObserver();
3386
+ }
3387
+ window[cleanupName] = () => {
3388
+ if (observer) {
3389
+ observer.disconnect();
3390
+ observer = null;
3391
+ }
3392
+ };
3393
+ })();
3394
+ }, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
3395
+ logger10.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
3396
+ cleanupFns.push(async () => {
3397
+ try {
3398
+ await page.evaluate((name) => {
3399
+ if (window[name]) {
3400
+ window[name]();
3401
+ delete window[name];
3402
+ }
3403
+ }, cleanerName);
3404
+ } catch {
3405
+ }
3406
+ });
3407
+ }
3408
+ if (urlPattern) {
3409
+ frameHandler = async (frame) => {
3410
+ if (frame !== page.mainFrame()) {
3411
+ return;
3412
+ }
3413
+ const currentUrl = page.url();
3414
+ if (currentUrl.includes(urlPattern)) {
3415
+ await triggerDetected();
3416
+ }
3417
+ };
3418
+ page.on("framenavigated", frameHandler);
3419
+ logger10.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
3420
+ cleanupFns.push(async () => {
3421
+ page.off("framenavigated", frameHandler);
3422
+ });
3423
+ }
3424
+ return {
3425
+ stop: async () => {
3426
+ logger10.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
3427
+ for (const fn of cleanupFns) {
3428
+ await fn();
3429
+ }
3430
+ isStopped = true;
3431
+ }
3432
+ };
3433
+ }
3434
+ var callCaptchaRecognitionApi = async (requestParams = {}) => {
3435
+ const { apiUrl, ...payload } = mergeDefinedOptions(
3436
+ DEFAULT_CAPTCHA_RECOGNITION_OPTIONS,
3437
+ requestParams
3438
+ );
3439
+ if (!apiUrl) {
3440
+ throw new Error("[Captcha] \u7F3A\u5C11\u9A8C\u8BC1\u7801\u8BC6\u522B\u63A5\u53E3\u5730\u5740 apiUrl\u3002");
3441
+ }
3442
+ const response = await fetch(apiUrl, {
3443
+ method: "POST",
3444
+ headers: {
3445
+ "Content-Type": "application/json"
3446
+ },
3447
+ body: JSON.stringify(payload)
3448
+ });
3449
+ if (!response.ok) {
3450
+ throw new Error(`Captcha API request failed with status ${response.status}`);
3451
+ }
3452
+ return await response.json();
3453
+ };
3454
+ async function solveCaptchaWithStrategy(strategyName, page, options = {}) {
3455
+ const strategy = CAPTCHA_STRATEGIES[strategyName];
3456
+ if (!strategy?.sloveCaptcha) {
3457
+ throw new Error(`[Captcha] \u672A\u627E\u5230\u9A8C\u8BC1\u7801\u7B56\u7565\uFF1A${strategyName}`);
3458
+ }
3459
+ const resolvedOptions = mergeDefinedOptions(
3460
+ DEFAULT_CAPTCHA_RECOGNITION_OPTIONS,
3461
+ options
3462
+ );
3463
+ return strategy.sloveCaptcha(page, resolvedOptions, {
3464
+ callCaptchaRecognitionApi,
3465
+ logger: logger10
3466
+ });
3467
+ }
3390
3468
  var Captcha = {
3391
3469
  useCaptchaMonitor,
3392
- solveBytedanceCaptcha
3470
+ solveCaptchaWithStrategy
3393
3471
  };
3394
3472
 
3395
3473
  // src/mutation.js
3396
3474
  var import_node_crypto = require("node:crypto");
3397
3475
  var import_uuid2 = require("uuid");
3398
- var logger10 = createInternalLogger("Mutation");
3476
+ var logger11 = createInternalLogger("Mutation");
3399
3477
  var MUTATION_MONITOR_MODE = Object.freeze({
3400
3478
  Added: "added",
3401
3479
  Changed: "changed",
@@ -3428,14 +3506,14 @@ var Mutation = {
3428
3506
  const stableTime = options.stableTime ?? 5 * 1e3;
3429
3507
  const timeout = options.timeout ?? 120 * 1e3;
3430
3508
  const onMutation = options.onMutation;
3431
- logger10.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
3509
+ logger11.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
3432
3510
  if (initialTimeout > 0) {
3433
3511
  const selectorQuery = selectorList.join(",");
3434
3512
  try {
3435
3513
  await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
3436
- logger10.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3514
+ logger11.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3437
3515
  } catch (e) {
3438
- logger10.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3516
+ logger11.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3439
3517
  throw e;
3440
3518
  }
3441
3519
  }
@@ -3451,7 +3529,7 @@ var Mutation = {
3451
3529
  return "__CONTINUE__";
3452
3530
  }
3453
3531
  });
3454
- logger10.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
3532
+ logger11.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
3455
3533
  } catch (e) {
3456
3534
  }
3457
3535
  }
@@ -3566,9 +3644,9 @@ var Mutation = {
3566
3644
  { selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }
3567
3645
  );
3568
3646
  if (result.mutationCount === 0 && result.stableTime === 0) {
3569
- logger10.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3647
+ logger11.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3570
3648
  }
3571
- logger10.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3649
+ logger11.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3572
3650
  return result;
3573
3651
  },
3574
3652
  /**
@@ -3740,22 +3818,22 @@ var Mutation = {
3740
3818
  return "__CONTINUE__";
3741
3819
  }
3742
3820
  };
3743
- logger10.start(
3821
+ logger11.start(
3744
3822
  "waitForStableAcrossRoots",
3745
3823
  `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668(\u8DE8 root), \u7A33\u5B9A\u65F6\u95F4=${waitForStableTime}ms`
3746
3824
  );
3747
3825
  if (initialTimeout > 0) {
3748
3826
  try {
3749
3827
  await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
3750
- logger10.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3828
+ logger11.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3751
3829
  } catch (e) {
3752
- logger10.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3830
+ logger11.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3753
3831
  throw e;
3754
3832
  }
3755
3833
  }
3756
3834
  let state = await buildState();
3757
3835
  if (!state?.hasMatched) {
3758
- logger10.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3836
+ logger11.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3759
3837
  return { mutationCount: 0, stableTime: 0, wasPaused: false };
3760
3838
  }
3761
3839
  let mutationCount = 0;
@@ -3792,7 +3870,7 @@ var Mutation = {
3792
3870
  if (lastState.snapshotKey !== lastSnapshotKey) {
3793
3871
  lastSnapshotKey = lastState.snapshotKey;
3794
3872
  mutationCount += 1;
3795
- logger10.info(
3873
+ logger11.info(
3796
3874
  `waitForStableAcrossRoots \u53D8\u5316#${mutationCount}, len=${lastState.snapshotLength}, path=${lastState.primaryPath || "unknown"}, preview="${truncate(lastState.text, 120)}"`
3797
3875
  );
3798
3876
  const signal = await invokeMutationCallback({
@@ -3805,7 +3883,7 @@ var Mutation = {
3805
3883
  continue;
3806
3884
  }
3807
3885
  if (!isPaused && stableSince > 0 && Date.now() - stableSince >= waitForStableTime) {
3808
- logger10.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3886
+ logger11.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3809
3887
  return {
3810
3888
  mutationCount,
3811
3889
  stableTime: waitForStableTime,
@@ -3832,7 +3910,7 @@ var Mutation = {
3832
3910
  const onMutation = options.onMutation;
3833
3911
  const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();
3834
3912
  const mode = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode) ? rawMode : MUTATION_MONITOR_MODE.Added;
3835
- logger10.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
3913
+ logger11.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
3836
3914
  const monitorKey = generateKey("pk_mon");
3837
3915
  const callbackName = generateKey("pk_mon_cb");
3838
3916
  const cleanerName = generateKey("pk_mon_clean");
@@ -3975,7 +4053,7 @@ var Mutation = {
3975
4053
  return total;
3976
4054
  };
3977
4055
  }, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });
3978
- logger10.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
4056
+ logger11.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
3979
4057
  return {
3980
4058
  stop: async () => {
3981
4059
  let totalMutations = 0;
@@ -3988,7 +4066,7 @@ var Mutation = {
3988
4066
  }, cleanerName);
3989
4067
  } catch (e) {
3990
4068
  }
3991
- logger10.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
4069
+ logger11.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
3992
4070
  return { totalMutations };
3993
4071
  }
3994
4072
  };
@@ -4857,7 +4935,7 @@ var createTemplateLogger = (baseLogger = createBaseLogger()) => {
4857
4935
  };
4858
4936
  var getDefaultBaseLogger = () => createBaseLogger("");
4859
4937
  var Logger = {
4860
- setLogger: (logger13) => setDefaultLogger(logger13),
4938
+ setLogger: (logger14) => setDefaultLogger(logger14),
4861
4939
  info: (message) => getDefaultBaseLogger().info(message),
4862
4940
  success: (message) => getDefaultBaseLogger().success(message),
4863
4941
  warning: (message) => getDefaultBaseLogger().warning(message),
@@ -4865,8 +4943,8 @@ var Logger = {
4865
4943
  error: (message) => getDefaultBaseLogger().error(message),
4866
4944
  debug: (message) => getDefaultBaseLogger().debug(message),
4867
4945
  start: (message) => getDefaultBaseLogger().start(message),
4868
- useTemplate: (logger13) => {
4869
- if (logger13) return createTemplateLogger(createBaseLogger("", logger13));
4946
+ useTemplate: (logger14) => {
4947
+ if (logger14) return createTemplateLogger(createBaseLogger("", logger14));
4870
4948
  return createTemplateLogger();
4871
4949
  }
4872
4950
  };
@@ -4931,7 +5009,7 @@ var LOCATION_NETWORK_SUFFIX_PATTERNS = [
4931
5009
  ];
4932
5010
  var cachedStripLogoSrcPromise = null;
4933
5011
  var cachedEnrichmentByContext = /* @__PURE__ */ new WeakMap();
4934
- var logger11 = createInternalLogger("Watermarkify");
5012
+ var logger12 = createInternalLogger("Watermarkify");
4935
5013
  var normalizeText = (value) => String(value || "").trim();
4936
5014
  var toInline = (value, maxLen = 200) => {
4937
5015
  const text = normalizeText(value);
@@ -5173,9 +5251,9 @@ var resolveWithCustomResolver = async (page, baseMeta, options = {}) => {
5173
5251
  location: toInline(resolved.location, 80)
5174
5252
  };
5175
5253
  if (enrichment.ip || enrichment.location) {
5176
- logger11.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
5254
+ logger12.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
5177
5255
  } else {
5178
- logger11.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
5256
+ logger12.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
5179
5257
  }
5180
5258
  return enrichment;
5181
5259
  } finally {
@@ -5359,12 +5437,12 @@ var buildWatermarkifyRenderHtml = ({ imageSrc, overlaySvg, width, height }) => {
5359
5437
  };
5360
5438
  var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageInfo = {}) => {
5361
5439
  if (!page || typeof page.context !== "function") {
5362
- logger11.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
5440
+ logger12.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
5363
5441
  return buffer;
5364
5442
  }
5365
5443
  const renderScope = await openProbePage(page);
5366
5444
  if (!renderScope?.page) {
5367
- logger11.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
5445
+ logger12.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
5368
5446
  return buffer;
5369
5447
  }
5370
5448
  try {
@@ -5407,13 +5485,13 @@ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageI
5407
5485
  fullPage: true,
5408
5486
  animations: "disabled"
5409
5487
  }).catch((error) => {
5410
- logger11.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
5488
+ logger12.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
5411
5489
  return null;
5412
5490
  });
5413
5491
  if (Buffer.isBuffer(composed) && composed.length > 0) {
5414
5492
  return composed;
5415
5493
  }
5416
- logger11.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
5494
+ logger12.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
5417
5495
  return buffer;
5418
5496
  } finally {
5419
5497
  await renderScope.close().catch(() => {
@@ -5426,7 +5504,7 @@ var resolveWithIpLookup = async (page, options = {}) => {
5426
5504
  }
5427
5505
  const probeScope = await openProbePage(page);
5428
5506
  if (!probeScope?.page) {
5429
- logger11.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
5507
+ logger12.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
5430
5508
  return null;
5431
5509
  }
5432
5510
  const timeoutMs = Math.max(
@@ -5435,12 +5513,12 @@ var resolveWithIpLookup = async (page, options = {}) => {
5435
5513
  );
5436
5514
  try {
5437
5515
  const probePage = probeScope.page;
5438
- logger11.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
5516
+ logger12.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
5439
5517
  const response = await probePage.goto(DEFAULT_IP_LOOKUP_URL, {
5440
5518
  waitUntil: "commit",
5441
5519
  timeout: timeoutMs
5442
5520
  }).catch((error) => {
5443
- logger11.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
5521
+ logger12.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
5444
5522
  return null;
5445
5523
  });
5446
5524
  const status = response && typeof response.status === "function" ? response.status() : 0;
@@ -5462,13 +5540,13 @@ var resolveWithIpLookup = async (page, options = {}) => {
5462
5540
  }
5463
5541
  const parsed = parseIpIpJsonResponse(rawText);
5464
5542
  if (parsed?.ip || parsed?.location) {
5465
- logger11.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
5543
+ logger12.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
5466
5544
  return parsed;
5467
5545
  }
5468
- logger11.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
5546
+ logger12.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
5469
5547
  return null;
5470
5548
  } catch (error) {
5471
- logger11.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
5549
+ logger12.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
5472
5550
  return null;
5473
5551
  } finally {
5474
5552
  await probeScope.close().catch(() => {
@@ -5482,10 +5560,10 @@ var resolveEnrichment = async (page, baseMeta, options) => {
5482
5560
  ip: toInline(options.ip, 80),
5483
5561
  location: toInline(options.location, 80)
5484
5562
  };
5485
- logger11.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
5563
+ logger12.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
5486
5564
  if (!merged.ip || !merged.location) {
5487
5565
  if (cached?.ip || cached?.location) {
5488
- logger11.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
5566
+ logger12.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
5489
5567
  }
5490
5568
  fillEnrichment(merged, cached);
5491
5569
  }
@@ -5509,15 +5587,15 @@ var resolveEnrichment = async (page, baseMeta, options) => {
5509
5587
  "x-geo-country"
5510
5588
  ]), 80);
5511
5589
  if (!merged.location || isWeakLocationValue(merged.location) && headerLocation) {
5512
- logger11.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
5590
+ logger12.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
5513
5591
  merged.location = headerLocation || merged.location;
5514
5592
  }
5515
5593
  }
5516
5594
  writeCachedEnrichment(page, merged);
5517
5595
  if (merged.ip || merged.location) {
5518
- logger11.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
5596
+ logger12.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
5519
5597
  } else {
5520
- logger11.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
5598
+ logger12.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
5521
5599
  }
5522
5600
  return merged;
5523
5601
  };
@@ -6185,7 +6263,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
6185
6263
  }
6186
6264
  const imageInfo = readImageInfo(buffer);
6187
6265
  if (!imageInfo.width || !imageInfo.height || !imageInfo.mimeType) {
6188
- logger11.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
6266
+ logger12.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
6189
6267
  return buffer;
6190
6268
  }
6191
6269
  const overlaySvg = buildWatermarkifySvg(meta, imageInfo.width, imageInfo.height);
@@ -6196,7 +6274,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
6196
6274
  };
6197
6275
 
6198
6276
  // src/share.js
6199
- var logger12 = createInternalLogger("Share");
6277
+ var logger13 = createInternalLogger("Share");
6200
6278
  var DEFAULT_TIMEOUT_MS2 = 50 * 1e3;
6201
6279
  var DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;
6202
6280
  var DEFAULT_POLL_INTERVAL_MS = 120;
@@ -6333,7 +6411,7 @@ var createDomShareMonitor = async (page, options = {}) => {
6333
6411
  const onMatch = typeof options.onMatch === "function" ? options.onMatch : null;
6334
6412
  const onTelemetry = typeof options.onTelemetry === "function" ? options.onTelemetry : null;
6335
6413
  let matched = false;
6336
- logger12.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
6414
+ logger13.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
6337
6415
  const monitor = await Mutation.useMonitor(page, selectors, {
6338
6416
  mode,
6339
6417
  onMutation: (context = {}) => {
@@ -6351,12 +6429,12 @@ ${text}`;
6351
6429
  });
6352
6430
  }
6353
6431
  if (mutationCount <= 5 || mutationCount % 50 === 0) {
6354
- logger12.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
6432
+ logger13.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
6355
6433
  }
6356
6434
  const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];
6357
6435
  if (!candidate) return;
6358
6436
  matched = true;
6359
- logger12.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
6437
+ logger13.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
6360
6438
  if (onMatch) {
6361
6439
  onMatch({
6362
6440
  link: candidate,
@@ -6372,7 +6450,7 @@ ${text}`;
6372
6450
  return {
6373
6451
  stop: async () => {
6374
6452
  const result = await monitor.stop();
6375
- logger12.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
6453
+ logger13.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
6376
6454
  return result;
6377
6455
  }
6378
6456
  };
@@ -6412,8 +6490,8 @@ var Share = {
6412
6490
  if (share.mode === "response" && apiMatchers.length === 0) {
6413
6491
  throw new Error("Share.captureLink requires share.xurl[0] api matcher when mode=response");
6414
6492
  }
6415
- logger12.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);
6416
- logger12.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
6493
+ logger13.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);
6494
+ logger13.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
6417
6495
  const stats = {
6418
6496
  actionTimedOut: false,
6419
6497
  domMutationCount: 0,
@@ -6438,7 +6516,7 @@ var Share = {
6438
6516
  link: validated,
6439
6517
  payloadText: String(payloadText || "")
6440
6518
  };
6441
- logger12.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
6519
+ logger13.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
6442
6520
  return true;
6443
6521
  };
6444
6522
  const resolveResponseCandidate = (responseText) => {
@@ -6473,7 +6551,7 @@ var Share = {
6473
6551
  try {
6474
6552
  await monitor.stop();
6475
6553
  } catch (error) {
6476
- logger12.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
6554
+ logger13.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
6477
6555
  }
6478
6556
  };
6479
6557
  const onResponse = async (response) => {
@@ -6486,29 +6564,29 @@ var Share = {
6486
6564
  stats.responseSampleUrls.push(url);
6487
6565
  }
6488
6566
  if (stats.responseObserved <= 5) {
6489
- logger12.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
6567
+ logger13.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
6490
6568
  }
6491
6569
  if (!apiMatchers.some((matcher) => url.includes(matcher))) return;
6492
6570
  stats.responseMatched += 1;
6493
6571
  stats.lastMatchedUrl = url;
6494
- logger12.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
6572
+ logger13.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
6495
6573
  const text = await response.text();
6496
6574
  const hit = resolveResponseCandidate(text);
6497
6575
  if (!hit?.link) {
6498
6576
  if (stats.responseMatched <= 3) {
6499
- logger12.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
6577
+ logger13.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
6500
6578
  }
6501
6579
  return;
6502
6580
  }
6503
6581
  stats.responseResolved += 1;
6504
- logger12.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
6582
+ logger13.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
6505
6583
  setCandidate("response", hit.link, hit.payloadText);
6506
6584
  } catch (error) {
6507
- logger12.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
6585
+ logger13.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
6508
6586
  }
6509
6587
  };
6510
6588
  if (share.mode === "dom") {
6511
- logger12.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
6589
+ logger13.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
6512
6590
  domMonitor = await createDomShareMonitor(page, {
6513
6591
  prefix: share.prefix,
6514
6592
  selectors: domSelectors,
@@ -6523,14 +6601,14 @@ var Share = {
6523
6601
  });
6524
6602
  }
6525
6603
  if (share.mode === "response") {
6526
- logger12.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
6604
+ logger13.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
6527
6605
  page.on("response", onResponse);
6528
6606
  }
6529
6607
  const deadline = Date.now() + timeoutMs;
6530
6608
  const getRemainingMs = () => Math.max(0, deadline - Date.now());
6531
6609
  try {
6532
6610
  const actionTimeout = getRemainingMs();
6533
- logger12.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);
6611
+ logger13.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);
6534
6612
  if (actionTimeout > 0) {
6535
6613
  let timer = null;
6536
6614
  let actionError = null;
@@ -6544,21 +6622,21 @@ var Share = {
6544
6622
  const actionResult = await Promise.race([actionPromise, timeoutPromise]);
6545
6623
  if (timer) clearTimeout(timer);
6546
6624
  if (actionResult === "__ACTION_ERROR__") {
6547
- logger12.fail("captureLink.performActions", actionError);
6625
+ logger13.fail("captureLink.performActions", actionError);
6548
6626
  throw actionError;
6549
6627
  }
6550
6628
  if (actionResult === "__ACTION_TIMEOUT__") {
6551
6629
  stats.actionTimedOut = true;
6552
- logger12.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
6630
+ logger13.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
6553
6631
  } else {
6554
- logger12.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
6632
+ logger13.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
6555
6633
  }
6556
6634
  }
6557
6635
  let nextProgressLogTs = Date.now() + 3e3;
6558
6636
  while (true) {
6559
6637
  const selected = share.mode === "dom" ? candidates.dom : candidates.response;
6560
6638
  if (selected?.link) {
6561
- logger12.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
6639
+ logger13.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
6562
6640
  return {
6563
6641
  link: selected.link,
6564
6642
  payloadText: selected.payloadText,
@@ -6570,7 +6648,7 @@ var Share = {
6570
6648
  if (remaining <= 0) break;
6571
6649
  const now = Date.now();
6572
6650
  if (now >= nextProgressLogTs) {
6573
- logger12.info(
6651
+ logger13.info(
6574
6652
  `captureLink \u7B49\u5F85\u4E2D: remaining=${remaining}ms, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`
6575
6653
  );
6576
6654
  nextProgressLogTs = now + 5e3;
@@ -6578,11 +6656,11 @@ var Share = {
6578
6656
  await (0, import_delay2.default)(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
6579
6657
  }
6580
6658
  if (share.mode === "response" && stats.responseMatched === 0) {
6581
- logger12.warning(
6659
+ logger13.warning(
6582
6660
  `\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`
6583
6661
  );
6584
6662
  }
6585
- logger12.warning(
6663
+ logger13.warning(
6586
6664
  `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"}`
6587
6665
  );
6588
6666
  return {
@@ -6594,7 +6672,7 @@ var Share = {
6594
6672
  } finally {
6595
6673
  if (share.mode === "response") {
6596
6674
  page.off("response", onResponse);
6597
- logger12.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
6675
+ logger13.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
6598
6676
  }
6599
6677
  await stopDomMonitor();
6600
6678
  }