import { useMemo } from 'react'; import { useClientConfig } from '../../hooks/useClientConfig'; import type { BotConfig, ClientConfig } from '../../hooks/useClientConfig'; export type BotPreset = { /** Stable URL slug — `/bots/`. Never reuse across bots. */ id: string; /** Bot user mxid. The DM with this user IS the bot's control room. */ mxid: string; name: string; }; const BOT_ID_RE = /^[A-Za-z0-9_-]+$/; const MXID_RE = /^@[^:\s]+:[^\s]+$/; const isValidBotPreset = (preset: BotConfig | undefined): preset is BotPreset => typeof preset?.id === 'string' && BOT_ID_RE.test(preset.id) && typeof preset.mxid === 'string' && MXID_RE.test(preset.mxid) && typeof preset.name === 'string' && preset.name.trim().length > 0; export const getBotPresets = (clientConfig: ClientConfig): BotPreset[] => { const seenIds = new Set(); const seenMxids = new Set(); const bots: BotPreset[] = []; const configuredBots = Array.isArray(clientConfig.bots) ? clientConfig.bots : []; configuredBots.forEach((preset) => { if (!isValidBotPreset(preset)) return; if (seenIds.has(preset.id) || seenMxids.has(preset.mxid)) return; seenIds.add(preset.id); seenMxids.add(preset.mxid); bots.push({ id: preset.id, mxid: preset.mxid, name: preset.name.trim(), }); }); return bots; }; export const useBotPresets = (): BotPreset[] => { const clientConfig = useClientConfig(); return useMemo(() => getBotPresets(clientConfig), [clientConfig]); }; export const findBotPresetById = ( presets: readonly BotPreset[], id: string ): BotPreset | undefined => presets.find((preset) => preset.id === id);