disable Playwright's handleSIGINT and close context ourselves to save recordings also on SIGINT

This commit is contained in:
Ralf Vogler 2023-09-18 12:58:20 +02:00
parent 1fbabbc0f2
commit b748460b73
5 changed files with 24 additions and 15 deletions

View file

@ -14,8 +14,6 @@ console.log(datetime(), 'started checking epic-games');
const db = await jsonDb('epic-games.json', {}); const db = await jsonDb('epic-games.json', {});
handleSIGINT();
if (cfg.time) console.time('startup'); if (cfg.time) console.time('startup');
// https://www.nopecha.com extension source from https://github.com/NopeCHA/NopeCHA/releases/tag/0.1.16 // 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 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 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 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 args: [ // https://peter.sh/experiments/chromium-command-line-switches
// don't want to see bubble 'Restore pages? Chrome didn't shut down correctly.' // don't want to see bubble 'Restore pages? Chrome didn't shut down correctly.'
// '--restore-last-session', // does not apply for crash/killed // '--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.'. // 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. // 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); await stealth(context);
@ -248,8 +249,9 @@ try {
} }
if (cfg.time) console.timeEnd('claim all games'); if (cfg.time) console.timeEnd('claim all games');
} catch (error) { } catch (error) {
console.error(error); // .toString()?
process.exitCode ||= 1; process.exitCode ||= 1;
console.error('--- Exception:');
console.error(error); // .toString()?
if (error.message && process.exitCode != 130) if (error.message && process.exitCode != 130)
notify(`epic-games failed: ${error.message.split('\n')[0]}`); notify(`epic-games failed: ${error.message.split('\n')[0]}`);
} finally { } finally {

12
gog.js
View file

@ -10,17 +10,18 @@ console.log(datetime(), 'started checking gog');
const db = await jsonDb('gog.json', {}); const db = await jsonDb('gog.json', {});
handleSIGINT();
// 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 firefox.launchPersistentContext(cfg.dir.browser, {
headless: cfg.headless, headless: cfg.headless,
viewport: { width: cfg.width, height: cfg.height }, 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 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: 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
// recordVideo: { dir: './data/videos' }, // console.log(await page.video().path()); 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); 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
@ -135,8 +136,9 @@ try {
} }
} }
} catch (error) { } catch (error) {
console.error(error); // .toString()?
process.exitCode ||= 1; process.exitCode ||= 1;
console.error('--- Exception:');
console.error(error); // .toString()?
if (error.message && process.exitCode != 130) if (error.message && process.exitCode != 130)
notify(`gog failed: ${error.message.split('\n')[0]}`); notify(`gog failed: ${error.message.split('\n')[0]}`);
} finally { } finally {

View file

@ -12,8 +12,6 @@ console.log(datetime(), 'started checking prime-gaming');
const db = await jsonDb('prime-gaming.json', {}); const db = await jsonDb('prime-gaming.json', {});
handleSIGINT();
// 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 firefox.launchPersistentContext(cfg.dir.browser, {
headless: cfg.headless, 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 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 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 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 // TODO test if needed
await stealth(context); await stealth(context);
@ -377,8 +378,9 @@ try {
console.log('DLC: Unlinked accounts:', dlc_unlinked); console.log('DLC: Unlinked accounts:', dlc_unlinked);
} }
} catch (error) { } catch (error) {
console.error(error); // .toString()?
process.exitCode ||= 1; process.exitCode ||= 1;
console.error('--- Exception:');
console.error(error); // .toString()?
if (error.message && process.exitCode != 130) if (error.message && process.exitCode != 130)
notify(`prime-gaming failed: ${error.message.split('\n')[0]}`); notify(`prime-gaming failed: ${error.message.split('\n')[0]}`);
} finally { } finally {

View file

@ -17,8 +17,6 @@ console.log(datetime(), 'started checking unrealengine');
const db = await jsonDb('unrealengine.json', {}); const db = await jsonDb('unrealengine.json', {});
handleSIGINT();
// 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 firefox.launchPersistentContext(cfg.dir.browser, {
headless: cfg.headless, 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 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 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 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); await stealth(context);
if (!cfg.debug) context.setDefaultTimeout(cfg.timeout); if (!cfg.debug) context.setDefaultTimeout(cfg.timeout);
@ -188,8 +189,9 @@ try {
console.log('Done'); console.log('Done');
} }
} catch (error) { } catch (error) {
console.error(error); // .toString()?
process.exitCode ||= 1; process.exitCode ||= 1;
console.error('--- Exception:');
console.error(error); // .toString()?
if (error.message && process.exitCode != 130) if (error.message && process.exitCode != 130)
notify(`unrealengine failed: ${error.message.split('\n')[0]}`); notify(`unrealengine failed: ${error.message.split('\n')[0]}`);
} finally { } finally {

View file

@ -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 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 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... 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 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 // stealth with playwright: https://github.com/berstend/puppeteer-extra/issues/454#issuecomment-917437212