Merge branch 'main' into gog
This commit is contained in:
commit
5202f7ac69
9 changed files with 63 additions and 46 deletions
12
.github/workflows/docker.yml
vendored
12
.github/workflows/docker.yml
vendored
|
|
@ -19,7 +19,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Set environment variables
|
||||
run: |
|
||||
|
|
@ -27,27 +27,27 @@ jobs:
|
|||
echo "NOW=$(date -R)" >> $GITHUB_ENV # date -Iseconds; date +'%Y-%m-%dT%H:%M:%S'
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
uses: docker/setup-qemu-action@v3
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v3
|
||||
-
|
||||
name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
# if: ${{ secrets.DOCKERHUB_USERNAME && secrets.DOCKERHUB_TOKEN }}
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
-
|
||||
name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
|
|
|
|||
|
|
@ -55,9 +55,10 @@ WORKDIR /fgc
|
|||
COPY package*.json ./
|
||||
|
||||
# Playwright installs patched firefox to ~/.cache/ms-playwright/firefox-*
|
||||
# Requires some system deps to run (see install-deps above).
|
||||
# Requires some system deps to run (see inlined install-deps above).
|
||||
RUN npm install
|
||||
# Old: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD + install firefox (had to be done after `npm install` to get the correct version). Now: playwright-firefox as npm dep and `npm install` will only install that.
|
||||
# From 1.38 Playwright will no longer install browser automatically for playwright, but apparently still for playwright-firefox: https://github.com/microsoft/playwright/releases/tag/v1.38.0
|
||||
# RUN npx playwright install firefox
|
||||
|
||||
COPY . .
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -31,8 +29,9 @@ const context = await firefox.launchPersistentContext(cfg.dir.browser, {
|
|||
// userAgent firefox (macOS): Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:106.0) Gecko/20100101 Firefox/106.0
|
||||
// userAgent firefox (docker): Mozilla/5.0 (X11; Linux aarch64; rv:109.0) Gecko/20100101 Firefox/115.0
|
||||
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: path.resolve('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);
|
||||
|
||||
|
|
@ -98,7 +99,7 @@ try {
|
|||
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 ...');
|
||||
// TODO locator for text (email or app?)
|
||||
const otp = cfg.eg_otpkey && authenticator.generate(cfg.eg_otpkey) || await prompt({type: 'text', message: 'Enter two-factor sign in code', validate: n => n.toString().length == 6 || 'The code must be 6 digits!'}); // can't use type: 'number' since it strips away leading zeros and codes sometimes have them
|
||||
await page.type('input[name="code-input-0"]', otp.toString());
|
||||
await page.locator('input[name="code-input-0"]').pressSequentially(otp.toString());
|
||||
await page.click('button[type="submit"]');
|
||||
}).catch(_ => { });
|
||||
} else {
|
||||
|
|
@ -195,7 +196,7 @@ try {
|
|||
console.error(' EG_PARENTALPIN not set. Need to enter Parental Control PIN manually.');
|
||||
notify('epic-games: EG_PARENTALPIN not set. Need to enter Parental Control PIN manually.');
|
||||
}
|
||||
await iframe.locator('input.payment-pin-code__input').first().type(cfg.eg_parentalpin);
|
||||
await iframe.locator('input.payment-pin-code__input').first().pressSequentially(cfg.eg_parentalpin);
|
||||
await iframe.locator('button:has-text("Continue")').click({ delay: 11 });
|
||||
}).catch(_ => { });
|
||||
|
||||
|
|
@ -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 {
|
||||
|
|
@ -259,4 +261,5 @@ try {
|
|||
}
|
||||
}
|
||||
if (cfg.debug) writeFileSync(path.resolve(cfg.dir.browser, 'cookies.json'), JSON.stringify(await context.cookies()));
|
||||
if (page.video()) console.log('Recorded video:', await page.video().path())
|
||||
await context.close();
|
||||
|
|
|
|||
17
gog.js
17
gog.js
|
|
@ -1,4 +1,5 @@
|
|||
import { firefox } from 'playwright-firefox'; // stealth plugin needs no outdated playwright-extra
|
||||
import path from 'path';
|
||||
import { resolve, jsonDb, datetime, filenamify, prompt, notify, html_game_list, handleSIGINT } from './util.js';
|
||||
import { cfg } from './config.js';
|
||||
import path from "path";
|
||||
|
|
@ -12,17 +13,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: path.resolve('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
|
||||
|
|
@ -61,7 +63,7 @@ try {
|
|||
console.log('Two-Step Verification - Enter security code');
|
||||
console.log(await iframe.locator('.form__description').innerText())
|
||||
const otp = await prompt({type: 'text', message: 'Enter two-factor sign in code', validate: n => n.toString().length == 4 || 'The code must be 4 digits!'}); // can't use type: 'number' since it strips away leading zeros and codes sometimes have them
|
||||
await iframe.locator('#second_step_authentication_token_letter_1').type(otp.toString(), {delay: 10});
|
||||
await iframe.locator('#second_step_authentication_token_letter_1').pressSequentially(otp.toString(), {delay: 10});
|
||||
await iframe.locator('#second_step_authentication_send').click();
|
||||
await page.waitForTimeout(1000); // TODO still needed with wait for username below?
|
||||
}).catch(_ => { });
|
||||
|
|
@ -96,8 +98,9 @@ try {
|
|||
await claimFreegames();
|
||||
}
|
||||
} 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 {
|
||||
|
|
@ -152,6 +155,7 @@ async function claimGiveaway() {
|
|||
if (status == 'claimed' && !cfg.gog_newsletter) {
|
||||
console.log("Unsubscribe from 'Promotions and hot deals' newsletter");
|
||||
await page.goto('https://www.gog.com/en/account/settings/subscriptions');
|
||||
await page.locator('li:has-text("Marketing communications through Trusted Partners") label').uncheck();
|
||||
await page.locator('li:has-text("Promotions and hot deals") label').uncheck();
|
||||
}
|
||||
}
|
||||
|
|
@ -291,4 +295,5 @@ function isNotClaimedUrl(url) {
|
|||
}
|
||||
}
|
||||
|
||||
if (page.video()) console.log('Recorded video:', await page.video().path())
|
||||
await context.close();
|
||||
|
|
|
|||
30
package-lock.json
generated
30
package-lock.json
generated
|
|
@ -14,7 +14,7 @@
|
|||
"enquirer": "^2.4.1",
|
||||
"lowdb": "^6.0.1",
|
||||
"otplib": "^12.0.1",
|
||||
"playwright-firefox": "^1.37.1",
|
||||
"playwright-firefox": "^1.38.0",
|
||||
"puppeteer-extra-plugin-stealth": "^2.11.2"
|
||||
}
|
||||
},
|
||||
|
|
@ -448,9 +448,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.37.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.37.1.tgz",
|
||||
"integrity": "sha512-17EuQxlSIYCmEMwzMqusJ2ztDgJePjrbttaefgdsiqeLWidjYz9BxXaTaZWxH1J95SHGk6tjE+dwgWILJoUZfA==",
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.0.tgz",
|
||||
"integrity": "sha512-f8z1y8J9zvmHoEhKgspmCvOExF2XdcxMW8jNRuX4vkQFrzV4MlZ55iwb5QeyiFQgOFCUolXiRHgpjSEnqvO48g==",
|
||||
"bin": {
|
||||
"playwright-core": "cli.js"
|
||||
},
|
||||
|
|
@ -459,12 +459,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/playwright-firefox": {
|
||||
"version": "1.37.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-firefox/-/playwright-firefox-1.37.1.tgz",
|
||||
"integrity": "sha512-I8QScyW+hjGltywqLNh3Y1W96/3x70el9wNneuI34l3uVhiCRt9Co27+kiL+UlA1V8MTzaMere3ONQ8lGeut5w==",
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-firefox/-/playwright-firefox-1.38.0.tgz",
|
||||
"integrity": "sha512-uNXdvj17JHbKir/EmdLtYEHkzI0ttFMX/3+HO/TW5z1hRmN5CydDNINm9xL/0AwvFSa5unZPM7S7+mUa3EiniA==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"playwright-core": "1.37.1"
|
||||
"playwright-core": "1.38.0"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
|
|
@ -1032,16 +1032,16 @@
|
|||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
|
||||
},
|
||||
"playwright-core": {
|
||||
"version": "1.37.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.37.1.tgz",
|
||||
"integrity": "sha512-17EuQxlSIYCmEMwzMqusJ2ztDgJePjrbttaefgdsiqeLWidjYz9BxXaTaZWxH1J95SHGk6tjE+dwgWILJoUZfA=="
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.0.tgz",
|
||||
"integrity": "sha512-f8z1y8J9zvmHoEhKgspmCvOExF2XdcxMW8jNRuX4vkQFrzV4MlZ55iwb5QeyiFQgOFCUolXiRHgpjSEnqvO48g=="
|
||||
},
|
||||
"playwright-firefox": {
|
||||
"version": "1.37.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-firefox/-/playwright-firefox-1.37.1.tgz",
|
||||
"integrity": "sha512-I8QScyW+hjGltywqLNh3Y1W96/3x70el9wNneuI34l3uVhiCRt9Co27+kiL+UlA1V8MTzaMere3ONQ8lGeut5w==",
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-firefox/-/playwright-firefox-1.38.0.tgz",
|
||||
"integrity": "sha512-uNXdvj17JHbKir/EmdLtYEHkzI0ttFMX/3+HO/TW5z1hRmN5CydDNINm9xL/0AwvFSa5unZPM7S7+mUa3EiniA==",
|
||||
"requires": {
|
||||
"playwright-core": "1.37.1"
|
||||
"playwright-core": "1.38.0"
|
||||
}
|
||||
},
|
||||
"puppeteer-extra-plugin": {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
"enquirer": "^2.4.1",
|
||||
"lowdb": "^6.0.1",
|
||||
"otplib": "^12.0.1",
|
||||
"playwright-firefox": "^1.37.1",
|
||||
"playwright-firefox": "^1.38.0",
|
||||
"puppeteer-extra-plugin-stealth": "^2.11.2"
|
||||
},
|
||||
"repository": {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { firefox } from 'playwright-firefox'; // stealth plugin needs no outdated playwright-extra
|
||||
import { authenticator } from 'otplib';
|
||||
import path from 'path';
|
||||
import { resolve, jsonDb, datetime, stealth, filenamify, prompt, confirm, notify, html_game_list, handleSIGINT } from './util.js';
|
||||
import { cfg } from './config.js';
|
||||
|
||||
|
|
@ -12,17 +13,18 @@ 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,
|
||||
viewport: { width: cfg.width, height: cfg.height },
|
||||
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: path.resolve('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);
|
||||
|
||||
|
|
@ -66,7 +68,7 @@ try {
|
|||
console.log('Two-Step Verification - enter the One Time Password (OTP), e.g. generated by your Authenticator App');
|
||||
await page.check('[name=rememberDevice]');
|
||||
const otp = cfg.pg_otpkey && authenticator.generate(cfg.pg_otpkey) || await prompt({type: 'text', message: 'Enter two-factor sign in code', validate: n => n.toString().length == 6 || 'The code must be 6 digits!'}); // can't use type: 'number' since it strips away leading zeros and codes sometimes have them
|
||||
await page.type('input[name=otpCode]', otp.toString());
|
||||
await page.locator('input[name=otpCode]').pressSequentially(otp.toString());
|
||||
await page.click('input[type="submit"]');
|
||||
}).catch(_ => { });
|
||||
} else {
|
||||
|
|
@ -377,8 +379,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 {
|
||||
|
|
@ -387,4 +390,5 @@ try {
|
|||
notify(`prime-gaming (${user}):<br>${html_game_list(notify_games)}`);
|
||||
}
|
||||
}
|
||||
if (page.video()) console.log('Recorded video:', await page.video().path())
|
||||
await context.close();
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -26,10 +24,13 @@ const context = await firefox.launchPersistentContext(cfg.dir.browser, {
|
|||
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36', // see replace of Headless in util.newStealthContext. TODO Windows UA enough to avoid 'device not supported'? update if browser is updated?
|
||||
// userAgent for firefox: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:106.0) Gecko/20100101 Firefox/106.0
|
||||
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: path.resolve('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);
|
||||
|
|
@ -71,7 +72,7 @@ try {
|
|||
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 ...');
|
||||
// TODO locator for text (email or app?)
|
||||
const otp = cfg.eg_otpkey && authenticator.generate(cfg.eg_otpkey) || await prompt({type: 'text', message: 'Enter two-factor sign in code', validate: n => n.toString().length == 6 || 'The code must be 6 digits!'}); // can't use type: 'number' since it strips away leading zeros and codes sometimes have them
|
||||
await page.type('input[name="code-input-0"]', otp.toString());
|
||||
await page.locator('input[name="code-input-0"]').pressSequentially(otp.toString());
|
||||
await page.click('button[type="submit"]');
|
||||
}).catch(_ => { });
|
||||
} else {
|
||||
|
|
@ -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 {
|
||||
|
|
@ -199,4 +201,5 @@ try {
|
|||
}
|
||||
}
|
||||
if (cfg.debug) writeFileSync(path.resolve(cfg.dir.browser, 'cookies.json'), JSON.stringify(await context.cookies()));
|
||||
if (page.video()) console.log('Recorded video:', await page.video().path())
|
||||
await context.close();
|
||||
|
|
|
|||
3
util.js
3
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue