feat(flow): stabilize step7-9, expand HeroSMS, and update usage tutorial

This commit is contained in:
daniellee2015
2026-04-29 00:51:05 +08:00
parent 9e26b16f20
commit 4c091a3d32
21 changed files with 5265 additions and 1021 deletions
File diff suppressed because it is too large Load Diff
+33 -8
View File
@@ -16,6 +16,7 @@
getTabId,
isTabAlive,
prepareStep8DebuggerClick,
recoverOAuthLocalhostTimeout,
reloadStep8ConsentPage,
reuseOrCreateTab,
sleepWithStop,
@@ -44,19 +45,43 @@
async function executeStep9(state) {
const visibleStep = getVisibleStep(state, 9);
if (!state.oauthUrl) {
let activeState = state;
if (!activeState.oauthUrl) {
const authLoginStep = getAuthLoginStepForVisibleStep(visibleStep);
throw new Error(`缺少登录用 OAuth 链接,请先完成步骤 ${authLoginStep}`);
}
await addLog(`步骤 ${visibleStep}:正在监听 localhost 回调地址...`);
const callbackTimeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
? await getOAuthFlowStepTimeoutMs(240000, {
step: visibleStep,
actionLabel: 'OAuth localhost 回调',
})
: 240000;
let callbackTimeoutMs = 240000;
let timeoutRecoveryAttempted = false;
while (true) {
try {
callbackTimeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
? await getOAuthFlowStepTimeoutMs(240000, {
step: visibleStep,
actionLabel: 'OAuth localhost 回调',
oauthUrl: activeState?.oauthUrl || '',
})
: 240000;
break;
} catch (error) {
if (timeoutRecoveryAttempted || typeof recoverOAuthLocalhostTimeout !== 'function') {
throw error;
}
const recoveredState = await recoverOAuthLocalhostTimeout({
error,
state: activeState,
visibleStep,
});
if (!recoveredState) {
throw error;
}
activeState = recoveredState;
timeoutRecoveryAttempted = true;
}
}
return new Promise((resolve, reject) => {
let resolved = false;
@@ -124,7 +149,7 @@
await chrome.tabs.update(signupTabId, { active: true });
await addLog(`步骤 ${visibleStep}:已切回认证页,正在准备调试器点击...`);
} else {
signupTabId = await reuseOrCreateTab('signup-page', state.oauthUrl);
signupTabId = await reuseOrCreateTab('signup-page', activeState.oauthUrl);
await addLog(`步骤 ${visibleStep}:已重新打开认证页,正在准备调试器点击...`);
}
+27 -1
View File
@@ -222,6 +222,28 @@
return Math.min(20, Math.max(0, Math.floor(numeric)));
}
function getVerificationRequestedAtStateKey(step) {
if (Number(step) === 4) return 'signupVerificationRequestedAt';
if (Number(step) === 8) return 'loginVerificationRequestedAt';
return '';
}
function resolveInitialVerificationRequestedAt(step, state = {}, fallback = 0) {
const stateKey = getVerificationRequestedAtStateKey(step);
const candidateValues = [
fallback,
stateKey ? state?.[stateKey] : 0,
];
for (const value of candidateValues) {
const numeric = Number(value);
if (Number.isFinite(numeric) && numeric > 0) {
return Math.floor(numeric);
}
}
return 0;
}
function getLegacyVerificationResendCountDefault(step, options = {}) {
const requestFreshCodeFirst = Boolean(options.requestFreshCodeFirst);
const legacyMaxRounds = Math.max(1, Math.floor(Number(VERIFICATION_POLL_MAX_ROUNDS) || 1));
@@ -919,10 +941,14 @@
: getConfiguredVerificationResendCount(step, state, { requestFreshCodeFirst });
const maxSubmitAttempts = mail.provider === LUCKMAIL_PROVIDER ? 3 : 15;
const resendIntervalMs = Math.max(0, Number(options.resendIntervalMs) || 0);
let lastResendAt = Number(options.lastResendAt) || 0;
const externalOnResendRequestedAt = typeof options.onResendRequestedAt === 'function'
? options.onResendRequestedAt
: null;
let lastResendAt = resolveInitialVerificationRequestedAt(
step,
state,
Number(options.lastResendAt) || 0
);
const updateFilterAfterTimestampForVerificationStep = async (requestedAt) => {
if (externalOnResendRequestedAt) {