@skrillex1224/playwright-toolkit 3.0.52 → 3.0.54

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
@@ -6769,6 +6769,167 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
6769
6769
  }
6770
6770
  var sloveCaptcha = solveCaptcha;
6771
6771
 
6772
+ // src/internals/captcha/qbot_chaptcha.js
6773
+ var QBOT_CAPTCHA_TYPE = "30119";
6774
+ var QBOT_IMAGE_BASE_WIDTH = 310;
6775
+ var QBOT_IMAGE_BASE_HEIGHT = 155;
6776
+ var DEFAULT_QBOT_PAGE_OPTIONS = Object.freeze({
6777
+ formSelector: 'xpath=//*[@id="seccodeForm"]',
6778
+ imageSelector: 'xpath=//*[@id="seccodeForm"]//img',
6779
+ extraSelector: 'xpath=//*[@id="seccodeForm"]//*[@class="verify-bar-area"]/span',
6780
+ submitSelector: 'xpath=//*[@id="submit"]',
6781
+ refreshSelector: 'xpath=//*[@class="verify-refresh"]',
6782
+ formVisibleTimeoutMs: 1e4,
6783
+ imageVisibleTimeoutMs: 1e4,
6784
+ extraVisibleTimeoutMs: 5e3,
6785
+ payloadReadyTimeoutMs: 1e4,
6786
+ payloadPollIntervalMs: 200,
6787
+ vcSelector: "#vc",
6788
+ vcValueTimeoutMs: 8e3,
6789
+ submitLoadTimeoutMs: 3e4,
6790
+ coordinateBaseWidth: QBOT_IMAGE_BASE_WIDTH,
6791
+ coordinateBaseHeight: QBOT_IMAGE_BASE_HEIGHT,
6792
+ clickIntervalMs: 250,
6793
+ refreshVisibleTimeoutMs: 1e3,
6794
+ refreshWaitMs: 1e3,
6795
+ maxRetries: 3
6796
+ });
6797
+ var normalizeQbotCaptchaImage = (src = "") => String(src || "").split(",").pop().trim();
6798
+ var extractQbotCaptchaExtra = (text = "") => {
6799
+ const content = String(text || "").match(/【([^】]+)】/)?.[1] || "";
6800
+ return content.split(/[,,]/).map((item) => item.trim()).filter(Boolean);
6801
+ };
6802
+ var parseQbotCaptchaCoordinates = (value = "") => String(value || "").split("|").map((pair) => {
6803
+ const [x, y] = pair.split(",").map(Number);
6804
+ return Number.isFinite(x) && Number.isFinite(y) ? { x, y } : null;
6805
+ }).filter(Boolean);
6806
+ var normalizeQbotCaptchaExtraPayload = (extra = []) => Array.isArray(extra) ? extra.join(",") : String(extra || "");
6807
+ async function solveQbotCaptcha(image, extra = [], token, options = {}, dependencies = {}) {
6808
+ const { callCaptchaRecognitionApi: callCaptchaRecognitionApi2 } = dependencies;
6809
+ if (!token) {
6810
+ throw new Error("[Captcha] \u7F3A\u5C11 qbot \u9A8C\u8BC1\u7801 token\u3002");
6811
+ }
6812
+ if (typeof callCaptchaRecognitionApi2 !== "function") {
6813
+ throw new Error("[Captcha] \u7F3A\u5C11\u901A\u7528\u8BC6\u522B\u8BF7\u6C42\u51FD\u6570 callCaptchaRecognitionApi\u3002");
6814
+ }
6815
+ const response = await callCaptchaRecognitionApi2({
6816
+ apiUrl: options.apiUrl,
6817
+ token,
6818
+ type: QBOT_CAPTCHA_TYPE,
6819
+ image,
6820
+ extra: normalizeQbotCaptchaExtraPayload(extra)
6821
+ });
6822
+ return response?.data?.data ?? response?.data;
6823
+ }
6824
+ var readQbotCaptcha = async (page, config) => {
6825
+ const imageLocator = page.locator(config.imageSelector).first();
6826
+ await imageLocator.waitFor({ state: "visible", timeout: config.imageVisibleTimeoutMs });
6827
+ const extraLocator = page.locator(config.extraSelector).first();
6828
+ await extraLocator.waitFor({ state: "visible", timeout: config.extraVisibleTimeoutMs });
6829
+ const deadline = Date.now() + config.payloadReadyTimeoutMs;
6830
+ let image = "";
6831
+ let extra = [];
6832
+ while (Date.now() <= deadline) {
6833
+ image = normalizeQbotCaptchaImage(await imageLocator.getAttribute("src"));
6834
+ extra = extractQbotCaptchaExtra(await extraLocator.textContent());
6835
+ if (image && extra.length > 0) {
6836
+ return { imageLocator, image, extra };
6837
+ }
6838
+ await page.waitForTimeout(config.payloadPollIntervalMs);
6839
+ }
6840
+ if (!image) {
6841
+ throw new Error("[Captcha] qbot \u9A8C\u8BC1\u7801\u56FE\u7247\u4E3A\u7A7A\u3002");
6842
+ }
6843
+ if (extra.length === 0) {
6844
+ throw new Error("[Captcha] qbot \u9A8C\u8BC1\u7801 extra \u4E3A\u7A7A\u3002");
6845
+ }
6846
+ return { imageLocator, image, extra };
6847
+ };
6848
+ var clickQbotPoints = async (page, imageLocator, coordinates, config, deviceInput) => {
6849
+ const box = await imageLocator.boundingBox();
6850
+ if (!box) {
6851
+ throw new Error("[Captcha] qbot \u9A8C\u8BC1\u7801\u56FE\u7247\u4F4D\u7F6E\u4E0D\u53EF\u7528\u3002");
6852
+ }
6853
+ const scaleX = box.width / config.coordinateBaseWidth;
6854
+ const scaleY = box.height / config.coordinateBaseHeight;
6855
+ for (const point of coordinates) {
6856
+ await deviceInput.clickPoint(page, {
6857
+ x: box.x + point.x * scaleX,
6858
+ y: box.y + point.y * scaleY
6859
+ }, config);
6860
+ if (config.clickIntervalMs > 0) {
6861
+ await page.waitForTimeout(config.clickIntervalMs);
6862
+ }
6863
+ }
6864
+ };
6865
+ var refreshQbotCaptcha = async (page, config, deviceInput, logger18) => {
6866
+ try {
6867
+ const refreshLocator = page.locator(config.refreshSelector).first();
6868
+ if (!await waitForVisible(refreshLocator, config.refreshVisibleTimeoutMs)) return;
6869
+ await deviceInput.click(page, refreshLocator, { ...config, fallbackDomClick: true });
6870
+ if (config.refreshWaitMs > 0) {
6871
+ await page.waitForTimeout(config.refreshWaitMs);
6872
+ }
6873
+ } catch (error) {
6874
+ logger18?.warn?.(`[Captcha] qbot \u9A8C\u8BC1\u7801\u5237\u65B0\u5931\u8D25\uFF0C\u7EE7\u7EED\u629B\u51FA\u539F\u9519\u8BEF\uFF1A${error?.message || error}`);
6875
+ }
6876
+ };
6877
+ var solveQbotCaptchaAttempt = async (page, config, dependencies) => {
6878
+ const { callCaptchaRecognitionApi: callCaptchaRecognitionApi2, deviceInput } = dependencies;
6879
+ const { imageLocator, image, extra } = await readQbotCaptcha(page, config);
6880
+ const coordinateText = await solveQbotCaptcha(image, extra, config.token, config, {
6881
+ callCaptchaRecognitionApi: callCaptchaRecognitionApi2
6882
+ });
6883
+ const coordinates = parseQbotCaptchaCoordinates(coordinateText);
6884
+ if (coordinates.length === 0) {
6885
+ throw new Error("[Captcha] qbot \u9A8C\u8BC1\u7801\u5750\u6807\u4E3A\u7A7A\u3002");
6886
+ }
6887
+ await clickQbotPoints(page, imageLocator, coordinates, config, deviceInput);
6888
+ await page.waitForFunction(
6889
+ (selector) => Boolean(document.querySelector(selector)?.value),
6890
+ config.vcSelector,
6891
+ { timeout: config.vcValueTimeoutMs }
6892
+ );
6893
+ await deviceInput.click(page, page.locator(config.submitSelector).first(), {
6894
+ ...config,
6895
+ fallbackDomClick: true
6896
+ });
6897
+ await page.waitForLoadState("domcontentloaded", { timeout: config.submitLoadTimeoutMs }).catch(() => {
6898
+ });
6899
+ return true;
6900
+ };
6901
+ async function solveCaptcha2(page, options = {}, dependencies = {}) {
6902
+ const config = { ...DEFAULT_QBOT_PAGE_OPTIONS, ...options };
6903
+ const logger18 = dependencies.logger || options.logger;
6904
+ const deviceInput = dependencies.deviceInput || DeviceInput;
6905
+ if (!config.token) {
6906
+ logger18?.warn?.("[Captcha] \u7F3A\u5C11 qbot \u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
6907
+ return false;
6908
+ }
6909
+ const formLocator = page.locator(config.formSelector).first();
6910
+ if (!await waitForVisible(formLocator, config.formVisibleTimeoutMs)) {
6911
+ return false;
6912
+ }
6913
+ const maxRetries = Math.max(1, Number(config.maxRetries) || 1);
6914
+ let lastError = null;
6915
+ for (let attempt = 1; attempt <= maxRetries; attempt += 1) {
6916
+ try {
6917
+ return await solveQbotCaptchaAttempt(page, config, {
6918
+ ...dependencies,
6919
+ deviceInput
6920
+ });
6921
+ } catch (error) {
6922
+ lastError = error;
6923
+ logger18?.warn?.(`[Captcha] qbot \u9A8C\u8BC1\u7801\u8BC6\u522B\u7B2C ${attempt}/${maxRetries} \u6B21\u5931\u8D25\uFF1A${error?.message || error}`);
6924
+ if (attempt < maxRetries) {
6925
+ await refreshQbotCaptcha(page, config, deviceInput, logger18);
6926
+ }
6927
+ }
6928
+ }
6929
+ throw lastError;
6930
+ }
6931
+ var sloveCaptcha2 = solveCaptcha2;
6932
+
6772
6933
  // src/chaptcha.js
6773
6934
  var logger13 = createInternalLogger("Captcha");
6774
6935
  var DOM_MONITOR_WAIT_TIMEOUT_MS = 1e3;
@@ -6781,6 +6942,9 @@ var DEFAULT_CAPTCHA_RECOGNITION_OPTIONS = Object.freeze({
6781
6942
  var CAPTCHA_STRATEGIES = Object.freeze({
6782
6943
  bytedance: {
6783
6944
  sloveCaptcha
6945
+ },
6946
+ qbot: {
6947
+ sloveCaptcha: sloveCaptcha2
6784
6948
  }
6785
6949
  });
6786
6950
  var mergeDefinedOptions = (...sources) => {
@@ -6925,9 +7089,15 @@ async function solveCaptchaWithStrategy(strategyName, page, options = {}) {
6925
7089
  logger: logger13
6926
7090
  });
6927
7091
  }
7092
+ async function solveQbotCaptcha2(image, extra = [], token, options = {}) {
7093
+ return solveQbotCaptcha(image, extra, token, options, {
7094
+ callCaptchaRecognitionApi
7095
+ });
7096
+ }
6928
7097
  var Captcha = {
6929
7098
  useCaptchaMonitor,
6930
- solveCaptchaWithStrategy
7099
+ solveCaptchaWithStrategy,
7100
+ solveQbotCaptcha: solveQbotCaptcha2
6931
7101
  };
6932
7102
 
6933
7103
  // src/mutation.js