Clean up Sonar issues and lint warnings
This commit is contained in:
parent
b9aa6e0073
commit
7ffc454e47
6 changed files with 124 additions and 89 deletions
|
|
@ -48,9 +48,18 @@ if (!cfg.debug) context.setDefaultTimeout(cfg.timeout);
|
|||
const page = context.pages().length ? context.pages()[0] : await context.newPage(); // should always exist
|
||||
await page.setViewportSize({ width: cfg.width, height: cfg.height }); // 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)
|
||||
// eslint-disable-next-line no-undef
|
||||
if (cfg.debug) console.debug(await page.evaluate(() => [(({ width, height, availWidth, availHeight }) => ({ width, height, availWidth, availHeight }))(window.screen), navigator.userAgent, navigator.platform, navigator.vendor])); // deconstruct screen needed since `window.screen` prints {}, `window.screen.toString()` '[object Screen]', and can't use some pick function without defining it on `page`
|
||||
// some debug info about the page (screen dimensions, user agent)
|
||||
if (cfg.debug) {
|
||||
// eslint-disable-next-line no-undef
|
||||
const debugInfo = await page.evaluate(() => {
|
||||
const { width, height, availWidth, availHeight } = window.screen;
|
||||
return {
|
||||
screen: { width, height, availWidth, availHeight },
|
||||
userAgent: navigator.userAgent,
|
||||
};
|
||||
});
|
||||
console.debug(debugInfo);
|
||||
}
|
||||
if (cfg.debug_network) {
|
||||
// const filter = _ => true;
|
||||
const filter = r => r.url().includes('store.epicgames.com');
|
||||
|
|
@ -90,9 +99,8 @@ try {
|
|||
}
|
||||
};
|
||||
const email = cfg.eg_email || await prompt({ message: 'Enter email' });
|
||||
if (!email) await notifyBrowserLogin();
|
||||
else {
|
||||
void (async () => {
|
||||
if (email) {
|
||||
const watchCaptchaChallenge = async () => {
|
||||
try {
|
||||
await page.waitForSelector('.h_captcha_challenge iframe', { timeout: 15000 });
|
||||
console.error('Got a captcha during login (likely due to too many attempts)! You may solve it in the browser, get a new IP or try again in a few hours.');
|
||||
|
|
@ -100,24 +108,25 @@ try {
|
|||
} catch {
|
||||
return;
|
||||
}
|
||||
})();
|
||||
void (async () => {
|
||||
};
|
||||
const watchCaptchaIncorrect = async () => {
|
||||
try {
|
||||
await page.waitForSelector('p:has-text("Incorrect response.")', { timeout: 15000 });
|
||||
console.error('Incorrect response for captcha!');
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
})();
|
||||
};
|
||||
watchCaptchaChallenge();
|
||||
watchCaptchaIncorrect();
|
||||
await page.fill('#email', email);
|
||||
const password = email && (cfg.eg_password || await prompt({ type: 'password', message: 'Enter password' }));
|
||||
if (!password) await notifyBrowserLogin();
|
||||
else {
|
||||
const password = cfg.eg_password || await prompt({ type: 'password', message: 'Enter password' });
|
||||
if (password) {
|
||||
await page.fill('#password', password);
|
||||
await page.click('button[type="submit"]');
|
||||
}
|
||||
} else await notifyBrowserLogin();
|
||||
const error = page.locator('#form-error-message');
|
||||
void (async () => {
|
||||
const watchLoginError = async () => {
|
||||
try {
|
||||
await error.waitFor({ timeout: 15000 });
|
||||
console.error('Login error:', await error.innerText());
|
||||
|
|
@ -125,8 +134,8 @@ try {
|
|||
} catch {
|
||||
return;
|
||||
}
|
||||
})();
|
||||
void (async () => {
|
||||
};
|
||||
const watchMfaStep = async () => {
|
||||
try {
|
||||
await page.waitForURL('**/id/login/mfa**', { timeout: cfg.login_timeout });
|
||||
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 ...');
|
||||
|
|
@ -136,8 +145,10 @@ try {
|
|||
} catch {
|
||||
return;
|
||||
}
|
||||
})();
|
||||
}
|
||||
};
|
||||
watchLoginError();
|
||||
watchMfaStep();
|
||||
} else await notifyBrowserLogin();
|
||||
await page.waitForURL(URL_CLAIM);
|
||||
if (!cfg.debug) context.setDefaultTimeout(cfg.timeout);
|
||||
}
|
||||
|
|
@ -223,14 +234,13 @@ try {
|
|||
console.log(' Base game:', baseUrl);
|
||||
// await page.click('a:has-text("Overview")');
|
||||
// re-add original add-on to queue after base game
|
||||
urls.push(baseUrl); // add base game to the list of games to claim
|
||||
urls.push(url); // add add-on itself again
|
||||
urls.push(baseUrl, url); // add base game to the list of games to claim and re-add add-on itself
|
||||
} else { // GET
|
||||
console.log(' Not in library yet! Click', btnText);
|
||||
await purchaseBtn.click({ delay: 11 }); // got stuck here without delay (or mouse move), see #75, 1ms was also enough
|
||||
|
||||
// Accept End User License Agreement (only needed once)
|
||||
void (async () => {
|
||||
const acceptEulaIfShown = async () => {
|
||||
try {
|
||||
await page.locator(':has-text("end user license agreement")').waitFor({ timeout: 10000 });
|
||||
console.log(' Accept End User License Agreement (only needed once)');
|
||||
|
|
@ -239,7 +249,8 @@ try {
|
|||
} catch {
|
||||
return;
|
||||
}
|
||||
})();
|
||||
};
|
||||
acceptEulaIfShown();
|
||||
|
||||
// it then creates an iframe for the purchase
|
||||
await page.waitForSelector('#webPurchaseContainer iframe');
|
||||
|
|
@ -252,7 +263,7 @@ try {
|
|||
continue;
|
||||
}
|
||||
|
||||
void (async () => {
|
||||
const enterParentalPinIfNeeded = async () => {
|
||||
try {
|
||||
await iframe.locator('.payment-pin-code').waitFor({ timeout: 10000 });
|
||||
if (!cfg.eg_parentalpin) {
|
||||
|
|
@ -264,7 +275,8 @@ try {
|
|||
} catch {
|
||||
return;
|
||||
}
|
||||
})();
|
||||
};
|
||||
enterParentalPinIfNeeded();
|
||||
|
||||
if (cfg.debug) await page.pause();
|
||||
if (cfg.dryrun) {
|
||||
|
|
@ -279,18 +291,19 @@ try {
|
|||
|
||||
// I Agree button is only shown for EU accounts! https://github.com/vogler/free-games-claimer/pull/7#issuecomment-1038964872
|
||||
const btnAgree = iframe.locator('button:has-text("I Accept")');
|
||||
void (async () => {
|
||||
const acceptIfRequired = async () => {
|
||||
try {
|
||||
await btnAgree.waitFor({ timeout: 10000 });
|
||||
await btnAgree.click();
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
})(); // EU: wait for and click 'I Agree'
|
||||
}; // EU: wait for and click 'I Agree'
|
||||
acceptIfRequired();
|
||||
try {
|
||||
// context.setDefaultTimeout(100 * 1000); // give time to solve captcha, iframe goes blank after 60s?
|
||||
const captcha = iframe.locator('#h_captcha_challenge_checkout_free_prod iframe');
|
||||
void (async () => {
|
||||
const watchCaptchaChallenge = async () => {
|
||||
try {
|
||||
await captcha.waitFor({ timeout: 10000 });
|
||||
console.error(' Got hcaptcha challenge! Lost trust due to too many login attempts? You can solve the captcha in the browser or get a new IP address.');
|
||||
|
|
@ -298,8 +311,8 @@ try {
|
|||
} catch {
|
||||
return;
|
||||
}
|
||||
})(); // may time out if not shown
|
||||
void (async () => {
|
||||
}; // may time out if not shown
|
||||
const watchCaptchaFailure = async () => {
|
||||
try {
|
||||
await iframe.locator('.payment__errors:has-text("Failed to challenge captcha, please try again later.")').waitFor({ timeout: 10000 });
|
||||
console.error(' Failed to challenge captcha, please try again later.');
|
||||
|
|
@ -307,7 +320,9 @@ try {
|
|||
} catch {
|
||||
return;
|
||||
}
|
||||
})();
|
||||
};
|
||||
watchCaptchaChallenge();
|
||||
watchCaptchaFailure();
|
||||
await page.locator('text=Thanks for your order!').waitFor({ state: 'attached' });
|
||||
db.data[user][game_id].status = 'claimed';
|
||||
db.data[user][game_id].time = datetime(); // claimed time overwrites failed/dryrun time
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export default [
|
|||
{
|
||||
ignores: ['data/**'],
|
||||
},
|
||||
js.configs.recommended, // TODO still needed?
|
||||
js.configs.recommended,
|
||||
{
|
||||
// files: ['*.js'],
|
||||
languageOptions: {
|
||||
|
|
|
|||
13
gog.js
13
gog.js
|
|
@ -60,7 +60,7 @@ try {
|
|||
await iframe.locator('#login_username').fill(email);
|
||||
await iframe.locator('#login_password').fill(password);
|
||||
await iframe.locator('#login_login').click();
|
||||
void (async () => {
|
||||
const handleTwoFactor = async () => {
|
||||
try {
|
||||
await iframe.locator('form[name=second_step_authentication]').waitFor({ timeout: 15000 });
|
||||
console.log('Two-Step Verification - Enter security code');
|
||||
|
|
@ -72,8 +72,8 @@ try {
|
|||
} catch {
|
||||
return;
|
||||
}
|
||||
})();
|
||||
void (async () => {
|
||||
};
|
||||
const watchInvalidCaptcha = async () => {
|
||||
try {
|
||||
await iframe.locator('text=Invalid captcha').waitFor({ timeout: 15000 });
|
||||
console.error('Got a captcha during login (likely due to too many attempts)! You may solve it in the browser, get a new IP or try again in a few hours.');
|
||||
|
|
@ -81,7 +81,9 @@ try {
|
|||
} catch {
|
||||
return;
|
||||
}
|
||||
})();
|
||||
};
|
||||
handleTwoFactor();
|
||||
watchInvalidCaptcha();
|
||||
await page.waitForSelector('#menuUsername');
|
||||
} else {
|
||||
console.log('Waiting for you to login in the browser.');
|
||||
|
|
@ -100,7 +102,8 @@ try {
|
|||
db.data[user] ||= {};
|
||||
|
||||
const banner = page.locator('#giveaway');
|
||||
if (!await banner.count()) {
|
||||
const hasGiveaway = await banner.count();
|
||||
if (!hasGiveaway) {
|
||||
console.log('Currently no free giveaway!');
|
||||
} else {
|
||||
const text = await page.locator('.giveaway__content-header').innerText();
|
||||
|
|
|
|||
|
|
@ -92,7 +92,11 @@ try {
|
|||
'[data-a-target="user-dropdown-first-name-text"]',
|
||||
'[data-testid="user-dropdown-first-name-text"]',
|
||||
].map(s => page.waitForSelector(s)));
|
||||
page.click('[aria-label="Cookies usage disclaimer banner"] button:has-text("Accept Cookies")').catch(() => { }); // to not waste screen space when non-headless; could be flaky
|
||||
try {
|
||||
await page.click('[aria-label="Cookies usage disclaimer banner"] button:has-text("Accept Cookies")'); // to not waste screen space when non-headless; could be flaky
|
||||
} catch {
|
||||
// ignore if banner not present
|
||||
}
|
||||
while (await page.locator('button:has-text("Sign in"), button:has-text("Anmelden")').count() > 0) {
|
||||
console.error('Not signed in anymore.');
|
||||
await page.click('button:has-text("Sign in")');
|
||||
|
|
@ -119,7 +123,11 @@ try {
|
|||
} catch {
|
||||
// navigation ok
|
||||
}
|
||||
handleMFA(page).catch(() => {});
|
||||
try {
|
||||
await handleMFA(page);
|
||||
} catch {
|
||||
// ignore MFA watcher errors
|
||||
}
|
||||
} else {
|
||||
console.log('Waiting for you to login in the browser.');
|
||||
await notify('prime-gaming: no longer signed in and not enough options set for automatic login.');
|
||||
|
|
@ -297,7 +305,6 @@ try {
|
|||
return [p, isNew];
|
||||
};
|
||||
const skipBasedOnTime = async url => {
|
||||
// console.log(' Checking time left for game:', url);
|
||||
const [p, isNew] = await sameOrNewPage(url);
|
||||
const dueDateLoc = p.locator('.availability-date .tw-bold, [data-testid="availability-end-date"], [data-test-selector="availability-end-date"]');
|
||||
if (!await dueDateLoc.count()) {
|
||||
|
|
@ -321,7 +328,10 @@ try {
|
|||
console.log('Current free game:', chalk.blue(title));
|
||||
if (cfg.pg_timeLeft && url && await skipBasedOnTime(url)) continue;
|
||||
if (cfg.dryrun) continue;
|
||||
if (cfg.interactive && !await confirm()) continue;
|
||||
if (cfg.interactive) {
|
||||
const confirmed = await confirm();
|
||||
if (!confirmed) continue;
|
||||
}
|
||||
await card.handle.locator('.tw-button:has-text("Claim"), .tw-button:has-text("Get"), button:has-text("Claim"), button:has-text("Get")').first().click();
|
||||
db.data[user][title] ||= { title, time: datetime(), url, store: 'internal' };
|
||||
notify_games.push({ title, status: 'claimed', url });
|
||||
|
|
@ -336,8 +346,6 @@ try {
|
|||
if (!url) continue;
|
||||
external_info.push({ title, url });
|
||||
}
|
||||
// external_info = [ { title: 'Fallout 76 (XBOX)', url: 'https://gaming.amazon.com/fallout-76-xbox-fgwp/dp/amzn1.pg.item.9fe17d7b-b6c2-4f58-b494-cc4e79528d0b?ingress=amzn&ref_=SM_Fallout76XBOX_S01_FGWP_CRWN' } ];
|
||||
|
||||
const clickCTA = async p => {
|
||||
const candidates = [
|
||||
p.locator('button[data-a-target="buy-box_call-to-action"]').first(),
|
||||
|
|
@ -353,14 +361,14 @@ try {
|
|||
if (await c.count()) {
|
||||
try {
|
||||
await c.waitFor({ state: 'visible', timeout: 5000 });
|
||||
if (!await c.isEnabled()) {
|
||||
const enabled = await c.isEnabled();
|
||||
if (enabled) await c.click();
|
||||
else {
|
||||
await c.evaluate(el => {
|
||||
el.disabled = false;
|
||||
el.removeAttribute('disabled');
|
||||
el.click();
|
||||
});
|
||||
} else {
|
||||
await c.click();
|
||||
}
|
||||
return true;
|
||||
} catch {
|
||||
|
|
@ -442,7 +450,10 @@ try {
|
|||
}
|
||||
if (cfg.pg_timeLeft && await skipBasedOnTime(url)) continue;
|
||||
if (cfg.dryrun) continue;
|
||||
if (cfg.interactive && !await confirm()) continue;
|
||||
if (cfg.interactive) {
|
||||
const confirmed = await confirm();
|
||||
if (!confirmed) continue;
|
||||
}
|
||||
await clickCTA(page);
|
||||
await Promise.any([
|
||||
page.waitForSelector('.thank-you-title:has-text("Success")', { timeout: cfg.timeout }).catch(() => {}),
|
||||
|
|
@ -499,13 +510,9 @@ try {
|
|||
const page2 = await context.newPage();
|
||||
await page2.goto(redeem[store], { waitUntil: 'domcontentloaded' });
|
||||
if (store == 'gog.com') {
|
||||
// await page.goto(`https://redeem.gog.com/v1/bonusCodes/${code}`); // {"reason":"Invalid or no captcha"}
|
||||
await page2.fill('#codeInput', code);
|
||||
// wait for responses before clicking on Continue and then Redeem
|
||||
// first there are requests with OPTIONS and GET to https://redeem.gog.com/v1/bonusCodes/XYZ?language=de-DE
|
||||
const r1 = page2.waitForResponse(r => r.request().method() == 'GET' && r.url().startsWith('https://redeem.gog.com/'));
|
||||
await page2.click('[type="submit"]'); // click Continue
|
||||
// console.log(await page2.locator('.warning-message').innerText()); // does not exist if there is no warning
|
||||
const r1t = await (await r1).text();
|
||||
const reason = JSON.parse(r1t).reason;
|
||||
// {"reason":"Invalid or no captcha"}
|
||||
|
|
@ -520,14 +527,12 @@ try {
|
|||
} else if (reason == 'code_not_found') {
|
||||
redeem_action = 'redeem (not found)';
|
||||
console.error(' Code was not found!');
|
||||
} else { // unknown state; keep info log for later analysis
|
||||
redeem_action = 'redeemed?';
|
||||
// console.log(' Redeemed successfully? Please report your Responses (if new) in https://github.com/vogler/free-games-claimer/issues/5');
|
||||
console.debug(` Response 1: ${r1t}`);
|
||||
// then after the click on Redeem there is a POST request which should return {} if claimed successfully
|
||||
const r2 = page2.waitForResponse(r => r.request().method() == 'POST' && r.url().startsWith('https://redeem.gog.com/'));
|
||||
await page2.click('[type="submit"]'); // click Redeem
|
||||
const r2t = await (await r2).text();
|
||||
} else { // unknown state; keep info log for later analysis
|
||||
redeem_action = 'redeemed?';
|
||||
console.debug(` Response 1: ${r1t}`);
|
||||
const r2 = page2.waitForResponse(r => r.request().method() == 'POST' && r.url().startsWith('https://redeem.gog.com/'));
|
||||
await page2.click('[type="submit"]'); // click Redeem
|
||||
const r2t = await (await r2).text();
|
||||
const reason2 = JSON.parse(r2t).reason;
|
||||
if (r2t == '{}') {
|
||||
redeem_action = 'redeemed';
|
||||
|
|
@ -543,7 +548,6 @@ try {
|
|||
}
|
||||
} else if (store == 'microsoft store' || store == 'xbox') {
|
||||
console.error(` Redeem on ${store} is experimental!`);
|
||||
// await page2.pause();
|
||||
if (page2.url().startsWith('https://login.')) {
|
||||
console.error(' Not logged in! Please redeem the code above manually. You can now login in the browser for next time. Waiting for 60s.');
|
||||
await page2.waitForTimeout(60 * 1000);
|
||||
|
|
@ -554,9 +558,7 @@ try {
|
|||
await input.waitFor();
|
||||
await input.fill(code);
|
||||
const r = page2.waitForResponse(r => r.url().startsWith('https://cart.production.store-web.dynamics.com/v1.0/Redeem/PrepareRedeem'));
|
||||
// console.log(await page2.locator('.redeem_code_error').innerText());
|
||||
const rt = await (await r).text();
|
||||
// {"code":"NotFound","data":[],"details":[],"innererror":{"code":"TokenNotFound",...
|
||||
const j = JSON.parse(rt);
|
||||
const reason = j?.events?.cart.length && j.events.cart[0]?.data?.reason;
|
||||
if (reason == 'TokenNotFound') {
|
||||
|
|
@ -582,14 +584,12 @@ try {
|
|||
}
|
||||
}
|
||||
} else if (store == 'legacy games') {
|
||||
// await page2.pause();
|
||||
await page2.fill('[name=coupon_code]', code);
|
||||
await page2.fill('[name=email]', cfg.lg_email);
|
||||
await page2.fill('[name=email_validate]', cfg.lg_email);
|
||||
await page2.uncheck('[name=newsletter_sub]');
|
||||
await page2.click('[type="submit"]');
|
||||
try {
|
||||
// await page2.waitForResponse(r => r.url().startsWith('https://promo.legacygames.com/promotion-processing/order-management.php')); // status code 302
|
||||
await page2.waitForSelector('h2:has-text("Thanks for redeeming")');
|
||||
redeem_action = 'redeemed';
|
||||
db.data[user][title].status = 'claimed and redeemed';
|
||||
|
|
@ -609,15 +609,16 @@ try {
|
|||
} else {
|
||||
notify_game.status = `claimed on ${store}`;
|
||||
db.data[user][title].status = 'claimed';
|
||||
}
|
||||
// save screenshot of potential code just in case
|
||||
await page.screenshot({ path: screenshot('external', `${filenamify(title)}.png`), fullPage: true });
|
||||
// console.info(' Saved a screenshot of page to', p);
|
||||
}
|
||||
// await page.pause();
|
||||
await page.screenshot({ path: screenshot('external', `${filenamify(title)}.png`), fullPage: true });
|
||||
}
|
||||
}
|
||||
await page.goto(URL_CLAIM, { waitUntil: 'domcontentloaded' });
|
||||
page.click('button[data-type="Game"]').catch(() => {});
|
||||
try {
|
||||
await page.click('button[data-type="Game"]');
|
||||
} catch {
|
||||
// ignore if filter already selected
|
||||
}
|
||||
|
||||
if (notify_games.length && games) { // make screenshot of all games if something was claimed and list exists
|
||||
const p = screenshot(`${filenamify(datetime())}.png`);
|
||||
|
|
@ -663,15 +664,28 @@ try {
|
|||
await page.goto(url, { waitUntil: 'domcontentloaded' });
|
||||
// most games have a button 'Get in-game content'
|
||||
// epic-games: Fall Guys: Claim -> Continue -> Go to Epic Games (despite account linked and logged into epic-games) -> not tied to account but via some cookie?
|
||||
await Promise.any([page.click('.tw-button:has-text("Get in-game content")'), page.click('.tw-button:has-text("Claim your gift")'), page.click('.tw-button:has-text("Claim")').then(() => page.click('button:has-text("Continue")'))]);
|
||||
page.click('button:has-text("Continue")').catch(() => { });
|
||||
const claimOptions = [
|
||||
page.click('.tw-button:has-text("Get in-game content")'),
|
||||
page.click('.tw-button:has-text("Claim your gift")'),
|
||||
(async () => {
|
||||
await page.click('.tw-button:has-text("Claim")');
|
||||
await page.click('button:has-text("Continue")').catch(() => {});
|
||||
})(),
|
||||
];
|
||||
await Promise.any(claimOptions);
|
||||
try {
|
||||
await page.click('button:has-text("Continue")');
|
||||
} catch {
|
||||
// continue button not always present
|
||||
}
|
||||
const linkAccountButton = page.locator('[data-a-target="LinkAccountButton"]');
|
||||
let unlinked_store;
|
||||
if (await linkAccountButton.count()) {
|
||||
unlinked_store = await linkAccountButton.first().getAttribute('aria-label');
|
||||
console.debug(' LinkAccountButton label:', unlinked_store);
|
||||
const match = unlinked_store.match(/Link (.*) account/);
|
||||
if (match && match.length == 2) unlinked_store = match[1];
|
||||
const match = unlinked_store?.match(/Link (.*) account/);
|
||||
const extracted = match?.[1];
|
||||
if (extracted) unlinked_store = extracted;
|
||||
} else if (await page.locator('text=Link game account').count()) { // epic-games only?
|
||||
console.error(' Missing account linking (epic-games specific button?):', await page.locator('button[data-a-target="gms-cta"]').innerText()); // track account-linking UI drift
|
||||
unlinked_store = 'epic-games';
|
||||
|
|
@ -685,9 +699,7 @@ try {
|
|||
console.log(' Code to redeem game:', chalk.blue(code));
|
||||
db.data[user][title].code = code;
|
||||
db.data[user][title].status = 'claimed';
|
||||
// notify_game.status = `<a href="${redeem[store]}">${redeem_action}</a> ${code} on ${store}`;
|
||||
}
|
||||
// await page.pause();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ handleSIGINT();
|
|||
console.log('hello');
|
||||
console.error('hello error');
|
||||
try {
|
||||
let i = await prompt(); // SIGINT no longer handled if this is executed
|
||||
i = await prompt(); // SIGINT no longer handled if this is executed
|
||||
console.log('value:', i);
|
||||
const first = await prompt(); // SIGINT no longer handled if this is executed
|
||||
const second = await prompt(); // SIGINT no longer handled if this is executed
|
||||
console.log('values:', first, second);
|
||||
setTimeout(() => console.log('timeout 3s'), 3000);
|
||||
} catch (e) {
|
||||
process.exitCode ||= 1;
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ try {
|
|||
await page.click('button[type="submit"]');
|
||||
await page.fill('#password', password);
|
||||
await page.click('button[type="submit"]');
|
||||
void (async () => {
|
||||
const watchCaptchaDuringLogin = async () => {
|
||||
try {
|
||||
await page.waitForSelector('#h_captcha_challenge_login_prod iframe', { timeout: 15000 });
|
||||
console.error('Got a captcha during login (likely due to too many attempts)! You may solve it in the browser, get a new IP or try again in a few hours.');
|
||||
|
|
@ -67,8 +67,8 @@ try {
|
|||
} catch {
|
||||
return;
|
||||
}
|
||||
})();
|
||||
void (async () => {
|
||||
};
|
||||
const watchMfa = async () => {
|
||||
try {
|
||||
await page.waitForURL('**/id/login/mfa**', { timeout: cfg.login_timeout });
|
||||
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 ...');
|
||||
|
|
@ -78,7 +78,9 @@ try {
|
|||
} catch {
|
||||
return;
|
||||
}
|
||||
})();
|
||||
};
|
||||
watchCaptchaDuringLogin();
|
||||
watchMfa();
|
||||
} else {
|
||||
console.log('Waiting for you to login in the browser.');
|
||||
await notify('unrealengine: no longer signed in and not enough options set for automatic login.');
|
||||
|
|
@ -125,7 +127,7 @@ try {
|
|||
}
|
||||
ids.push(id);
|
||||
}
|
||||
if (!ids.length) {
|
||||
if (ids.length === 0) {
|
||||
console.log('Nothing to claim');
|
||||
} else {
|
||||
await page.waitForTimeout(2000);
|
||||
|
|
@ -142,7 +144,7 @@ try {
|
|||
await page.locator('button.checkout').click();
|
||||
console.log('Click checkout');
|
||||
// maybe: Accept End User License Agreement
|
||||
void (async () => {
|
||||
const acceptEulaIfPresent = async () => {
|
||||
try {
|
||||
await page.locator('[name=accept-label]').check({ timeout: 10000 });
|
||||
console.log('Accept End User License Agreement');
|
||||
|
|
@ -150,7 +152,8 @@ try {
|
|||
} catch {
|
||||
return;
|
||||
}
|
||||
})();
|
||||
};
|
||||
acceptEulaIfPresent();
|
||||
await page.waitForSelector('#webPurchaseContainer iframe');
|
||||
const iframe = page.frameLocator('#webPurchaseContainer iframe');
|
||||
|
||||
|
|
@ -166,25 +169,27 @@ try {
|
|||
|
||||
// I Agree button is only shown for EU accounts! https://github.com/vogler/free-games-claimer/pull/7#issuecomment-1038964872
|
||||
const btnAgree = iframe.locator('button:has-text("I Agree")');
|
||||
void (async () => {
|
||||
const acceptIfRequired = async () => {
|
||||
try {
|
||||
await btnAgree.waitFor({ timeout: 10000 });
|
||||
await btnAgree.click();
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
})(); // EU: wait for and click 'I Agree'
|
||||
}; // EU: wait for and click 'I Agree'
|
||||
acceptIfRequired();
|
||||
try {
|
||||
// context.setDefaultTimeout(100 * 1000); // give time to solve captcha, iframe goes blank after 60s?
|
||||
const captcha = iframe.locator('#h_captcha_challenge_checkout_free_prod iframe');
|
||||
void (async () => {
|
||||
const watchCaptchaChallenge = async () => {
|
||||
try {
|
||||
await captcha.waitFor({ timeout: 10000 });
|
||||
console.error(' Got hcaptcha challenge! Lost trust due to too many login attempts? You can solve the captcha in the browser or get a new IP address.');
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
})(); // may time out if not shown
|
||||
}; // may time out if not shown
|
||||
watchCaptchaChallenge();
|
||||
await page.waitForSelector('text=Thank you');
|
||||
for (const id of ids) {
|
||||
db.data[user][id].status = 'claimed';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue