rename repo epicgames-claimer -> free-games-claimer, cleanup, comments
This commit is contained in:
parent
dc6414129b
commit
38b074384d
4 changed files with 31 additions and 108 deletions
39
README.md
39
README.md
|
|
@ -1,15 +1,34 @@
|
||||||
# epicgames-claimer
|
# free-games-claimer
|
||||||
## usage
|
## Usage
|
||||||
|
|
||||||
Setup: `npm install && npx playwright install` (downloads {chromium, firefox, webkit} (742 MB) to cache in home ([doc](https://playwright.dev/docs/browsers#managing-browser-binaries))).
|
Setup: `npm install && npx playwright install`
|
||||||
|
|
||||||
|
This downloads {chromium, firefox, webkit} (742 MB) to a cache in home ([doc](https://playwright.dev/docs/browsers#managing-browser-binaries)).
|
||||||
|
|
||||||
<!-- Use `npm run login` which opens a browser where you can login. When closing the browser, it writes a file `auth.json` containing cookies that should keep you logged in for some time (`expires` in a month?). -->
|
<!-- Use `npm run login` which opens a browser where you can login. When closing the browser, it writes a file `auth.json` containing cookies that should keep you logged in for some time (`expires` in a month?). -->
|
||||||
|
|
||||||
Use `npm start` to start Chrome to claim the current free games.
|
So far, claiming free games has only been implemented for the two stores below.
|
||||||
The first time, the script will wait for you to login. Instead of redirecting back, the website seems to just reload the login URL. Go to https://www.epicgames.com/store/en-US/free-games manually, or restart the script.
|
Both start an automated Chrome instance. It will first check if you are logged in, and if not wait for you to do so. After login, you can also restart the script if it does not redirect back.
|
||||||
If something goes wrong, use `PWDEBUG=1 npm start` to [inspect](https://playwright.dev/docs/inspector).
|
|
||||||
|
|
||||||
## log
|
If something goes wrong, use `PWDEBUG=1 node epic-games` to [inspect](https://playwright.dev/docs/inspector).
|
||||||
|
|
||||||
|
Ideally, claiming would run in *headless mode* (without browser GUI - comment out `headless: false` to test), and on a RPi:
|
||||||
|
- Epic Games Store detects running in headless mode (despite stealth plugin) and gets stuck with a captcha challenge. Did not test it yet for Prime Gaming.
|
||||||
|
- Playwright seems to not run on (headless) RPi?
|
||||||
|
|
||||||
|
### Epic Games Store
|
||||||
|
Command: `node epic-games`
|
||||||
|
|
||||||
|
Login: Instead of redirecting back, the website seems to just reload the login URL. Go to https://www.epicgames.com/store/en-US/free-games manually, or restart the script.
|
||||||
|
|
||||||
|
### Amazon Prime Gaming
|
||||||
|
Command: `node prime-gaming`
|
||||||
|
|
||||||
|
Claiming the Amazon Games works, external Epic Games also work if the account is linked.
|
||||||
|
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
|
||||||
|
|
||||||
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)).
|
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)).
|
||||||
|
|
||||||
|
|
@ -28,4 +47,8 @@ The listed evasions are enough to not show an hcaptcha. Script claimed game succ
|
||||||
|
|
||||||
Removed `main.captcha.js`.
|
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`.
|
Using Playwright Test (`main.spec.ts`) instead of Library (`main.stealth.js`) has the advantage of free CLI like `--debug` and `--timeout`.
|
||||||
TODO: check if stealth plugin can be setup with `contextOptions` ([doc](https://playwright.dev/docs/test-configuration#more-browser-and-context-options)).
|
<!-- TODO: check if stealth plugin can be setup with `contextOptions` ([doc](https://playwright.dev/docs/test-configuration#more-browser-and-context-options)). -->
|
||||||
|
|
||||||
|
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`.
|
||||||
|
|
|
||||||
26
main.spec.ts
26
main.spec.ts
|
|
@ -1,26 +0,0 @@
|
||||||
import { test, expect } from '@playwright/test'; // only npm dep needed for this file
|
|
||||||
import { existsSync } from 'fs';
|
|
||||||
|
|
||||||
if (!existsSync('auth.json')) {
|
|
||||||
console.error('Missing auth.json! Use `npm run login` to login and create this file by closing the opened browser.');
|
|
||||||
}
|
|
||||||
test.use({
|
|
||||||
storageState: 'auth.json',
|
|
||||||
viewport: { width: 1280, height: 1280 },
|
|
||||||
});
|
|
||||||
|
|
||||||
test('claim game', async ({ page }) => {
|
|
||||||
await page.goto('https://www.epicgames.com/store/en-US/free-games');
|
|
||||||
await expect(page.locator('a[role="button"]:has-text("Sign In")')).toHaveCount(0);
|
|
||||||
await page.click('button:has-text("Accept All Cookies")'); // to not waste screen space in --debug
|
|
||||||
await page.click('[data-testid="offer-card-image-landscape"]');
|
|
||||||
// TODO check if already claimed
|
|
||||||
await page.click('[data-testid="purchase-cta-button"]');
|
|
||||||
await page.click('button:has-text("Continue")');
|
|
||||||
// it then creates an iframe for the rest
|
|
||||||
// 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 iframe.locator('button:has-text("I Agree")').click();
|
|
||||||
await page.pause();
|
|
||||||
});
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
const { existsSync } = require('fs');
|
|
||||||
if (!existsSync('auth.json')) {
|
|
||||||
console.error('Missing auth.json! Run `npm login` to login and create this file by closing the opened browser.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const { chromium } = require('playwright');
|
|
||||||
|
|
||||||
(async () => {
|
|
||||||
const browser = await chromium.launch({
|
|
||||||
channel: 'chrome',
|
|
||||||
headless: false,
|
|
||||||
});
|
|
||||||
// https://github.com/berstend/puppeteer-extra/issues/454#issuecomment-917437212
|
|
||||||
const originalUserAgent = await (await (await browser.newContext()).newPage()).evaluate(() => { return navigator.userAgent });
|
|
||||||
console.log(originalUserAgent);
|
|
||||||
const context = await browser.newContext({
|
|
||||||
storageState: 'auth.json',
|
|
||||||
viewport: { width: 1280, height: 1280 },
|
|
||||||
userAgent: originalUserAgent.replace("Headless", ""),
|
|
||||||
});
|
|
||||||
const enabledEvasions = [
|
|
||||||
'chrome.app',
|
|
||||||
'chrome.csi',
|
|
||||||
'chrome.loadTimes',
|
|
||||||
'chrome.runtime',
|
|
||||||
'iframe.contentWindow',
|
|
||||||
'media.codecs',
|
|
||||||
'navigator.hardwareConcurrency',
|
|
||||||
'navigator.languages',
|
|
||||||
'navigator.permissions',
|
|
||||||
'navigator.plugins',
|
|
||||||
'navigator.webdriver',
|
|
||||||
'sourceurl',
|
|
||||||
// 'user-agent-override', // doesn't work since playwright has no page.browser()
|
|
||||||
'webgl.vendor',
|
|
||||||
'window.outerdimensions'
|
|
||||||
];
|
|
||||||
const evasions = enabledEvasions.map(e => new require(`puppeteer-extra-plugin-stealth/evasions/${e}`));
|
|
||||||
const stealth = {
|
|
||||||
callbacks: [],
|
|
||||||
async evaluateOnNewDocument(...args) {
|
|
||||||
this.callbacks.push({ cb: args[0], a: args[1] })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
evasions.forEach(e => e().onPageCreated(stealth));
|
|
||||||
for (let evasion of stealth.callbacks) {
|
|
||||||
await context.addInitScript(evasion.cb, evasion.a);
|
|
||||||
}
|
|
||||||
|
|
||||||
const page = await context.newPage();
|
|
||||||
console.log('userAgent:', await page.evaluate(() => navigator.userAgent));
|
|
||||||
await page.goto('https://www.epicgames.com/store/en-US/free-games');
|
|
||||||
// await expect(page.locator('a[role="button"]:has-text("Sign In")')).toHaveCount(0);
|
|
||||||
await page.click('button:has-text("Accept All Cookies")'); // to not waste screen space in --debug
|
|
||||||
await page.click('[data-testid="offer-card-image-landscape"]');
|
|
||||||
// TODO check if already claimed
|
|
||||||
const game = await page.locator('h1 div').first().innerText();
|
|
||||||
console.log('Current free game:', game);
|
|
||||||
// click Continue if 'This game contains mature content recommended only for ages 18+'
|
|
||||||
if (await page.locator(':has-text("Continue")').count() > 0) {
|
|
||||||
console.log('This game contains mature content recommended only for ages 18+');
|
|
||||||
await page.click('button:has-text("Continue")');
|
|
||||||
}
|
|
||||||
await page.click('[data-testid="purchase-cta-button"]');
|
|
||||||
await page.click('button:has-text("Continue")');
|
|
||||||
// it then creates an iframe for the rest
|
|
||||||
// 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 iframe.locator('button:has-text("I Agree")').click();
|
|
||||||
await page.pause();
|
|
||||||
await context.close();
|
|
||||||
await browser.close();
|
|
||||||
})();
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue