From 20fd9f7f6757c00c2c0ac824bf9ef04d76f442df Mon Sep 17 00:00:00 2001 From: Manuel Maly Date: Sun, 4 Jan 2026 20:28:29 +0100 Subject: [PATCH] feat(telegram): use sendVoice for audio with opt-out Use Telegram's sendVoice API for audio files by default, displaying them as round playable voice bubbles instead of file attachments. Changes: - Add asVoice option to TelegramSendOpts (defaults to true) - When asVoice is true (default): use api.sendVoice() for voice bubbles - When asVoice is false: use api.sendAudio() for traditional audio files This gives callers control: voice messages for TTS/quick responses, audio files for music/podcasts with metadata display. --- src/telegram/send.ts | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/telegram/send.ts b/src/telegram/send.ts index 087cb4dfa..a2181655c 100644 --- a/src/telegram/send.ts +++ b/src/telegram/send.ts @@ -18,6 +18,8 @@ type TelegramSendOpts = { maxBytes?: number; api?: Bot["api"]; retry?: RetryConfig; + /** Send audio as voice message (voice bubble) instead of audio file. Defaults to false. */ + asVoice?: boolean; /** Message ID to reply to (for threading) */ replyToMessageId?: number; /** Forum topic thread ID (for forum supergroups) */ @@ -160,6 +162,7 @@ export async function sendMessageTelegram( | Awaited> | Awaited> | Awaited> + | Awaited> | Awaited> | Awaited>; if (isGif) { @@ -184,12 +187,22 @@ export async function sendMessageTelegram( throw wrapChatNotFound(err); }); } else if (kind === "audio") { - result = await request( - () => api.sendAudio(chatId, file, mediaParams), - "audio", - ).catch((err) => { - throw wrapChatNotFound(err); - }); + const useVoice = opts.asVoice === true; // default false (backward compatible) + if (useVoice) { + result = await request( + () => api.sendVoice(chatId, file, mediaParams), + "voice", + ).catch((err) => { + throw wrapChatNotFound(err); + }); + } else { + result = await request( + () => api.sendAudio(chatId, file, mediaParams), + "audio", + ).catch((err) => { + throw wrapChatNotFound(err); + }); + } } else { result = await request( () => api.sendDocument(chatId, file, mediaParams),