chore: preserve step-aware logging after upstream sync
- 吸收 master 的核心改动:按可见步骤归类日志显示,覆盖 OAuth、手机号验证、平台验证和内容脚本日志链路。 - 本地补充修复:保留平台验证成功后的手机号接码确认收尾,避免 #193/#194 恢复的手机号复用链路被合并覆盖。 - 影响范围:background routing、phone verification、platform verify、content scripts、sidepanel 与相关测试/文档。
This commit is contained in:
@@ -31,10 +31,28 @@
|
||||
return labels[source] || source || '未知来源';
|
||||
}
|
||||
|
||||
async function addLog(message, level = 'info') {
|
||||
function normalizeLogStep(value) {
|
||||
const step = Math.floor(Number(value) || 0);
|
||||
return step > 0 ? step : null;
|
||||
}
|
||||
|
||||
function buildLogEntry(message, level = 'info', options = {}) {
|
||||
const normalizedOptions = options && typeof options === 'object' ? options : {};
|
||||
const step = normalizeLogStep(normalizedOptions.step);
|
||||
const stepKey = String(normalizedOptions.stepKey || '').trim();
|
||||
return {
|
||||
message: String(message || ''),
|
||||
level,
|
||||
timestamp: Date.now(),
|
||||
step,
|
||||
stepKey,
|
||||
};
|
||||
}
|
||||
|
||||
async function addLog(message, level = 'info', options = {}) {
|
||||
const state = await getState();
|
||||
const logs = state.logs || [];
|
||||
const entry = { message, level, timestamp: Date.now() };
|
||||
const entry = buildLogEntry(message, level, options);
|
||||
logs.push(entry);
|
||||
if (logs.length > 500) logs.splice(0, logs.length - 500);
|
||||
await setState({ logs });
|
||||
|
||||
@@ -222,6 +222,9 @@
|
||||
if (typeof markCurrentRegistrationAccountUsed !== 'function') {
|
||||
await finalizeIcloudAliasAfterSuccessfulFlow(latestState);
|
||||
}
|
||||
if (typeof finalizePhoneActivationAfterSuccessfulFlow === 'function') {
|
||||
await finalizePhoneActivationAfterSuccessfulFlow(latestState);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleStepData(step, payload) {
|
||||
@@ -258,7 +261,10 @@
|
||||
const currentStatus = latestState.stepStatuses?.[loginCodeStep];
|
||||
if (!isStepProtectedFromAutoSkip(currentStatus)) {
|
||||
await setStepStatus(loginCodeStep, 'skipped');
|
||||
await addLog(`步骤 ${step}:认证页已直接进入 OAuth 授权页,已自动跳过步骤 ${loginCodeStep} 的登录验证码。`, 'warn');
|
||||
await addLog(`认证页已直接进入 OAuth 授权页,已自动跳过步骤 ${loginCodeStep} 的登录验证码。`, 'warn', {
|
||||
step,
|
||||
stepKey: 'oauth-login',
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (payload.loginVerificationRequestedAt) {
|
||||
@@ -433,6 +439,9 @@
|
||||
if (typeof markCurrentRegistrationAccountUsed !== 'function' && typeof markCurrentCustomEmailPoolEntryUsed === 'function') {
|
||||
await markCurrentCustomEmailPoolEntryUsed(latestState);
|
||||
}
|
||||
if (typeof finalizePhoneActivationAfterSuccessfulFlow === 'function') {
|
||||
await finalizePhoneActivationAfterSuccessfulFlow(latestState);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -453,8 +462,16 @@
|
||||
}
|
||||
|
||||
case 'LOG': {
|
||||
const { message: msg, level } = message.payload;
|
||||
await addLog(`[${getSourceLabel(message.source)}] ${msg}`, level);
|
||||
const { message: msg, level, step: payloadStep, stepKey } = message.payload;
|
||||
const logStep = Math.floor(Number(message.step || payloadStep) || 0);
|
||||
await addLog(
|
||||
`[${getSourceLabel(message.source)}] ${msg}`,
|
||||
level,
|
||||
{
|
||||
step: logStep > 0 ? logStep : null,
|
||||
stepKey,
|
||||
}
|
||||
);
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
@@ -479,7 +496,7 @@
|
||||
}
|
||||
const errorMessage = error?.message || String(error || '步骤 3 提交后确认失败');
|
||||
await setStepStatus(message.step, 'failed');
|
||||
await addLog(`步骤 ${message.step} 失败:${errorMessage}`, 'error');
|
||||
await addLog(`失败:${errorMessage}`, 'error', { step: message.step });
|
||||
await appendManualAccountRunRecordIfNeeded(`step${message.step}_failed`, null, errorMessage);
|
||||
notifyStepError(message.step, errorMessage);
|
||||
return { ok: true, error: errorMessage };
|
||||
@@ -491,7 +508,7 @@
|
||||
: 10;
|
||||
const completionState = message.step === lastStepId ? completionStateCandidate : null;
|
||||
await setStepStatus(message.step, 'completed');
|
||||
await addLog(`步骤 ${message.step} 已完成`, 'ok');
|
||||
await addLog('已完成', 'ok', { step: message.step });
|
||||
await handleStepData(message.step, message.payload);
|
||||
if (message.step === lastStepId && typeof appendAccountRunRecord === 'function') {
|
||||
await appendAccountRunRecord('success', completionState);
|
||||
@@ -510,12 +527,12 @@
|
||||
}
|
||||
if (isStopError(message.error)) {
|
||||
await setStepStatus(message.step, 'stopped');
|
||||
await addLog(`步骤 ${message.step} 已被用户停止`, 'warn');
|
||||
await addLog('已被用户停止', 'warn', { step: message.step });
|
||||
await appendManualAccountRunRecordIfNeeded(`step${message.step}_stopped`, null, message.error);
|
||||
notifyStepError(message.step, message.error);
|
||||
} else {
|
||||
await setStepStatus(message.step, 'failed');
|
||||
await addLog(`步骤 ${message.step} 失败:${message.error}`, 'error');
|
||||
await addLog(`失败:${message.error}`, 'error', { step: message.step });
|
||||
await appendManualAccountRunRecordIfNeeded(`step${message.step}_failed`, null, message.error);
|
||||
notifyStepError(message.step, message.error);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
})(typeof self !== 'undefined' ? self : globalThis, function createBackgroundPhoneVerificationModule() {
|
||||
function createPhoneVerificationHelpers(deps = {}) {
|
||||
const {
|
||||
addLog,
|
||||
addLog: rawAddLog = async () => {},
|
||||
ensureStep8SignupPageReady,
|
||||
fetchImpl = (...args) => fetch(...args),
|
||||
getOAuthFlowStepTimeoutMs,
|
||||
@@ -91,6 +91,35 @@
|
||||
const PHONE_SMS_FAILURE_SKIP_THRESHOLD = 2;
|
||||
const MAX_ACTIVATION_PRICE_HINTS = 256;
|
||||
const activationPriceHintsByKey = new Map();
|
||||
let activePhoneVerificationLogStep = null;
|
||||
|
||||
function normalizeLogStep(value) {
|
||||
const step = Math.floor(Number(value) || 0);
|
||||
return step > 0 ? step : null;
|
||||
}
|
||||
|
||||
function normalizePhoneVerificationLogMessage(message) {
|
||||
return String(message || '')
|
||||
.replace(/^Step\s+9\s+diagnostics\s*:\s*/i, 'diagnostics: ')
|
||||
.replace(/^Step\s+9\s*[::]\s*/i, '')
|
||||
.replace(/^步骤\s*9\s*[::]\s*/, '')
|
||||
.replace(/\bstep\s+9\b/gi, 'current step')
|
||||
.trim();
|
||||
}
|
||||
|
||||
async function addLog(message, level = 'info', options = {}) {
|
||||
const normalizedOptions = options && typeof options === 'object' ? { ...options } : {};
|
||||
const step = normalizeLogStep(normalizedOptions.step || normalizedOptions.visibleStep)
|
||||
|| normalizeLogStep(activePhoneVerificationLogStep);
|
||||
if (step) {
|
||||
normalizedOptions.step = step;
|
||||
if (!normalizedOptions.stepKey) {
|
||||
normalizedOptions.stepKey = 'phone-verification';
|
||||
}
|
||||
}
|
||||
delete normalizedOptions.visibleStep;
|
||||
return rawAddLog(normalizePhoneVerificationLogMessage(message), level, normalizedOptions);
|
||||
}
|
||||
|
||||
function normalizeUrl(value, fallback = DEFAULT_HERO_SMS_BASE_URL) {
|
||||
const trimmed = String(value || '').trim();
|
||||
@@ -3475,19 +3504,24 @@
|
||||
}
|
||||
|
||||
async function readPhonePageState(tabId, timeoutMs = 10000) {
|
||||
const visibleStep = normalizeLogStep(activePhoneVerificationLogStep) || 9;
|
||||
await ensureStep8SignupPageReady(tabId, {
|
||||
timeoutMs,
|
||||
logMessage: '步骤 9:等待认证页脚本恢复后继续手机号验证。',
|
||||
visibleStep,
|
||||
logStepKey: 'phone-verification',
|
||||
});
|
||||
const result = await sendToContentScriptResilient('signup-page', {
|
||||
type: 'STEP8_GET_STATE',
|
||||
source: 'background',
|
||||
payload: {},
|
||||
payload: { visibleStep },
|
||||
}, {
|
||||
timeoutMs,
|
||||
responseTimeoutMs: timeoutMs,
|
||||
retryDelayMs: 600,
|
||||
logMessage: '步骤 9:认证页正在切换,等待后重新检查手机号验证状态...',
|
||||
logStep: visibleStep,
|
||||
logStepKey: 'phone-verification',
|
||||
});
|
||||
|
||||
if (result?.error) {
|
||||
@@ -3546,8 +3580,9 @@
|
||||
async function submitPhoneNumber(tabId, phoneNumber, activation = null) {
|
||||
const state = await getState();
|
||||
const countryConfig = resolveCountryConfigFromActivation(activation, state);
|
||||
const visibleStep = normalizeLogStep(activePhoneVerificationLogStep) || 9;
|
||||
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||
? await getOAuthFlowStepTimeoutMs(30000, { step: 9, actionLabel: '提交添加手机号' })
|
||||
? await getOAuthFlowStepTimeoutMs(30000, { step: visibleStep, actionLabel: '提交添加手机号' })
|
||||
: 30000;
|
||||
const result = await sendToContentScriptResilient('signup-page', {
|
||||
type: 'SUBMIT_PHONE_NUMBER',
|
||||
@@ -3562,6 +3597,8 @@
|
||||
responseTimeoutMs: timeoutMs,
|
||||
retryDelayMs: 600,
|
||||
logMessage: '步骤 9:等待添加手机号页面就绪...',
|
||||
logStep: visibleStep,
|
||||
logStepKey: 'phone-verification',
|
||||
});
|
||||
|
||||
if (result?.error) {
|
||||
@@ -3571,8 +3608,9 @@
|
||||
}
|
||||
|
||||
async function submitPhoneVerificationCode(tabId, code) {
|
||||
const visibleStep = normalizeLogStep(activePhoneVerificationLogStep) || 9;
|
||||
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||
? await getOAuthFlowStepTimeoutMs(45000, { step: 9, actionLabel: '提交手机验证码' })
|
||||
? await getOAuthFlowStepTimeoutMs(45000, { step: visibleStep, actionLabel: '提交手机验证码' })
|
||||
: 45000;
|
||||
const result = await sendToContentScriptResilient('signup-page', {
|
||||
type: 'SUBMIT_PHONE_VERIFICATION_CODE',
|
||||
@@ -3583,6 +3621,8 @@
|
||||
responseTimeoutMs: timeoutMs,
|
||||
retryDelayMs: 600,
|
||||
logMessage: '步骤 9:等待手机验证码页面就绪后填写短信验证码...',
|
||||
logStep: visibleStep,
|
||||
logStepKey: 'phone-verification',
|
||||
});
|
||||
|
||||
if (result?.error) {
|
||||
@@ -3598,8 +3638,9 @@
|
||||
}
|
||||
|
||||
async function resendPhoneVerificationCode(tabId) {
|
||||
const visibleStep = normalizeLogStep(activePhoneVerificationLogStep) || 9;
|
||||
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||
? await getOAuthFlowStepTimeoutMs(65000, { step: 9, actionLabel: 'resend phone verification code' })
|
||||
? await getOAuthFlowStepTimeoutMs(65000, { step: visibleStep, actionLabel: 'resend phone verification code' })
|
||||
: 65000;
|
||||
const result = await sendToContentScriptResilient('signup-page', {
|
||||
type: 'RESEND_PHONE_VERIFICATION_CODE',
|
||||
@@ -3610,6 +3651,8 @@
|
||||
responseTimeoutMs: timeoutMs,
|
||||
retryDelayMs: 600,
|
||||
logMessage: '步骤 9:等待手机验证码重发按钮出现...',
|
||||
logStep: visibleStep,
|
||||
logStepKey: 'phone-verification',
|
||||
});
|
||||
|
||||
if (result?.error) {
|
||||
@@ -3619,8 +3662,9 @@
|
||||
}
|
||||
|
||||
async function returnToAddPhone(tabId) {
|
||||
const visibleStep = normalizeLogStep(activePhoneVerificationLogStep) || 9;
|
||||
const timeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||
? await getOAuthFlowStepTimeoutMs(30000, { step: 9, actionLabel: 'return to add-phone page' })
|
||||
? await getOAuthFlowStepTimeoutMs(30000, { step: visibleStep, actionLabel: 'return to add-phone page' })
|
||||
: 30000;
|
||||
const result = await sendToContentScriptResilient('signup-page', {
|
||||
type: 'RETURN_TO_ADD_PHONE',
|
||||
@@ -3631,6 +3675,8 @@
|
||||
responseTimeoutMs: timeoutMs,
|
||||
retryDelayMs: 600,
|
||||
logMessage: '步骤 9:返回添加手机号页面以更换号码...',
|
||||
logStep: visibleStep,
|
||||
logStepKey: 'phone-verification',
|
||||
});
|
||||
|
||||
if (result?.error) {
|
||||
@@ -4105,7 +4151,8 @@
|
||||
throw new Error('手机号验证未完成。');
|
||||
}
|
||||
|
||||
async function completePhoneVerificationFlow(tabId, initialPageState = null) {
|
||||
async function completePhoneVerificationFlow(tabId, initialPageState = null, options = {}) {
|
||||
activePhoneVerificationLogStep = normalizeLogStep(options.visibleStep || options.step) || 9;
|
||||
let state = await getState();
|
||||
let activation = normalizeActivation(state[PHONE_ACTIVATION_STATE_KEY]);
|
||||
let pageState = initialPageState || await readPhonePageState(tabId);
|
||||
|
||||
@@ -47,6 +47,10 @@
|
||||
return visibleStep >= 12 ? 10 : 7;
|
||||
}
|
||||
|
||||
function addStepLog(step, message, level = 'info') {
|
||||
return addLog(message, level, { step, stepKey: 'confirm-oauth' });
|
||||
}
|
||||
|
||||
async function executeStep9(state) {
|
||||
const visibleStep = getVisibleStep(state, 9);
|
||||
let activeState = state;
|
||||
@@ -56,7 +60,7 @@
|
||||
throw new Error(`缺少登录用 OAuth 链接,请先完成步骤 ${authLoginStep}。`);
|
||||
}
|
||||
|
||||
await addLog(`步骤 ${visibleStep}:正在监听 localhost 回调地址...`);
|
||||
await addStepLog(visibleStep, '正在监听 localhost 回调地址...');
|
||||
|
||||
let callbackTimeoutMs = LOCALHOST_CALLBACK_LOCAL_TIMEOUT_MS;
|
||||
let timeoutRecoveryAttempted = false;
|
||||
@@ -115,7 +119,7 @@
|
||||
resolved = true;
|
||||
cleanupListener();
|
||||
|
||||
addLog(`步骤 ${visibleStep}:已捕获 localhost 地址:${callbackUrl}`, 'ok').then(() => {
|
||||
addStepLog(visibleStep, `已捕获 localhost 地址:${callbackUrl}`, 'ok').then(() => {
|
||||
return completeStepFromBackground(visibleStep, { localhostUrl: callbackUrl });
|
||||
}).then(() => {
|
||||
resolve();
|
||||
@@ -185,10 +189,10 @@
|
||||
|
||||
if (signupTabId && await isTabAlive('signup-page')) {
|
||||
await chrome.tabs.update(signupTabId, { active: true });
|
||||
await addLog(`步骤 ${visibleStep}:已切回认证页,正在准备调试器点击...`);
|
||||
await addStepLog(visibleStep, '已切回认证页,正在准备调试器点击...');
|
||||
} else {
|
||||
signupTabId = await reuseOrCreateTab('signup-page', activeState.oauthUrl);
|
||||
await addLog(`步骤 ${visibleStep}:已重新打开认证页,正在准备调试器点击...`);
|
||||
await addStepLog(visibleStep, '已重新打开认证页,正在准备调试器点击...');
|
||||
}
|
||||
|
||||
throwIfStep8SettledOrStopped(resolved);
|
||||
@@ -202,7 +206,9 @@
|
||||
actionLabel: '等待 OAuth 同意页内容脚本就绪',
|
||||
})
|
||||
: 15000,
|
||||
logMessage: `步骤 ${visibleStep}:认证页内容脚本尚未就绪,正在等待页面恢复...`,
|
||||
visibleStep,
|
||||
logStepKey: 'confirm-oauth',
|
||||
logMessage: '认证页内容脚本尚未就绪,正在等待页面恢复...',
|
||||
});
|
||||
|
||||
for (let round = 1; round <= STEP8_MAX_ROUNDS && !resolved; round++) {
|
||||
@@ -214,7 +220,8 @@
|
||||
step: visibleStep,
|
||||
actionLabel: '等待 OAuth 同意页出现',
|
||||
})
|
||||
: STEP8_READY_WAIT_TIMEOUT_MS
|
||||
: STEP8_READY_WAIT_TIMEOUT_MS,
|
||||
{ visibleStep }
|
||||
);
|
||||
if (!pageState?.consentReady) {
|
||||
await sleepWithStop(STEP8_CLICK_RETRY_DELAY_MS);
|
||||
@@ -223,7 +230,7 @@
|
||||
|
||||
const strategy = STEP8_STRATEGIES[Math.min(round - 1, STEP8_STRATEGIES.length - 1)];
|
||||
|
||||
await addLog(`步骤 ${visibleStep}:第 ${round}/${STEP8_MAX_ROUNDS} 轮尝试点击“继续”(${strategy.label})...`);
|
||||
await addStepLog(visibleStep, `第 ${round}/${STEP8_MAX_ROUNDS} 轮尝试点击“继续”(${strategy.label})...`);
|
||||
|
||||
if (strategy.mode === 'debugger') {
|
||||
const clickActionTimeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||
@@ -235,9 +242,10 @@
|
||||
const clickTarget = await prepareStep8DebuggerClick(signupTabId, {
|
||||
timeoutMs: clickActionTimeoutMs,
|
||||
responseTimeoutMs: clickActionTimeoutMs,
|
||||
visibleStep,
|
||||
});
|
||||
throwIfStep8SettledOrStopped(resolved);
|
||||
await clickWithDebugger(signupTabId, clickTarget?.rect);
|
||||
await clickWithDebugger(signupTabId, clickTarget?.rect, { visibleStep });
|
||||
} else {
|
||||
const clickActionTimeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||
? await getOAuthFlowStepTimeoutMs(15000, {
|
||||
@@ -248,6 +256,7 @@
|
||||
await triggerStep8ContentStrategy(signupTabId, strategy.strategy, {
|
||||
timeoutMs: clickActionTimeoutMs,
|
||||
responseTimeoutMs: clickActionTimeoutMs,
|
||||
visibleStep,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -263,14 +272,15 @@
|
||||
step: visibleStep,
|
||||
actionLabel: '等待 OAuth 同意页点击生效',
|
||||
})
|
||||
: 15000
|
||||
: 15000,
|
||||
{ visibleStep }
|
||||
);
|
||||
if (resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (effect.progressed) {
|
||||
await addLog(`步骤 ${visibleStep}:检测到本次点击已生效,${getStep8EffectLabel(effect)},继续等待 localhost 回调...`, 'info');
|
||||
await addStepLog(visibleStep, `检测到本次点击已生效,${getStep8EffectLabel(effect)},继续等待 localhost 回调...`, 'info');
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -278,7 +288,7 @@
|
||||
throw new Error(`步骤 ${visibleStep}:连续 ${STEP8_MAX_ROUNDS} 轮点击“继续”后页面仍无反应。`);
|
||||
}
|
||||
|
||||
await addLog(`步骤 ${visibleStep}:${strategy.label} 本轮点击后页面无反应,正在刷新认证页后重试(下一轮 ${round + 1}/${STEP8_MAX_ROUNDS})...`, 'warn');
|
||||
await addStepLog(visibleStep, `${strategy.label} 本轮点击后页面无反应,正在刷新认证页后重试(下一轮 ${round + 1}/${STEP8_MAX_ROUNDS})...`, 'warn');
|
||||
await reloadStep8ConsentPage(
|
||||
signupTabId,
|
||||
typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||
@@ -286,7 +296,8 @@
|
||||
step: visibleStep,
|
||||
actionLabel: '刷新 OAuth 同意页',
|
||||
})
|
||||
: 30000
|
||||
: 30000,
|
||||
{ visibleStep }
|
||||
);
|
||||
await sleepWithStop(STEP8_CLICK_RETRY_DELAY_MS);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
function createStep8Executor(deps = {}) {
|
||||
const {
|
||||
addLog,
|
||||
addLog: rawAddLog = async () => {},
|
||||
chrome,
|
||||
CLOUDFLARE_TEMP_EMAIL_PROVIDER,
|
||||
completeStepFromBackground,
|
||||
@@ -32,6 +32,33 @@
|
||||
STEP7_MAIL_POLLING_RECOVERY_MAX_ATTEMPTS,
|
||||
throwIfStopped,
|
||||
} = deps;
|
||||
let activeFetchLoginCodeStep = null;
|
||||
|
||||
function normalizeLogStep(value) {
|
||||
const step = Math.floor(Number(value) || 0);
|
||||
return step > 0 ? step : null;
|
||||
}
|
||||
|
||||
function normalizeStepLogMessage(message) {
|
||||
return String(message || '')
|
||||
.replace(/^步骤\s*\d+\s*[::]\s*/, '')
|
||||
.replace(/^Step\s+\d+\s*[::]\s*/i, '')
|
||||
.trim();
|
||||
}
|
||||
|
||||
function addLog(message, level = 'info', options = {}) {
|
||||
const normalizedOptions = options && typeof options === 'object' ? { ...options } : {};
|
||||
const step = normalizeLogStep(normalizedOptions.step || normalizedOptions.visibleStep)
|
||||
|| normalizeLogStep(activeFetchLoginCodeStep);
|
||||
if (step) {
|
||||
normalizedOptions.step = step;
|
||||
if (!normalizedOptions.stepKey) {
|
||||
normalizedOptions.stepKey = 'fetch-login-code';
|
||||
}
|
||||
}
|
||||
delete normalizedOptions.visibleStep;
|
||||
return rawAddLog(normalizeStepLogMessage(message), level, normalizedOptions);
|
||||
}
|
||||
|
||||
function getVisibleStep(state, fallback = 8) {
|
||||
const visibleStep = Math.floor(Number(state?.visibleStep) || 0);
|
||||
@@ -181,6 +208,7 @@
|
||||
|
||||
async function runStep8Attempt(state, runtime = {}) {
|
||||
const visibleStep = getVisibleStep(state, 8);
|
||||
activeFetchLoginCodeStep = visibleStep;
|
||||
const mail = getMailConfig(state);
|
||||
if (mail.error) throw new Error(mail.error);
|
||||
const stateLastResendAt = Number(state?.loginVerificationRequestedAt) || 0;
|
||||
@@ -371,7 +399,9 @@
|
||||
'warn'
|
||||
);
|
||||
await rerunStep7ForStep8Recovery({
|
||||
logMessage: `步骤 ${visibleStep}:邮箱通信异常持续未恢复,正在回到步骤 ${authLoginStep} 重新发起登录流程...`,
|
||||
logMessage: `邮箱通信异常持续未恢复,正在回到步骤 ${authLoginStep} 重新发起登录流程...`,
|
||||
logStep: visibleStep,
|
||||
logStepKey: 'fetch-login-code',
|
||||
});
|
||||
currentState = await getState();
|
||||
retryWithoutStep7Streak = 0;
|
||||
@@ -415,8 +445,10 @@
|
||||
);
|
||||
await rerunStep7ForStep8Recovery({
|
||||
logMessage: isStep8RestartStep7Error(currentError)
|
||||
? `步骤 ${visibleStep}:认证页进入重试/超时报错状态,正在回到步骤 ${authLoginStep} 重新发起登录流程...`
|
||||
: `步骤 ${visibleStep}:正在回到步骤 ${authLoginStep},重新发起登录验证码流程...`,
|
||||
? `认证页进入重试/超时报错状态,正在回到步骤 ${authLoginStep} 重新发起登录流程...`
|
||||
: `正在回到步骤 ${authLoginStep},重新发起登录验证码流程...`,
|
||||
logStep: visibleStep,
|
||||
logStepKey: 'fetch-login-code',
|
||||
});
|
||||
currentState = await getState();
|
||||
}
|
||||
|
||||
@@ -59,20 +59,26 @@
|
||||
const password = currentState.password || currentState.customPassword || '';
|
||||
const oauthUrl = await refreshOAuthUrlBeforeStep6(currentState);
|
||||
if (typeof startOAuthFlowTimeoutWindow === 'function') {
|
||||
await startOAuthFlowTimeoutWindow({ step: 7, oauthUrl });
|
||||
await startOAuthFlowTimeoutWindow({ step: completionStep, oauthUrl });
|
||||
}
|
||||
const loginTimeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||
? await getOAuthFlowStepTimeoutMs(180000, {
|
||||
step: 7,
|
||||
step: completionStep,
|
||||
actionLabel: 'OAuth 登录并进入验证码页',
|
||||
oauthUrl,
|
||||
})
|
||||
: 180000;
|
||||
|
||||
if (attempt === 1) {
|
||||
await addLog('步骤 7:正在打开最新 OAuth 链接并登录...');
|
||||
await addLog('正在打开最新 OAuth 链接并登录...', 'info', {
|
||||
step: completionStep,
|
||||
stepKey: 'oauth-login',
|
||||
});
|
||||
} else {
|
||||
await addLog(`步骤 7:上一轮失败后,正在进行第 ${attempt} 次尝试(最多 ${STEP6_MAX_ATTEMPTS} 次)...`, 'warn');
|
||||
await addLog(`上一轮失败后,正在进行第 ${attempt} 次尝试(最多 ${STEP6_MAX_ATTEMPTS} 次)...`, 'warn', {
|
||||
step: completionStep,
|
||||
stepKey: 'oauth-login',
|
||||
});
|
||||
}
|
||||
|
||||
await reuseOrCreateTab('signup-page', oauthUrl, { forceNew: true });
|
||||
@@ -86,13 +92,16 @@
|
||||
payload: {
|
||||
email: currentState.email,
|
||||
password,
|
||||
visibleStep: completionStep,
|
||||
},
|
||||
},
|
||||
{
|
||||
timeoutMs: loginTimeoutMs,
|
||||
responseTimeoutMs: loginTimeoutMs,
|
||||
retryDelayMs: 700,
|
||||
logMessage: '步骤 7:认证页正在切换,等待页面重新就绪后继续登录...',
|
||||
logMessage: '认证页正在切换,等待页面重新就绪后继续登录...',
|
||||
logStep: completionStep,
|
||||
logStepKey: 'oauth-login',
|
||||
}
|
||||
);
|
||||
|
||||
@@ -117,11 +126,11 @@
|
||||
|
||||
if (isStep6RecoverableResult(result)) {
|
||||
const reasonMessage = result.message
|
||||
|| `当前停留在${getLoginAuthStateLabel(result.state)},准备重新执行步骤 7。`;
|
||||
|| `当前停留在${getLoginAuthStateLabel(result.state)},准备重新执行步骤 ${completionStep}。`;
|
||||
throw new Error(reasonMessage);
|
||||
}
|
||||
|
||||
throw new Error('步骤 7:认证页未返回可识别的登录结果。');
|
||||
throw new Error(`步骤 ${completionStep}:认证页未返回可识别的登录结果。`);
|
||||
} catch (err) {
|
||||
throwIfStopped(err);
|
||||
if (isAddPhoneAuthFailure(err)) {
|
||||
@@ -129,8 +138,9 @@
|
||||
}
|
||||
if (isManagementSecretConfigError(err)) {
|
||||
await addLog(
|
||||
`步骤 7:检测到来源后台管理密钥缺失或错误,不再重试,当前流程停止。原因:${getErrorMessage(err)}`,
|
||||
'error'
|
||||
`检测到来源后台管理密钥缺失或错误,不再重试,当前流程停止。原因:${getErrorMessage(err)}`,
|
||||
'error',
|
||||
{ step: completionStep, stepKey: 'oauth-login' }
|
||||
);
|
||||
throw err;
|
||||
}
|
||||
@@ -139,11 +149,14 @@
|
||||
break;
|
||||
}
|
||||
|
||||
await addLog(`步骤 7:第 ${attempt} 次尝试失败,原因:${getErrorMessage(err)};准备重试...`, 'warn');
|
||||
await addLog(`第 ${attempt} 次尝试失败,原因:${getErrorMessage(err)};准备重试...`, 'warn', {
|
||||
step: completionStep,
|
||||
stepKey: 'oauth-login',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`步骤 7:判断失败后已重试 ${STEP6_MAX_ATTEMPTS - 1} 次,仍未成功。最后原因:${getErrorMessage(lastError)}`);
|
||||
throw new Error(`步骤 ${completionStep}:判断失败后已重试 ${STEP6_MAX_ATTEMPTS - 1} 次,仍未成功。最后原因:${getErrorMessage(lastError)}`);
|
||||
}
|
||||
|
||||
return { executeStep7 };
|
||||
|
||||
@@ -31,18 +31,31 @@
|
||||
return visibleStep >= 10 ? visibleStep : 10;
|
||||
}
|
||||
|
||||
function parseLocalhostCallback(rawUrl) {
|
||||
function resolveConfirmOauthStep(platformVerifyStep = 10) {
|
||||
return Number(platformVerifyStep) >= 13 ? 12 : 9;
|
||||
}
|
||||
|
||||
function resolveAuthLoginStep(platformVerifyStep = 10) {
|
||||
return Number(platformVerifyStep) >= 13 ? 10 : 7;
|
||||
}
|
||||
|
||||
function addStepLog(step, message, level = 'info') {
|
||||
return addLog(message, level, { step, stepKey: 'platform-verify' });
|
||||
}
|
||||
|
||||
function parseLocalhostCallback(rawUrl, platformVerifyStep = 10) {
|
||||
const confirmOauthStep = resolveConfirmOauthStep(platformVerifyStep);
|
||||
let parsed;
|
||||
try {
|
||||
parsed = new URL(rawUrl);
|
||||
} catch {
|
||||
throw new Error('步骤 10 捕获到的 localhost OAuth 回调地址格式无效,请重新执行步骤 9。');
|
||||
throw new Error(`步骤 ${platformVerifyStep} 捕获到的 localhost OAuth 回调地址格式无效,请重新执行步骤 ${confirmOauthStep}。`);
|
||||
}
|
||||
|
||||
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(`步骤 ${platformVerifyStep} 捕获到的 localhost OAuth 回调地址缺少 code 或 state,请重新执行步骤 ${confirmOauthStep}。`);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -206,18 +219,20 @@
|
||||
|
||||
async function executeCpaStep10(state) {
|
||||
const platformVerifyStep = resolvePlatformVerifyStep(state);
|
||||
const confirmOauthStep = resolveConfirmOauthStep(platformVerifyStep);
|
||||
const authLoginStep = resolveAuthLoginStep(platformVerifyStep);
|
||||
if (state.localhostUrl && !isLocalhostOAuthCallbackUrl(state.localhostUrl)) {
|
||||
throw new Error('步骤 9 捕获到的 localhost OAuth 回调地址无效,请重新执行步骤 9。');
|
||||
throw new Error(`步骤 ${confirmOauthStep} 捕获到的 localhost OAuth 回调地址无效,请重新执行步骤 ${confirmOauthStep}。`);
|
||||
}
|
||||
if (!state.localhostUrl) {
|
||||
throw new Error('缺少 localhost 回调地址,请先完成步骤 9。');
|
||||
throw new Error(`缺少 localhost 回调地址,请先完成步骤 ${confirmOauthStep}。`);
|
||||
}
|
||||
if (!state.vpsUrl) {
|
||||
throw new Error('尚未填写 CPA 地址,请先在侧边栏输入。');
|
||||
}
|
||||
|
||||
if (shouldBypassStep9ForLocalCpa(state)) {
|
||||
await addLog('步骤 10:检测到本地 CPA,且当前策略为“跳过第10步”,本轮不再重复提交回调地址。', 'info');
|
||||
await addStepLog(platformVerifyStep, '检测到本地 CPA,且当前策略为“跳过平台回调验证”,本轮不再重复提交回调地址。', 'info');
|
||||
await completeStepFromBackground(platformVerifyStep, {
|
||||
localhostUrl: state.localhostUrl,
|
||||
verifiedStatus: 'local-auto',
|
||||
@@ -225,17 +240,17 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const callback = parseLocalhostCallback(state.localhostUrl);
|
||||
const callback = parseLocalhostCallback(state.localhostUrl, platformVerifyStep);
|
||||
const expectedState = normalizeString(state.cpaOAuthState);
|
||||
if (expectedState && expectedState !== callback.state) {
|
||||
throw new Error('CPA 回调 state 与当前授权会话不匹配,请重新执行步骤 7。');
|
||||
throw new Error(`CPA 回调 state 与当前授权会话不匹配,请重新执行步骤 ${authLoginStep}。`);
|
||||
}
|
||||
const managementKey = normalizeString(state.vpsPassword);
|
||||
if (!managementKey) {
|
||||
throw new Error('尚未配置 CPA 管理密钥,请先在侧边栏填写。');
|
||||
}
|
||||
|
||||
await addLog('步骤 10:正在通过 CPA 管理接口提交回调地址...');
|
||||
await addStepLog(platformVerifyStep, '正在通过 CPA 管理接口提交回调地址...');
|
||||
try {
|
||||
const origin = normalizeString(state.cpaManagementOrigin) || deriveCpaManagementOrigin(state.vpsUrl);
|
||||
const result = await fetchCpaManagementJson(origin, '/v0/management/oauth-callback', {
|
||||
@@ -250,43 +265,45 @@
|
||||
const verifiedStatus = normalizeString(result?.message)
|
||||
|| normalizeString(result?.status_message)
|
||||
|| 'CPA 已通过接口提交回调';
|
||||
await addLog(`步骤 10:${verifiedStatus}`, 'ok');
|
||||
await addStepLog(platformVerifyStep, verifiedStatus, 'ok');
|
||||
await completeStepFromBackground(platformVerifyStep, {
|
||||
localhostUrl: callback.url,
|
||||
verifiedStatus,
|
||||
});
|
||||
} catch (error) {
|
||||
const reason = normalizeString(error?.message) || 'unknown error';
|
||||
await addLog(`步骤 10:CPA 接口提交失败:${reason}`, 'error');
|
||||
await addStepLog(platformVerifyStep, `CPA 接口提交失败:${reason}`, 'error');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function executeCodex2ApiStep10(state) {
|
||||
const platformVerifyStep = resolvePlatformVerifyStep(state);
|
||||
const confirmOauthStep = resolveConfirmOauthStep(platformVerifyStep);
|
||||
const authLoginStep = resolveAuthLoginStep(platformVerifyStep);
|
||||
if (state.localhostUrl && !isLocalhostOAuthCallbackUrl(state.localhostUrl)) {
|
||||
throw new Error('步骤 9 捕获到的 localhost OAuth 回调地址无效,请重新执行步骤 9。');
|
||||
throw new Error(`步骤 ${confirmOauthStep} 捕获到的 localhost OAuth 回调地址无效,请重新执行步骤 ${confirmOauthStep}。`);
|
||||
}
|
||||
if (!state.localhostUrl) {
|
||||
throw new Error('缺少 localhost 回调地址,请先完成步骤 9。');
|
||||
throw new Error(`缺少 localhost 回调地址,请先完成步骤 ${confirmOauthStep}。`);
|
||||
}
|
||||
if (!state.codex2apiSessionId) {
|
||||
throw new Error('缺少 Codex2API 会话信息,请重新执行步骤 7。');
|
||||
throw new Error(`缺少 Codex2API 会话信息,请重新执行步骤 ${authLoginStep}。`);
|
||||
}
|
||||
if (!normalizeString(state.codex2apiAdminKey)) {
|
||||
throw new Error('尚未配置 Codex2API 管理密钥,请先在侧边栏填写。');
|
||||
}
|
||||
|
||||
const callback = parseLocalhostCallback(state.localhostUrl);
|
||||
const callback = parseLocalhostCallback(state.localhostUrl, platformVerifyStep);
|
||||
const expectedState = normalizeString(state.codex2apiOAuthState);
|
||||
if (expectedState && expectedState !== callback.state) {
|
||||
throw new Error('Codex2API 回调 state 与当前授权会话不匹配,请重新执行步骤 7。');
|
||||
throw new Error(`Codex2API 回调 state 与当前授权会话不匹配,请重新执行步骤 ${authLoginStep}。`);
|
||||
}
|
||||
|
||||
const codex2apiUrl = normalizeCodex2ApiUrl(state.codex2apiUrl);
|
||||
const origin = new URL(codex2apiUrl).origin;
|
||||
|
||||
await addLog('步骤 10:正在向 Codex2API 提交回调并创建账号...');
|
||||
await addStepLog(platformVerifyStep, '正在向 Codex2API 提交回调并创建账号...');
|
||||
const result = await fetchCodex2ApiJson(origin, '/api/admin/oauth/exchange-code', {
|
||||
adminKey: state.codex2apiAdminKey,
|
||||
method: 'POST',
|
||||
@@ -298,7 +315,7 @@
|
||||
});
|
||||
|
||||
const verifiedStatus = normalizeString(result?.message) || 'Codex2API OAuth 账号添加成功';
|
||||
await addLog(`步骤 10:${verifiedStatus}`, 'ok');
|
||||
await addStepLog(platformVerifyStep, verifiedStatus, 'ok');
|
||||
await completeStepFromBackground(platformVerifyStep, {
|
||||
localhostUrl: callback.url,
|
||||
verifiedStatus,
|
||||
@@ -308,11 +325,12 @@
|
||||
async function executeSub2ApiStep10(state) {
|
||||
const platformVerifyStep = resolvePlatformVerifyStep(state);
|
||||
const visibleStep = platformVerifyStep;
|
||||
const confirmOauthStep = resolveConfirmOauthStep(visibleStep);
|
||||
if (state.localhostUrl && !isLocalhostOAuthCallbackUrl(state.localhostUrl)) {
|
||||
throw new Error('步骤 9 捕获到的 localhost OAuth 回调地址无效,请重新执行步骤 9。');
|
||||
throw new Error(`步骤 ${confirmOauthStep} 捕获到的 localhost OAuth 回调地址无效,请重新执行步骤 ${confirmOauthStep}。`);
|
||||
}
|
||||
if (!state.localhostUrl) {
|
||||
throw new Error('缺少 localhost 回调地址,请先完成步骤 9。');
|
||||
throw new Error(`缺少 localhost 回调地址,请先完成步骤 ${confirmOauthStep}。`);
|
||||
}
|
||||
if (!state.sub2apiSessionId) {
|
||||
throw new Error('缺少 SUB2API 会话信息,请重新执行步骤 1。');
|
||||
@@ -327,7 +345,7 @@
|
||||
const sub2apiUrl = normalizeSub2ApiUrl(state.sub2apiUrl);
|
||||
const injectFiles = ['content/utils.js', 'content/sub2api-panel.js'];
|
||||
|
||||
await addLog('步骤 10:正在打开 SUB2API 后台...');
|
||||
await addStepLog(visibleStep, '正在打开 SUB2API 后台...');
|
||||
|
||||
let tabId = await getTabId('sub2api-panel');
|
||||
const alive = tabId && await isTabAlive('sub2api-panel');
|
||||
@@ -349,13 +367,14 @@
|
||||
injectSource: 'sub2api-panel',
|
||||
});
|
||||
|
||||
await addLog(`步骤 ${visibleStep}:正在向 SUB2API 提交回调并创建账号...`);
|
||||
await addStepLog(visibleStep, '正在向 SUB2API 提交回调并创建账号...');
|
||||
const requestMessage = {
|
||||
type: 'EXECUTE_STEP',
|
||||
step: platformVerifyStep,
|
||||
source: 'background',
|
||||
payload: {
|
||||
localhostUrl: state.localhostUrl,
|
||||
visibleStep,
|
||||
sub2apiUrl,
|
||||
sub2apiEmail: state.sub2apiEmail,
|
||||
sub2apiPassword: state.sub2apiPassword,
|
||||
@@ -386,8 +405,9 @@
|
||||
throw error;
|
||||
}
|
||||
await addLog(
|
||||
`步骤 ${visibleStep}:SUB2API 回调交换出现临时网络波动(${error.message}),正在重试 ${attempt + 1}/${maxExchangeAttempts}...`,
|
||||
'warn'
|
||||
`SUB2API 回调交换出现临时网络波动(${error.message}),正在重试 ${attempt + 1}/${maxExchangeAttempts}...`,
|
||||
'warn',
|
||||
{ step: visibleStep, stepKey: 'platform-verify' }
|
||||
);
|
||||
await sleep(1200 * attempt);
|
||||
}
|
||||
|
||||
@@ -339,6 +339,8 @@
|
||||
timeoutMs = 30000,
|
||||
retryDelayMs = 700,
|
||||
logMessage = '',
|
||||
logStep = null,
|
||||
logStepKey = '',
|
||||
} = options;
|
||||
|
||||
const start = Date.now();
|
||||
@@ -399,7 +401,10 @@
|
||||
|
||||
if (logMessage && !logged) {
|
||||
console.warn(LOG_PREFIX, `[ensureContentScriptReadyOnTab] ${source} tab=${tabId} still not ready after ${Date.now() - start}ms`);
|
||||
await addLog(logMessage, 'warn');
|
||||
await addLog(logMessage, 'warn', {
|
||||
step: logStep,
|
||||
stepKey: logStepKey,
|
||||
});
|
||||
logged = true;
|
||||
}
|
||||
|
||||
@@ -670,6 +675,8 @@
|
||||
timeoutMs = 30000,
|
||||
retryDelayMs = 600,
|
||||
logMessage = '',
|
||||
logStep = null,
|
||||
logStepKey = '',
|
||||
responseTimeoutMs,
|
||||
} = options;
|
||||
const start = Date.now();
|
||||
@@ -701,7 +708,10 @@
|
||||
|
||||
lastError = err;
|
||||
if (logMessage && !logged) {
|
||||
await addLog(logMessage, 'warn');
|
||||
await addLog(logMessage, 'warn', {
|
||||
step: logStep,
|
||||
stepKey: logStepKey,
|
||||
});
|
||||
logged = true;
|
||||
}
|
||||
|
||||
@@ -716,6 +726,8 @@
|
||||
const {
|
||||
timeoutMs = 45000,
|
||||
maxRecoveryAttempts = 2,
|
||||
logStep = null,
|
||||
logStepKey = '',
|
||||
responseTimeoutMs,
|
||||
} = options;
|
||||
const start = Date.now();
|
||||
@@ -745,7 +757,10 @@
|
||||
|
||||
lastError = err;
|
||||
if (!logged) {
|
||||
await addLog(`步骤 ${message.step}:${mail.label} 页面通信异常,正在尝试让邮箱页重新就绪...`, 'warn');
|
||||
await addLog(`${mail.label} 页面通信异常,正在尝试让邮箱页重新就绪...`, 'warn', {
|
||||
step: logStep,
|
||||
stepKey: logStepKey,
|
||||
});
|
||||
logged = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
function createVerificationFlowHelpers(deps = {}) {
|
||||
const {
|
||||
addLog,
|
||||
addLog: rawAddLog = async () => {},
|
||||
chrome,
|
||||
closeConflictingTabsForSource,
|
||||
CLOUDFLARE_TEMP_EMAIL_PROVIDER,
|
||||
@@ -34,6 +34,33 @@
|
||||
throwIfStopped,
|
||||
VERIFICATION_POLL_MAX_ROUNDS,
|
||||
} = deps;
|
||||
let activeVerificationLogStep = null;
|
||||
|
||||
function normalizeLogStep(value) {
|
||||
const step = Math.floor(Number(value) || 0);
|
||||
return step > 0 ? step : null;
|
||||
}
|
||||
|
||||
function normalizeVerificationLogMessage(message) {
|
||||
return String(message || '')
|
||||
.replace(/^步骤\s*\d+\s*[::]\s*/, '')
|
||||
.replace(/^Step\s+\d+\s*[::]\s*/i, '')
|
||||
.trim();
|
||||
}
|
||||
|
||||
function addLog(message, level = 'info', options = {}) {
|
||||
const normalizedOptions = options && typeof options === 'object' ? { ...options } : {};
|
||||
const step = normalizeLogStep(normalizedOptions.step || normalizedOptions.visibleStep)
|
||||
|| normalizeLogStep(activeVerificationLogStep);
|
||||
if (step) {
|
||||
normalizedOptions.step = step;
|
||||
if (!normalizedOptions.stepKey) {
|
||||
normalizedOptions.stepKey = step === 4 ? 'fetch-signup-code' : 'fetch-login-code';
|
||||
}
|
||||
}
|
||||
delete normalizedOptions.visibleStep;
|
||||
return rawAddLog(normalizeVerificationLogMessage(message), level, normalizedOptions);
|
||||
}
|
||||
|
||||
const isRetryableVerificationTransportError = typeof deps.isRetryableContentScriptTransportError === 'function'
|
||||
? deps.isRetryableContentScriptTransportError
|
||||
@@ -518,6 +545,8 @@
|
||||
timeoutMs: responseTimeoutMs,
|
||||
responseTimeoutMs,
|
||||
maxRecoveryAttempts: 2,
|
||||
logStep: activeVerificationLogStep,
|
||||
logStepKey: step === 4 ? 'fetch-signup-code' : 'fetch-login-code',
|
||||
}
|
||||
);
|
||||
|
||||
@@ -583,6 +612,8 @@
|
||||
timeoutMs: 10000,
|
||||
responseTimeoutMs: 5000,
|
||||
maxRecoveryAttempts: 1,
|
||||
logStep: activeVerificationLogStep,
|
||||
logStepKey: step === 4 ? 'fetch-signup-code' : 'fetch-login-code',
|
||||
}
|
||||
);
|
||||
} catch (_) {
|
||||
@@ -693,6 +724,8 @@
|
||||
timeoutMs: timeoutWindow.timeoutMs,
|
||||
maxRecoveryAttempts: 2,
|
||||
responseTimeoutMs: timeoutWindow.responseTimeoutMs,
|
||||
logStep: activeVerificationLogStep,
|
||||
logStepKey: step === 4 ? 'fetch-signup-code' : 'fetch-login-code',
|
||||
}
|
||||
);
|
||||
|
||||
@@ -959,6 +992,8 @@
|
||||
timeoutMs: timeoutWindow.timeoutMs,
|
||||
maxRecoveryAttempts: 2,
|
||||
responseTimeoutMs: timeoutWindow.responseTimeoutMs,
|
||||
logStep: activeVerificationLogStep,
|
||||
logStepKey: step === 4 ? 'fetch-signup-code' : 'fetch-login-code',
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1000,6 +1035,8 @@
|
||||
}
|
||||
|
||||
async function submitVerificationCode(step, code, options = {}) {
|
||||
const completionStep = getCompletionStep(step, options);
|
||||
const authLoginStep = completionStep >= 11 ? 10 : 7;
|
||||
const signupTabId = await getTabId('signup-page');
|
||||
if (!signupTabId) {
|
||||
throw new Error('认证页面标签页已关闭,无法填写验证码。');
|
||||
@@ -1028,7 +1065,9 @@
|
||||
timeoutMs: Math.max(baseResponseTimeoutMs + 15000, 30000),
|
||||
retryDelayMs: 700,
|
||||
responseTimeoutMs: baseResponseTimeoutMs,
|
||||
logMessage: `步骤 ${step}:认证页正在切换,等待页面重新就绪后继续确认验证码提交结果...`,
|
||||
logMessage: '认证页正在切换,等待页面重新就绪后继续确认验证码提交结果...',
|
||||
logStep: completionStep,
|
||||
logStepKey: step === 4 ? 'fetch-signup-code' : 'fetch-login-code',
|
||||
});
|
||||
} catch (err) {
|
||||
if (step === 4 && isRetryableVerificationTransportError(err)) {
|
||||
@@ -1058,9 +1097,15 @@
|
||||
});
|
||||
if (fallback.success) {
|
||||
if (fallback.addPhonePage) {
|
||||
await addLog('步骤 8:验证码提交后通信中断,但页面已进入手机号验证页,按提交成功继续。', 'warn');
|
||||
await addLog('验证码提交后通信中断,但页面已进入手机号验证页,按提交成功继续。', 'warn', {
|
||||
step: completionStep,
|
||||
stepKey: 'fetch-login-code',
|
||||
});
|
||||
} else {
|
||||
await addLog('步骤 8:验证码提交后通信中断,但页面已进入 OAuth 授权页,按提交成功继续。', 'warn');
|
||||
await addLog('验证码提交后通信中断,但页面已进入 OAuth 授权页,按提交成功继续。', 'warn', {
|
||||
step: completionStep,
|
||||
stepKey: 'fetch-login-code',
|
||||
});
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
@@ -1072,7 +1117,7 @@
|
||||
}
|
||||
if (fallback.restartStep7) {
|
||||
const urlPart = fallback.url ? ` URL: ${fallback.url}` : '';
|
||||
throw new Error(`STEP8_RESTART_STEP7::步骤 8:验证码提交后认证页进入登录超时报错页,请回到步骤 7 重新开始。${urlPart}`.trim());
|
||||
throw new Error(`STEP8_RESTART_STEP7::步骤 ${completionStep}:验证码提交后认证页进入登录超时报错页,请回到步骤 ${authLoginStep} 重新开始。${urlPart}`.trim());
|
||||
}
|
||||
}
|
||||
throw err;
|
||||
@@ -1092,6 +1137,7 @@
|
||||
|
||||
async function resolveVerificationStep(step, state, mail, options = {}) {
|
||||
const completionStep = getCompletionStep(step, options);
|
||||
activeVerificationLogStep = completionStep;
|
||||
const stateKey = getVerificationCodeStateKey(step);
|
||||
const rejectedCodes = new Set();
|
||||
const hotmailPollConfig = mail.provider === HOTMAIL_PROVIDER
|
||||
|
||||
Reference in New Issue
Block a user