eg: login from CLI, prompts for email, password, OTP
This commit is contained in:
parent
ac0ecc0f7a
commit
f450d29bc3
3 changed files with 74 additions and 3 deletions
|
|
@ -3,6 +3,11 @@ import path from 'path';
|
||||||
import { dirs, jsonDb, datetime, stealth, filenamify } from './util.js';
|
import { dirs, jsonDb, datetime, stealth, filenamify } from './util.js';
|
||||||
import { existsSync, writeFileSync } from 'fs';
|
import { existsSync, writeFileSync } from 'fs';
|
||||||
|
|
||||||
|
import prompts from 'prompts'; // alternatives: enquirer, inquirer
|
||||||
|
// import enquirer from 'enquirer'; const { prompt } = enquirer;
|
||||||
|
// single prompt that just returns the non-empty value instead of an object - why name things if there's just one?
|
||||||
|
const prompt = async o => (await prompts({name: 'name', type: 'text', message: 'Enter value', validate: s => s.length, ...o})).name;
|
||||||
|
|
||||||
const debug = process.env.PWDEBUG == '1'; // runs non-headless 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_CLAIM = 'https://store.epicgames.com/en-US/free-games';
|
const URL_CLAIM = 'https://store.epicgames.com/en-US/free-games';
|
||||||
|
|
@ -61,14 +66,28 @@ try {
|
||||||
// Accept cookies to get rid of banner to save space on screen. Clicking this did not always work since the message was animated in too slowly.
|
// Accept cookies to get rid of banner to save space on screen. Clicking this did not always work since the message was animated in too slowly.
|
||||||
// page.click('button:has-text("Accept All Cookies")').catch(_ => { }); // not needed anymore since we set the cookie above
|
// page.click('button:has-text("Accept All Cookies")').catch(_ => { }); // not needed anymore since we set the cookie above
|
||||||
|
|
||||||
while (await page.locator('a[role="button"]:has-text("Sign In")').count() > 0) { // TODO also check alternative for signed-in state
|
while (await page.locator('a[role="button"]:has-text("Sign In")').count() > 0) {
|
||||||
console.error("Not signed in anymore. Please login and then navigate to the 'Free Games' page. If using docker, open http://localhost:6080");
|
console.error("Not signed in anymore. Please login and then navigate to the 'Free Games' page. If using docker, open http://localhost:6080");
|
||||||
context.setDefaultTimeout(0); // give user time to log in without timeout
|
context.setDefaultTimeout(0); // give user time to log in without timeout
|
||||||
await page.goto(URL_LOGIN, { waitUntil: 'domcontentloaded' });
|
await page.goto(URL_LOGIN, { waitUntil: 'domcontentloaded' });
|
||||||
// after login it just reloads the login page...
|
|
||||||
|
const email = process.env.EMAIL || await prompt({message: 'Enter email'});
|
||||||
|
const password = process.env.PASSWORD || await prompt({type: 'password', message: 'Enter password'});
|
||||||
|
if (email && password) {
|
||||||
|
await page.click('text=Sign in with Epic Games');
|
||||||
|
await page.fill('#email', email);
|
||||||
|
await page.fill('#password', password);
|
||||||
|
await page.click('button[type="submit"]');
|
||||||
|
// TODO alternatively wait for redirectUrl
|
||||||
|
await page.waitForNavigation({ url: '**/id/login/mfa**'}).then(async () => {
|
||||||
|
console.log('Enter the security code to continue - This appears to be a new device, browser or location. A security code has been sent to your email address at ...');
|
||||||
|
const otp = await prompt({type: 'number', message: 'Enter two-factor sign in code', validate: n => n.toString().length == 6 || 'The code must be 6 digits!'});
|
||||||
|
await page.type('input[name="code-input-0"]', otp);
|
||||||
|
await page.click('button[type="submit"]');
|
||||||
|
});
|
||||||
|
}
|
||||||
await page.waitForNavigation({ url: URL_CLAIM });
|
await page.waitForNavigation({ url: URL_CLAIM });
|
||||||
context.setDefaultTimeout(TIMEOUT);
|
context.setDefaultTimeout(TIMEOUT);
|
||||||
// process.exit(1);
|
|
||||||
}
|
}
|
||||||
const user = await page.locator('#user span').first().innerHTML();
|
const user = await page.locator('#user span').first().innerHTML();
|
||||||
console.log(`Signed in as ${user}`);
|
console.log(`Signed in as ${user}`);
|
||||||
|
|
|
||||||
51
package-lock.json
generated
51
package-lock.json
generated
|
|
@ -8,6 +8,7 @@
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"lowdb": "^4.0.0",
|
"lowdb": "^4.0.0",
|
||||||
"playwright": "^1.27.1",
|
"playwright": "^1.27.1",
|
||||||
|
"prompts": "^2.4.2",
|
||||||
"puppeteer-extra-plugin-stealth": "^2.11.1"
|
"puppeteer-extra-plugin-stealth": "^2.11.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -280,6 +281,15 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/kleur": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lazy-cache": {
|
"node_modules/lazy-cache": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
|
||||||
|
|
@ -413,6 +423,19 @@
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prompts": {
|
||||||
|
"version": "2.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
|
||||||
|
"integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"kleur": "^3.0.3",
|
||||||
|
"sisteransi": "^1.0.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/puppeteer-extra-plugin": {
|
"node_modules/puppeteer-extra-plugin": {
|
||||||
"version": "3.2.2",
|
"version": "3.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/puppeteer-extra-plugin/-/puppeteer-extra-plugin-3.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/puppeteer-extra-plugin/-/puppeteer-extra-plugin-3.2.2.tgz",
|
||||||
|
|
@ -591,6 +614,12 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sisteransi": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/steno": {
|
"node_modules/steno": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/steno/-/steno-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/steno/-/steno-3.0.0.tgz",
|
||||||
|
|
@ -846,6 +875,12 @@
|
||||||
"is-buffer": "^1.1.5"
|
"is-buffer": "^1.1.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"kleur": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"lazy-cache": {
|
"lazy-cache": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
|
||||||
|
|
@ -941,6 +976,16 @@
|
||||||
"integrity": "sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q==",
|
"integrity": "sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"prompts": {
|
||||||
|
"version": "2.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
|
||||||
|
"integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"kleur": "^3.0.3",
|
||||||
|
"sisteransi": "^1.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"puppeteer-extra-plugin": {
|
"puppeteer-extra-plugin": {
|
||||||
"version": "3.2.2",
|
"version": "3.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/puppeteer-extra-plugin/-/puppeteer-extra-plugin-3.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/puppeteer-extra-plugin/-/puppeteer-extra-plugin-3.2.2.tgz",
|
||||||
|
|
@ -1040,6 +1085,12 @@
|
||||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"sisteransi": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"steno": {
|
"steno": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/steno/-/steno-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/steno/-/steno-3.0.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"lowdb": "^4.0.0",
|
"lowdb": "^4.0.0",
|
||||||
"playwright": "^1.27.1",
|
"playwright": "^1.27.1",
|
||||||
|
"prompts": "^2.4.2",
|
||||||
"puppeteer-extra-plugin-stealth": "^2.11.1"
|
"puppeteer-extra-plugin-stealth": "^2.11.1"
|
||||||
},
|
},
|
||||||
"type": "module"
|
"type": "module"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue