Skip to content

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

Package listing

@kody/telegram

src/send-message.ts

73 lines · 2.0 KB · TypeScript
import { telegramRequest } from './request.ts'
import {
	inputRecord,
	optionalBoolean,
	optionalInteger,
	optionalString,
	requiredChatId,
	requiredString,
	secretNameFrom,
} from './validation.ts'

type SendMessageResult = {
	message_id?: number
	date?: number
	chat?: { id?: number; type?: string }
	text?: string
	[key: string]: unknown
}

const PARSE_MODES = new Set(['MarkdownV2', 'HTML', 'Markdown'])

/** Preview or send a Telegram message as the bot. */
export default async function sendMessage(params: Record<string, unknown>) {
	const input = inputRecord(params)
	const chatId = requiredChatId(input)
	const text = requiredString(input, 'text')
	const secretName = secretNameFrom(input)
	const parseMode = optionalString(input, 'parseMode')
	if (parseMode !== undefined && !PARSE_MODES.has(parseMode)) {
		throw new Error('parseMode must be MarkdownV2, HTML, or Markdown.')
	}

	const payload: Record<string, unknown> = {
		chat_id: chatId,
		text,
		parse_mode: parseMode,
		message_thread_id: optionalInteger(input, 'messageThreadId'),
		reply_to_message_id: optionalInteger(input, 'replyToMessageId'),
		disable_notification: optionalBoolean(input, 'disableNotification'),
		protect_content: optionalBoolean(input, 'protectContent'),
		disable_web_page_preview: optionalBoolean(input, 'disableWebPagePreview'),
	}

	if (input.dryRun === true) {
		return {
			dryRun: true,
			method: 'sendMessage',
			identity: 'bot',
			secretName,
			payload,
		}
	}

	if (input.confirm !== true) {
		throw new Error(
			'Sending a Telegram message requires confirm: true after explicit user approval of the destination and content. Use dryRun: true to preview. Telegram Bot API has no OAuth scopes.',
		)
	}

	const result = await telegramRequest<SendMessageResult>({
		method: 'sendMessage',
		secretName,
		params: payload,
	})

	return {
		ok: true,
		messageId: result.message_id ?? null,
		date: result.date ?? null,
		chatId: result.chat?.id ?? chatId,
		chatType: result.chat?.type ?? null,
	}
}