merge: sync origin/dev into pr-112
This commit is contained in:
@@ -96,6 +96,12 @@
|
||||
.join(';');
|
||||
}
|
||||
|
||||
function shouldKeepCustomMailProviderPoolEmail(state = {}) {
|
||||
return String(state?.mailProvider || '').trim().toLowerCase() === 'custom'
|
||||
&& Array.isArray(state?.customMailProviderPool)
|
||||
&& state.customMailProviderPool.length > 0;
|
||||
}
|
||||
|
||||
async function logAutoRunFinalSummary(totalRuns, roundSummaries = []) {
|
||||
const summaries = buildAutoRunRoundSummaries(totalRuns, roundSummaries);
|
||||
const successRounds = summaries.filter((item) => item.status === 'success');
|
||||
@@ -328,8 +334,10 @@
|
||||
const resumingCurrentRound = continueCurrentOnFirstAttempt && targetRun === resumeCurrentRun;
|
||||
let attemptRun = resumingCurrentRound ? resumeAttemptRun : 1;
|
||||
let reuseExistingProgress = resumingCurrentRound;
|
||||
const currentRoundState = await getState();
|
||||
const keepSameEmailUntilAddPhone = autoRunSkipFailures && shouldKeepCustomMailProviderPoolEmail(currentRoundState);
|
||||
const maxAttemptsForRound = autoRunSkipFailures
|
||||
? AUTO_RUN_MAX_RETRIES_PER_ROUND + 1
|
||||
? (keepSameEmailUntilAddPhone ? Number.MAX_SAFE_INTEGER : AUTO_RUN_MAX_RETRIES_PER_ROUND + 1)
|
||||
: Math.max(1, attemptRun);
|
||||
|
||||
while (attemptRun <= maxAttemptsForRound) {
|
||||
@@ -461,6 +469,7 @@
|
||||
roundSummary.failureReasons.push(reason);
|
||||
const blockedByAddPhone = typeof isAddPhoneAuthFailure === 'function' && isAddPhoneAuthFailure(err);
|
||||
const blockedBySignupUserAlreadyExists = typeof isSignupUserAlreadyExistsFailure === 'function'
|
||||
&& !keepSameEmailUntilAddPhone
|
||||
&& isSignupUserAlreadyExistsFailure(err);
|
||||
const canRetry = !blockedByAddPhone && !blockedBySignupUserAlreadyExists && autoRunSkipFailures && attemptRun < maxAttemptsForRound;
|
||||
|
||||
@@ -555,7 +564,9 @@
|
||||
});
|
||||
forceFreshTabsNextRun = true;
|
||||
await addLog(
|
||||
`自动重试:${Math.round(AUTO_RUN_RETRY_DELAY_MS / 1000)} 秒后开始第 ${targetRun}/${totalRuns} 轮第 ${attemptRun + 1} 次尝试(第 ${retryIndex}/${AUTO_RUN_MAX_RETRIES_PER_ROUND} 次重试)。`,
|
||||
keepSameEmailUntilAddPhone
|
||||
? `自动重试:${Math.round(AUTO_RUN_RETRY_DELAY_MS / 1000)} 秒后继续使用当前邮箱,开始第 ${targetRun}/${totalRuns} 轮第 ${attemptRun + 1} 次尝试。`
|
||||
: `自动重试:${Math.round(AUTO_RUN_RETRY_DELAY_MS / 1000)} 秒后开始第 ${targetRun}/${totalRuns} 轮第 ${attemptRun + 1} 次尝试(第 ${retryIndex}/${AUTO_RUN_MAX_RETRIES_PER_ROUND} 次重试)。`,
|
||||
'warn'
|
||||
);
|
||||
try {
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
buildGeneratedAliasEmail,
|
||||
buildCloudflareTempEmailHeaders,
|
||||
CLOUDFLARE_TEMP_EMAIL_GENERATOR,
|
||||
CUSTOM_EMAIL_POOL_GENERATOR,
|
||||
DUCK_AUTOFILL_URL,
|
||||
fetch,
|
||||
fetchIcloudHideMyEmail,
|
||||
getCloudflareTempEmailAddressFromResponse,
|
||||
getCloudflareTempEmailConfig,
|
||||
getCustomEmailPoolEmail,
|
||||
getState,
|
||||
ensureMail2925AccountForFlow,
|
||||
joinCloudflareTempEmailUrl,
|
||||
@@ -189,6 +191,24 @@
|
||||
return result.email;
|
||||
}
|
||||
|
||||
async function fetchCustomEmailPoolEmail(state, options = {}) {
|
||||
throwIfStopped();
|
||||
const latestState = state || await getState();
|
||||
const requestedIndex = Math.max(0, Math.floor(Number(options.poolIndex) || 0));
|
||||
const email = String(getCustomEmailPoolEmail?.(latestState, requestedIndex + 1) || '').trim().toLowerCase();
|
||||
if (!email) {
|
||||
throw new Error(
|
||||
requestedIndex > 0
|
||||
? `自定义邮箱池第 ${requestedIndex + 1} 个邮箱不存在,请检查邮箱池配置。`
|
||||
: '自定义邮箱池为空,请先至少填写 1 个邮箱。'
|
||||
);
|
||||
}
|
||||
|
||||
await setEmailState(email);
|
||||
await addLog(`自定义邮箱池:已取用 ${email}`, 'ok');
|
||||
return email;
|
||||
}
|
||||
|
||||
async function fetchManagedAliasEmail(state, options = {}) {
|
||||
throwIfStopped();
|
||||
const provider = String(options.mailProvider || state?.mailProvider || '').trim().toLowerCase();
|
||||
@@ -234,21 +254,42 @@
|
||||
const mail2925Mode = options.mail2925Mode !== undefined
|
||||
? options.mail2925Mode
|
||||
: currentState.mail2925Mode;
|
||||
if (isGeneratedAliasProvider?.(provider, mail2925Mode)) {
|
||||
return fetchManagedAliasEmail(currentState, options);
|
||||
}
|
||||
const generator = normalizeEmailGenerator(options.generator ?? currentState.emailGenerator);
|
||||
const mergedState = {
|
||||
...currentState,
|
||||
mailProvider: provider || currentState.mailProvider,
|
||||
mail2925Mode,
|
||||
emailGenerator: generator,
|
||||
};
|
||||
if (options.gmailBaseEmail !== undefined) {
|
||||
mergedState.gmailBaseEmail = String(options.gmailBaseEmail || '').trim();
|
||||
}
|
||||
if (options.mail2925BaseEmail !== undefined) {
|
||||
mergedState.mail2925BaseEmail = String(options.mail2925BaseEmail || '').trim();
|
||||
}
|
||||
if (options.customEmailPool !== undefined) {
|
||||
mergedState.customEmailPool = options.customEmailPool;
|
||||
}
|
||||
if (generator === 'custom') {
|
||||
throw new Error('当前邮箱生成方式为自定义邮箱,请直接填写注册邮箱。');
|
||||
}
|
||||
if (generator === CUSTOM_EMAIL_POOL_GENERATOR) {
|
||||
return fetchCustomEmailPoolEmail(mergedState, options);
|
||||
}
|
||||
const shouldUseManagedAlias = typeof isGeneratedAliasProvider === 'function'
|
||||
? isGeneratedAliasProvider(mergedState, mail2925Mode)
|
||||
: false;
|
||||
if (shouldUseManagedAlias) {
|
||||
return fetchManagedAliasEmail(mergedState, options);
|
||||
}
|
||||
if (generator === 'icloud') {
|
||||
return fetchIcloudHideMyEmail();
|
||||
}
|
||||
if (generator === 'cloudflare') {
|
||||
return fetchCloudflareEmail(currentState, options);
|
||||
return fetchCloudflareEmail(mergedState, options);
|
||||
}
|
||||
if (generator === CLOUDFLARE_TEMP_EMAIL_GENERATOR) {
|
||||
return fetchCloudflareTempEmailAddress(currentState, options);
|
||||
return fetchCloudflareTempEmailAddress(mergedState, options);
|
||||
}
|
||||
return fetchDuckEmail(options);
|
||||
}
|
||||
@@ -256,6 +297,7 @@
|
||||
return {
|
||||
ensureCloudflareTempEmailConfig,
|
||||
fetchCloudflareEmail,
|
||||
fetchCustomEmailPoolEmail,
|
||||
fetchCloudflareTempEmailAddress,
|
||||
fetchDuckEmail,
|
||||
fetchGeneratedEmail,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
})(typeof self !== 'undefined' ? self : globalThis, function createSignupFlowHelpersModule() {
|
||||
function createSignupFlowHelpers(deps = {}) {
|
||||
const {
|
||||
addLog,
|
||||
buildGeneratedAliasEmail,
|
||||
chrome,
|
||||
ensureContentScriptReadyOnTab,
|
||||
@@ -12,6 +13,7 @@
|
||||
isGeneratedAliasProvider,
|
||||
isReusableGeneratedAliasEmail,
|
||||
isHotmailProvider,
|
||||
isRetryableContentScriptTransportError = () => false,
|
||||
isLuckmailProvider,
|
||||
isSignupEmailVerificationPageUrl,
|
||||
isSignupPasswordPageUrl,
|
||||
@@ -164,20 +166,32 @@
|
||||
logMessage: `步骤 ${step}:认证页仍在切换,正在等待页面恢复后继续确认提交流程...`,
|
||||
});
|
||||
|
||||
const result = await sendToContentScriptResilient('signup-page', {
|
||||
type: 'PREPARE_SIGNUP_VERIFICATION',
|
||||
step,
|
||||
source: 'background',
|
||||
payload: {
|
||||
password: password || '',
|
||||
prepareSource: 'step3_finalize',
|
||||
prepareLogLabel: '步骤 3 收尾',
|
||||
},
|
||||
}, {
|
||||
timeoutMs: 30000,
|
||||
retryDelayMs: 700,
|
||||
logMessage: `步骤 ${step}:密码已提交,正在确认是否进入下一页面,必要时自动恢复重试页...`,
|
||||
});
|
||||
let result;
|
||||
try {
|
||||
result = await sendToContentScriptResilient('signup-page', {
|
||||
type: 'PREPARE_SIGNUP_VERIFICATION',
|
||||
step,
|
||||
source: 'background',
|
||||
payload: {
|
||||
password: password || '',
|
||||
prepareSource: 'step3_finalize',
|
||||
prepareLogLabel: '步骤 3 收尾',
|
||||
},
|
||||
}, {
|
||||
timeoutMs: 30000,
|
||||
retryDelayMs: 700,
|
||||
logMessage: `步骤 ${step}:密码已提交,正在确认是否进入下一页面,必要时自动恢复重试页...`,
|
||||
});
|
||||
} catch (error) {
|
||||
if (isRetryableContentScriptTransportError(error)) {
|
||||
const message = `步骤 ${step}:认证页在提交后切换过程中页面通信超时,未能重新就绪,暂时无法确认是否进入下一页面。请重试当前轮。`;
|
||||
if (typeof addLog === 'function') {
|
||||
await addLog(message, 'warn');
|
||||
}
|
||||
throw new Error(message);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (result?.error) {
|
||||
throw new Error(result.error);
|
||||
|
||||
@@ -376,6 +376,17 @@
|
||||
return 30000;
|
||||
}
|
||||
|
||||
function resolveResponseTimeoutMs(message, requestedResponseTimeoutMs, remainingTimeoutMs = null) {
|
||||
const fallbackTimeoutMs = getContentScriptResponseTimeoutMs(message);
|
||||
const requestedTimeoutMs = Number.isFinite(Number(requestedResponseTimeoutMs))
|
||||
? Math.max(1, Math.floor(Number(requestedResponseTimeoutMs)))
|
||||
: fallbackTimeoutMs;
|
||||
if (!Number.isFinite(Number(remainingTimeoutMs))) {
|
||||
return requestedTimeoutMs;
|
||||
}
|
||||
return Math.max(1, Math.min(requestedTimeoutMs, Math.floor(Number(remainingTimeoutMs))));
|
||||
}
|
||||
|
||||
function getMessageDebugLabel(source, message, tabId = null) {
|
||||
const parts = [source || 'unknown', message?.type || 'UNKNOWN'];
|
||||
if (Number.isInteger(message?.step)) parts.push(`step=${message.step}`);
|
||||
@@ -439,7 +450,13 @@
|
||||
pendingCommands.delete(source);
|
||||
reject(new Error(`Content script on ${source} did not respond in ${timeout / 1000}s. Try refreshing the tab and retry.`));
|
||||
}, timeout);
|
||||
pendingCommands.set(source, { message, resolve, reject, timer });
|
||||
pendingCommands.set(source, {
|
||||
message,
|
||||
resolve,
|
||||
reject,
|
||||
timer,
|
||||
responseTimeoutMs: timeout,
|
||||
});
|
||||
console.log(LOG_PREFIX, `Command queued for ${source} (waiting for ready)`);
|
||||
});
|
||||
}
|
||||
@@ -449,7 +466,7 @@
|
||||
if (pending) {
|
||||
clearTimeout(pending.timer);
|
||||
pendingCommands.delete(source);
|
||||
sendTabMessageWithTimeout(tabId, source, pending.message).then(pending.resolve).catch(pending.reject);
|
||||
sendTabMessageWithTimeout(tabId, source, pending.message, pending.responseTimeoutMs).then(pending.resolve).catch(pending.reject);
|
||||
console.log(LOG_PREFIX, `Flushed queued command to ${source} (tab ${tabId})`);
|
||||
}
|
||||
}
|
||||
@@ -564,13 +581,13 @@
|
||||
|
||||
if (!entry || !entry.ready) {
|
||||
throwIfStopped();
|
||||
return queueCommand(source, message);
|
||||
return queueCommand(source, message, responseTimeoutMs);
|
||||
}
|
||||
|
||||
const alive = await isTabAlive(source);
|
||||
throwIfStopped();
|
||||
if (!alive) {
|
||||
return queueCommand(source, message);
|
||||
return queueCommand(source, message, responseTimeoutMs);
|
||||
}
|
||||
|
||||
throwIfStopped();
|
||||
@@ -592,12 +609,18 @@
|
||||
while (Date.now() - start < timeoutMs) {
|
||||
throwIfStopped();
|
||||
attempt += 1;
|
||||
const remainingTimeoutMs = Math.max(1, timeoutMs - (Date.now() - start));
|
||||
const effectiveResponseTimeoutMs = resolveResponseTimeoutMs(
|
||||
message,
|
||||
responseTimeoutMs,
|
||||
remainingTimeoutMs
|
||||
);
|
||||
|
||||
try {
|
||||
return await sendToContentScript(
|
||||
source,
|
||||
message,
|
||||
responseTimeoutMs !== undefined ? { responseTimeoutMs } : {}
|
||||
{ responseTimeoutMs: effectiveResponseTimeoutMs }
|
||||
);
|
||||
} catch (err) {
|
||||
const retryable = isRetryableContentScriptTransportError(err);
|
||||
@@ -631,12 +654,18 @@
|
||||
|
||||
while (Date.now() - start < timeoutMs) {
|
||||
throwIfStopped();
|
||||
const remainingTimeoutMs = Math.max(1, timeoutMs - (Date.now() - start));
|
||||
const effectiveResponseTimeoutMs = resolveResponseTimeoutMs(
|
||||
message,
|
||||
responseTimeoutMs,
|
||||
remainingTimeoutMs
|
||||
);
|
||||
|
||||
try {
|
||||
return await sendToContentScript(
|
||||
mail.source,
|
||||
message,
|
||||
responseTimeoutMs !== undefined ? { responseTimeoutMs } : {}
|
||||
{ responseTimeoutMs: effectiveResponseTimeoutMs }
|
||||
);
|
||||
} catch (err) {
|
||||
if (!isRetryableContentScriptTransportError(err)) {
|
||||
@@ -684,6 +713,7 @@
|
||||
queueCommand,
|
||||
registerTab,
|
||||
rememberSourceLastUrl,
|
||||
resolveResponseTimeoutMs,
|
||||
reuseOrCreateTab,
|
||||
sendTabMessageWithTimeout,
|
||||
sendToContentScript,
|
||||
|
||||
@@ -98,6 +98,9 @@
|
||||
if (response?.error) {
|
||||
throw new Error(response.error);
|
||||
}
|
||||
if (step === 8 && response?.addPhoneDetected) {
|
||||
throw new Error('步骤 8:验证码提交后页面进入手机号页面,当前流程无法继续自动授权。 URL: https://auth.openai.com/add-phone');
|
||||
}
|
||||
if (!response?.confirmed) {
|
||||
throw new Error(`步骤 ${step}:已取消手动${verificationLabel}验证码确认。`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user