53 lines
1.6 KiB
TypeScript
53 lines
1.6 KiB
TypeScript
import { useMemo } from 'react';
|
|
import { useClientConfig } from '../../hooks/useClientConfig';
|
|
import type { BotConfig, ClientConfig } from '../../hooks/useClientConfig';
|
|
|
|
export type BotPreset = {
|
|
/** Stable URL slug — `/bots/<id>`. 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<string>();
|
|
const seenMxids = new Set<string>();
|
|
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);
|