From 4ba86894a6f6414ddf411579a6f7a23f5ca3ef9a Mon Sep 17 00:00:00 2001 From: Orkun Manap Date: Mon, 23 Mar 2026 00:11:05 +0100 Subject: [PATCH] fix: move voice-bubble detection into Telegram channel to avoid regression in other channels Address review feedback: keep inferMediaType returning "audio" for all OGG files. Voice-bubble detection (SendVoice vs SendAudio) is now done inside the Telegram channel based on filename, so other channels that map "audio" explicitly are unaffected. --- pkg/agent/loop.go | 6 ----- pkg/channels/telegram/telegram.go | 33 ++++++++++++++---------- pkg/voice/elevenlabs_transcriber.go | 2 +- pkg/voice/elevenlabs_transcriber_test.go | 4 +-- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index e5d842c6c..725d42614 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -1152,12 +1152,6 @@ func inferMediaType(filename, contentType string) string { ct := strings.ToLower(contentType) fn := strings.ToLower(filename) - // Detect voice messages: OGG files with "voice" in the filename. - // These are sent as Telegram voice bubbles rather than audio attachments. - if strings.Contains(fn, "voice") && (strings.HasSuffix(fn, ".ogg") || strings.HasSuffix(fn, ".oga")) { - return "voice" - } - if strings.HasPrefix(ct, "image/") { return "image" } diff --git a/pkg/channels/telegram/telegram.go b/pkg/channels/telegram/telegram.go index dc67e06a8..d0011d21b 100644 --- a/pkg/channels/telegram/telegram.go +++ b/pkg/channels/telegram/telegram.go @@ -480,22 +480,27 @@ func (c *TelegramChannel) SendMedia(ctx context.Context, msg bus.OutboundMediaMe } _, err = c.bot.SendDocument(ctx, docParams) } - case "voice": - params := &telego.SendVoiceParams{ - ChatID: tu.ID(chatID), - MessageThreadID: threadID, - Voice: telego.InputFile{File: file}, - Caption: part.Caption, - } - _, err = c.bot.SendVoice(ctx, params) case "audio": - params := &telego.SendAudioParams{ - ChatID: tu.ID(chatID), - MessageThreadID: threadID, - Audio: telego.InputFile{File: file}, - Caption: part.Caption, + // Send OGG files with "voice" in the filename as Telegram voice + // bubbles (SendVoice) instead of audio attachments (SendAudio). + fn := strings.ToLower(part.Filename) + if strings.Contains(fn, "voice") && (strings.HasSuffix(fn, ".ogg") || strings.HasSuffix(fn, ".oga")) { + vparams := &telego.SendVoiceParams{ + ChatID: tu.ID(chatID), + MessageThreadID: threadID, + Voice: telego.InputFile{File: file}, + Caption: part.Caption, + } + _, err = c.bot.SendVoice(ctx, vparams) + } else { + params := &telego.SendAudioParams{ + ChatID: tu.ID(chatID), + MessageThreadID: threadID, + Audio: telego.InputFile{File: file}, + Caption: part.Caption, + } + _, err = c.bot.SendAudio(ctx, params) } - _, err = c.bot.SendAudio(ctx, params) case "video": params := &telego.SendVideoParams{ ChatID: tu.ID(chatID), diff --git a/pkg/voice/elevenlabs_transcriber.go b/pkg/voice/elevenlabs_transcriber.go index 44f4bd88e..93db10f8d 100644 --- a/pkg/voice/elevenlabs_transcriber.go +++ b/pkg/voice/elevenlabs_transcriber.go @@ -87,7 +87,7 @@ func (t *ElevenLabsTranscriber) Transcribe(ctx context.Context, audioFilePath st } req.Header.Set("Content-Type", writer.FormDataContentType()) - req.Header.Set("xi-api-key", t.apiKey) + req.Header.Set("Xi-Api-Key", t.apiKey) logger.DebugCF("voice", "Sending transcription request to ElevenLabs API", map[string]any{ "url": url, diff --git a/pkg/voice/elevenlabs_transcriber_test.go b/pkg/voice/elevenlabs_transcriber_test.go index 119282542..78be8958a 100644 --- a/pkg/voice/elevenlabs_transcriber_test.go +++ b/pkg/voice/elevenlabs_transcriber_test.go @@ -32,8 +32,8 @@ func TestElevenLabsTranscribe(t *testing.T) { if r.URL.Path != "/v1/speech-to-text" { t.Errorf("unexpected path: %s", r.URL.Path) } - if r.Header.Get("xi-api-key") != "sk_test" { - t.Errorf("unexpected xi-api-key header: %s", r.Header.Get("xi-api-key")) + if r.Header.Get("Xi-Api-Key") != "sk_test" { + t.Errorf("unexpected xi-api-key header: %s", r.Header.Get("Xi-Api-Key")) } w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(TranscriptionResponse{