From 13e6f05cd0732c21a226caf002c9998fbd23cc8a Mon Sep 17 00:00:00 2001 From: Ralf Vogler Date: Wed, 25 Jan 2023 18:54:23 +0100 Subject: [PATCH] pg: notify about games and login --- epic-games.js | 2 +- prime-gaming.js | 28 ++++++++++++++++++++++------ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/epic-games.js b/epic-games.js index 98bcf3d..6ab8d2d 100644 --- a/epic-games.js +++ b/epic-games.js @@ -194,7 +194,7 @@ try { } } catch (error) { console.error(error); // .toString()? - if (!error.message.contains('Target closed')) // e.g. when killed by Ctrl-C + if (error.message && !error.message.contains('Target closed')) // e.g. when killed by Ctrl-C notify(`epic-games failed: ${error.message}`); } finally { await db.write(); // write out json db diff --git a/prime-gaming.js b/prime-gaming.js index e562452..ebf4785 100644 --- a/prime-gaming.js +++ b/prime-gaming.js @@ -1,7 +1,7 @@ import { firefox } from 'playwright'; // stealth plugin needs no outdated playwright-extra import { authenticator } from 'otplib'; import path from 'path'; -import { dirs, jsonDb, datetime, stealth, filenamify } from './util.js'; +import { dirs, jsonDb, datetime, stealth, filenamify, notify } from './util.js'; import { cfg } from './config.js'; import prompts from 'prompts'; // alternatives: enquirer, inquirer @@ -41,6 +41,8 @@ if (!cfg.debug) context.setDefaultTimeout(cfg.timeout); const page = context.pages().length ? context.pages()[0] : await context.newPage(); // should always exist // console.debug('userAgent:', await page.evaluate(() => navigator.userAgent)); +const notify_games = []; + try { await page.goto(URL_CLAIM, { waitUntil: 'domcontentloaded' }); // default 'load' takes forever // need to wait for some elements to exist before checking if signed in or accepting cookies: @@ -60,7 +62,7 @@ try { await page.click('input[type="submit"]'); page.waitForNavigation({ url: '**/ap/signin**'}).then(async () => { // TODO check for wrong credentials console.error(await page.locator('.a-alert-content').first().innerText()); - }).catch(_ => { }); + }); // handle MFA, but don't await it page.waitForNavigation({ url: '**/ap/mfa**'}).then(async () => { console.log('Two-Step Verification - enter the One Time Password (OTP), e.g. generated by your Authenticator App'); @@ -70,12 +72,13 @@ try { await page.click('input[type="submit"]'); }).catch(_ => { }); } else { + console.log('Waiting for you to login in the browser.'); + notify('prime-gaming: no longer signed in and not enough options set for automatic login.'); if (cfg.headless) { console.log('Please run `node prime-gaming show` to login in the opened browser.'); await context.close(); // not needed? process.exit(1); } - console.log('Waiting for you to login in the browser.'); } await page.waitForNavigation({ url: 'https://gaming.amazon.com/home?signedIn=true' }); if (!cfg.debug) context.setDefaultTimeout(cfg.timeout); @@ -108,6 +111,7 @@ try { await card.screenshot({ path: p }); await (await card.$('button:has-text("Claim game")')).click(); db.data[user][title] ||= { title, time: datetime(), store: 'internal' }; + notify_games.push({ title, status: 'claimed', url: URL_CLAIM }); // await page.pause(); } // claim games in external/linked stores. Linked: origin.com, epicgames.com; Redeem-key: gog.com, legacygames.com, microsoft @@ -129,6 +133,10 @@ try { // 3 Full PC Games on Legacy Games const store = store_text.toLowerCase().replace(/.* on /, ''); console.log(' External store:', store); + const url = page.url().split('?')[0]; + db.data[user][title] ||= { title, time: datetime(), url, store }; + const notify_game = {title, url, status: `failed - link ${store}`}; + notify_games.push(notify_game); // status is updated below if (await page.locator('div:has-text("Link game account")').count()) { console.error(' Account linking is required to claim this offer!'); } else { @@ -139,16 +147,18 @@ try { 'legacy games': 'https://www.legacygames.com/primedeal', 'microsoft games': 'https://redeem.microsoft.com', }; - let code; if (store in redeem) { // did not work for linked origin: && !await page.locator('div:has-text("Successfully Claimed")').count() - code = await page.inputValue('input[type="text"]'); + const code = await page.inputValue('input[type="text"]'); console.log(' Code to redeem game:', code); if (store == 'legacy games') { // may be different URL like https://legacygames.com/primeday/puzzleoftheyear/ redeem[store] = await (await page.$('li:has-text("Click here") a')).getAttribute('href'); } console.log(' URL to redeem game:', redeem[store]); + db.data[user][title].code = code; + notify_game.status = `redeem ${code} on ${store}`; + } else { + notify_game.status = `claimed on ${store}`; } - db.data[user][title] ||= { title, time: datetime(), store, code, url: page.url() }; // save screenshot of potential code just in case const p = path.resolve(dirs.screenshots, 'prime-gaming', 'external', `${filenamify(title)}.png`); await page.screenshot({ path: p, fullPage: true }); @@ -163,7 +173,13 @@ try { await page.locator(games_sel).screenshot({ path: p }); } catch (error) { console.error(error); // .toString()? + if (error.message && !error.message.contains('Target closed')) // e.g. when killed by Ctrl-C + notify(`prime-gaming failed: ${error.message}`); } finally { await db.write(); // write out json db + if (notify_games.length) { // list should only include claimed games + const list = notify_games.map(g => `- ${g.title} (${g.status})
`); + notify(`prime-gaming:
${list}`); + } } await context.close();