Skip to content

Built for people who want to own their automations. Join the waitlist for an invite.

Package listing

@kentcdodds/grok-bot

src/list.ts

59 lines · 1.6 KB · TypeScript
import {
	listChannelMappings,
	readCategoryId,
	type ChannelMapping,
} from './discord-map.ts'
import {
	listBotRecords,
	listKnownSecretNames,
	normalizeName,
	secretNameFor,
	urlHostOf,
	type BotSummary,
} from './registry.ts'

export type ListResult = {
	categoryId: string
	channels: ChannelMapping[]
	bots: BotSummary[]
}

/**
 * List registered Grok Bots without full webhook URLs.
 *
 * @returns Roster summaries with urlHost, pendingSecret, and channelId when mapped
 * @example
 * import list from 'kody:@kentcdodds/grok-bot/list'
 * const roster = await list()
 * // => { categoryId, channels, bots: [{ id, name, aliases, secretName, pendingSecret, urlHost, channelId }] }
 */
export default async function list(): Promise<ListResult> {
	const [records, secretNames, categoryId, channels] = await Promise.all([
		listBotRecords(),
		listKnownSecretNames(),
		readCategoryId(),
		listChannelMappings(),
	])
	const bots: BotSummary[] = records.map((record) => ({
		id: record.id,
		name: record.name,
		aliases: record.aliases,
		secretName: record.secretName,
		pendingSecret: secretNames ? !secretNames.has(record.secretName) : true,
		urlHost: urlHostOf(record.url),
		...(record.channelId ? { channelId: record.channelId } : {}),
	}))
	for (const channel of channels) {
		if (bots.some((bot) => bot.id === channel.botId)) continue
		bots.push({
			id: channel.botId,
			name: channel.name,
			aliases: [normalizeName(channel.name)],
			secretName: secretNameFor(channel.botId),
			pendingSecret: true,
			urlHost: '',
			channelId: channel.channelId,
		})
	}
	return { categoryId, channels, bots }
}