抽取cookie清理逻辑为新的第六步
This commit is contained in:
+35
-35
@@ -37,7 +37,7 @@ if (document.documentElement.getAttribute(SIGNUP_PAGE_LISTENER_SENTINEL) !== '1'
|
||||
}
|
||||
|
||||
if (message.type === 'STEP8_FIND_AND_CLICK') {
|
||||
log(`步骤 8:${err.message}`, 'error');
|
||||
log(`步骤 9:${err.message}`, 'error');
|
||||
sendResponse({ error: err.message });
|
||||
return;
|
||||
}
|
||||
@@ -61,8 +61,8 @@ async function handleCommand(message) {
|
||||
case 2: return await step2_clickRegister(message.payload);
|
||||
case 3: return await step3_fillEmailPassword(message.payload);
|
||||
case 5: return await step5_fillNameBirthday(message.payload);
|
||||
case 6: return await step6_login(message.payload);
|
||||
case 8: return await step8_findAndClick();
|
||||
case 7: return await step6_login(message.payload);
|
||||
case 9: return await step8_findAndClick();
|
||||
default: throw new Error(`signup-page.js 不处理步骤 ${message.step}`);
|
||||
}
|
||||
case 'FILL_CODE':
|
||||
@@ -199,7 +199,7 @@ function isEmailVerificationPage() {
|
||||
}
|
||||
|
||||
async function resendVerificationCode(step, timeout = 45000) {
|
||||
if (step === 7) {
|
||||
if (step === 8) {
|
||||
await waitForLoginVerificationPageReady();
|
||||
}
|
||||
|
||||
@@ -1185,7 +1185,7 @@ async function waitForLoginVerificationPageReady(timeout = 10000) {
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`当前未进入登录验证码页面,请先重新完成步骤 6。当前状态:${getLoginAuthStateLabel(snapshot)}。URL: ${snapshot?.url || location.href}`
|
||||
`当前未进入登录验证码页面,请先重新完成步骤 7。当前状态:${getLoginAuthStateLabel(snapshot)}。URL: ${snapshot?.url || location.href}`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1216,15 +1216,15 @@ async function createStep6LoginTimeoutRecoverableResult(reason, snapshot, messag
|
||||
try {
|
||||
const recoveryResult = await recoverCurrentAuthRetryPage({
|
||||
flow: 'login',
|
||||
logLabel: '步骤 6:检测到登录超时报错,正在点击“重试”恢复当前页面',
|
||||
logLabel: '步骤 7:检测到登录超时报错,正在点击“重试”恢复当前页面',
|
||||
step: 6,
|
||||
timeoutMs: 12000,
|
||||
});
|
||||
if (recoveryResult?.recovered) {
|
||||
log('步骤 6:登录超时报错页已点击“重试”,准备重新执行当前步骤。', 'warn');
|
||||
log('步骤 7:登录超时报错页已点击“重试”,准备重新执行当前步骤。', 'warn');
|
||||
}
|
||||
} catch (error) {
|
||||
log(`步骤 6:登录超时报错页自动点击“重试”失败:${error.message}`, 'warn');
|
||||
log(`步骤 7:登录超时报错页自动点击“重试”失败:${error.message}`, 'warn');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1248,9 +1248,9 @@ function throwForStep6FatalState(snapshot) {
|
||||
snapshot = normalizeStep6Snapshot(snapshot);
|
||||
switch (snapshot?.state) {
|
||||
case 'oauth_consent_page':
|
||||
throw new Error(`当前页面已进入 OAuth 授权页,未经过登录验证码页,无法完成步骤 6。URL: ${snapshot.url}`);
|
||||
throw new Error(`当前页面已进入 OAuth 授权页,未经过登录验证码页,无法完成步骤 7。URL: ${snapshot.url}`);
|
||||
case 'add_phone_page':
|
||||
throw new Error(`当前页面已进入手机号页面,未经过登录验证码页,无法完成步骤 6。URL: ${snapshot.url}`);
|
||||
throw new Error(`当前页面已进入手机号页面,未经过登录验证码页,无法完成步骤 7。URL: ${snapshot.url}`);
|
||||
case 'unknown':
|
||||
throw new Error(`无法识别当前登录页面状态。URL: ${snapshot?.url || location.href}`);
|
||||
default:
|
||||
@@ -1412,7 +1412,7 @@ async function prepareSignupVerificationFlow(payload = {}, timeout = 30000) {
|
||||
|
||||
|
||||
async function waitForVerificationSubmitOutcome(step, timeout) {
|
||||
const resolvedTimeout = timeout ?? (step === 7 ? 30000 : 12000);
|
||||
const resolvedTimeout = timeout ?? (step === 8 ? 30000 : 12000);
|
||||
const start = Date.now();
|
||||
|
||||
while (Date.now() - start < resolvedTimeout) {
|
||||
@@ -1427,11 +1427,11 @@ async function waitForVerificationSubmitOutcome(step, timeout) {
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
if (step === 7 && isStep8Ready()) {
|
||||
if (step === 8 && isStep8Ready()) {
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
if (step === 7 && isAddPhonePageReady()) {
|
||||
if (step === 8 && isAddPhonePageReady()) {
|
||||
return { success: true, addPhonePage: true };
|
||||
}
|
||||
|
||||
@@ -1454,7 +1454,7 @@ async function fillVerificationCode(step, payload) {
|
||||
|
||||
log(`步骤 ${step}:正在填写验证码:${code}`);
|
||||
|
||||
if (step === 7) {
|
||||
if (step === 8) {
|
||||
await waitForLoginVerificationPageReady();
|
||||
}
|
||||
|
||||
@@ -1771,11 +1771,11 @@ async function step6SwitchToOneTimeCodeLogin(snapshot) {
|
||||
});
|
||||
}
|
||||
|
||||
log('步骤 6:已检测到一次性验证码登录入口,准备切换...');
|
||||
log('步骤 7:已检测到一次性验证码登录入口,准备切换...');
|
||||
const loginVerificationRequestedAt = Date.now();
|
||||
await humanPause(350, 900);
|
||||
simulateClick(switchTrigger);
|
||||
log('步骤 6:已点击一次性验证码登录');
|
||||
log('步骤 7:已点击一次性验证码登录');
|
||||
await sleep(1200);
|
||||
return waitForStep6SwitchTransition(loginVerificationRequestedAt);
|
||||
}
|
||||
@@ -1785,26 +1785,26 @@ async function step6LoginFromPasswordPage(payload, snapshot) {
|
||||
|
||||
if (currentSnapshot.passwordInput) {
|
||||
if (!payload.password) {
|
||||
throw new Error('登录时缺少密码,步骤 6 无法继续。');
|
||||
throw new Error('登录时缺少密码,步骤 7 无法继续。');
|
||||
}
|
||||
|
||||
log('步骤 6:已进入密码页,准备填写密码...');
|
||||
log('步骤 7:已进入密码页,准备填写密码...');
|
||||
await humanPause(550, 1450);
|
||||
fillInput(currentSnapshot.passwordInput, payload.password);
|
||||
log('步骤 6:已填写密码');
|
||||
log('步骤 7:已填写密码');
|
||||
|
||||
await sleep(500);
|
||||
const passwordSubmittedAt = Date.now();
|
||||
await triggerLoginSubmitAction(currentSnapshot.submitButton, currentSnapshot.passwordInput);
|
||||
log('步骤 6:已提交密码');
|
||||
log('步骤 7:已提交密码');
|
||||
|
||||
const transition = await waitForStep6PasswordSubmitTransition(passwordSubmittedAt);
|
||||
if (transition.action === 'done') {
|
||||
log('步骤 6:已进入登录验证码页面。', 'ok');
|
||||
log('步骤 7:已进入登录验证码页面。', 'ok');
|
||||
return transition.result;
|
||||
}
|
||||
if (transition.action === 'recoverable') {
|
||||
log(`步骤 6:${transition.result.message || '提交密码后仍未进入登录验证码页面,准备重新执行步骤 6。'}`, 'warn');
|
||||
log(`步骤 7:${transition.result.message || '提交密码后仍未进入登录验证码页面,准备重新执行步骤 7。'}`, 'warn');
|
||||
return transition.result;
|
||||
}
|
||||
if (transition.action === 'switch') {
|
||||
@@ -1835,23 +1835,23 @@ async function step6LoginFromEmailPage(payload, snapshot) {
|
||||
if ((emailInput.value || '').trim() !== payload.email) {
|
||||
await humanPause(500, 1400);
|
||||
fillInput(emailInput, payload.email);
|
||||
log('步骤 6:已填写邮箱');
|
||||
log('步骤 7:已填写邮箱');
|
||||
} else {
|
||||
log('步骤 6:邮箱已在输入框中,准备提交...');
|
||||
log('步骤 7:邮箱已在输入框中,准备提交...');
|
||||
}
|
||||
|
||||
await sleep(500);
|
||||
const emailSubmittedAt = Date.now();
|
||||
await triggerLoginSubmitAction(currentSnapshot.submitButton, emailInput);
|
||||
log('步骤 6:已提交邮箱');
|
||||
log('步骤 7:已提交邮箱');
|
||||
|
||||
const transition = await waitForStep6EmailSubmitTransition(emailSubmittedAt);
|
||||
if (transition.action === 'done') {
|
||||
log('步骤 6:已进入登录验证码页面。', 'ok');
|
||||
log('步骤 7:已进入登录验证码页面。', 'ok');
|
||||
return transition.result;
|
||||
}
|
||||
if (transition.action === 'recoverable') {
|
||||
log(`步骤 6:${transition.result.message || '提交邮箱后仍未进入目标页面,准备重新执行步骤 6。'}`, 'warn');
|
||||
log(`步骤 7:${transition.result.message || '提交邮箱后仍未进入目标页面,准备重新执行步骤 7。'}`, 'warn');
|
||||
return transition.result;
|
||||
}
|
||||
if (transition.action === 'password') {
|
||||
@@ -1867,17 +1867,17 @@ async function step6_login(payload) {
|
||||
const { email } = payload;
|
||||
if (!email) throw new Error('登录时缺少邮箱地址。');
|
||||
|
||||
log(`步骤 6:正在使用 ${email} 登录...`);
|
||||
log(`步骤 7:正在使用 ${email} 登录...`);
|
||||
|
||||
const snapshot = normalizeStep6Snapshot(await waitForKnownLoginAuthState(15000));
|
||||
|
||||
if (snapshot.state === 'verification_page') {
|
||||
log('步骤 6:登录验证码页面已就绪。', 'ok');
|
||||
log('步骤 7:登录验证码页面已就绪。', 'ok');
|
||||
return createStep6SuccessResult(snapshot, { via: 'already_on_verification_page' });
|
||||
}
|
||||
|
||||
if (snapshot.state === 'login_timeout_error_page') {
|
||||
log('步骤 6:检测到登录超时报错,准备重新执行步骤 6。', 'warn');
|
||||
log('步骤 7:检测到登录超时报错,准备重新执行步骤 7。', 'warn');
|
||||
return await createStep6LoginTimeoutRecoverableResult(
|
||||
'login_timeout_error_page',
|
||||
snapshot,
|
||||
@@ -1898,19 +1898,19 @@ async function step6_login(payload) {
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Step 8: Find "继续" on OAuth consent page for debugger click
|
||||
// Step 9: Find "继续" on OAuth consent page for debugger click
|
||||
// ============================================================
|
||||
// After login + verification, page shows:
|
||||
// "使用 ChatGPT 登录到 Codex" with a "继续" submit button.
|
||||
// Background performs the actual click through the debugger Input API.
|
||||
|
||||
async function step8_findAndClick() {
|
||||
log('步骤 8:正在查找 OAuth 同意页的“继续”按钮...');
|
||||
log('步骤 9:正在查找 OAuth 同意页的“继续”按钮...');
|
||||
|
||||
const continueBtn = await prepareStep8ContinueButton();
|
||||
|
||||
const rect = getSerializableRect(continueBtn);
|
||||
log('步骤 8:已找到“继续”按钮并准备好调试器点击坐标。');
|
||||
log('步骤 9:已找到“继续”按钮并准备好调试器点击坐标。');
|
||||
return {
|
||||
rect,
|
||||
buttonText: (continueBtn.textContent || '').trim(),
|
||||
@@ -1969,10 +1969,10 @@ async function step8_triggerContinue(payload = {}) {
|
||||
simulateClick(continueBtn);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`未知的 Step 8 触发策略:${strategy}`);
|
||||
throw new Error(`未知的 Step 9 触发策略:${strategy}`);
|
||||
}
|
||||
|
||||
log(`Step 8: continue button triggered via ${strategy}.`);
|
||||
log(`Step 9: continue button triggered via ${strategy}.`);
|
||||
return {
|
||||
strategy,
|
||||
...getStep8State(),
|
||||
|
||||
@@ -66,7 +66,7 @@ async function handleStep(step, payload = {}) {
|
||||
switch (step) {
|
||||
case 1:
|
||||
return step1_generateOpenAiAuthUrl(payload);
|
||||
case 9:
|
||||
case 10:
|
||||
return step9_submitOpenAiCallback(payload);
|
||||
default:
|
||||
throw new Error(`sub2api-panel.js 不处理步骤 ${step}`);
|
||||
@@ -218,7 +218,7 @@ function parseLocalhostCallback(rawUrl) {
|
||||
throw new Error('回调 URL 协议不正确。');
|
||||
}
|
||||
if (!['localhost', '127.0.0.1'].includes(parsed.hostname)) {
|
||||
throw new Error('步骤 9 只接受 localhost / 127.0.0.1 回调地址。');
|
||||
throw new Error('步骤 10 只接受 localhost / 127.0.0.1 回调地址。');
|
||||
}
|
||||
if (parsed.pathname !== '/auth/callback') {
|
||||
throw new Error('回调 URL 路径必须是 /auth/callback。');
|
||||
@@ -365,7 +365,7 @@ async function step9_submitOpenAiCallback(payload = {}) {
|
||||
throw new Error('本次 localhost 回调中的 state 与步骤 1 生成的 state 不一致,请重新执行步骤 1。');
|
||||
}
|
||||
|
||||
log('步骤 9:正在向 SUB2API 交换 OpenAI 授权码...');
|
||||
log('步骤 10:正在向 SUB2API 交换 OpenAI 授权码...');
|
||||
const exchangeData = await requestJson(origin, '/api/v1/admin/openai/exchange-code', {
|
||||
method: 'POST',
|
||||
token,
|
||||
@@ -399,7 +399,7 @@ async function step9_submitOpenAiCallback(payload = {}) {
|
||||
createPayload.extra = extra;
|
||||
}
|
||||
|
||||
log(`步骤 9:授权码交换成功,正在创建 SUB2API 账号(名称:${accountName})...`);
|
||||
log(`步骤 10:授权码交换成功,正在创建 SUB2API 账号(名称:${accountName})...`);
|
||||
const createdAccount = await requestJson(origin, '/api/v1/admin/accounts', {
|
||||
method: 'POST',
|
||||
token,
|
||||
@@ -407,8 +407,8 @@ async function step9_submitOpenAiCallback(payload = {}) {
|
||||
});
|
||||
|
||||
const verifiedStatus = `SUB2API 已创建账号 #${createdAccount?.id || 'unknown'}`;
|
||||
log(`步骤 9:${verifiedStatus}`, 'ok');
|
||||
reportComplete(9, {
|
||||
log(`步骤 10:${verifiedStatus}`, 'ok');
|
||||
reportComplete(10, {
|
||||
localhostUrl: callback.url,
|
||||
verifiedStatus,
|
||||
});
|
||||
|
||||
+15
-15
@@ -83,7 +83,7 @@ if (document.documentElement.getAttribute(VPS_PANEL_LISTENER_SENTINEL) !== '1')
|
||||
async function handleStep(step, payload) {
|
||||
switch (step) {
|
||||
case 1: return await step1_getOAuthLink(payload);
|
||||
case 9: return await step9_vpsVerify(payload);
|
||||
case 10: return await step9_vpsVerify(payload);
|
||||
default:
|
||||
throw new Error(`vps-panel.js 不处理步骤 ${step}`);
|
||||
}
|
||||
@@ -467,11 +467,11 @@ async function waitForExactSuccessBadge(timeout = STEP9_SUCCESS_BADGE_TIMEOUT_MS
|
||||
if (diagnostics.signature !== lastDiagnosticsSignature) {
|
||||
lastDiagnosticsSignature = diagnostics.signature;
|
||||
lastHeartbeatLoggedAt = elapsed;
|
||||
log(`步骤 9:认证状态检测中,${diagnostics.summary}`);
|
||||
log(`步骤 10:认证状态检测中,${diagnostics.summary}`);
|
||||
console.log(LOG_PREFIX, '[Step 9] status badge diagnostics changed', diagnostics);
|
||||
} else if (elapsed - lastHeartbeatLoggedAt >= 10000) {
|
||||
lastHeartbeatLoggedAt = elapsed;
|
||||
log(`步骤 9:仍在等待认证成功,${diagnostics.summary}`);
|
||||
log(`步骤 10:仍在等待认证成功,${diagnostics.summary}`);
|
||||
console.log(LOG_PREFIX, '[Step 9] still waiting for success badge', diagnostics);
|
||||
}
|
||||
|
||||
@@ -488,7 +488,7 @@ async function waitForExactSuccessBadge(timeout = STEP9_SUCCESS_BADGE_TIMEOUT_MS
|
||||
? `;错误样式徽标:${diagnostics.errorStyledSummary}`
|
||||
: '';
|
||||
log(
|
||||
`步骤 9:检测到“认证成功”相关徽标,但未命中精确成功条件。当前聚焦="${getInlineTextSnippet(diagnostics.selectedText || '(空)', 80)}";成功相关徽标:${diagnostics.successLikeSummary}${errorStyledSuffix}`,
|
||||
`步骤 10:检测到“认证成功”相关徽标,但未命中精确成功条件。当前聚焦="${getInlineTextSnippet(diagnostics.selectedText || '(空)', 80)}";成功相关徽标:${diagnostics.successLikeSummary}${errorStyledSuffix}`,
|
||||
'warn'
|
||||
);
|
||||
console.warn(LOG_PREFIX, '[Step 9] success-like badge detected without exact match', diagnostics);
|
||||
@@ -507,7 +507,7 @@ async function waitForExactSuccessBadge(timeout = STEP9_SUCCESS_BADGE_TIMEOUT_MS
|
||||
? diagnostics.pageErrorSummary
|
||||
: diagnostics.failureSummary;
|
||||
log(
|
||||
`步骤 9:同时检测到成功徽标和失败提示,本轮不判定成功。成功徽标:${diagnostics.exactSuccessSummary};失败提示:${failureSummary}`,
|
||||
`步骤 10:同时检测到成功徽标和失败提示,本轮不判定成功。成功徽标:${diagnostics.exactSuccessSummary};失败提示:${failureSummary}`,
|
||||
'warn'
|
||||
);
|
||||
console.warn(LOG_PREFIX, '[Step 9] success badge is blocked by visible failure', diagnostics);
|
||||
@@ -777,7 +777,7 @@ async function step1_getOAuthLink(payload, options = {}) {
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 步骤 9:CPA 回调验证——填写 localhost 回调地址并提交
|
||||
// 步骤 10:CPA 回调验证——填写 localhost 回调地址并提交
|
||||
// ============================================================
|
||||
|
||||
async function step9_vpsVerify(payload) {
|
||||
@@ -786,22 +786,22 @@ async function step9_vpsVerify(payload) {
|
||||
// 优先从 payload 读取 localhostUrl;没有时再回退到全局状态
|
||||
let localhostUrl = payload?.localhostUrl;
|
||||
if (localhostUrl && !isLocalhostOAuthCallbackUrl(localhostUrl)) {
|
||||
throw new Error('步骤 9 只接受真实的 localhost OAuth 回调地址,请重新执行步骤 8。');
|
||||
throw new Error('步骤 10 只接受真实的 localhost OAuth 回调地址,请重新执行步骤 9。');
|
||||
}
|
||||
if (!localhostUrl) {
|
||||
log('步骤 9:payload 中没有 localhostUrl,正在从状态中读取...');
|
||||
log('步骤 10:payload 中没有 localhostUrl,正在从状态中读取...');
|
||||
const state = await chrome.runtime.sendMessage({ type: 'GET_STATE' });
|
||||
localhostUrl = state.localhostUrl;
|
||||
if (localhostUrl && !isLocalhostOAuthCallbackUrl(localhostUrl)) {
|
||||
throw new Error('步骤 9 只接受真实的 localhost OAuth 回调地址,请重新执行步骤 8。');
|
||||
throw new Error('步骤 10 只接受真实的 localhost OAuth 回调地址,请重新执行步骤 9。');
|
||||
}
|
||||
}
|
||||
if (!localhostUrl) {
|
||||
throw new Error('未找到 localhost 回调地址,请先完成步骤 8。');
|
||||
}
|
||||
log(`步骤 9:已获取 localhostUrl:${localhostUrl.slice(0, 60)}...`);
|
||||
log(`步骤 10:已获取 localhostUrl:${localhostUrl.slice(0, 60)}...`);
|
||||
|
||||
log('步骤 9:正在查找回调地址输入框...');
|
||||
log('步骤 10:正在查找回调地址输入框...');
|
||||
|
||||
// Find the callback URL input
|
||||
// Actual DOM: <input class="input" placeholder="http://localhost:1455/auth/callback?code=...&state=...">
|
||||
@@ -818,7 +818,7 @@ async function step9_vpsVerify(payload) {
|
||||
|
||||
await humanPause(600, 1500);
|
||||
fillInput(urlInput, localhostUrl);
|
||||
log(`步骤 9:已填写回调地址:${localhostUrl.slice(0, 80)}...`);
|
||||
log(`步骤 10:已填写回调地址:${localhostUrl.slice(0, 80)}...`);
|
||||
|
||||
// Find and click the callback submit button in supported UI languages.
|
||||
const callbackSubmitPattern = /提交回调\s*URL|Submit\s+Callback\s+URL|Отправить\s+Callback\s+URL/i;
|
||||
@@ -839,9 +839,9 @@ async function step9_vpsVerify(payload) {
|
||||
|
||||
await humanPause(450, 1200);
|
||||
simulateClick(submitBtn);
|
||||
log('步骤 9:已点击回调提交按钮,正在等待认证结果...');
|
||||
log('步骤 10:已点击回调提交按钮,正在等待认证结果...');
|
||||
|
||||
const verifiedStatus = await waitForExactSuccessBadge();
|
||||
log(`步骤 9:${verifiedStatus}`, 'ok');
|
||||
reportComplete(9, { localhostUrl, verifiedStatus });
|
||||
log(`步骤 10:${verifiedStatus}`, 'ok');
|
||||
reportComplete(10, { localhostUrl, verifiedStatus });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user