From 71cb370ce92dfbfce7c33338804e4f29bb94cf5b Mon Sep 17 00:00:00 2001 From: samc621 Date: Sun, 8 Aug 2021 12:38:23 -0400 Subject: [PATCH 1/3] usinng recaptchaV2 helper --- sites/shopify.js | 4 ++-- sites/supremenewyork.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sites/shopify.js b/sites/shopify.js index eab2e5e..5c036d2 100644 --- a/sites/shopify.js +++ b/sites/shopify.js @@ -1,4 +1,4 @@ -const { solveCaptcha } = require('../helpers/captcha'); +const { solveReCAPTCHAV2 } = require('../helpers/captcha'); const { sendEmail } = require('../helpers/email'); const { getCardDetailsByFriendlyName } = require('../helpers/credit-cards'); @@ -120,7 +120,7 @@ async function checkout({ if (hasCaptcha) { if (autoSolveCaptchas) { - const solved = await solveCaptcha({ + const solved = await solveReCAPTCHAV2({ taskLogger, page, captchaSelector }); if (solved) hasCaptcha = false; diff --git a/sites/supremenewyork.js b/sites/supremenewyork.js index 1358a6d..9fef64d 100644 --- a/sites/supremenewyork.js +++ b/sites/supremenewyork.js @@ -1,4 +1,4 @@ -const { solveCaptcha } = require('../helpers/captcha'); +const { solveReCAPTCHAV2 } = require('../helpers/captcha'); const { sendEmail } = require('../helpers/email'); const { getCardDetailsByFriendlyName } = require('../helpers/credit-cards'); @@ -157,7 +157,7 @@ async function checkout({ if (hasCaptcha) { if (autoSolveCaptchas) { - const solved = await solveCaptcha({ + const solved = await solveReCAPTCHAV2({ taskLogger, page, captchaSelector }); if (solved) hasCaptcha = false; From 7dc7ab6a9d3d512de4452277b5a181faef5a2880 Mon Sep 17 00:00:00 2001 From: samc621 Date: Sun, 8 Aug 2021 12:38:31 -0400 Subject: [PATCH 2/3] adding support for geetest --- helpers/captcha.js | 90 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 5 deletions(-) diff --git a/helpers/captcha.js b/helpers/captcha.js index 1652a64..a1c23f9 100644 --- a/helpers/captcha.js +++ b/helpers/captcha.js @@ -2,7 +2,7 @@ const rp = require('request-promise'); const apiKey = process.env.API_KEY_2CAPTCHA; -async function submitCaptcha(googleKey, pageUrl) { +async function submitReCAPTCHAV2(googleKey, pageUrl) { try { const options = { uri: `http://2captcha.com/in.php?key=${apiKey}&method=userrecaptcha&googlekey=${googleKey}&pageurl=${pageUrl}&json=1`, @@ -21,6 +21,27 @@ async function submitCaptcha(googleKey, pageUrl) { } } +async function submitGeeTest(gt, challenge, api_server, pageUrl) { + try { + const options = { + uri: ` + http://2captcha.com/in.php?key=${apiKey}&method=geetest>=${gt}&challenge=${challenge}&api_server=${api_server}&pageurl=${pageUrl}&json=1 + `, + method: 'POST' + }; + + const response = await rp(options); + const responseJson = JSON.parse(response); + if (responseJson.status) { + return responseJson; + } + + throw new Error(responseJson.error_text); + } catch (err) { + throw err; + } +} + async function getCaptchaResult(captchaId) { try { const options = { @@ -40,7 +61,7 @@ async function getCaptchaResult(captchaId) { } } -exports.solveCaptcha = async ({ +exports.solveReCAPTCHAV2 = async ({ taskLogger, page, captchaSelector, captchaIframeSelector }) => { try { @@ -66,7 +87,7 @@ exports.solveCaptcha = async ({ }, { captchaSelector, captchaIframeSelector }); taskLogger.info(`Extracted googleKey ${googleKey}`); - const captcha = await submitCaptcha(googleKey, context.url()); + const captcha = await submitReCAPTCHAV2(googleKey, context.url()); const captchaId = captcha.request; taskLogger.info(`Submitted captcha to 2captcha, got id ${captchaId}`); @@ -75,13 +96,14 @@ exports.solveCaptcha = async ({ while (!solved) { try { const result = await getCaptchaResult(captchaId); - if (result && result.request) { + if (result && result.request && result.status !== 0) { captchaAnswer = result.request; solved = true; } } catch (err) { - await page.waitForTimeout(1000); + // no-op } + await page.waitForTimeout(1000); } if (captchaAnswer) { @@ -144,3 +166,61 @@ exports.solveCaptcha = async ({ throw err; } }; + +exports.solveGeeTest = async ({ taskLogger, page, captchaIframeSelector }) => { + try { + taskLogger.info('Detected captcha, solving'); + + if (!apiKey) { + throw new Error('You must set an API_KEY_2CAPTCHA in your .env file.'); + } + + let context = page; + if (captchaIframeSelector) { + const frameHandle = await page.$(captchaIframeSelector); + context = await frameHandle.contentFrame(); + } + + const iframeUrl = context.url(); + taskLogger.info(`Geetest iframe URL: ${iframeUrl}`); + const pageHtml = await rp(iframeUrl); + const [api_server, gt, challenge] = pageHtml + .split('initGeetest({').pop().split('}, handlerEmbed')[0] + .split(/:|,/) + .filter((e, i) => i % 2 !== 0) + .map((val) => val.trim().replace(/'/g, '')); + taskLogger.info(`Extracted gt ${gt}, challenge ${challenge}, api_server ${api_server}, pageurl=${page.url()}`); + + const captcha = await submitGeeTest(gt, challenge, api_server, page.url()); + const captchaId = captcha.request; + taskLogger.info(`Submitted captcha to 2captcha, got id ${captchaId}`); + + let solved = false; + let captchaAnswer; + while (!solved) { + try { + const result = await getCaptchaResult(captchaId); + if (result && result.request && result.status !== 0) { + captchaAnswer = result.request; + solved = true; + } + } catch (err) { + // no-op + } + await page.waitForTimeout(1000); + } + + if (captchaAnswer) { + taskLogger.info(`Got captcha result ${JSON.stringify(captchaAnswer)} from 2captcha, submitting`); + + await context.evaluate((captchaAnswerObj) => { + window.geetestResponse = captchaAnswerObj; + window.captchaCallback(); + }, captchaAnswer); + } + const submissionSucccess = true; + return submissionSucccess; + } catch (err) { + throw err; + } +}; From 5256c5bbaa95efa826909d72b6836147be23e1c7 Mon Sep 17 00:00:00 2001 From: samc621 Date: Sun, 8 Aug 2021 12:38:38 -0400 Subject: [PATCH 3/3] using geetest helper --- sites/footsites.js | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/sites/footsites.js b/sites/footsites.js index da3ceed..e860369 100644 --- a/sites/footsites.js +++ b/sites/footsites.js @@ -1,4 +1,4 @@ -const { solveCaptcha } = require('../helpers/captcha'); +const { solveGeeTest } = require('../helpers/captcha'); const { sendEmail } = require('../helpers/email'); const { getCardDetailsByFriendlyName } = require('../helpers/credit-cards'); @@ -253,7 +253,7 @@ async function checkout({ async function closeModal({ taskLogger, page }) { try { const modalSelector = 'div#bluecoreActionScreen'; - await page.waitForSelector(modalSelector, { visible: true }); + await page.waitForSelector(modalSelector, { visible: true, timeout: 0 }); const modal = await page.$(modalSelector); taskLogger.info('Closing modal'); await modal.evaluate(() => { @@ -364,45 +364,49 @@ exports.guestCheckout = async ({ const atcButtonSelector = 'button.Button.Button.ProductDetails-form__action'; await page.waitForSelector(atcButtonSelector, { timeout: 0 }); await page.click(atcButtonSelector); + taskLogger.info('Clicked ATC button'); await page.waitForTimeout(2000); const captchaIframeSelector = 'iframe#dataDomeCaptcha'; - const captchaSelector = 'div.g-recaptcha'; const cartSelector = 'span.CartCount-badge'; await Promise.race([ (async () => { try { - hasCaptcha = await page.waitForSelector(captchaIframeSelector, { timeout: 10 * 1000 }); + hasCaptcha = await page.waitForSelector(captchaIframeSelector); } catch (err) { // no-op if timeout occurs } })(), (async () => { try { - await page.waitForSelector(cartSelector, { timeout: 5 * 1000 }); + await page.waitForSelector(cartSelector); } catch (err) { - taskLogger.info('Retrying clicking ATC button'); - await page.click(atcButtonSelector); - await page.waitForTimeout(2000); + if (!hasCaptcha) { + taskLogger.info('Retrying clicking ATC button'); + await page.click(atcButtonSelector); + await page.waitForTimeout(2000); + } } - taskLogger.info('Checking if ATC was successful'); - const cartCount = await page.evaluate((cartTextSelector) => { - const elem = document.querySelector(cartTextSelector); - return (elem && elem.innerText) || '0'; - }, cartSelector); + if (!hasCaptcha) { + taskLogger.info('Checking if ATC was successful'); + const cartCount = await page.evaluate((cartTextSelector) => { + const elem = document.querySelector(cartTextSelector); + return (elem && elem.innerText) || '0'; + }, cartSelector); - if (parseInt(cartCount) === 1) { - isInCart = true; + if (parseInt(cartCount) === 1) { + isInCart = true; + } } })() ]); if (hasCaptcha) { if (autoSolveCaptchas) { - const solved = await solveCaptcha({ - taskLogger, page, captchaSelector, captchaIframeSelector + const solved = await solveGeeTest({ + taskLogger, page, captchaIframeSelector }); if (solved) hasCaptcha = false; } else { @@ -410,7 +414,7 @@ exports.guestCheckout = async ({ const recipient = notificationEmailAddress; const subject = 'Checkout task unsuccessful'; const text = `The checkout task for ${url} size ${size} has a captcha. Please open the browser and complete it within 5 minutes.`; - await sendEmail(recipient, subject, text); + await sendEmail({ recipient, subject, text }); taskLogger.info(text); try {