feat: 添加贡献模式支持,增强状态管理和错误处理逻辑
This commit is contained in:
+12
-1
@@ -179,7 +179,8 @@ const MICROSOFT_TOKEN_DNR_RULE_ID = 1001;
|
|||||||
const PERSISTENT_ALIAS_STATE_KEYS = ['manualAliasUsage', 'preservedAliases'];
|
const PERSISTENT_ALIAS_STATE_KEYS = ['manualAliasUsage', 'preservedAliases'];
|
||||||
const ACCOUNT_RUN_HISTORY_STORAGE_KEY = 'accountRunHistory';
|
const ACCOUNT_RUN_HISTORY_STORAGE_KEY = 'accountRunHistory';
|
||||||
const CONTRIBUTION_RUNTIME_DEFAULTS = self.MultiPageBackgroundContributionOAuth?.RUNTIME_DEFAULTS || {
|
const CONTRIBUTION_RUNTIME_DEFAULTS = self.MultiPageBackgroundContributionOAuth?.RUNTIME_DEFAULTS || {
|
||||||
...CONTRIBUTION_RUNTIME_DEFAULTS,
|
contributionMode: false,
|
||||||
|
contributionModeExpected: false,
|
||||||
contributionSessionId: '',
|
contributionSessionId: '',
|
||||||
contributionAuthUrl: '',
|
contributionAuthUrl: '',
|
||||||
contributionAuthState: '',
|
contributionAuthState: '',
|
||||||
@@ -1149,6 +1150,7 @@ function buildContributionModeState(enabled, persistedSettings = {}, currentStat
|
|||||||
return {
|
return {
|
||||||
...currentContributionState,
|
...currentContributionState,
|
||||||
contributionMode: true,
|
contributionMode: true,
|
||||||
|
contributionModeExpected: true,
|
||||||
panelMode: 'cpa',
|
panelMode: 'cpa',
|
||||||
customPassword: '',
|
customPassword: '',
|
||||||
accountRunHistoryTextEnabled: false,
|
accountRunHistoryTextEnabled: false,
|
||||||
@@ -1158,6 +1160,7 @@ function buildContributionModeState(enabled, persistedSettings = {}, currentStat
|
|||||||
return {
|
return {
|
||||||
...CONTRIBUTION_RUNTIME_DEFAULTS,
|
...CONTRIBUTION_RUNTIME_DEFAULTS,
|
||||||
contributionMode: false,
|
contributionMode: false,
|
||||||
|
contributionModeExpected: false,
|
||||||
panelMode: persistedSettings.panelMode || DEFAULT_STATE.panelMode,
|
panelMode: persistedSettings.panelMode || DEFAULT_STATE.panelMode,
|
||||||
customPassword: persistedSettings.customPassword || '',
|
customPassword: persistedSettings.customPassword || '',
|
||||||
accountRunHistoryTextEnabled: Boolean(persistedSettings.accountRunHistoryTextEnabled),
|
accountRunHistoryTextEnabled: Boolean(persistedSettings.accountRunHistoryTextEnabled),
|
||||||
@@ -6454,7 +6457,11 @@ async function runPreStep6CookieCleanup() {
|
|||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
async function refreshOAuthUrlBeforeStep6(state) {
|
async function refreshOAuthUrlBeforeStep6(state) {
|
||||||
|
if (state?.contributionModeExpected && !state?.contributionMode) {
|
||||||
|
throw new Error('步骤 7:当前自动流程预期使用贡献模式,但运行态 contributionMode 已丢失,已阻止回退到普通 CPA 面板。请重新进入贡献模式后再点击自动。');
|
||||||
|
}
|
||||||
if (state?.contributionMode && contributionOAuthManager?.startContributionFlow) {
|
if (state?.contributionMode && contributionOAuthManager?.startContributionFlow) {
|
||||||
|
await addLog('步骤 7:contributionMode=true,正在通过公开贡献接口申请 OAuth 链接...', 'info');
|
||||||
await addLog('步骤 7:贡献模式正在申请贡献登录地址...');
|
await addLog('步骤 7:贡献模式正在申请贡献登录地址...');
|
||||||
const contributionState = await contributionOAuthManager.startContributionFlow({
|
const contributionState = await contributionOAuthManager.startContributionFlow({
|
||||||
nickname: state.email,
|
nickname: state.email,
|
||||||
@@ -6469,6 +6476,7 @@ async function refreshOAuthUrlBeforeStep6(state) {
|
|||||||
return oauthUrl;
|
return oauthUrl;
|
||||||
}
|
}
|
||||||
await addLog(`步骤 7:正在刷新登录用的 ${getPanelModeLabel(state)} OAuth 链接...`);
|
await addLog(`步骤 7:正在刷新登录用的 ${getPanelModeLabel(state)} OAuth 链接...`);
|
||||||
|
await addLog(`步骤 7:contributionMode=${Boolean(state?.contributionMode)},当前将回退到 ${getPanelModeLabel(state)} 面板刷新 OAuth。`, 'warn');
|
||||||
console.log(LOG_PREFIX, '[refreshOAuthUrlBeforeStep6] requesting fresh OAuth directly from panel');
|
console.log(LOG_PREFIX, '[refreshOAuthUrlBeforeStep6] requesting fresh OAuth directly from panel');
|
||||||
const refreshResult = await requestOAuthUrlFromPanel(state, { logLabel: '步骤 7' });
|
const refreshResult = await requestOAuthUrlFromPanel(state, { logLabel: '步骤 7' });
|
||||||
await handleStepData(1, refreshResult);
|
await handleStepData(1, refreshResult);
|
||||||
@@ -7145,6 +7153,9 @@ async function executeContributionStep10(state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function executeStep10(state) {
|
async function executeStep10(state) {
|
||||||
|
if (state?.contributionModeExpected && !state?.contributionMode) {
|
||||||
|
throw new Error('步骤 10:当前自动流程预期使用贡献模式,但运行态 contributionMode 已丢失,已阻止回退到普通 CPA / SUB2API 提交。请重新进入贡献模式后再点击自动。');
|
||||||
|
}
|
||||||
if (state?.contributionMode) {
|
if (state?.contributionMode) {
|
||||||
return executeContributionStep10(state);
|
return executeContributionStep10(state);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
const RUNTIME_DEFAULTS = {
|
const RUNTIME_DEFAULTS = {
|
||||||
contributionMode: false,
|
contributionMode: false,
|
||||||
|
contributionModeExpected: false,
|
||||||
contributionSessionId: '',
|
contributionSessionId: '',
|
||||||
contributionAuthUrl: '',
|
contributionAuthUrl: '',
|
||||||
contributionAuthState: '',
|
contributionAuthState: '',
|
||||||
|
|||||||
@@ -372,6 +372,9 @@
|
|||||||
|
|
||||||
case 'AUTO_RUN': {
|
case 'AUTO_RUN': {
|
||||||
clearStopRequest();
|
clearStopRequest();
|
||||||
|
if (Boolean(message.payload?.contributionMode) && typeof setContributionMode === 'function') {
|
||||||
|
await setContributionMode(true);
|
||||||
|
}
|
||||||
const state = await getState();
|
const state = await getState();
|
||||||
if (getPendingAutoRunTimerPlan(state)) {
|
if (getPendingAutoRunTimerPlan(state)) {
|
||||||
throw new Error('已有自动运行倒计时计划,请先取消或立即开始。');
|
throw new Error('已有自动运行倒计时计划,请先取消或立即开始。');
|
||||||
@@ -386,6 +389,9 @@
|
|||||||
|
|
||||||
case 'SCHEDULE_AUTO_RUN': {
|
case 'SCHEDULE_AUTO_RUN': {
|
||||||
clearStopRequest();
|
clearStopRequest();
|
||||||
|
if (Boolean(message.payload?.contributionMode) && typeof setContributionMode === 'function') {
|
||||||
|
await setContributionMode(true);
|
||||||
|
}
|
||||||
const totalRuns = normalizeRunCount(message.payload?.totalRuns || 1);
|
const totalRuns = normalizeRunCount(message.payload?.totalRuns || 1);
|
||||||
return await scheduleAutoRun(totalRuns, {
|
return await scheduleAutoRun(totalRuns, {
|
||||||
delayMinutes: message.payload?.delayMinutes,
|
delayMinutes: message.payload?.delayMinutes,
|
||||||
|
|||||||
@@ -3423,6 +3423,7 @@ async function startAutoRunFromCurrentSettings() {
|
|||||||
totalRuns,
|
totalRuns,
|
||||||
delayMinutes,
|
delayMinutes,
|
||||||
autoRunSkipFailures,
|
autoRunSkipFailures,
|
||||||
|
contributionMode: Boolean(latestState?.contributionMode),
|
||||||
mode,
|
mode,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ test('buildContributionModeState preserves active contribution runtime while for
|
|||||||
const DEFAULT_STATE = { panelMode: 'cpa' };
|
const DEFAULT_STATE = { panelMode: 'cpa' };
|
||||||
const CONTRIBUTION_RUNTIME_DEFAULTS = {
|
const CONTRIBUTION_RUNTIME_DEFAULTS = {
|
||||||
contributionMode: false,
|
contributionMode: false,
|
||||||
|
contributionModeExpected: false,
|
||||||
contributionSessionId: '',
|
contributionSessionId: '',
|
||||||
contributionAuthUrl: '',
|
contributionAuthUrl: '',
|
||||||
contributionAuthState: '',
|
contributionAuthState: '',
|
||||||
@@ -121,6 +122,7 @@ return { buildContributionModeState };
|
|||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
contributionMode: true,
|
contributionMode: true,
|
||||||
|
contributionModeExpected: true,
|
||||||
contributionSessionId: 'session-001',
|
contributionSessionId: 'session-001',
|
||||||
contributionAuthUrl: 'https://auth.example.com',
|
contributionAuthUrl: 'https://auth.example.com',
|
||||||
contributionAuthState: '',
|
contributionAuthState: '',
|
||||||
@@ -150,6 +152,7 @@ return { buildContributionModeState };
|
|||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
contributionMode: false,
|
contributionMode: false,
|
||||||
|
contributionModeExpected: false,
|
||||||
contributionSessionId: '',
|
contributionSessionId: '',
|
||||||
contributionAuthUrl: '',
|
contributionAuthUrl: '',
|
||||||
contributionAuthState: '',
|
contributionAuthState: '',
|
||||||
@@ -229,6 +232,50 @@ test('message router handles contribution mode, start flow, and status polling m
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('message router re-syncs contribution mode before AUTO_RUN when sidepanel payload marks contributionMode=true', async () => {
|
||||||
|
const source = fs.readFileSync('background/message-router.js', 'utf8');
|
||||||
|
const globalScope = {};
|
||||||
|
const api = new Function('self', `${source}; return self.MultiPageBackgroundMessageRouter;`)(globalScope);
|
||||||
|
|
||||||
|
const calls = [];
|
||||||
|
const router = api.createMessageRouter({
|
||||||
|
clearStopRequest: () => {},
|
||||||
|
getPendingAutoRunTimerPlan: () => null,
|
||||||
|
getState: async () => ({
|
||||||
|
contributionMode: false,
|
||||||
|
stepStatuses: {},
|
||||||
|
}),
|
||||||
|
normalizeRunCount: (value) => Number(value) || 1,
|
||||||
|
setContributionMode: async (enabled) => {
|
||||||
|
calls.push({ type: 'toggle', enabled });
|
||||||
|
return { contributionMode: true };
|
||||||
|
},
|
||||||
|
setState: async (updates) => {
|
||||||
|
calls.push({ type: 'setState', updates });
|
||||||
|
},
|
||||||
|
startAutoRunLoop: (totalRuns, options) => {
|
||||||
|
calls.push({ type: 'startAutoRunLoop', totalRuns, options });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await router.handleMessage({
|
||||||
|
type: 'AUTO_RUN',
|
||||||
|
payload: {
|
||||||
|
totalRuns: 2,
|
||||||
|
autoRunSkipFailures: true,
|
||||||
|
mode: 'restart',
|
||||||
|
contributionMode: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(response.ok, true);
|
||||||
|
assert.deepStrictEqual(calls, [
|
||||||
|
{ type: 'toggle', enabled: true },
|
||||||
|
{ type: 'setState', updates: { autoRunSkipFailures: true } },
|
||||||
|
{ type: 'startAutoRunLoop', totalRuns: 2, options: { autoRunSkipFailures: true, mode: 'restart' } },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
test('account run history snapshot sync is disabled in contribution mode', () => {
|
test('account run history snapshot sync is disabled in contribution mode', () => {
|
||||||
const source = fs.readFileSync('background/account-run-history.js', 'utf8');
|
const source = fs.readFileSync('background/account-run-history.js', 'utf8');
|
||||||
const globalScope = {};
|
const globalScope = {};
|
||||||
@@ -411,6 +458,7 @@ return { refreshOAuthUrlBeforeStep6 };
|
|||||||
|
|
||||||
assert.equal(oauthUrl, 'https://auth.example.com/oauth?state=oauth-state-001');
|
assert.equal(oauthUrl, 'https://auth.example.com/oauth?state=oauth-state-001');
|
||||||
assert.deepStrictEqual(calls, [
|
assert.deepStrictEqual(calls, [
|
||||||
|
{ type: 'log', message: '步骤 7:contributionMode=true,正在通过公开贡献接口申请 OAuth 链接...' },
|
||||||
{ type: 'log', message: '步骤 7:贡献模式正在申请贡献登录地址...' },
|
{ type: 'log', message: '步骤 7:贡献模式正在申请贡献登录地址...' },
|
||||||
{
|
{
|
||||||
type: 'contribution',
|
type: 'contribution',
|
||||||
@@ -439,3 +487,30 @@ return { refreshOAuthUrlBeforeStep6 };
|
|||||||
delete globalThis.requestOAuthUrlFromPanel;
|
delete globalThis.requestOAuthUrlFromPanel;
|
||||||
delete globalThis.LOG_PREFIX;
|
delete globalThis.LOG_PREFIX;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('executeStep10 blocks silent fallback when contributionModeExpected=true but contributionMode=false', async () => {
|
||||||
|
const bundle = extractFunction(backgroundSource, 'executeStep10');
|
||||||
|
|
||||||
|
const api = new Function(`
|
||||||
|
${bundle}
|
||||||
|
return { executeStep10 };
|
||||||
|
`)();
|
||||||
|
|
||||||
|
globalThis.executeContributionStep10 = async () => ({ ok: true });
|
||||||
|
globalThis.step10Executor = {
|
||||||
|
async executeStep10() {
|
||||||
|
return { ok: true };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await assert.rejects(
|
||||||
|
() => api.executeStep10({
|
||||||
|
contributionModeExpected: true,
|
||||||
|
contributionMode: false,
|
||||||
|
}),
|
||||||
|
/步骤 10:当前自动流程预期使用贡献模式/
|
||||||
|
);
|
||||||
|
|
||||||
|
delete globalThis.executeContributionStep10;
|
||||||
|
delete globalThis.step10Executor;
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user