修改登陆及后续逻辑,统一使用一个逻辑

This commit is contained in:
QLHazyCoder
2026-04-26 05:22:36 +08:00
parent ef52ff806b
commit 88ceb79af6
21 changed files with 868 additions and 370 deletions
-1
View File
@@ -70,7 +70,6 @@
}
function getLoginAuthStateLabel(state) {
state = state === 'oauth_consent_page' ? 'unknown' : state;
switch (state) {
case 'verification_page':
return '登录验证码页';
+39 -2
View File
@@ -137,6 +137,31 @@
return '';
}
function isStepProtectedFromAutoSkip(status) {
return status === 'running'
|| status === 'completed'
|| status === 'manual_completed'
|| status === 'skipped';
}
function findStepByKeyAfter(currentStep, targetKey, state = {}) {
const activeStepIds = typeof getStepIdsForState === 'function'
? getStepIdsForState(state)
: [];
const candidates = activeStepIds.length ? activeStepIds : [Number(currentStep) + 1, 8];
return candidates.find((stepId) => {
const numericStep = Number(stepId);
if (!Number.isFinite(numericStep) || numericStep <= Number(currentStep)) {
return false;
}
const stepKey = getStepKeyForState(numericStep, state);
if (stepKey) {
return stepKey === targetKey;
}
return targetKey === 'fetch-login-code' && Number(currentStep) === 7 && numericStep === 8;
}) || null;
}
async function handlePlatformVerifyStepData(payload) {
if (payload.localhostUrl) {
await closeLocalhostCallbackTabs(payload.localhostUrl);
@@ -180,7 +205,18 @@
const stepKey = getStepKeyForState(step, stateForStep);
if (stepKey === 'oauth-login') {
if (payload.loginVerificationRequestedAt) {
if (payload.skipLoginVerificationStep) {
await setState({ loginVerificationRequestedAt: null });
const latestState = await getState();
const loginCodeStep = findStepByKeyAfter(step, 'fetch-login-code', latestState);
if (loginCodeStep) {
const currentStatus = latestState.stepStatuses?.[loginCodeStep];
if (!isStepProtectedFromAutoSkip(currentStatus)) {
await setStepStatus(loginCodeStep, 'skipped');
await addLog(`步骤 ${step}:认证页已直接进入 OAuth 授权页,已自动跳过步骤 ${loginCodeStep} 的登录验证码。`, 'warn');
}
}
} else if (payload.loginVerificationRequestedAt) {
await setState({ loginVerificationRequestedAt: payload.loginVerificationRequestedAt });
}
return;
@@ -484,7 +520,8 @@
await setPersistentSettings({ emailPrefix: message.payload.emailPrefix });
await setState({ emailPrefix: message.payload.emailPrefix });
}
if (doesStepUseCompletionSignal(step)) {
const executionState = await getState();
if (doesStepUseCompletionSignal(step, executionState)) {
await executeStepViaCompletionSignal(step);
} else {
await executeStep(step);
+5 -1
View File
@@ -38,10 +38,14 @@
return visibleStep > 0 ? visibleStep : fallback;
}
function getAuthLoginStepForVisibleStep(visibleStep) {
return visibleStep >= 12 ? 10 : 7;
}
async function executeStep9(state) {
const visibleStep = getVisibleStep(state, 9);
if (!state.oauthUrl) {
const authLoginStep = visibleStep === 11 ? 10 : 7;
const authLoginStep = getAuthLoginStepForVisibleStep(visibleStep);
throw new Error(`缺少登录用 OAuth 链接,请先完成步骤 ${authLoginStep}`);
}
+41 -22
View File
@@ -31,25 +31,34 @@
throwIfStopped,
} = deps;
async function getStep8ReadyTimeoutMs(actionLabel, expectedOauthUrl = '') {
function getVisibleStep(state, fallback = 8) {
const visibleStep = Math.floor(Number(state?.visibleStep) || 0);
return visibleStep > 0 ? visibleStep : fallback;
}
function getAuthLoginStepForVisibleStep(visibleStep) {
return visibleStep >= 11 ? 10 : 7;
}
async function getStep8ReadyTimeoutMs(actionLabel, expectedOauthUrl = '', visibleStep = 8) {
if (typeof getOAuthFlowStepTimeoutMs !== 'function') {
return 15000;
}
return getOAuthFlowStepTimeoutMs(15000, {
step: 8,
step: visibleStep,
actionLabel,
oauthUrl: expectedOauthUrl,
});
}
function getStep8RemainingTimeResolver(expectedOauthUrl = '') {
function getStep8RemainingTimeResolver(expectedOauthUrl = '', visibleStep = 8) {
if (typeof getOAuthFlowRemainingMs !== 'function') {
return undefined;
}
return async (details = {}) => getOAuthFlowRemainingMs({
step: 8,
step: visibleStep,
actionLabel: details.actionLabel || '登录验证码流程',
oauthUrl: expectedOauthUrl,
});
@@ -96,6 +105,7 @@
}
async function runStep8Attempt(state) {
const visibleStep = getVisibleStep(state, 8);
const mail = getMailConfig(state);
if (mail.error) throw new Error(mail.error);
@@ -110,14 +120,16 @@
await chrome.tabs.update(authTabId, { active: true });
} else {
if (!state.oauthUrl) {
throw new Error('缺少登录用 OAuth 链接,请先完成步骤 7。');
throw new Error(`缺少登录用 OAuth 链接,请先完成步骤 ${getAuthLoginStepForVisibleStep(visibleStep)}`);
}
await reuseOrCreateTab('signup-page', state.oauthUrl);
}
throwIfStopped();
const pageState = await ensureStep8VerificationPageReady({
timeoutMs: await getStep8ReadyTimeoutMs('确认登录验证码页已就绪', state?.oauthUrl || ''),
visibleStep,
authLoginStep: getAuthLoginStepForVisibleStep(visibleStep),
timeoutMs: await getStep8ReadyTimeoutMs('确认登录验证码页已就绪', state?.oauthUrl || '', visibleStep),
});
const shouldCompareVerificationEmail = mail.provider !== '2925';
const displayedVerificationEmail = shouldCompareVerificationEmail
@@ -131,22 +143,25 @@
step8VerificationTargetEmail: displayedVerificationEmail || '',
});
await addLog('步骤 8:登录验证码页面已就绪,开始获取验证码。', 'info');
await addLog(`步骤 ${visibleStep}:登录验证码页面已就绪,开始获取验证码。`, 'info');
if (shouldCompareVerificationEmail && displayedVerificationEmail) {
await addLog(`步骤 8:已固定当前验证码页显示邮箱 ${displayedVerificationEmail} 作为后续匹配目标。`, 'info');
await addLog(`步骤 ${visibleStep}:已固定当前验证码页显示邮箱 ${displayedVerificationEmail} 作为后续匹配目标。`, 'info');
}
if (shouldUseCustomRegistrationEmail(state)) {
await confirmCustomVerificationStepBypass(8);
await confirmCustomVerificationStepBypass(8, {
completionStep: visibleStep,
promptStep: visibleStep,
});
return;
}
if (mail.source === 'icloud-mail' && typeof ensureIcloudMailSession === 'function') {
await addLog('步骤 8:正在确认 iCloud 邮箱登录态...', 'info');
await addLog(`步骤 ${visibleStep}:正在确认 iCloud 邮箱登录态...`, 'info');
await ensureIcloudMailSession({
state,
step: 8,
actionLabel: '步骤 8:确认 iCloud 邮箱登录态',
actionLabel: `步骤 ${visibleStep}:确认 iCloud 邮箱登录态`,
});
}
@@ -156,22 +171,22 @@
|| mail.provider === LUCKMAIL_PROVIDER
|| mail.provider === CLOUDFLARE_TEMP_EMAIL_PROVIDER
) {
await addLog(`步骤 8:正在通过 ${mail.label} 轮询验证码...`);
await addLog(`步骤 ${visibleStep}:正在通过 ${mail.label} 轮询验证码...`);
} else {
await addLog(`步骤 8:正在打开${mail.label}...`);
await addLog(`步骤 ${visibleStep}:正在打开${mail.label}...`);
if (mail.provider === '2925' && typeof ensureMail2925MailboxSession === 'function') {
await ensureMail2925MailboxSession({
accountId: state.currentMail2925AccountId || null,
forceRelogin: false,
allowLoginWhenOnLoginPage: Boolean(state?.mail2925UseAccountPool),
expectedMailboxEmail: getExpectedMail2925MailboxEmail(state),
actionLabel: 'Step 8: ensure 2925 mailbox session',
actionLabel: `Step ${visibleStep}: ensure 2925 mailbox session`,
});
} else {
await focusOrOpenMailTab(mail);
}
if (mail.provider === '2925') {
await addLog(`步骤 8:将直接使用当前已登录的 ${mail.label} 轮询验证码。`, 'info');
await addLog(`步骤 ${visibleStep}:将直接使用当前已登录的 ${mail.label} 轮询验证码。`, 'info');
}
}
@@ -179,10 +194,11 @@
...state,
step8VerificationTargetEmail: displayedVerificationEmail || '',
}, mail, {
completionStep: visibleStep,
filterAfterTimestamp: verificationFilterAfterTimestamp,
sessionKey: verificationSessionKey,
disableTimeBudgetCap: mail.provider === '2925',
getRemainingTimeMs: getStep8RemainingTimeResolver(state?.oauthUrl || ''),
getRemainingTimeMs: getStep8RemainingTimeResolver(state?.oauthUrl || '', visibleStep),
requestFreshCodeFirst: false,
targetEmail: fixedTargetEmail,
resendIntervalMs: (mail.provider === HOTMAIL_PROVIDER || mail.provider === '2925')
@@ -206,6 +222,8 @@
await runStep8Attempt(currentState);
return;
} catch (err) {
const visibleStep = getVisibleStep(currentState, 8);
const authLoginStep = getAuthLoginStepForVisibleStep(visibleStep);
if (!isVerificationMailPollingError(err) && !isStep8RestartStep7Error(err)) {
throw err;
}
@@ -218,26 +236,27 @@
mailPollingAttempt += 1;
await addLog(
isStep8RestartStep7Error(err)
? `步骤 8:检测到认证页进入重试/超时报错状态,准备从步骤 7 重新开始(${mailPollingAttempt}/${STEP7_MAIL_POLLING_RECOVERY_MAX_ATTEMPTS}...`
: `步骤 8:检测到邮箱轮询类失败,准备从步骤 7 重新开始(${mailPollingAttempt}/${STEP7_MAIL_POLLING_RECOVERY_MAX_ATTEMPTS}...`,
? `步骤 ${visibleStep}:检测到认证页进入重试/超时报错状态,准备从步骤 ${authLoginStep} 重新开始(${mailPollingAttempt}/${STEP7_MAIL_POLLING_RECOVERY_MAX_ATTEMPTS}...`
: `步骤 ${visibleStep}:检测到邮箱轮询类失败,准备从步骤 ${authLoginStep} 重新开始(${mailPollingAttempt}/${STEP7_MAIL_POLLING_RECOVERY_MAX_ATTEMPTS}...`,
'warn'
);
await rerunStep7ForStep8Recovery({
logMessage: isStep8RestartStep7Error(err)
? '步骤 8:认证页进入重试/超时报错状态,正在回到步骤 7 重新发起登录流程...'
: '步骤 8:正在回到步骤 7,重新发起登录验证码流程...',
? `步骤 ${visibleStep}:认证页进入重试/超时报错状态,正在回到步骤 ${authLoginStep} 重新发起登录流程...`
: `步骤 ${visibleStep}:正在回到步骤 ${authLoginStep},重新发起登录验证码流程...`,
});
currentState = await getState();
}
}
const visibleStep = getVisibleStep(currentState, 8);
if (lastMailPollingError) {
throw new Error(
`步骤 8:登录验证码流程在 ${STEP7_MAIL_POLLING_RECOVERY_MAX_ATTEMPTS} 轮邮箱轮询恢复后仍未成功。最后一次原因:${lastMailPollingError.message}`
`步骤 ${visibleStep}:登录验证码流程在 ${STEP7_MAIL_POLLING_RECOVERY_MAX_ATTEMPTS} 轮邮箱轮询恢复后仍未成功。最后一次原因:${lastMailPollingError.message}`
);
}
throw new Error('步骤 8:登录验证码流程未成功完成。');
throw new Error(`步骤 ${visibleStep}:登录验证码流程未成功完成。`);
}
return { executeStep8 };
+10 -3
View File
@@ -60,7 +60,7 @@
try {
const currentState = attempt === 1 ? state : await getState();
const password = currentState.password || currentState.customPassword || '';
const oauthUrl = await refreshOAuthUrlBeforeStep6(currentState);
const oauthUrl = await refreshOAuthUrlBeforeStep6(currentState, { visibleStep });
if (typeof startOAuthFlowTimeoutWindow === 'function') {
await startOAuthFlowTimeoutWindow({ step: visibleStep, oauthUrl });
}
@@ -105,9 +105,16 @@
}
if (isStep6SuccessResult(result)) {
await completeStepFromBackground(visibleStep, {
const completionPayload = {
loginVerificationRequestedAt: result.loginVerificationRequestedAt || null,
});
};
if (result.skipLoginVerificationStep) {
completionPayload.skipLoginVerificationStep = true;
}
if (result.directOAuthConsentPage) {
completionPayload.directOAuthConsentPage = true;
}
await completeStepFromBackground(visibleStep, completionPayload);
return;
}
+11 -7
View File
@@ -32,21 +32,25 @@
}
function getConfirmStepForVisibleStep(visibleStep) {
return visibleStep === 12 ? 11 : 9;
return visibleStep >= 13 ? 12 : 9;
}
function parseLocalhostCallback(rawUrl) {
function getAuthLoginStepForVisibleStep(visibleStep) {
return visibleStep >= 13 ? 10 : 7;
}
function parseLocalhostCallback(rawUrl, visibleStep = 10, confirmStep = 9) {
let parsed;
try {
parsed = new URL(rawUrl);
} catch {
throw new Error('步骤 10 捕获到的 localhost OAuth 回调地址格式无效,请重新执行步骤 9。');
throw new Error(`步骤 ${visibleStep} 捕获到的 localhost OAuth 回调地址格式无效,请重新执行步骤 ${confirmStep}`);
}
const code = normalizeString(parsed.searchParams.get('code'));
const state = normalizeString(parsed.searchParams.get('state'));
if (!code || !state) {
throw new Error('步骤 10 捕获到的 localhost OAuth 回调地址缺少 code 或 state,请重新执行步骤 9。');
throw new Error(`步骤 ${visibleStep} 捕获到的 localhost OAuth 回调地址缺少 code 或 state,请重新执行步骤 ${confirmStep}`);
}
return {
@@ -191,16 +195,16 @@
throw new Error(`缺少 localhost 回调地址,请先完成步骤 ${confirmStep}`);
}
if (!state.codex2apiSessionId) {
throw new Error(`缺少 Codex2API 会话信息,请重新执行步骤 ${visibleStep === 12 ? 10 : 7}`);
throw new Error(`缺少 Codex2API 会话信息,请重新执行步骤 ${getAuthLoginStepForVisibleStep(visibleStep)}`);
}
if (!normalizeString(state.codex2apiAdminKey)) {
throw new Error('尚未配置 Codex2API 管理密钥,请先在侧边栏填写。');
}
const callback = parseLocalhostCallback(state.localhostUrl);
const callback = parseLocalhostCallback(state.localhostUrl, visibleStep, confirmStep);
const expectedState = normalizeString(state.codex2apiOAuthState);
if (expectedState && expectedState !== callback.state) {
throw new Error('Codex2API 回调 state 与当前授权会话不匹配,请重新执行步骤 7。');
throw new Error(`Codex2API 回调 state 与当前授权会话不匹配,请重新执行步骤 ${getAuthLoginStepForVisibleStep(visibleStep)}`);
}
const codex2apiUrl = normalizeCodex2ApiUrl(state.codex2apiUrl);
+17 -9
View File
@@ -175,25 +175,32 @@
return Math.max(0, Math.floor(Number(VERIFICATION_POLL_MAX_ROUNDS) || 1) - 1);
}
async function confirmCustomVerificationStepBypass(step) {
function getCompletionStep(step, options = {}) {
const completionStep = Number(options.completionStep);
return Number.isFinite(completionStep) && completionStep > 0 ? completionStep : step;
}
async function confirmCustomVerificationStepBypass(step, options = {}) {
const completionStep = getCompletionStep(step, options);
const promptStep = getCompletionStep(step, { completionStep: options.promptStep ?? completionStep });
const verificationLabel = getVerificationCodeLabel(step);
await addLog(`步骤 ${step}:当前为自定义邮箱模式,请手动在页面中输入${verificationLabel}验证码并进入下一页面。`, 'warn');
await addLog(`步骤 ${completionStep}:当前为自定义邮箱模式,请手动在页面中输入${verificationLabel}验证码并进入下一页面。`, 'warn');
let response = null;
try {
response = await confirmCustomVerificationStepBypassRequest(step);
response = await confirmCustomVerificationStepBypassRequest(promptStep);
} catch {
throw new Error(`步骤 ${step}:无法打开确认弹窗,请先保持侧边栏打开后重试。`);
throw new Error(`步骤 ${completionStep}:无法打开确认弹窗,请先保持侧边栏打开后重试。`);
}
if (response?.error) {
throw new Error(response.error);
}
if (step === 8 && response?.addPhoneDetected) {
throw new Error('步骤 8:验证码提交后页面进入手机号页面,当前流程无法继续自动授权。 URL: https://auth.openai.com/add-phone');
throw new Error(`步骤 ${completionStep}:验证码提交后页面进入手机号页面,当前流程无法继续自动授权。 URL: https://auth.openai.com/add-phone`);
}
if (!response?.confirmed) {
throw new Error(`步骤 ${step}:已取消手动${verificationLabel}验证码确认。`);
throw new Error(`步骤 ${completionStep}:已取消手动${verificationLabel}验证码确认。`);
}
await setState({
@@ -201,8 +208,8 @@
signupVerificationRequestedAt: null,
loginVerificationRequestedAt: null,
});
await deps.setStepStatus(step, 'skipped');
await addLog(`步骤 ${step}:已确认手动完成${verificationLabel}验证码输入,当前步骤已跳过。`, 'warn');
await deps.setStepStatus(completionStep, 'skipped');
await addLog(`步骤 ${completionStep}:已确认手动完成${verificationLabel}验证码输入,当前步骤已跳过。`, 'warn');
}
function getVerificationPollPayload(step, state, overrides = {}) {
@@ -781,6 +788,7 @@
}
async function resolveVerificationStep(step, state, mail, options = {}) {
const completionStep = getCompletionStep(step, options);
const stateKey = getVerificationCodeStateKey(step);
const rejectedCodes = new Set();
const hotmailPollConfig = mail.provider === HOTMAIL_PROVIDER
@@ -918,7 +926,7 @@
[stateKey]: result.code,
});
await completeStepFromBackground(step, {
await completeStepFromBackground(completionStep, {
emailTimestamp: result.emailTimestamp,
code: result.code,
phoneVerificationRequired: Boolean(submitResult.addPhonePage),