Skip to content
← Public packages

@kody/slack

Read Slack conversations and safely send messages as the authorizing user through the saved slack OAuth integration.

src/send-message.ts

55 lines · 1.5 KB · TypeScript
import { resolveIntegrationName, slackRequest } from './request.ts'
import { inputRecord, optionalBoolean, optionalString, requiredString } from './validation.ts'

type SendMessageResponse = {
	ok: boolean
	channel?: string
	ts?: string
	message?: unknown
	[key: string]: unknown
}

/** Preview or send a Slack message as the authorizing user. */
export default async function sendMessage(params: Record<string, unknown>) {
	const input = inputRecord(params)
	const channel = requiredString(input, 'channel')
	const text = requiredString(input, 'text')
	const blocks = input.blocks
	if (blocks !== undefined && !Array.isArray(blocks)) {
		throw new Error('blocks must be an array when provided.')
	}

	const payload: Record<string, unknown> = {
		channel,
		text,
		thread_ts: optionalString(input, 'threadTs'),
		unfurl_links: optionalBoolean(input, 'unfurlLinks'),
		unfurl_media: optionalBoolean(input, 'unfurlMedia'),
	}
	if (blocks !== undefined) payload.blocks = blocks

	if (input.dryRun === true) {
		return {
			dryRun: true,
			method: 'chat.postMessage',
			identity: 'authorizing-user',
			payload,
		}
	}

	if (input.confirm !== true) {
		throw new Error('Sending a Slack message requires confirm: true after explicit user approval of the destination and content.')
	}

	const result = await slackRequest<SendMessageResponse>(
		'chat.postMessage',
		payload,
		resolveIntegrationName(input.integration),
	)
	return {
		ok: true,
		channel: result.channel ?? channel,
		ts: result.ts ?? null,
		message: result.message ?? null,
	}
}