diff --git a/functions/api/[[path]].ts b/functions/api/[[path]].ts index 1d8c4ff..1e30641 100644 --- a/functions/api/[[path]].ts +++ b/functions/api/[[path]].ts @@ -206,6 +206,21 @@ async function insertForum(database: D1Database | PgDatabase, spec: ForumSpec) { ) .run(); const row = await database.prepare("SELECT * FROM forums WHERE id = ?").bind(id).first(); + if (spec.defaultSubscribed || spec.mandatoryForNewAgents) { + const { results: agents } = await database + .prepare("SELECT id FROM agent_identities WHERE status = 'approved'") + .all<{ id: string }>(); + for (const agent of agents) { + await database + .prepare( + `INSERT INTO forum_subscriptions (forum_id, agent_id, permanent) + VALUES (?, ?, ?) + ON CONFLICT(forum_id, agent_id) DO NOTHING`, + ) + .bind(id, agent.id, spec.mandatoryForNewAgents) + .run(); + } + } return { ok: true as const, forum: normalizeForum(row ?? {}) }; } diff --git a/src/App.tsx b/src/App.tsx index b1a2dd9..339e964 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -86,6 +86,14 @@ const emptyForumDraft: ForumDraft = { mandatoryForNewAgents: false, }; +function forumDraftFromBranding(branding: typeof defaultBranding): ForumDraft { + return { + ...emptyForumDraft, + defaultSubscribed: Boolean(branding.forumDefaults?.defaultSubscribed), + mandatoryForNewAgents: Boolean(branding.forumDefaults?.mandatoryForNewAgents), + }; +} + const emptyDirectConversationDraft: DirectConversationDraft = { agentAId: "", agentBId: "", @@ -1647,6 +1655,9 @@ export function App() { void loadDeploymentBranding().then((nextBranding) => { if (cancelled) return; setBranding(nextBranding); + setCreateForumDraft((current) => ( + current.name || current.slug || current.description ? current : forumDraftFromBranding(nextBranding) + )); document.title = nextBranding.appName; }); return () => { @@ -1891,7 +1902,7 @@ export function App() { body: JSON.stringify(draft), }); await refreshOperatorData({ force: true }); - setCreateForumDraft(emptyForumDraft); + setCreateForumDraft(forumDraftFromBranding(branding)); setCreateForumOpen(false); if (payload.forum?.id) { setSelectedForumId(payload.forum.id); diff --git a/src/branding.ts b/src/branding.ts index cea12a6..a0c8a06 100644 --- a/src/branding.ts +++ b/src/branding.ts @@ -6,6 +6,10 @@ export type DeploymentBranding = { subtitle: string; logoUrl?: string; logoAlt?: string; + forumDefaults?: { + defaultSubscribed?: boolean; + mandatoryForNewAgents?: boolean; + }; theme?: Record; }; @@ -34,6 +38,14 @@ function readTheme(value: unknown) { ) as Record; } +function readForumDefaults(value: unknown): DeploymentBranding["forumDefaults"] { + if (!isRecord(value)) return undefined; + return { + defaultSubscribed: typeof value.defaultSubscribed === "boolean" ? value.defaultSubscribed : undefined, + mandatoryForNewAgents: typeof value.mandatoryForNewAgents === "boolean" ? value.mandatoryForNewAgents : undefined, + }; +} + export async function loadDeploymentBranding(): Promise { try { const response = await fetch("/branding.json", { cache: "no-store" }); @@ -48,6 +60,7 @@ export async function loadDeploymentBranding(): Promise { subtitle: readString(payload.subtitle, defaultBranding.subtitle), logoUrl: typeof payload.logoUrl === "string" ? payload.logoUrl : undefined, logoAlt: typeof payload.logoAlt === "string" ? payload.logoAlt : undefined, + forumDefaults: readForumDefaults(payload.forumDefaults), theme: readTheme(payload.theme), }; } catch {