@thetypefounders/continue-with-google 1.2.1 → 1.3.1
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/dist/index.d.ts +1 -0
- package/dist/index.js +27 -9
- package/package.json +5 -5
- package/src/index.ts +30 -11
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export type Options = {
|
|
|
8
8
|
challengeTimeoutSeconds?: number;
|
|
9
9
|
trialCount?: number;
|
|
10
10
|
trialTimeoutSeconds?: number;
|
|
11
|
+
screenshot?: boolean;
|
|
11
12
|
waitForSelector?: WaitForSelectorOptions;
|
|
12
13
|
};
|
|
13
14
|
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,23 +7,32 @@ const DEFAULTS = {
|
|
|
7
7
|
trialTimeoutSeconds: 2,
|
|
8
8
|
};
|
|
9
9
|
export async function authenticate(page, email, password, secret, selector, options = DEFAULTS, logger = console) {
|
|
10
|
+
const mergedOptions = { ...DEFAULTS, ...options };
|
|
10
11
|
logger.info('Waiting to enter the email...');
|
|
12
|
+
if (mergedOptions.screenshot)
|
|
13
|
+
await takeScreenshotToDisplay(page);
|
|
11
14
|
await page.waitForSelector('input[type=email]', { visible: true });
|
|
12
15
|
logger.info('Entering the email...');
|
|
16
|
+
if (mergedOptions.screenshot)
|
|
17
|
+
await takeScreenshotToDisplay(page);
|
|
13
18
|
await page.type('input[type=email]', email);
|
|
14
19
|
await page.keyboard.press('Enter');
|
|
15
20
|
logger.info('Waiting to enter the password...');
|
|
21
|
+
if (mergedOptions.screenshot)
|
|
22
|
+
await takeScreenshotToDisplay(page);
|
|
16
23
|
await page.waitForSelector('input[type=password]', { visible: true });
|
|
17
24
|
logger.info('Entering the password...');
|
|
25
|
+
if (mergedOptions.screenshot)
|
|
26
|
+
await takeScreenshotToDisplay(page);
|
|
18
27
|
await page.type('input[type=password]', password);
|
|
19
28
|
await page.keyboard.press('Enter');
|
|
20
|
-
for (let attempt = 0, found = false; attempt <
|
|
29
|
+
for (let attempt = 0, found = false; attempt < mergedOptions.challengeCount && !found; attempt++) {
|
|
21
30
|
if (attempt > 0) {
|
|
22
31
|
logger.warn(`Challenged on attempt ${attempt}. Entering the code...`);
|
|
32
|
+
if (mergedOptions.screenshot)
|
|
33
|
+
await takeScreenshotToDisplay(page);
|
|
23
34
|
if (attempt > 1) {
|
|
24
|
-
await setTimeout(1000 *
|
|
25
|
-
(options.challengeTimeoutSeconds ||
|
|
26
|
-
DEFAULTS.challengeTimeoutSeconds));
|
|
35
|
+
await setTimeout(1000 * mergedOptions.challengeTimeoutSeconds);
|
|
27
36
|
}
|
|
28
37
|
const code = generateToken(secret);
|
|
29
38
|
await page.evaluate(() => {
|
|
@@ -32,10 +41,12 @@ export async function authenticate(page, email, password, secret, selector, opti
|
|
|
32
41
|
});
|
|
33
42
|
await page.type('input[type=tel]', code);
|
|
34
43
|
await page.keyboard.press('Enter');
|
|
35
|
-
await waitForTrial(page,
|
|
44
|
+
await waitForTrial(page, mergedOptions.trialCount, mergedOptions.trialTimeoutSeconds, mergedOptions.screenshot, logger);
|
|
36
45
|
}
|
|
37
46
|
found = await Promise.any([
|
|
38
|
-
page
|
|
47
|
+
page
|
|
48
|
+
.waitForSelector(selector, mergedOptions.waitForSelector)
|
|
49
|
+
.then(() => true),
|
|
39
50
|
page
|
|
40
51
|
.waitForSelector('input[type=tel]', { visible: true })
|
|
41
52
|
.then(() => false),
|
|
@@ -43,22 +54,24 @@ export async function authenticate(page, email, password, secret, selector, opti
|
|
|
43
54
|
}
|
|
44
55
|
return await page.$(selector);
|
|
45
56
|
}
|
|
46
|
-
async function waitForTrial(page, attemptCount, attemptTimeoutSeconds, logger) {
|
|
57
|
+
async function waitForTrial(page, attemptCount, attemptTimeoutSeconds, screenshot, logger) {
|
|
47
58
|
for (let attempt = -1, previous = undefined, current = undefined; attempt < attemptCount && (current === undefined || previous !== current); attempt++) {
|
|
48
59
|
if (attempt > 0) {
|
|
49
60
|
logger.warn(`Tried on attempt ${attempt}. Waiting to finish...`);
|
|
61
|
+
if (screenshot)
|
|
62
|
+
await takeScreenshotToDisplay(page);
|
|
50
63
|
}
|
|
51
64
|
if (attempt > -1) {
|
|
52
65
|
await setTimeout(1000 * attemptTimeoutSeconds);
|
|
53
66
|
}
|
|
54
|
-
const future = await
|
|
67
|
+
const future = await takeScreenshotToCompare(page);
|
|
55
68
|
if (future) {
|
|
56
69
|
previous = current;
|
|
57
70
|
current = future;
|
|
58
71
|
}
|
|
59
72
|
}
|
|
60
73
|
}
|
|
61
|
-
async function
|
|
74
|
+
async function takeScreenshotToCompare(page) {
|
|
62
75
|
try {
|
|
63
76
|
const content = '* { caret-color: transparent !important; }';
|
|
64
77
|
await page.addStyleTag({ content });
|
|
@@ -68,3 +81,8 @@ async function screenshot(page) {
|
|
|
68
81
|
return undefined;
|
|
69
82
|
}
|
|
70
83
|
}
|
|
84
|
+
async function takeScreenshotToDisplay(page) {
|
|
85
|
+
await page.screenshot({
|
|
86
|
+
path: `continue-with-google-${Date.now()}.png`,
|
|
87
|
+
});
|
|
88
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thetypefounders/continue-with-google",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
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",
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
"types": "dist/index.d.ts",
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"authenticator": "^1.1.5",
|
|
16
|
-
"puppeteer": "^24.
|
|
16
|
+
"puppeteer": "^24.9.0"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@trivago/prettier-plugin-sort-imports": "^5.2.
|
|
19
|
+
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
|
20
20
|
"@types/authenticator": "^1.1.4",
|
|
21
|
-
"prettier": "^3.
|
|
22
|
-
"typescript": "^5.
|
|
21
|
+
"prettier": "^3.5.3",
|
|
22
|
+
"typescript": "^5.8.3"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
25
|
"build": "tsc",
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ export type Options = {
|
|
|
12
12
|
challengeTimeoutSeconds?: number;
|
|
13
13
|
trialCount?: number;
|
|
14
14
|
trialTimeoutSeconds?: number;
|
|
15
|
+
screenshot?: boolean;
|
|
15
16
|
waitForSelector?: WaitForSelectorOptions;
|
|
16
17
|
};
|
|
17
18
|
|
|
@@ -31,31 +32,36 @@ export async function authenticate(
|
|
|
31
32
|
options: Options = DEFAULTS,
|
|
32
33
|
logger: Logger = console
|
|
33
34
|
): Promise<ElementHandle | null> {
|
|
35
|
+
const mergedOptions = { ...DEFAULTS, ...options };
|
|
36
|
+
|
|
34
37
|
logger.info('Waiting to enter the email...');
|
|
38
|
+
if (mergedOptions.screenshot) await takeScreenshotToDisplay(page);
|
|
35
39
|
await page.waitForSelector('input[type=email]', { visible: true });
|
|
40
|
+
|
|
36
41
|
logger.info('Entering the email...');
|
|
42
|
+
if (mergedOptions.screenshot) await takeScreenshotToDisplay(page);
|
|
37
43
|
await page.type('input[type=email]', email);
|
|
38
44
|
await page.keyboard.press('Enter');
|
|
39
45
|
|
|
40
46
|
logger.info('Waiting to enter the password...');
|
|
47
|
+
if (mergedOptions.screenshot) await takeScreenshotToDisplay(page);
|
|
41
48
|
await page.waitForSelector('input[type=password]', { visible: true });
|
|
49
|
+
|
|
42
50
|
logger.info('Entering the password...');
|
|
51
|
+
if (mergedOptions.screenshot) await takeScreenshotToDisplay(page);
|
|
43
52
|
await page.type('input[type=password]', password);
|
|
44
53
|
await page.keyboard.press('Enter');
|
|
45
54
|
|
|
46
55
|
for (
|
|
47
56
|
let attempt = 0, found = false;
|
|
48
|
-
attempt <
|
|
57
|
+
attempt < mergedOptions.challengeCount! && !found;
|
|
49
58
|
attempt++
|
|
50
59
|
) {
|
|
51
60
|
if (attempt > 0) {
|
|
52
61
|
logger.warn(`Challenged on attempt ${attempt}. Entering the code...`);
|
|
62
|
+
if (mergedOptions.screenshot) await takeScreenshotToDisplay(page);
|
|
53
63
|
if (attempt > 1) {
|
|
54
|
-
await setTimeout(
|
|
55
|
-
1000 *
|
|
56
|
-
(options.challengeTimeoutSeconds ||
|
|
57
|
-
DEFAULTS.challengeTimeoutSeconds!)
|
|
58
|
-
);
|
|
64
|
+
await setTimeout(1000 * mergedOptions.challengeTimeoutSeconds!);
|
|
59
65
|
}
|
|
60
66
|
const code = generateToken(secret);
|
|
61
67
|
await page.evaluate(() => {
|
|
@@ -66,13 +72,16 @@ export async function authenticate(
|
|
|
66
72
|
await page.keyboard.press('Enter');
|
|
67
73
|
await waitForTrial(
|
|
68
74
|
page,
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
mergedOptions.trialCount!,
|
|
76
|
+
mergedOptions.trialTimeoutSeconds!,
|
|
77
|
+
mergedOptions.screenshot,
|
|
71
78
|
logger
|
|
72
79
|
);
|
|
73
80
|
}
|
|
74
81
|
found = await Promise.any([
|
|
75
|
-
page
|
|
82
|
+
page
|
|
83
|
+
.waitForSelector(selector, mergedOptions.waitForSelector)
|
|
84
|
+
.then(() => true),
|
|
76
85
|
page
|
|
77
86
|
.waitForSelector('input[type=tel]', { visible: true })
|
|
78
87
|
.then(() => false),
|
|
@@ -86,6 +95,7 @@ async function waitForTrial(
|
|
|
86
95
|
page: Page,
|
|
87
96
|
attemptCount: number,
|
|
88
97
|
attemptTimeoutSeconds: number,
|
|
98
|
+
screenshot: boolean | undefined,
|
|
89
99
|
logger: Logger
|
|
90
100
|
): Promise<void> {
|
|
91
101
|
for (
|
|
@@ -95,11 +105,12 @@ async function waitForTrial(
|
|
|
95
105
|
) {
|
|
96
106
|
if (attempt > 0) {
|
|
97
107
|
logger.warn(`Tried on attempt ${attempt}. Waiting to finish...`);
|
|
108
|
+
if (screenshot) await takeScreenshotToDisplay(page);
|
|
98
109
|
}
|
|
99
110
|
if (attempt > -1) {
|
|
100
111
|
await setTimeout(1000 * attemptTimeoutSeconds);
|
|
101
112
|
}
|
|
102
|
-
const future = await
|
|
113
|
+
const future = await takeScreenshotToCompare(page);
|
|
103
114
|
if (future) {
|
|
104
115
|
previous = current;
|
|
105
116
|
current = future;
|
|
@@ -107,7 +118,9 @@ async function waitForTrial(
|
|
|
107
118
|
}
|
|
108
119
|
}
|
|
109
120
|
|
|
110
|
-
async function
|
|
121
|
+
async function takeScreenshotToCompare(
|
|
122
|
+
page: Page
|
|
123
|
+
): Promise<string | undefined> {
|
|
111
124
|
try {
|
|
112
125
|
const content = '* { caret-color: transparent !important; }';
|
|
113
126
|
await page.addStyleTag({ content });
|
|
@@ -116,3 +129,9 @@ async function screenshot(page: Page): Promise<string | undefined> {
|
|
|
116
129
|
return undefined;
|
|
117
130
|
}
|
|
118
131
|
}
|
|
132
|
+
|
|
133
|
+
async function takeScreenshotToDisplay(page: Page): Promise<void> {
|
|
134
|
+
await page.screenshot({
|
|
135
|
+
path: `continue-with-google-${Date.now()}.png`,
|
|
136
|
+
});
|
|
137
|
+
}
|