| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553 |
- (function attachBackgroundMessageRouter(root, factory) {
- root.MultiPageBackgroundMessageRouter = factory();
- })(typeof self !== 'undefined' ? self : globalThis, function createBackgroundMessageRouterModule() {
- function createMessageRouter(deps = {}) {
- const {
- addLog,
- appendAccountRunRecord,
- batchUpdateLuckmailPurchases,
- buildLocalhostCleanupPrefix,
- buildLuckmailSessionSettingsPayload,
- buildPersistentSettingsPayload,
- broadcastDataUpdate,
- cancelScheduledAutoRun,
- checkIcloudSession,
- clearAutoRunTimerAlarm,
- clearLuckmailRuntimeState,
- clearStopRequest,
- closeLocalhostCallbackTabs,
- closeTabsByUrlPrefix,
- deleteHotmailAccount,
- deleteHotmailAccounts,
- deleteIcloudAlias,
- deleteUsedIcloudAliases,
- disableUsedLuckmailPurchases,
- doesStepUseCompletionSignal,
- ensureManualInteractionAllowed,
- executeStep,
- executeStepViaCompletionSignal,
- exportSettingsBundle,
- fetchGeneratedEmail,
- finalizeIcloudAliasAfterSuccessfulFlow,
- findHotmailAccount,
- flushCommand,
- getCurrentLuckmailPurchase,
- getPendingAutoRunTimerPlan,
- getSourceLabel,
- getState,
- getStopRequested,
- handleAutoRunLoopUnhandledError,
- importSettingsBundle,
- invalidateDownstreamAfterStepRestart,
- isAutoRunLockedState,
- isHotmailProvider,
- isLocalhostOAuthCallbackUrl,
- isLuckmailProvider,
- isStopError,
- launchAutoRunTimerPlan,
- listIcloudAliases,
- listLuckmailPurchasesForManagement,
- normalizeHotmailAccounts,
- normalizeRunCount,
- AUTO_RUN_TIMER_KIND_SCHEDULED_START,
- notifyStepComplete,
- notifyStepError,
- patchHotmailAccount,
- registerTab,
- requestStop,
- resetState,
- resumeAutoRun,
- scheduleAutoRun,
- selectLuckmailPurchase,
- setCurrentHotmailAccount,
- setEmailState,
- setEmailStateSilently,
- setIcloudAliasPreservedState,
- setIcloudAliasUsedState,
- setLuckmailPurchaseDisabledState,
- setLuckmailPurchasePreservedState,
- setLuckmailPurchaseUsedState,
- setPersistentSettings,
- setState,
- setStepStatus,
- skipAutoRunCountdown,
- skipStep,
- startAutoRunLoop,
- syncHotmailAccounts,
- testHotmailAccountMailAccess,
- upsertHotmailAccount,
- verifyHotmailAccount,
- } = deps;
- async function appendManualAccountRunRecordIfNeeded(status, stateOverride = null, reason = '') {
- if (typeof appendAccountRunRecord !== 'function') {
- return null;
- }
- const state = stateOverride || await getState();
- if (isAutoRunLockedState(state)) {
- return null;
- }
- return appendAccountRunRecord(status, state, reason);
- }
- async function handleStepData(step, payload) {
- switch (step) {
- case 1: {
- const updates = {};
- if (payload.oauthUrl) {
- updates.oauthUrl = payload.oauthUrl;
- broadcastDataUpdate({ oauthUrl: payload.oauthUrl });
- }
- if (payload.sub2apiSessionId !== undefined) updates.sub2apiSessionId = payload.sub2apiSessionId || null;
- if (payload.sub2apiOAuthState !== undefined) updates.sub2apiOAuthState = payload.sub2apiOAuthState || null;
- if (payload.sub2apiGroupId !== undefined) updates.sub2apiGroupId = payload.sub2apiGroupId || null;
- if (payload.sub2apiDraftName !== undefined) updates.sub2apiDraftName = payload.sub2apiDraftName || null;
- if (Object.keys(updates).length) {
- await setState(updates);
- }
- break;
- }
- case 3:
- if (payload.email) await setEmailState(payload.email);
- if (payload.signupVerificationRequestedAt) {
- await setState({ signupVerificationRequestedAt: payload.signupVerificationRequestedAt });
- }
- if (payload.loginVerificationRequestedAt) {
- await setState({ loginVerificationRequestedAt: payload.loginVerificationRequestedAt });
- }
- break;
- case 6:
- if (payload.loginVerificationRequestedAt) {
- await setState({ loginVerificationRequestedAt: payload.loginVerificationRequestedAt });
- }
- break;
- case 4:
- await setState({
- lastEmailTimestamp: payload.emailTimestamp || null,
- signupVerificationRequestedAt: null,
- });
- break;
- case 7:
- await setState({
- lastEmailTimestamp: payload.emailTimestamp || null,
- loginVerificationRequestedAt: null,
- });
- break;
- case 8:
- if (payload.localhostUrl) {
- if (!isLocalhostOAuthCallbackUrl(payload.localhostUrl)) {
- throw new Error('步骤 8 返回了无效的 localhost OAuth 回调地址。');
- }
- await setState({ localhostUrl: payload.localhostUrl });
- broadcastDataUpdate({ localhostUrl: payload.localhostUrl });
- }
- break;
- case 9: {
- if (payload.localhostUrl) {
- await closeLocalhostCallbackTabs(payload.localhostUrl);
- }
- const latestState = await getState();
- if (latestState.currentHotmailAccountId && isHotmailProvider(latestState)) {
- await patchHotmailAccount(latestState.currentHotmailAccountId, {
- used: true,
- lastUsedAt: Date.now(),
- });
- await addLog('当前 Hotmail 账号已自动标记为已用。', 'ok');
- }
- if (isLuckmailProvider(latestState)) {
- const currentPurchase = getCurrentLuckmailPurchase(latestState);
- if (currentPurchase?.id) {
- await setLuckmailPurchaseUsedState(currentPurchase.id, true);
- await addLog(`当前 LuckMail 邮箱 ${currentPurchase.email_address} 已在本地标记为已用。`, 'ok');
- }
- await clearLuckmailRuntimeState({ clearEmail: true });
- await addLog('当前 LuckMail 邮箱运行态已清空,下轮将优先复用未用邮箱或重新购买邮箱。', 'ok');
- }
- const localhostPrefix = buildLocalhostCleanupPrefix(payload.localhostUrl);
- if (localhostPrefix) {
- await closeTabsByUrlPrefix(localhostPrefix, {
- excludeUrls: [payload.localhostUrl],
- excludeLocalhostCallbacks: true,
- });
- }
- await finalizeIcloudAliasAfterSuccessfulFlow(latestState);
- break;
- }
- default:
- break;
- }
- }
- async function handleMessage(message, sender) {
- switch (message.type) {
- case 'CONTENT_SCRIPT_READY': {
- const tabId = sender.tab?.id;
- if (tabId && message.source) {
- await registerTab(message.source, tabId);
- flushCommand(message.source, tabId);
- await addLog(`内容脚本已就绪:${getSourceLabel(message.source)}(标签页 ${tabId})`);
- }
- return { ok: true };
- }
- case 'LOG': {
- const { message: msg, level } = message.payload;
- await addLog(`[${getSourceLabel(message.source)}] ${msg}`, level);
- return { ok: true };
- }
- case 'STEP_COMPLETE': {
- if (getStopRequested()) {
- await setStepStatus(message.step, 'stopped');
- await appendManualAccountRunRecordIfNeeded(`step${message.step}_stopped`, null, '流程已被用户停止。');
- notifyStepError(message.step, '流程已被用户停止。');
- return { ok: true };
- }
- const completionState = message.step === 9 ? await getState() : null;
- await setStepStatus(message.step, 'completed');
- await addLog(`步骤 ${message.step} 已完成`, 'ok');
- await handleStepData(message.step, message.payload);
- if (message.step === 9 && typeof appendAccountRunRecord === 'function') {
- await appendAccountRunRecord('success', completionState);
- }
- notifyStepComplete(message.step, message.payload);
- return { ok: true };
- }
- case 'STEP_ERROR': {
- if (isStopError(message.error)) {
- await setStepStatus(message.step, 'stopped');
- await addLog(`步骤 ${message.step} 已被用户停止`, 'warn');
- 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 appendManualAccountRunRecordIfNeeded(`step${message.step}_failed`, null, message.error);
- notifyStepError(message.step, message.error);
- }
- return { ok: true };
- }
- case 'GET_STATE': {
- return await getState();
- }
- case 'RESET': {
- clearStopRequest();
- await clearAutoRunTimerAlarm();
- await resetState();
- await addLog('流程已重置', 'info');
- return { ok: true };
- }
- case 'EXECUTE_STEP': {
- clearStopRequest();
- if (message.source === 'sidepanel') {
- await ensureManualInteractionAllowed('手动执行步骤');
- }
- const step = message.payload.step;
- if (message.source === 'sidepanel') {
- await invalidateDownstreamAfterStepRestart(step, { logLabel: `步骤 ${step} 重新执行` });
- }
- if (message.payload.email) {
- await setEmailState(message.payload.email);
- }
- if (message.payload.emailPrefix !== undefined) {
- await setPersistentSettings({ emailPrefix: message.payload.emailPrefix });
- await setState({ emailPrefix: message.payload.emailPrefix });
- }
- if (doesStepUseCompletionSignal(step)) {
- await executeStepViaCompletionSignal(step);
- } else {
- await executeStep(step);
- }
- return { ok: true };
- }
- case 'AUTO_RUN': {
- clearStopRequest();
- const state = await getState();
- if (getPendingAutoRunTimerPlan(state)) {
- throw new Error('已有自动运行倒计时计划,请先取消或立即开始。');
- }
- const totalRuns = normalizeRunCount(message.payload?.totalRuns || 1);
- const autoRunSkipFailures = Boolean(message.payload?.autoRunSkipFailures);
- const mode = message.payload?.mode === 'continue' ? 'continue' : 'restart';
- await setState({ autoRunSkipFailures });
- startAutoRunLoop(totalRuns, { autoRunSkipFailures, mode });
- return { ok: true };
- }
- case 'SCHEDULE_AUTO_RUN': {
- clearStopRequest();
- const totalRuns = normalizeRunCount(message.payload?.totalRuns || 1);
- return await scheduleAutoRun(totalRuns, {
- delayMinutes: message.payload?.delayMinutes,
- autoRunSkipFailures: Boolean(message.payload?.autoRunSkipFailures),
- mode: message.payload?.mode,
- });
- }
- case 'START_SCHEDULED_AUTO_RUN_NOW': {
- clearStopRequest();
- const started = await launchAutoRunTimerPlan('manual', {
- expectedKinds: [AUTO_RUN_TIMER_KIND_SCHEDULED_START],
- });
- if (!started) {
- throw new Error('当前没有可立即开始的倒计时计划。');
- }
- return { ok: true };
- }
- case 'CANCEL_SCHEDULED_AUTO_RUN': {
- const cancelled = await cancelScheduledAutoRun();
- if (!cancelled) {
- throw new Error('当前没有可取消的倒计时计划。');
- }
- return { ok: true };
- }
- case 'SKIP_AUTO_RUN_COUNTDOWN': {
- clearStopRequest();
- const skipped = await skipAutoRunCountdown();
- if (!skipped) {
- throw new Error('当前没有可立即开始的倒计时。');
- }
- return { ok: true };
- }
- case 'RESUME_AUTO_RUN': {
- clearStopRequest();
- if (message.payload.email) {
- await setEmailState(message.payload.email);
- }
- resumeAutoRun().catch((error) => {
- handleAutoRunLoopUnhandledError(error).catch(() => {});
- });
- return { ok: true };
- }
- case 'TAKEOVER_AUTO_RUN': {
- await requestStop({ logMessage: '已确认手动接管,正在停止自动流程并切换为手动控制...' });
- await addLog('自动流程已切换为手动控制。', 'warn');
- return { ok: true };
- }
- case 'SKIP_STEP': {
- const step = Number(message.payload?.step);
- return await skipStep(step);
- }
- case 'SAVE_SETTING': {
- const updates = buildPersistentSettingsPayload(message.payload || {});
- const sessionUpdates = buildLuckmailSessionSettingsPayload(message.payload || {});
- await setPersistentSettings(updates);
- await setState({
- ...updates,
- ...sessionUpdates,
- });
- return { ok: true, state: await getState() };
- }
- case 'EXPORT_SETTINGS': {
- return { ok: true, ...(await exportSettingsBundle()) };
- }
- case 'IMPORT_SETTINGS': {
- const state = await importSettingsBundle(message.payload?.config || null);
- return { ok: true, state };
- }
- case 'UPSERT_HOTMAIL_ACCOUNT': {
- const account = await upsertHotmailAccount(message.payload || {});
- return { ok: true, account };
- }
- case 'DELETE_HOTMAIL_ACCOUNT': {
- await deleteHotmailAccount(String(message.payload?.accountId || ''));
- return { ok: true };
- }
- case 'DELETE_HOTMAIL_ACCOUNTS': {
- const result = await deleteHotmailAccounts(String(message.payload?.mode || 'all'));
- return { ok: true, ...result };
- }
- case 'SELECT_HOTMAIL_ACCOUNT': {
- const account = await setCurrentHotmailAccount(String(message.payload?.accountId || ''), {
- markUsed: false,
- syncEmail: true,
- });
- return { ok: true, account };
- }
- case 'PATCH_HOTMAIL_ACCOUNT': {
- const account = await patchHotmailAccount(
- String(message.payload?.accountId || ''),
- message.payload?.updates || {}
- );
- return { ok: true, account };
- }
- case 'VERIFY_HOTMAIL_ACCOUNT':
- case 'AUTHORIZE_HOTMAIL_ACCOUNT': {
- const accountId = String(message.payload?.accountId || '');
- try {
- const result = await verifyHotmailAccount(accountId);
- await setCurrentHotmailAccount(result.account.id, { markUsed: false, syncEmail: true });
- await addLog(`Hotmail 账号 ${result.account.email} 校验通过,可直接用于收信。`, 'ok');
- return { ok: true, account: result.account, messageCount: result.messageCount };
- } catch (err) {
- const state = await getState();
- const accounts = normalizeHotmailAccounts(state.hotmailAccounts);
- const target = findHotmailAccount(accounts, accountId);
- if (target) {
- target.status = 'error';
- target.lastError = err.message;
- await syncHotmailAccounts(accounts.map((item) => (item.id === target.id ? target : item)));
- }
- throw err;
- }
- }
- case 'TEST_HOTMAIL_ACCOUNT': {
- const result = await testHotmailAccountMailAccess(String(message.payload?.accountId || ''));
- return { ok: true, ...result };
- }
- case 'LIST_LUCKMAIL_PURCHASES': {
- const purchases = await listLuckmailPurchasesForManagement();
- return { ok: true, purchases };
- }
- case 'SELECT_LUCKMAIL_PURCHASE': {
- const purchase = await selectLuckmailPurchase(message.payload?.purchaseId);
- return { ok: true, purchase };
- }
- case 'SET_LUCKMAIL_PURCHASE_USED_STATE': {
- const result = await setLuckmailPurchaseUsedState(message.payload?.purchaseId, Boolean(message.payload?.used));
- return { ok: true, ...result };
- }
- case 'SET_LUCKMAIL_PURCHASE_PRESERVED_STATE': {
- const purchase = await setLuckmailPurchasePreservedState(message.payload?.purchaseId, Boolean(message.payload?.preserved));
- return { ok: true, purchase };
- }
- case 'SET_LUCKMAIL_PURCHASE_DISABLED_STATE': {
- const purchase = await setLuckmailPurchaseDisabledState(message.payload?.purchaseId, Boolean(message.payload?.disabled));
- return { ok: true, purchase };
- }
- case 'BATCH_UPDATE_LUCKMAIL_PURCHASES': {
- const result = await batchUpdateLuckmailPurchases(message.payload || {});
- return { ok: true, ...result };
- }
- case 'DISABLE_USED_LUCKMAIL_PURCHASES': {
- const result = await disableUsedLuckmailPurchases();
- return { ok: true, ...result };
- }
- case 'SET_EMAIL_STATE': {
- const state = await getState();
- if (isAutoRunLockedState(state)) {
- throw new Error('自动流程运行中,当前不能手动修改邮箱。');
- }
- const email = String(message.payload?.email || '').trim() || null;
- await setEmailStateSilently(email);
- return { ok: true, email };
- }
- case 'SAVE_EMAIL': {
- const state = await getState();
- if (isAutoRunLockedState(state)) {
- throw new Error('自动流程运行中,当前不能手动修改邮箱。');
- }
- await setEmailState(message.payload.email);
- await resumeAutoRun();
- return { ok: true, email: message.payload.email };
- }
- case 'FETCH_GENERATED_EMAIL': {
- clearStopRequest();
- const state = await getState();
- if (isAutoRunLockedState(state)) {
- throw new Error('自动流程运行中,当前不能手动获取邮箱。');
- }
- const email = await fetchGeneratedEmail(state, message.payload || {});
- await resumeAutoRun();
- return { ok: true, email };
- }
- case 'FETCH_DUCK_EMAIL': {
- clearStopRequest();
- const state = await getState();
- if (isAutoRunLockedState(state)) {
- throw new Error('自动流程运行中,当前不能手动获取邮箱。');
- }
- const email = await fetchGeneratedEmail(state, { ...(message.payload || {}), generator: 'duck' });
- await resumeAutoRun();
- return { ok: true, email };
- }
- case 'CHECK_ICLOUD_SESSION': {
- clearStopRequest();
- return await checkIcloudSession();
- }
- case 'LIST_ICLOUD_ALIASES': {
- clearStopRequest();
- const aliases = await listIcloudAliases();
- return { ok: true, aliases };
- }
- case 'SET_ICLOUD_ALIAS_USED_STATE': {
- clearStopRequest();
- const result = await setIcloudAliasUsedState(message.payload || {});
- return { ok: true, ...result };
- }
- case 'SET_ICLOUD_ALIAS_PRESERVED_STATE': {
- clearStopRequest();
- const result = await setIcloudAliasPreservedState(message.payload || {});
- return { ok: true, ...result };
- }
- case 'DELETE_ICLOUD_ALIAS': {
- clearStopRequest();
- const result = await deleteIcloudAlias(message.payload || {});
- return { ok: true, ...result };
- }
- case 'DELETE_USED_ICLOUD_ALIASES': {
- clearStopRequest();
- const result = await deleteUsedIcloudAliases();
- return { ok: true, ...result };
- }
- case 'STOP_FLOW': {
- await requestStop();
- return { ok: true };
- }
- default:
- console.warn('Unknown message type:', message.type);
- return { error: `Unknown message type: ${message.type}` };
- }
- }
- return {
- handleMessage,
- handleStepData,
- };
- }
- return {
- createMessageRouter,
- };
- });
|