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,
}
}