134 lines
4.4 KiB
TypeScript
134 lines
4.4 KiB
TypeScript
import "server-only";
|
|
|
|
import type { Account } from "@prisma/client";
|
|
import { getActiveAccountProfile } from "@/lib/account-context";
|
|
import { assertAccountOwnedByUser } from "@/lib/auth/accounts";
|
|
import { prisma } from "@/lib/db";
|
|
import {
|
|
DEFAULT_SEARCH_SOURCE_MODE,
|
|
parseSearchSourceMode,
|
|
type SearchSourceMode,
|
|
} from "@/lib/search/source-mode";
|
|
|
|
export interface AccountConnectionSettings {
|
|
searchViaApi: boolean;
|
|
searchSourceMode: SearchSourceMode;
|
|
publishViaApi: boolean;
|
|
devMode: boolean;
|
|
scrapeReplies: boolean;
|
|
repliesPerPost: number;
|
|
publishHeaded: boolean;
|
|
playwrightDebug: boolean;
|
|
}
|
|
|
|
export function fromAccountPublic(settings: AccountConnectionSettings) {
|
|
return settings;
|
|
}
|
|
|
|
export const DEFAULT_ACCOUNT_CONNECTION: AccountConnectionSettings = {
|
|
searchViaApi: false,
|
|
searchSourceMode: DEFAULT_SEARCH_SOURCE_MODE,
|
|
publishViaApi: false,
|
|
devMode: true,
|
|
scrapeReplies: true,
|
|
repliesPerPost: 10,
|
|
publishHeaded: false,
|
|
playwrightDebug: false,
|
|
};
|
|
|
|
function fromAccount(account: Account): AccountConnectionSettings {
|
|
return {
|
|
searchViaApi: account.searchViaApi,
|
|
searchSourceMode: parseSearchSourceMode(account.searchSourceMode),
|
|
publishViaApi: account.publishViaApi,
|
|
devMode: account.devMode,
|
|
scrapeReplies: account.scrapeReplies,
|
|
repliesPerPost: account.repliesPerPost,
|
|
publishHeaded: account.publishHeaded,
|
|
playwrightDebug: account.playwrightDebug,
|
|
};
|
|
}
|
|
|
|
/** 將舊版使用者層級連線設定一次性複製到各經營帳號。失敗時略過,不阻擋連線頁載入。 */
|
|
export async function migrateUserConnectionSettingsIfNeeded(userId: string) {
|
|
try {
|
|
const settings = await prisma.setting.findUnique({ where: { userId } });
|
|
if (!settings || settings.connectionMigrated) return;
|
|
|
|
await prisma.account.updateMany({
|
|
where: { userId },
|
|
data: {
|
|
searchViaApi: settings.searchViaApi,
|
|
publishViaApi: settings.publishViaApi,
|
|
devMode: settings.devMode,
|
|
scrapeReplies: settings.scrapeReplies,
|
|
repliesPerPost: settings.repliesPerPost,
|
|
publishHeaded: settings.publishHeaded,
|
|
playwrightDebug: settings.playwrightDebug,
|
|
},
|
|
});
|
|
|
|
await prisma.setting.update({
|
|
where: { userId },
|
|
data: { connectionMigrated: true },
|
|
});
|
|
} catch (error) {
|
|
console.warn("[connection-migrate] skipped:", error);
|
|
}
|
|
}
|
|
|
|
export async function getAccountConnectionSettings(
|
|
accountId: string
|
|
): Promise<AccountConnectionSettings> {
|
|
const account = await prisma.account.findUnique({ where: { id: accountId } });
|
|
if (!account) return DEFAULT_ACCOUNT_CONNECTION;
|
|
return fromAccount(account);
|
|
}
|
|
|
|
export async function getActiveAccountConnectionSettings(): Promise<AccountConnectionSettings> {
|
|
const account = await getActiveAccountProfile();
|
|
if (!account) return DEFAULT_ACCOUNT_CONNECTION;
|
|
|
|
if (account.userId) {
|
|
await migrateUserConnectionSettingsIfNeeded(account.userId);
|
|
const fresh = await prisma.account.findUnique({ where: { id: account.id } });
|
|
if (fresh) return fromAccount(fresh);
|
|
}
|
|
|
|
return fromAccount(account);
|
|
}
|
|
|
|
export async function updateActiveAccountConnectionSettings(
|
|
userId: string,
|
|
patch: Partial<AccountConnectionSettings>
|
|
) {
|
|
await migrateUserConnectionSettingsIfNeeded(userId);
|
|
|
|
const user = await prisma.user.findUnique({
|
|
where: { id: userId },
|
|
select: { activeAccountId: true },
|
|
});
|
|
if (!user?.activeAccountId) {
|
|
throw new Error("請先建立並選擇一個經營帳號");
|
|
}
|
|
|
|
await assertAccountOwnedByUser(userId, user.activeAccountId);
|
|
|
|
const account = await prisma.account.update({
|
|
where: { id: user.activeAccountId },
|
|
data: {
|
|
...(patch.searchViaApi !== undefined && { searchViaApi: patch.searchViaApi }),
|
|
...(patch.searchSourceMode !== undefined && {
|
|
searchSourceMode: parseSearchSourceMode(patch.searchSourceMode),
|
|
}),
|
|
...(patch.publishViaApi !== undefined && { publishViaApi: patch.publishViaApi }),
|
|
...(patch.devMode !== undefined && { devMode: patch.devMode }),
|
|
...(patch.scrapeReplies !== undefined && { scrapeReplies: patch.scrapeReplies }),
|
|
...(patch.repliesPerPost !== undefined && { repliesPerPost: patch.repliesPerPost }),
|
|
...(patch.publishHeaded !== undefined && { publishHeaded: patch.publishHeaded }),
|
|
...(patch.playwrightDebug !== undefined && { playwrightDebug: patch.playwrightDebug }),
|
|
},
|
|
});
|
|
|
|
return { account };
|
|
} |