Skip to content

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

Package listing

@kody/discord

src/fetch-channel-messages.ts

48 lines · 1.7 KB · TypeScript
import { discordBotRequest } from './bot.ts'
import { boundedInteger, inputRecord, snowflake } from './validation.ts'

type DiscordMessage = {
	id?: string
	content?: string
	timestamp?: string
	author?: { id?: string; username?: string; bot?: boolean }
	thread?: { id?: string; name?: string }
}

/**
 * List recent messages in a Discord channel through the bot-token lane.
 *
 * Reading message text requires the privileged Message Content intent on the
 * bot. Empty `content` with a 200 response usually means that intent is off.
 *
 * @param params.secretName - Bot-token secret; default `discordBotToken`.
 * @param params.limit - 1–100; default 50.
 */
export default async function fetchChannelMessages(params: Record<string, unknown> = {}) {
	const input = inputRecord(params)
	const channelId = snowflake(input, 'channelId', ['channel_id'])
	const limit = boundedInteger(input.limit, 50, 1, 100, 'limit')
	const messages = (await discordBotRequest('/channels/' + channelId + '/messages', input, {
		query: { limit },
	})) as DiscordMessage[]

	if (!Array.isArray(messages)) {
		throw new Error('Unexpected Discord messages response; expected an array.')
	}

	return {
		channelId,
		count: messages.length,
		messages: messages.map((message) => ({
			id: typeof message.id === 'string' ? message.id : null,
			content: typeof message.content === 'string' ? message.content : '',
			timestamp: typeof message.timestamp === 'string' ? message.timestamp : null,
			author: {
				id: typeof message.author?.id === 'string' ? message.author.id : null,
				username: typeof message.author?.username === 'string' ? message.author.username : null,
				bot: message.author?.bot === true,
			},
			threadId: typeof message.thread?.id === 'string' ? message.thread.id : null,
		})),
	}
}