@thetypefounders/continue-with-google 1.5.0 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env-example +3 -0
- package/.github/workflows/build.yml +3 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +15 -3
- package/package.json +11 -7
- package/src/index.ts +13 -1
- package/test/index.test.ts +31 -0
package/.env-example
ADDED
package/dist/index.d.ts
CHANGED
|
@@ -12,4 +12,6 @@ export type Options = {
|
|
|
12
12
|
screenshot?: string;
|
|
13
13
|
waitForSelector?: WaitForSelectorOptions;
|
|
14
14
|
};
|
|
15
|
+
export declare class CaptchaError extends Error {
|
|
16
|
+
}
|
|
15
17
|
export declare function authenticate(page: Page, email: string, password: string, secret: string, selector: string, options?: Options, logger?: Logger): Promise<ElementHandle | null>;
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,8 @@ const DEFAULTS = {
|
|
|
7
7
|
trialCount: 10,
|
|
8
8
|
trialTimeoutSeconds: 2,
|
|
9
9
|
};
|
|
10
|
+
export class CaptchaError extends Error {
|
|
11
|
+
}
|
|
10
12
|
export async function authenticate(page, email, password, secret, selector, options = DEFAULTS, logger = console) {
|
|
11
13
|
const mergedOptions = { ...DEFAULTS, ...options };
|
|
12
14
|
logger.info('Waiting to enter the email...');
|
|
@@ -18,7 +20,17 @@ export async function authenticate(page, email, password, secret, selector, opti
|
|
|
18
20
|
await page.keyboard.press('Enter');
|
|
19
21
|
logger.info('Waiting to enter the password...');
|
|
20
22
|
await showScreenshot(page, mergedOptions.screenshot, logger);
|
|
21
|
-
await
|
|
23
|
+
const captcha = await Promise.any([
|
|
24
|
+
page
|
|
25
|
+
.waitForSelector('input[type=password]', { visible: true })
|
|
26
|
+
.then(() => false),
|
|
27
|
+
page
|
|
28
|
+
.waitForSelector('input[type=text]', { visible: true })
|
|
29
|
+
.then(() => true),
|
|
30
|
+
]);
|
|
31
|
+
if (captcha) {
|
|
32
|
+
throw new CaptchaError('failed to proceed due to CAPTCHA');
|
|
33
|
+
}
|
|
22
34
|
logger.info('Entering the password...');
|
|
23
35
|
await showScreenshot(page, mergedOptions.screenshot, logger);
|
|
24
36
|
await page.type('input[type=password]', password);
|
|
@@ -73,7 +85,7 @@ async function takeContent(page, logger) {
|
|
|
73
85
|
return await page.evaluate(() => document.body.innerText);
|
|
74
86
|
}
|
|
75
87
|
catch (cause) {
|
|
76
|
-
logger.error(new Error(`
|
|
88
|
+
logger.error(new Error(`failed to take the content`, { cause }));
|
|
77
89
|
return undefined;
|
|
78
90
|
}
|
|
79
91
|
}
|
|
@@ -84,7 +96,7 @@ async function takeImage(page, logger) {
|
|
|
84
96
|
return await page.screenshot({ encoding: 'base64' });
|
|
85
97
|
}
|
|
86
98
|
catch (cause) {
|
|
87
|
-
logger.error(new Error(`
|
|
99
|
+
logger.error(new Error(`failed to take a screenshot`, { cause }));
|
|
88
100
|
return undefined;
|
|
89
101
|
}
|
|
90
102
|
}
|
package/package.json
CHANGED
|
@@ -1,31 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thetypefounders/continue-with-google",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.2",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"author": "Ivan Ukhov <ivan.ukhov@gmail.com>",
|
|
6
6
|
"description": "Two-factor authentication with Google via Puppeteer",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "https://github.com/the-type-founders/continue-with-google.git"
|
|
9
|
+
"url": "git+https://github.com/the-type-founders/continue-with-google.git"
|
|
10
10
|
},
|
|
11
11
|
"type": "module",
|
|
12
12
|
"main": "dist/index.js",
|
|
13
13
|
"types": "dist/index.d.ts",
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"authenticator": "^1.1.5",
|
|
16
|
-
"puppeteer": "^24.
|
|
16
|
+
"puppeteer": "^24.34.0"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@trivago/prettier-plugin-sort-imports": "^
|
|
19
|
+
"@trivago/prettier-plugin-sort-imports": "^6.0.0",
|
|
20
20
|
"@types/authenticator": "^1.1.4",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
21
|
+
"dotenv": "^17.2.3",
|
|
22
|
+
"prettier": "^3.7.4",
|
|
23
|
+
"puppeteer-extra": "^3.3.6",
|
|
24
|
+
"puppeteer-extra-plugin-stealth": "^2.11.2",
|
|
25
|
+
"typescript": "^5.9.3",
|
|
26
|
+
"vitest": "^4.0.16"
|
|
23
27
|
},
|
|
24
28
|
"scripts": {
|
|
25
29
|
"build": "tsc",
|
|
26
30
|
"check": "prettier . --check",
|
|
27
31
|
"format": "prettier . --check --write",
|
|
28
32
|
"prepublish": "tsc",
|
|
29
|
-
"test": "
|
|
33
|
+
"test": "vitest --bail=1"
|
|
30
34
|
}
|
|
31
35
|
}
|
package/src/index.ts
CHANGED
|
@@ -25,6 +25,8 @@ const DEFAULTS: Options = {
|
|
|
25
25
|
trialTimeoutSeconds: 2,
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
+
export class CaptchaError extends Error {}
|
|
29
|
+
|
|
28
30
|
export async function authenticate(
|
|
29
31
|
page: Page,
|
|
30
32
|
email: string,
|
|
@@ -47,7 +49,17 @@ export async function authenticate(
|
|
|
47
49
|
|
|
48
50
|
logger.info('Waiting to enter the password...');
|
|
49
51
|
await showScreenshot(page, mergedOptions.screenshot, logger);
|
|
50
|
-
await
|
|
52
|
+
const captcha = await Promise.any([
|
|
53
|
+
page
|
|
54
|
+
.waitForSelector('input[type=password]', { visible: true })
|
|
55
|
+
.then(() => false),
|
|
56
|
+
page
|
|
57
|
+
.waitForSelector('input[type=text]', { visible: true })
|
|
58
|
+
.then(() => true),
|
|
59
|
+
]);
|
|
60
|
+
if (captcha) {
|
|
61
|
+
throw new CaptchaError('failed to proceed due to CAPTCHA');
|
|
62
|
+
}
|
|
51
63
|
|
|
52
64
|
logger.info('Entering the password...');
|
|
53
65
|
await showScreenshot(page, mergedOptions.screenshot, logger);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import PuppeteerExtra from 'puppeteer-extra';
|
|
4
|
+
import StealthPlugin from 'puppeteer-extra-plugin-stealth';
|
|
5
|
+
import { test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { authenticate } from '../src/index.js';
|
|
8
|
+
|
|
9
|
+
test('authenticate', { timeout: 5 * 60 * 1000 }, async () => {
|
|
10
|
+
PuppeteerExtra.use(StealthPlugin());
|
|
11
|
+
const browser = await PuppeteerExtra.launch({
|
|
12
|
+
args: ['--no-sandbox'],
|
|
13
|
+
slowMo: parseInt(process.env.PUPPETEER_SLOW_MOTION || '100'),
|
|
14
|
+
});
|
|
15
|
+
try {
|
|
16
|
+
const page = await browser.newPage();
|
|
17
|
+
await page.setViewport({ width: 1280, height: 800 });
|
|
18
|
+
await page.goto('https://mail.google.com');
|
|
19
|
+
await assert.doesNotReject(
|
|
20
|
+
authenticate(
|
|
21
|
+
page,
|
|
22
|
+
process.env.GOOGLE_USER_EMAIL!,
|
|
23
|
+
process.env.GOOGLE_USER_PASSWORD!,
|
|
24
|
+
process.env.GOOGLE_USER_SECRET!,
|
|
25
|
+
'[aria-label="Search mail"]'
|
|
26
|
+
)
|
|
27
|
+
);
|
|
28
|
+
} finally {
|
|
29
|
+
await browser.close();
|
|
30
|
+
}
|
|
31
|
+
});
|