From b748460b731bd565592e1c68c01a2c4eca9ae1a2 Mon Sep 17 00:00:00 2001 From: Ralf Vogler Date: Mon, 18 Sep 2023 12:58:20 +0200 Subject: [PATCH] disable Playwright's handleSIGINT and close context ourselves to save recordings also on SIGINT --- epic-games.js | 8 +++++--- gog.js | 12 +++++++----- prime-gaming.js | 8 +++++--- unrealengine.js | 8 +++++--- util.js | 3 ++- 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/epic-games.js b/epic-games.js index 56c1035..e58725b 100644 --- a/epic-games.js +++ b/epic-games.js @@ -14,8 +14,6 @@ console.log(datetime(), 'started checking epic-games'); const db = await jsonDb('epic-games.json', {}); -handleSIGINT(); - if (cfg.time) console.time('startup'); // https://www.nopecha.com extension source from https://github.com/NopeCHA/NopeCHA/releases/tag/0.1.16 @@ -33,6 +31,7 @@ const context = await firefox.launchPersistentContext(cfg.dir.browser, { 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-${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 args: [ // https://peter.sh/experiments/chromium-command-line-switches // don't want to see bubble 'Restore pages? Chrome didn't shut down correctly.' // '--restore-last-session', // does not apply for crash/killed @@ -43,6 +42,8 @@ const context = await firefox.launchPersistentContext(cfg.dir.browser, { // ignoreDefaultArgs: ['--enable-automation'], // remove default arg that shows the info bar with 'Chrome is being controlled by automated test software.'. Since Chromeium 106 this leads to show another info bar with 'You are using an unsupported command-line flag: --no-sandbox. Stability and security will suffer.'. }); +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); @@ -248,8 +249,9 @@ try { } if (cfg.time) console.timeEnd('claim all games'); } catch (error) { - console.error(error); // .toString()? process.exitCode ||= 1; + console.error('--- Exception:'); + console.error(error); // .toString()? if (error.message && process.exitCode != 130) notify(`epic-games failed: ${error.message.split('\n')[0]}`); } finally { diff --git a/gog.js b/gog.js index 6b02ee5..341ee6c 100644 --- a/gog.js +++ b/gog.js @@ -10,17 +10,18 @@ console.log(datetime(), 'started checking gog'); const db = await jsonDb('gog.json', {}); -handleSIGINT(); - // https://playwright.dev/docs/auth#multi-factor-authentication const context = await firefox.launchPersistentContext(cfg.dir.browser, { headless: cfg.headless, viewport: { width: cfg.width, height: cfg.height }, locale: "en-US", // ignore OS locale to be sure to have english text for locators -> done via /en in URL - // recordHar: { path: './data/gog.har' }, // https://toolbox.googleapps.com/apps/har_analyzer/ - // recordVideo: { dir: './data/videos' }, // console.log(await page.video().path()); + 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/gog-${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 }); +handleSIGINT(context); + if (!cfg.debug) context.setDefaultTimeout(cfg.timeout); const page = context.pages().length ? context.pages()[0] : await context.newPage(); // should always exist @@ -135,8 +136,9 @@ try { } } } catch (error) { - console.error(error); // .toString()? process.exitCode ||= 1; + console.error('--- Exception:'); + console.error(error); // .toString()? if (error.message && process.exitCode != 130) notify(`gog failed: ${error.message.split('\n')[0]}`); } finally { diff --git a/prime-gaming.js b/prime-gaming.js index 1523e5f..a5df36d 100644 --- a/prime-gaming.js +++ b/prime-gaming.js @@ -12,8 +12,6 @@ console.log(datetime(), 'started checking prime-gaming'); const db = await jsonDb('prime-gaming.json', {}); -handleSIGINT(); - // https://playwright.dev/docs/auth#multi-factor-authentication const context = await firefox.launchPersistentContext(cfg.dir.browser, { headless: cfg.headless, @@ -21,8 +19,11 @@ const context = await firefox.launchPersistentContext(cfg.dir.browser, { 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/pg-${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 }); +handleSIGINT(context); + // TODO test if needed await stealth(context); @@ -377,8 +378,9 @@ try { console.log('DLC: Unlinked accounts:', dlc_unlinked); } } catch (error) { - console.error(error); // .toString()? process.exitCode ||= 1; + console.error('--- Exception:'); + console.error(error); // .toString()? if (error.message && process.exitCode != 130) notify(`prime-gaming failed: ${error.message.split('\n')[0]}`); } finally { diff --git a/unrealengine.js b/unrealengine.js index a5d3282..6523503 100644 --- a/unrealengine.js +++ b/unrealengine.js @@ -17,8 +17,6 @@ console.log(datetime(), 'started checking unrealengine'); const db = await jsonDb('unrealengine.json', {}); -handleSIGINT(); - // https://playwright.dev/docs/auth#multi-factor-authentication const context = await firefox.launchPersistentContext(cfg.dir.browser, { headless: cfg.headless, @@ -28,8 +26,11 @@ const context = await firefox.launchPersistentContext(cfg.dir.browser, { 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/ue-${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 }); +handleSIGINT(context); + await stealth(context); if (!cfg.debug) context.setDefaultTimeout(cfg.timeout); @@ -188,8 +189,9 @@ try { console.log('Done'); } } catch (error) { - console.error(error); // .toString()? process.exitCode ||= 1; + console.error('--- Exception:'); + console.error(error); // .toString()? if (error.message && process.exitCode != 130) notify(`unrealengine failed: ${error.message.split('\n')[0]}`); } finally { diff --git a/util.js b/util.js index 60ff4a5..94cccfd 100644 --- a/util.js +++ b/util.js @@ -27,9 +27,10 @@ export const datetimeUTC = (d = new Date()) => d.toISOString().replace('T', ' ') export const datetime = (d = new Date()) => datetimeUTC(new Date(d.getTime() - d.getTimezoneOffset() * 60000)); export const filenamify = s => s.replaceAll(':', '.').replace(/[^a-z0-9 _\-.]/gi, '_'); // alternative: https://www.npmjs.com/package/filenamify - On Unix-like systems, / is reserved. On Windows, <>:"/\|?* along with trailing periods are reserved. -export const handleSIGINT = () => process.on('SIGINT', () => { // e.g. when killed by Ctrl-C +export const handleSIGINT = (context = null) => process.on('SIGINT', async () => { // e.g. when killed by Ctrl-C console.error('\nInterrupted by SIGINT. Exit!'); // Exception shows where the script was:\n'); // killed before catch in docker... process.exitCode = 130; // 128+SIGINT to indicate to parent that process was killed + if (context) await context.close(); // in order to save recordings also on SIGINT, we need to disable Playwright's handleSIGINT and close the context ourselves }); // stealth with playwright: https://github.com/berstend/puppeteer-extra/issues/454#issuecomment-917437212