-
-
Save Brandawg93/728a93e84ed7b66d8dd0af966cb20ecb to your computer and use it in GitHub Desktop.
| import puppeteer from 'puppeteer-extra'; | |
| import pluginStealth from 'puppeteer-extra-plugin-stealth'; // Use v2.4.5 instead of latest | |
| import * as readline from 'readline'; | |
| puppeteer.use(pluginStealth()); | |
| // Use '-h' arg for headful login. | |
| const headless = !process.argv.includes('-h'); | |
| // Prompt user for email and password. | |
| const prompt = (query: string, hidden = false): Promise<string> => | |
| new Promise((resolve, reject) => { | |
| const rl = readline.createInterface({ | |
| input: process.stdin, | |
| output: process.stdout, | |
| }); | |
| try { | |
| if (hidden) { | |
| const stdin = process.openStdin(); | |
| process.stdin.on('data', (char: string) => { | |
| char = char + ''; | |
| switch (char) { | |
| case '\n': | |
| case '\r': | |
| case '\u0004': | |
| stdin.pause(); | |
| break; | |
| default: | |
| process.stdout.clearLine(0); | |
| readline.cursorTo(process.stdout, 0); | |
| process.stdout.write(query + Array(rl.line.length + 1).join('*')); | |
| break; | |
| } | |
| }); | |
| } | |
| rl.question(query, (value) => { | |
| resolve(value); | |
| rl.close(); | |
| }); | |
| } catch (err) { | |
| reject(err); | |
| } | |
| }); | |
| // Launch puppeteer browser. | |
| puppeteer.launch({ headless: headless }).then(async (browser: any) => { | |
| console.log('Opening chromium browser...'); | |
| const page = await browser.newPage(); | |
| const pages = await browser.pages(); | |
| // Close the new tab that chromium always opens first. | |
| pages[0].close(); | |
| await page.goto('https://accounts.google.com/signin/v2/identifier', { waitUntil: 'networkidle2' }); | |
| if (headless) { | |
| // Only needed if sign in requires you to click 'sign in with google' button. | |
| // await page.waitForSelector('button[data-test="google-button-login"]'); | |
| // await page.waitFor(1000); | |
| // await page.click('button[data-test="google-button-login"]'); | |
| // Wait for email input. | |
| await page.waitForSelector('#identifierId'); | |
| let badInput = true; | |
| // Keep trying email until user inputs email correctly. | |
| // This will error due to captcha if too many incorrect inputs. | |
| while (badInput) { | |
| const email = await prompt('Email or phone: '); | |
| await page.type('#identifierId', email); | |
| await page.waitFor(1000); | |
| await page.keyboard.press('Enter'); | |
| await page.waitFor(1000); | |
| badInput = await page.evaluate(() => document.querySelector('#identifierId[aria-invalid="true"]') !== null); | |
| if (badInput) { | |
| console.log('Incorrect email or phone. Please try again.'); | |
| await page.click('#identifierId', { clickCount: 3 }); | |
| } | |
| } | |
| const password = await prompt('Enter your password: ', true); | |
| console.log('Finishing up...'); | |
| // Wait for password input | |
| await page.type('input[type="password"]', password); | |
| await page.waitFor(1000); | |
| await page.keyboard.press('Enter'); | |
| // For headless mode, 2FA needs to be handled here. | |
| // Login via gmail app works autmatically. | |
| } | |
| }); |
| { | |
| "displayName": "Puppeteer Google Login", | |
| "name": "puppeteer-google-login", | |
| "version": "1.0.0", | |
| "description": "Login to your google account using puppeteer", | |
| "main": "dist/login.js", | |
| "scripts": { | |
| "clean": "rimraf ./dist ./coverage", | |
| "build": "rimraf ./dist ./coverage && tsc" | |
| }, | |
| "engines": { | |
| "node": ">=10" | |
| }, | |
| "files": [ | |
| "dist/**/*" | |
| ], | |
| "dependencies": { | |
| }, | |
| "devDependencies": { | |
| "@types/node": "14.0.11", | |
| "@types/puppeteer": "^3.0.0", | |
| "puppeteer": "^3.3.0", | |
| "puppeteer-extra": "^3.1.9", | |
| "puppeteer-extra-plugin-stealth": "^2.4.5", | |
| "rimraf": "^3.0.2", | |
| "typescript": "^3.8.3" | |
| } | |
| } |
| { | |
| "compilerOptions": { | |
| "target": "ES2018", | |
| "module": "commonjs", | |
| "lib": [ | |
| "ES2015", | |
| "ES2016", | |
| "ES2017", | |
| "ES2018", | |
| "dom" | |
| ], | |
| "sourceMap": true, | |
| "rootDir": "src", | |
| "outDir": "dist", | |
| "allowJs": true, | |
| "strict": true, | |
| "esModuleInterop": true, | |
| "forceConsistentCasingInFileNames": true | |
| }, | |
| "include": [ | |
| "src" | |
| ] | |
| } |
I agree. I’ve made many updates to this code in its parent project, and then found a way to not need it at all. 😀 The code is probably outdated.
I agree. I’ve made many updates to this code in its parent project, and then found a way to not need it at all. 😀 The code is probably outdated.
You're welcome! I didn't pay attention to the date of the project... I found it while searching on puppeteer ^^
I agree. I’ve made many updates to this code in its parent project, and then found a way to not need it at all. 😀 The code is probably outdated.
What parent project?
I agree. I’ve made many updates to this code in its parent project, and then found a way to not need it at all. 😀 The code is probably outdated.
You're welcome! I didn't pay attention to the date of the project... I found it while searching on puppeteer ^^
Share your update
I agree. I’ve made many updates to this code in its parent project, and then found a way to not need it at all. 😀 The code is probably outdated.
You're welcome! I didn't pay attention to the date of the project... I found it while searching on puppeteer ^^
Share your update
You talking to me or @Brandawg93 ?
Hi ! This part is not very logical:
It would make more sense to do :
the do {} while() execute the code THEN check the loop condition, in your case you want to execute your code once and then check if you have to continue or loop