From 3766754a5fbed1c22fcd3145b47e7d6f8d2ad9ed Mon Sep 17 00:00:00 2001 From: Ralf Vogler Date: Wed, 2 Feb 2022 12:50:53 +0100 Subject: [PATCH] epic-games: catch timeout and save screenshot of hcaptcha --- .gitignore | 1 + README.md | 6 ++++-- epic-games.js | 21 +++++++++++++++------ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 8d0833c..b2ff24b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules/ auth.json .env userDataDir/ +screenshots/ diff --git a/README.md b/README.md index 3d782f0..410eec1 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Claiming the Amazon Games works, external Epic Games also work if the account is Origin needs testing - it shows a key, which should be printed to the console, but the selector may be wrong. Other stores not tested. -## Log +## DevLog Tried [epicgames-freebies-claimer](https://github.com/Revadike/epicgames-freebies-claimer), but does not work anymore since epicgames introduced hcaptcha (see [issue](https://github.com/Revadike/epicgames-freebies-claimer/issues/172)). @@ -43,7 +43,7 @@ Also, solving via [2captcha](https://2captcha.com?from=13225256) is a paid servi Added [main.stealth.js](https://github.com/vogler/epicgames-claimer/commit/64d0ba8ce71baec3947d1b64acd567befcb39340#diff-f70d3bd29df4a343f11062a97063953173491ce30fe34f69a0fc52517adbf342) which uses the stealth plugin without `playwright-extra` wrapper but up-to-date `playwright` (from [comment](https://github.com/berstend/puppeteer-extra/issues/454#issuecomment-917437212)). -The listed evasions are enough to not show an hcaptcha. Script claimed game successfully in headful mode. +The listed evasions are enough to not show an hcaptcha. Script claimed game successfully in non-headless mode. Removed `main.captcha.js`. Using Playwright Test (`main.spec.ts`) instead of Library (`main.stealth.js`) has the advantage of free CLI like `--debug` and `--timeout`. @@ -52,3 +52,5 @@ Using Playwright Test (`main.spec.ts`) instead of Library (`main.stealth.js`) ha Button selectors should preferably use text in order to be more stable against changes in the DOM. Renamed repository from epicgames-claimer to free-games-claimer since a script for Amazon Prime Gaming was also added. Removed all old scripts in favor of just `epic-games.js` and `prime-gaming.js`. + +epic games: `headless` mode gets hcaptcha challenge. More details/references in [issue](https://github.com/vogler/free-games-claimer/issues/2). diff --git a/epic-games.js b/epic-games.js index 83984b3..d67053c 100644 --- a/epic-games.js +++ b/epic-games.js @@ -1,7 +1,7 @@ //@ts-check const { chromium } = require('playwright'); // stealth plugin needs no outdated playwright-extra const path = require('path'); -const debug = process.env.PWDEBUG == '1'; // runs headful and opens https://playwright.dev/docs/inspector +const debug = process.env.PWDEBUG == '1'; // runs non-headless and opens https://playwright.dev/docs/inspector const URL_LOGIN = 'https://www.epicgames.com/login'; const URL_CLAIM = 'https://www.epicgames.com/store/en-US/free-games'; @@ -64,7 +64,7 @@ const TIMEOUT = 20 * 1000; // 20s, default is 30s await page.goto(URL_CLAIM, {waitUntil: 'domcontentloaded'}); // default 'load' takes forever // with persistent context the cookie message will only show up the first time, so we can't unconditionally wait for it - try to catch it or let the user click it. await clickIfExists('button:has-text("Accept All Cookies")'); // to not waste screen space in --debug - while (await page.locator('a[role="button"]:has-text("Sign In")').count() > 0) { + while (await page.locator('a[role="button"]:has-text("Sign In")').count() > 0) { // TODO also check alternative for signed-in state console.error("Not signed in anymore. Please login and then navigate to the 'Free Games' page."); context.setDefaultTimeout(0); // give user time to log in without timeout await page.goto(URL_LOGIN, {waitUntil: 'domcontentloaded'}); @@ -96,7 +96,6 @@ const TIMEOUT = 20 * 1000; // 20s, default is 30s console.log('Not in library yet! Click GET.') await page.click('[data-testid="purchase-cta-button"]'); // click Continue if 'Device not supported. This product is not compatible with your current device.' - // await page.waitForTimeout(1000); // wait for 1s since count does not wait. // @ts-ignore https://caniuse.com/?search=promise.any await Promise.any([':has-text("Continue")', '#webPurchaseContainer iframe'].map(s => page.waitForSelector(s))); // wait for Continue xor iframe if (await page.locator(':has-text("Continue")').count() > 0) { @@ -107,15 +106,25 @@ const TIMEOUT = 20 * 1000; // 20s, default is 30s // await page.frame({ url: /.*store\/purchase.*/ }).click('button:has-text("Place Order")'); // not found because it does not wait for iframe const iframe = page.frameLocator('#webPurchaseContainer iframe') await iframe.locator('button:has-text("Place Order")').click(); + // await page.pause(); await iframe.locator('button:has-text("I Agree")').click(); - // This is true even when there is no captcha shown! That was the reason why old.stealth.js worked - it did not have this check... TODO check for hcaptcha + // This is true even when there is no captcha challenge shown! That was the reason why old.stealth.js worked - it did not have this check... TODO check for hcaptcha // if (await iframe.frameLocator('#talon_frame_checkout_free_prod').locator('text=Please complete a security check to continue').count() > 0) { // console.error('Encountered hcaptcha. Giving up :('); // await page.pause(); // process.exit(1); // } - await page.waitForSelector('text=Thank you for buying'); - console.log('Claimed successfully!'); + // await page.waitForTimeout(3000); + try { + await page.waitForSelector('text=Thank you for buying'); + console.log('Claimed successfully!'); + } catch (e) { + console.log(e); + const p = `screenshots/${new Date().toISOString()}.png`; + await page.screenshot({ path: p, fullPage: true }) + console.info('Saved a screenshot of hcaptcha challenge to', p); + console.error('Got hcaptcha challenge. To avoid it, get a link from https://www.hcaptcha.com/accessibility'); // TODO save this link in config and visit it daily to set accessibility cookie to avoid captcha challenge? + } // await page.pause(); } if (i