haixunMaster/app/api/accounts/route.ts

117 lines
3.4 KiB
TypeScript

import { NextResponse } from "next/server";
import { accountHasStoredSession } from "@/lib/threads-browser";
import { prisma } from "@/lib/db";
import { setActiveAccountForUser } from "@/lib/account-context";
import { apiRouteErrorResponse } from "@/lib/auth/api";
import { requireSessionUser } from "@/lib/auth/session";
function accountSelect() {
return {
id: true,
username: true,
displayName: true,
persona: true,
styleProfile: true,
styleBenchmark: true,
brief: true,
productBrief: true,
targetAudience: true,
goals: true,
valid: true,
storageState: true,
updatedAt: true,
threadsUserId: true,
threadsTokenExpiresAt: true,
} as const;
}
type RawAccount = Awaited<
ReturnType<typeof prisma.account.findFirst<{ select: ReturnType<typeof accountSelect> }>>
>;
function toPublicAccount(account: NonNullable<RawAccount>) {
const { threadsUserId, threadsTokenExpiresAt } = account;
return {
id: account.id,
username: account.username,
displayName: account.displayName,
persona: account.persona,
styleProfile: account.styleProfile,
styleBenchmark: account.styleBenchmark,
brief: account.brief,
productBrief: account.productBrief,
targetAudience: account.targetAudience,
goals: account.goals,
valid: account.valid,
updatedAt: account.updatedAt,
apiConnected: !!threadsUserId,
browserConnected: accountHasStoredSession(account),
sessionSynced: accountHasStoredSession(account),
threadsUserId,
threadsTokenExpiresAt: threadsTokenExpiresAt?.toISOString() ?? null,
};
}
export async function GET() {
try {
const user = await requireSessionUser();
const accounts = await prisma.account.findMany({
where: { userId: user.id },
orderBy: { updatedAt: "desc" },
select: accountSelect(),
});
const activeAccountId = user.activeAccountId ?? accounts[0]?.id ?? null;
if (!user.activeAccountId && activeAccountId) {
await setActiveAccountForUser(user.id, activeAccountId);
}
return NextResponse.json({
accounts: accounts.map(toPublicAccount),
activeAccountId,
});
} catch (error) {
return apiRouteErrorResponse(error, "accounts");
}
}
export async function POST(request: Request) {
try {
const user = await requireSessionUser();
const body = (await request.json()) as {
displayName?: string;
username?: string;
persona?: string;
brief?: string;
productBrief?: string;
targetAudience?: string;
goals?: string;
activate?: boolean;
};
const account = await prisma.account.create({
data: {
userId: user.id,
displayName: body.displayName?.trim() || body.username?.trim() || "新經營帳號",
username: body.username?.replace(/^@/, "").trim() || null,
persona: body.persona?.trim() || null,
brief: body.brief?.trim() || null,
productBrief: body.productBrief?.trim() || null,
targetAudience: body.targetAudience?.trim() || null,
goals: body.goals?.trim() || null,
storageState: "",
valid: false,
},
select: accountSelect(),
});
if (body.activate ?? true) {
await setActiveAccountForUser(user.id, account.id);
}
return NextResponse.json({ account: toPublicAccount(account) });
} catch (error) {
return apiRouteErrorResponse(error, "accounts/create");
}
}