Merge origin/dev into codex2api source

- resolve the sidepanel contribution-mode test conflict while keeping the new Codex2API assertions\n- update the mail2925 payload test harness for newly added Codex2API and random-subdomain inputs\n- renumber the README quick-start plan headings and strip trailing whitespace from the new tutorial doc
This commit is contained in:
Q3CC
2026-04-22 22:18:09 +08:00
31 changed files with 2587 additions and 176 deletions
+1
View File
@@ -146,6 +146,7 @@
const requestedName = String(options.localPart || options.name || '').trim().toLowerCase() || generateCloudflareAliasLocalPart();
const payload = {
enablePrefix: true,
enableRandomSubdomain: Boolean(config.useRandomSubdomain),
name: requestedName,
domain: config.domain,
};
+41 -6
View File
@@ -168,6 +168,10 @@
}
}
function normalizeMailboxEmail(value = '') {
return String(value || '').trim().toLowerCase();
}
async function setCurrentMail2925Account(accountId, options = {}) {
const { logMessage = '', updateLastUsedAt = false } = options;
const state = await getState();
@@ -186,6 +190,7 @@
await syncMail2925Accounts(accounts.map((item) => (item.id === account.id ? nextAccount : item)));
}
await setPersistentSettings({ currentMail2925AccountId: nextAccount.id });
await setState({ currentMail2925AccountId: nextAccount.id });
broadcastDataUpdate({ currentMail2925AccountId: nextAccount.id });
if (logMessage) {
@@ -210,6 +215,7 @@
await syncMail2925Accounts(accounts.map((item) => (item.id === account.id ? nextAccount : item)));
if (state.currentMail2925AccountId === account.id && nextAccount.enabled === false) {
await setPersistentSettings({ currentMail2925AccountId: '' });
await setState({ currentMail2925AccountId: null });
broadcastDataUpdate({ currentMail2925AccountId: null });
}
@@ -224,6 +230,7 @@
await syncMail2925Accounts(nextAccounts);
if (state.currentMail2925AccountId === accountId) {
await setPersistentSettings({ currentMail2925AccountId: '' });
await setState({ currentMail2925AccountId: null });
broadcastDataUpdate({ currentMail2925AccountId: null });
}
@@ -239,6 +246,7 @@
await syncMail2925Accounts(nextAccounts);
if (state.currentMail2925AccountId && !findMail2925Account(nextAccounts, state.currentMail2925AccountId)) {
await setPersistentSettings({ currentMail2925AccountId: '' });
await setState({ currentMail2925AccountId: null });
broadcastDataUpdate({ currentMail2925AccountId: null });
}
@@ -397,10 +405,13 @@
forceRelogin = false,
actionLabel = '确保 2925 邮箱登录态',
allowLoginWhenOnLoginPage = true,
expectedMailboxEmail = '',
} = options;
const normalizedExpectedMailboxEmail = normalizeMailboxEmail(expectedMailboxEmail);
let account = null;
if (forceRelogin) {
if (forceRelogin || (allowLoginWhenOnLoginPage && normalizedExpectedMailboxEmail)) {
account = await ensureMail2925AccountForFlow({
allowAllocate: true,
preferredAccountId: accountId,
@@ -477,16 +488,16 @@
}
}
if (!forceRelogin && !isMail2925LoginUrl(openedUrl)) {
if (!forceRelogin && !isMail2925LoginUrl(openedUrl) && !normalizedExpectedMailboxEmail) {
await addLog('2925:当前邮箱页未跳转到登录页,将直接复用已登录会话。', 'info');
return buildSuccessPayload();
}
if (!forceRelogin && !allowLoginWhenOnLoginPage) {
if (!forceRelogin && isMail2925LoginUrl(openedUrl) && !allowLoginWhenOnLoginPage) {
await failMailboxSession(`2925${actionLabel}失败,当前页面已跳转到登录页,且当前未启用 2925 账号池,不执行自动登录。`);
}
if (!account) {
if (!account && (forceRelogin || allowLoginWhenOnLoginPage)) {
account = await ensureMail2925AccountForFlow({
allowAllocate: true,
preferredAccountId: accountId,
@@ -519,9 +530,10 @@
step: 0,
source: 'background',
payload: {
email: account.email,
password: account.password,
email: account?.email || '',
password: account?.password || '',
forceLogin: forceRelogin,
allowLoginWhenOnLoginPage,
},
},
{
@@ -546,6 +558,28 @@
if (result?.limitReached) {
throw new Error(`${MAIL2925_LIMIT_ERROR_PREFIX}${result.limitMessage || '子邮箱已达上限邮箱'}`);
}
const actualMailboxEmail = normalizeMailboxEmail(result?.mailboxEmail || '');
if (normalizedExpectedMailboxEmail && actualMailboxEmail && actualMailboxEmail !== normalizedExpectedMailboxEmail) {
if (allowLoginWhenOnLoginPage) {
await addLog(
`2925:当前邮箱页显示账号 ${actualMailboxEmail},与目标账号 ${normalizedExpectedMailboxEmail} 不一致,准备登出当前账号并登录目标账号。`,
'warn'
);
return ensureMail2925MailboxSession({
accountId: account?.id || accountId || null,
forceRelogin: true,
allowLoginWhenOnLoginPage: true,
expectedMailboxEmail: normalizedExpectedMailboxEmail,
actionLabel,
});
}
await failMailboxSession(
`2925${actionLabel}失败,当前邮箱页显示账号 ${actualMailboxEmail},与目标账号 ${normalizedExpectedMailboxEmail} 不一致,且当前未启用 2925 账号池。`
);
}
if (normalizedExpectedMailboxEmail && !actualMailboxEmail && result?.currentView === 'mailbox') {
await addLog('2925:未能识别当前邮箱页顶部邮箱地址,已跳过邮箱一致性校验。', 'warn');
}
if (!result?.loggedIn) {
await failMailboxSession(`2925${actionLabel}失败,登录后仍未进入收件箱。`);
}
@@ -613,6 +647,7 @@
});
if (!nextAccount) {
await setPersistentSettings({ currentMail2925AccountId: '' });
await setState({ currentMail2925AccountId: null });
broadcastDataUpdate({ currentMail2925AccountId: null });
if (typeof requestStop === 'function') {
-6
View File
@@ -200,12 +200,6 @@
break;
}
if (effect.restartCurrentStep) {
await addLog(`步骤 9${getStep8EffectLabel(effect)},准备重新定位“继续”按钮并重试...`, 'warn');
await sleepWithStop(STEP8_CLICK_RETRY_DELAY_MS);
continue;
}
if (round >= STEP8_MAX_ROUNDS) {
throw new Error(`步骤 9:连续 ${STEP8_MAX_ROUNDS} 轮点击“继续”后页面仍无反应。`);
}
+15
View File
@@ -24,6 +24,20 @@
throwIfStopped,
} = deps;
function getExpectedMail2925MailboxEmail(state = {}) {
if (Boolean(state?.mail2925UseAccountPool)) {
const currentAccountId = String(state?.currentMail2925AccountId || '').trim();
const accounts = Array.isArray(state?.mail2925Accounts) ? state.mail2925Accounts : [];
const currentAccount = accounts.find((account) => String(account?.id || '') === currentAccountId) || null;
const accountEmail = String(currentAccount?.email || '').trim().toLowerCase();
if (accountEmail) {
return accountEmail;
}
}
return String(state?.mail2925BaseEmail || '').trim().toLowerCase();
}
async function focusOrOpenMailTab(mail) {
const alive = await isTabAlive(mail.source);
if (alive) {
@@ -111,6 +125,7 @@
accountId: state.currentMail2925AccountId || null,
forceRelogin: false,
allowLoginWhenOnLoginPage: Boolean(state?.mail2925UseAccountPool),
expectedMailboxEmail: getExpectedMail2925MailboxEmail(state),
actionLabel: '步骤 4:确认 2925 邮箱登录态',
});
} else {
+2 -1
View File
@@ -159,7 +159,8 @@
source: 'background',
payload: { localhostUrl: state.localhostUrl, vpsPassword: state.vpsPassword },
}, {
timeoutMs: 30000,
timeoutMs: 125000,
responseTimeoutMs: 125000,
retryDelayMs: 700,
logMessage: '步骤 10:CPA 面板通信未就绪,正在等待页面恢复...',
});