Skip to content

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

Package listing

@kentcdodds/grok-bot

src/sync-discord.ts

64 lines · 1.7 KB · TypeScript
import {
	GROK_BOT_CATEGORY_ID,
	KNOWN_GROK_BOT_CHANNELS,
	listChannelMappings,
	readCategoryId,
	upsertStubBotRecord,
	writeCategoryId,
	writeChannelMapping,
	type ChannelMapping,
} from './discord-map.ts'

export type SyncDiscordInput = {
	/** Override the stored Grok Bot category id. */
	categoryId?: string
}

export type SyncDiscordResult = {
	categoryId: string
	channels: ChannelMapping[]
	upserted: number
}

/**
 * Persist the Grok Bot Discord category and existing per-bot channel map.
 *
 * Channels can exist before a bot is wake-registered. Does not need webhook
 * URLs. Safe to re-run; existing webhook URLs on roster rows are kept.
 *
 * @param input.categoryId - Optional category id override
 * @returns Stored category id and channel mappings
 * @example
 * import syncDiscord from 'kody:@kentcdodds/grok-bot/sync-discord'
 * const synced = await syncDiscord()
 * // => { categoryId: '1542616354274676827', channels: [{ channelId, botId, name }], upserted: 10 }
 */
export default async function syncDiscord(
	input: SyncDiscordInput = {},
): Promise<SyncDiscordResult> {
	const categoryId = await writeCategoryId(
		typeof input.categoryId === 'string' && input.categoryId.trim()
			? input.categoryId.trim()
			: GROK_BOT_CATEGORY_ID,
	)
	let upserted = 0
	for (const channel of KNOWN_GROK_BOT_CHANNELS) {
		await writeChannelMapping({
			channelId: channel.channelId,
			botId: channel.botId,
			name: channel.name,
		})
		await upsertStubBotRecord({
			id: channel.botId,
			name: channel.name,
			channelId: channel.channelId,
		})
		upserted += 1
	}
	const channels = await listChannelMappings()
	return {
		categoryId: categoryId || (await readCategoryId()),
		channels,
		upserted,
	}
}