Files
go_bt/scripts/obtain_gmail_app_password.js

106 lines
3.8 KiB
JavaScript

'use strict';
const path = require('path');
const { chromium } = require('playwright');
const db = require('../src/core/database');
const { openBrowserWithRetry, closeBrowser } = require('../src/core/bit_api');
const { createGmailAppPassword } = require('../src/services/gmail_app_password_service');
async function inspectPage(page, email) {
return page.evaluate(targetEmail => {
const visible = element => {
const style = window.getComputedStyle(element);
return style.display !== 'none' && style.visibility !== 'hidden';
};
const clean = value => String(value || '')
.replace(new RegExp(targetEmail.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'ig'), '[email]')
.replace(/\s+/g, ' ')
.trim();
return {
title: document.title,
bodyText: clean(document.body && document.body.innerText).slice(0, 1200),
inputs: [...document.querySelectorAll('input')].filter(visible).map(input => ({
type: input.type,
name: input.name,
id: input.id,
ariaLabel: input.getAttribute('aria-label'),
placeholder: input.getAttribute('placeholder'),
hasValue: !!input.value,
})),
buttons: [...document.querySelectorAll('button, [role="button"]')].filter(visible)
.map(button => clean(button.innerText || button.getAttribute('aria-label')))
.filter(Boolean)
.slice(0, 30),
};
}, email).catch(() => ({ title: '', bodyText: '', inputs: [], buttons: [] }));
}
async function main() {
const email = String(process.argv[2] || '').trim();
if (!email) throw new Error('用法: node scripts/obtain_gmail_app_password.js <email>');
db.initDB();
const account = db.getAllAccounts().find(item => String(item.email || '').toLowerCase() === email.toLowerCase());
if (!account) throw new Error('数据库中不存在该邮箱');
if (!account.browser_id) throw new Error('该邮箱没有浏览器编号');
if (db.hasGmailAppPassword(email)) {
console.log(JSON.stringify({ ok: true, alreadySaved: true, email }));
return;
}
const opened = await openBrowserWithRetry(account.browser_id, {
email,
logCallback: message => console.log(message),
});
if (!opened || !opened.success || !opened.data || !opened.data.ws) {
throw new Error(`打开比特浏览器失败:${opened && opened.msg ? opened.msg : '无 ws 端点'}`);
}
let browser;
let page;
let succeeded = false;
try {
browser = await chromium.connectOverCDP(opened.data.ws);
const context = browser.contexts()[0];
page = await context.newPage();
await page.bringToFront().catch(() => {});
const result = await createGmailAppPassword(page, account, message => console.log(message), {
appName: 'zhaoqiaoqing2001',
timeoutMs: 60000,
captchaWaitMs: 5 * 60 * 1000,
});
if (result.ok && result.appPassword) {
db.upsertGmailAppPassword(email, result.appPassword);
succeeded = true;
console.log(JSON.stringify({ ok: true, saved: true, email, passwordLength: result.appPassword.length }));
return;
}
const inspection = await inspectPage(page, email);
const screenshotPath = path.join(
db.getDb().name ? path.dirname(db.getDb().name) : path.join(__dirname, '..', 'data'),
'screenshots',
`gmail_app_password_${email.replace(/[^a-z0-9]+/gi, '_')}.png`,
);
await page.screenshot({ path: screenshotPath, fullPage: true }).catch(() => {});
console.log(JSON.stringify({
ok: false,
email,
message: result.msg,
url: page.url(),
inspection,
screenshotPath,
}));
process.exitCode = 2;
} finally {
if (browser) await browser.close().catch(() => {});
if (succeeded) await closeBrowser(account.browser_id).catch(() => {});
}
}
main().catch(error => {
console.error(JSON.stringify({ ok: false, message: error.message }));
process.exitCode = 1;
});