change playwright implementation
This commit is contained in:
parent
99c1f05302
commit
3558221696
3 changed files with 86 additions and 21 deletions
|
|
@ -1,9 +1,10 @@
|
||||||
import { firefox } from 'playwright-firefox'; // stealth plugin needs no outdated playwright-extra
|
// import { firefox } from 'playwright-firefox'; // stealth plugin needs no outdated playwright-extra
|
||||||
|
import { chromium } from 'patchright';
|
||||||
import { authenticator } from 'otplib';
|
import { authenticator } from 'otplib';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { existsSync, writeFileSync, appendFileSync } from 'fs';
|
import { existsSync, writeFileSync, appendFileSync } from 'fs';
|
||||||
import { resolve, jsonDb, datetime, stealth, filenamify, prompt, notify, html_game_list, handleSIGINT } from './src/util.js';
|
import { resolve, jsonDb, datetime, filenamify, prompt, notify, html_game_list, handleSIGINT } from './src/util.js';
|
||||||
import { cfg } from './src/config.js';
|
import { cfg } from './src/config.js';
|
||||||
|
|
||||||
const screenshot = (...a) => resolve(cfg.dir.screenshots, 'epic-games', ...a);
|
const screenshot = (...a) => resolve(cfg.dir.screenshots, 'epic-games', ...a);
|
||||||
|
|
@ -26,31 +27,17 @@ if (existsSync(browserPrefs)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://playwright.dev/docs/auth#multi-factor-authentication
|
// https://playwright.dev/docs/auth#multi-factor-authentication
|
||||||
const context = await firefox.launchPersistentContext(cfg.dir.browser, {
|
const context = await chromium.launchPersistentContext(cfg.dir.browser, {
|
||||||
headless: cfg.headless,
|
channel: 'chrome',
|
||||||
viewport: { width: cfg.width, height: cfg.height },
|
headless: false,
|
||||||
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0', // see replace of Headless in util.newStealthContext. TODO Windows UA enough to avoid 'device not supported'? update if browser is updated?
|
viewport: null,
|
||||||
// userAgent firefox (macOS): Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:106.0) Gecko/20100101 Firefox/106.0
|
|
||||||
// userAgent firefox (docker): Mozilla/5.0 (X11; Linux aarch64; rv:109.0) Gecko/20100101 Firefox/115.0
|
|
||||||
locale: 'en-US', // ignore OS locale to be sure to have english text for locators
|
|
||||||
recordVideo: cfg.record ? { dir: 'data/record/', size: { width: cfg.width, height: cfg.height } } : undefined, // will record a .webm video for each page navigated; without size, video would be scaled down to fit 800x800
|
|
||||||
recordHar: cfg.record ? { path: `data/record/eg-${filenamify(datetime())}.har` } : undefined, // will record a HAR file with network requests and responses; can be imported in Chrome devtools
|
|
||||||
handleSIGINT: false, // have to handle ourselves and call context.close(), otherwise recordings from above won't be saved
|
|
||||||
// user settings for firefox have to be put in $BROWSER_DIR/user.js
|
|
||||||
args: [ // https://wiki.mozilla.org/Firefox/CommandLineOptions
|
|
||||||
// '-kiosk',
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
handleSIGINT(context);
|
handleSIGINT(context);
|
||||||
|
|
||||||
// Without stealth plugin, the website shows an hcaptcha on login with username/password and in the last step of claiming a game. It may have other heuristics like unsuccessful logins as well. After <6h (TBD) it resets to no captcha again. Getting a new IP also resets.
|
|
||||||
await stealth(context);
|
|
||||||
|
|
||||||
if (!cfg.debug) context.setDefaultTimeout(cfg.timeout);
|
if (!cfg.debug) context.setDefaultTimeout(cfg.timeout);
|
||||||
|
|
||||||
const page = context.pages().length ? context.pages()[0] : await context.newPage(); // should always exist
|
const page = context.pages().length ? context.pages()[0] : await context.newPage(); // should always exist
|
||||||
await page.setViewportSize({ width: cfg.width, height: cfg.height }); // TODO workaround for https://github.com/vogler/free-games-claimer/issues/277 until Playwright fixes it
|
|
||||||
|
|
||||||
// some debug info about the page (screen dimensions, user agent, platform)
|
// some debug info about the page (screen dimensions, user agent, platform)
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
|
|
@ -107,13 +94,24 @@ try {
|
||||||
console.error('Incorrect response for captcha!');
|
console.error('Incorrect response for captcha!');
|
||||||
}).catch(_ => { });
|
}).catch(_ => { });
|
||||||
await page.fill('#email', email);
|
await page.fill('#email', email);
|
||||||
// await page.click('button[type="submit"]'); login was split in two steps for some time, now email and password are on the same form again
|
await page.click('button[type="submit"]');
|
||||||
const password = email && (cfg.eg_password || await prompt({ type: 'password', message: 'Enter password' }));
|
const password = email && (cfg.eg_password || await prompt({ type: 'password', message: 'Enter password' }));
|
||||||
if (!password) await notifyBrowserLogin();
|
if (!password) await notifyBrowserLogin();
|
||||||
else {
|
else {
|
||||||
await page.fill('#password', password);
|
await page.fill('#password', password);
|
||||||
|
console.info('Filled in email and password.');
|
||||||
|
await page.waitForTimeout(2000); // Waits for 2 seconds
|
||||||
|
console.info('Submitting login form...');
|
||||||
|
await page.click('button[type="submit"]');
|
||||||
|
await page.waitForTimeout(5000); // Waits for 2 seconds
|
||||||
|
}
|
||||||
|
// find h1 with text 'Is this the right account?'
|
||||||
|
const accountHeader = page.locator('h1:has-text("Is this the right account?")');
|
||||||
|
// if accountHeader exists, click button type submit
|
||||||
|
if (await accountHeader.count() > 0) {
|
||||||
await page.click('button[type="submit"]');
|
await page.click('button[type="submit"]');
|
||||||
}
|
}
|
||||||
|
|
||||||
const error = page.locator('#form-error-message');
|
const error = page.locator('#form-error-message');
|
||||||
error.waitFor().then(async () => {
|
error.waitFor().then(async () => {
|
||||||
console.error('Login error:', await error.innerText());
|
console.error('Login error:', await error.innerText());
|
||||||
|
|
@ -125,6 +123,7 @@ try {
|
||||||
// TODO locator for text (email or app?)
|
// TODO locator for text (email or app?)
|
||||||
const otp = cfg.eg_otpkey && authenticator.generate(cfg.eg_otpkey) || await prompt({ type: 'text', message: 'Enter two-factor sign in code', validate: n => n.toString().length == 6 || 'The code must be 6 digits!' }); // can't use type: 'number' since it strips away leading zeros and codes sometimes have them
|
const otp = cfg.eg_otpkey && authenticator.generate(cfg.eg_otpkey) || await prompt({ type: 'text', message: 'Enter two-factor sign in code', validate: n => n.toString().length == 6 || 'The code must be 6 digits!' }); // can't use type: 'number' since it strips away leading zeros and codes sometimes have them
|
||||||
await page.locator('input[name="code-input-0"]').pressSequentially(otp.toString());
|
await page.locator('input[name="code-input-0"]').pressSequentially(otp.toString());
|
||||||
|
await page.waitForTimeout(3000); // Waits for 3 seconds
|
||||||
await page.click('button[type="submit"]');
|
await page.click('button[type="submit"]');
|
||||||
}).catch(_ => { });
|
}).catch(_ => { });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
65
package-lock.json
generated
65
package-lock.json
generated
|
|
@ -16,6 +16,7 @@
|
||||||
"fingerprint-injector": "^2.1.66",
|
"fingerprint-injector": "^2.1.66",
|
||||||
"lowdb": "^7.0.1",
|
"lowdb": "^7.0.1",
|
||||||
"otplib": "^12.0.1",
|
"otplib": "^12.0.1",
|
||||||
|
"patchright": "^1.56.1",
|
||||||
"playwright-firefox": "^1.52.0",
|
"playwright-firefox": "^1.52.0",
|
||||||
"puppeteer-extra-plugin-stealth": "^2.11.2"
|
"puppeteer-extra-plugin-stealth": "^2.11.2"
|
||||||
},
|
},
|
||||||
|
|
@ -1386,6 +1387,20 @@
|
||||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/fsevents": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/function-bind": {
|
"node_modules/function-bind": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
|
|
@ -2138,6 +2153,36 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/patchright": {
|
||||||
|
"version": "1.56.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/patchright/-/patchright-1.56.1.tgz",
|
||||||
|
"integrity": "sha512-HY4s3vJNPVoasoy0X7sOm2dufQwlicvXoCpoINYFUWYkEaSBM2l4UtSOdI4/MYQHNskfOFpIqE+Usj748qbtYg==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"patchright-core": "1.56.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"patchright": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"fsevents": "2.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/patchright-core": {
|
||||||
|
"version": "1.56.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/patchright-core/-/patchright-core-1.56.1.tgz",
|
||||||
|
"integrity": "sha512-ot1WU31T+FLjBg8LUbEnPPhzh6uRYji25ZONHpxVUEXtANuVJf6tI4nv6jw6n37qsjgS4u12sq7Go0Vdte3JJQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bin": {
|
||||||
|
"patchright-core": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/path-exists": {
|
"node_modules/path-exists": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||||
|
|
@ -3786,6 +3831,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||||
},
|
},
|
||||||
|
"fsevents": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"function-bind": {
|
"function-bind": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
|
|
@ -4301,6 +4352,20 @@
|
||||||
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
|
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"patchright": {
|
||||||
|
"version": "1.56.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/patchright/-/patchright-1.56.1.tgz",
|
||||||
|
"integrity": "sha512-HY4s3vJNPVoasoy0X7sOm2dufQwlicvXoCpoINYFUWYkEaSBM2l4UtSOdI4/MYQHNskfOFpIqE+Usj748qbtYg==",
|
||||||
|
"requires": {
|
||||||
|
"fsevents": "2.3.2",
|
||||||
|
"patchright-core": "1.56.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patchright-core": {
|
||||||
|
"version": "1.56.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/patchright-core/-/patchright-core-1.56.1.tgz",
|
||||||
|
"integrity": "sha512-ot1WU31T+FLjBg8LUbEnPPhzh6uRYji25ZONHpxVUEXtANuVJf6tI4nv6jw6n37qsjgS4u12sq7Go0Vdte3JJQ=="
|
||||||
|
},
|
||||||
"path-exists": {
|
"path-exists": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
"fingerprint-injector": "^2.1.66",
|
"fingerprint-injector": "^2.1.66",
|
||||||
"lowdb": "^7.0.1",
|
"lowdb": "^7.0.1",
|
||||||
"otplib": "^12.0.1",
|
"otplib": "^12.0.1",
|
||||||
|
"patchright": "^1.56.1",
|
||||||
"playwright-firefox": "^1.52.0",
|
"playwright-firefox": "^1.52.0",
|
||||||
"puppeteer-extra-plugin-stealth": "^2.11.2"
|
"puppeteer-extra-plugin-stealth": "^2.11.2"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue