feat: 增强步骤 9 的认证状态检测,确保仅在出现“认证成功!”状态徽标后判定成功,并自动关闭残留 localhost 标签页
This commit is contained in:
@@ -257,7 +257,8 @@ Step 3 使用的注册邮箱。
|
|||||||
|
|
||||||
- 自动填写 localhost 回调地址
|
- 自动填写 localhost 回调地址
|
||||||
- 自动点击“提交回调 URL”
|
- 自动点击“提交回调 URL”
|
||||||
- 等待“认证成功”状态
|
- 必须等到 VPS 面板出现精确的 `认证成功!` 状态徽标后,才判定成功
|
||||||
|
- 成功后会自动关闭匹配 `http://localhost:1455/auth` 这一类前缀的 localhost 残留页面
|
||||||
|
|
||||||
## Duck 邮箱自动获取
|
## Duck 邮箱自动获取
|
||||||
|
|
||||||
|
|||||||
@@ -222,6 +222,18 @@ function isSignupPageHost(hostname = '') {
|
|||||||
return ['auth0.openai.com', 'auth.openai.com', 'accounts.openai.com'].includes(hostname);
|
return ['auth0.openai.com', 'auth.openai.com', 'accounts.openai.com'].includes(hostname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildLocalhostCleanupPrefix(rawUrl) {
|
||||||
|
const parsed = parseUrlSafely(rawUrl);
|
||||||
|
if (!parsed || parsed.hostname !== 'localhost') return '';
|
||||||
|
|
||||||
|
const segments = parsed.pathname.split('/').filter(Boolean);
|
||||||
|
if (!segments.length) {
|
||||||
|
return parsed.origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${parsed.origin}/${segments[0]}`;
|
||||||
|
}
|
||||||
|
|
||||||
function matchesSourceUrlFamily(source, candidateUrl, referenceUrl) {
|
function matchesSourceUrlFamily(source, candidateUrl, referenceUrl) {
|
||||||
const candidate = parseUrlSafely(candidateUrl);
|
const candidate = parseUrlSafely(candidateUrl);
|
||||||
if (!candidate) return false;
|
if (!candidate) return false;
|
||||||
@@ -284,6 +296,24 @@ async function closeConflictingTabsForSource(source, currentUrl, options = {}) {
|
|||||||
await addLog(`已关闭 ${matchedIds.length} 个旧的${getSourceLabel(source)}标签页。`, 'info');
|
await addLog(`已关闭 ${matchedIds.length} 个旧的${getSourceLabel(source)}标签页。`, 'info');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function closeTabsByUrlPrefix(prefix, options = {}) {
|
||||||
|
if (!prefix) return 0;
|
||||||
|
|
||||||
|
const { excludeTabIds = [] } = options;
|
||||||
|
const excluded = new Set(excludeTabIds.filter(id => Number.isInteger(id)));
|
||||||
|
const tabs = await chrome.tabs.query({});
|
||||||
|
const matchedIds = tabs
|
||||||
|
.filter((tab) => Number.isInteger(tab.id) && !excluded.has(tab.id))
|
||||||
|
.filter((tab) => typeof tab.url === 'string' && tab.url.startsWith(prefix))
|
||||||
|
.map((tab) => tab.id);
|
||||||
|
|
||||||
|
if (!matchedIds.length) return 0;
|
||||||
|
|
||||||
|
await chrome.tabs.remove(matchedIds).catch(() => {});
|
||||||
|
await addLog(`已关闭 ${matchedIds.length} 个匹配 ${prefix} 的 localhost 残留标签页。`, 'info');
|
||||||
|
return matchedIds.length;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Command Queue (for content scripts not yet ready)
|
// Command Queue (for content scripts not yet ready)
|
||||||
// ============================================================
|
// ============================================================
|
||||||
@@ -897,6 +927,13 @@ async function handleStepData(step, payload) {
|
|||||||
broadcastDataUpdate({ localhostUrl: payload.localhostUrl });
|
broadcastDataUpdate({ localhostUrl: payload.localhostUrl });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 9: {
|
||||||
|
const localhostPrefix = buildLocalhostCleanupPrefix(payload.localhostUrl);
|
||||||
|
if (localhostPrefix) {
|
||||||
|
await closeTabsByUrlPrefix(localhostPrefix);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+31
-16
@@ -76,6 +76,34 @@ function getActionText(el) {
|
|||||||
.trim();
|
.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getStatusBadgeElement() {
|
||||||
|
const candidates = document.querySelectorAll('.status-badge');
|
||||||
|
return Array.from(candidates).find(isVisibleElement) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatusBadgeText() {
|
||||||
|
const statusEl = getStatusBadgeElement();
|
||||||
|
return statusEl ? (statusEl.textContent || '').replace(/\s+/g, ' ').trim() : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
async function waitForExactSuccessBadge(timeout = 30000) {
|
||||||
|
const start = Date.now();
|
||||||
|
|
||||||
|
while (Date.now() - start < timeout) {
|
||||||
|
throwIfStopped();
|
||||||
|
const statusText = getStatusBadgeText();
|
||||||
|
if (statusText === '认证成功!') {
|
||||||
|
return statusText;
|
||||||
|
}
|
||||||
|
await sleep(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
const finalText = getStatusBadgeText();
|
||||||
|
throw new Error(finalText
|
||||||
|
? `VPS 面板状态不是“认证成功!”,当前为“${finalText}”。`
|
||||||
|
: 'VPS 面板长时间未出现“认证成功!”状态徽标。');
|
||||||
|
}
|
||||||
|
|
||||||
function findManagementKeyInput() {
|
function findManagementKeyInput() {
|
||||||
const candidates = document.querySelectorAll(
|
const candidates = document.querySelectorAll(
|
||||||
'.LoginPage-module__loginCard___OgP-R input[type="password"], input[placeholder*="管理密钥"], input[aria-label*="管理密钥"]'
|
'.LoginPage-module__loginCard___OgP-R input[type="password"], input[placeholder*="管理密钥"], input[aria-label*="管理密钥"]'
|
||||||
@@ -300,20 +328,7 @@ async function step9_vpsVerify(payload) {
|
|||||||
simulateClick(submitBtn);
|
simulateClick(submitBtn);
|
||||||
log('步骤 9:已点击“提交回调 URL”,正在等待认证结果...');
|
log('步骤 9:已点击“提交回调 URL”,正在等待认证结果...');
|
||||||
|
|
||||||
// Wait for "认证成功!" status badge to appear
|
const verifiedStatus = await waitForExactSuccessBadge();
|
||||||
try {
|
log(`步骤 9:${verifiedStatus}`, 'ok');
|
||||||
await waitForElementByText('.status-badge, [class*="status"]', /认证成功/, 30000);
|
reportComplete(9, { localhostUrl, verifiedStatus });
|
||||||
log('步骤 9:认证成功!', 'ok');
|
|
||||||
} catch {
|
|
||||||
// Check if there's an error message instead
|
|
||||||
const statusEl = document.querySelector('.status-badge, [class*="status"]');
|
|
||||||
const statusText = statusEl ? statusEl.textContent : 'unknown';
|
|
||||||
if (/成功|success/i.test(statusText)) {
|
|
||||||
log('步骤 9:认证成功!', 'ok');
|
|
||||||
} else {
|
|
||||||
log(`步骤 9:提交后的状态为“${statusText}”,可能仍在处理中。`, 'warn');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reportComplete(9);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user