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