package main import ( "os" "path/filepath" "testing" "github.com/stretchr/testify/require" ) func TestTelegramVoiceNotesReachTheAgentAsStoredText(t *testing.T) { server := newModelFake(t) test := newTestTurnLoop(t, server) telegram := newTelegramFake(t) bot, logs := telegramStartTestBot(t, telegram) _, bot.voice = voiceTestInput(t, voiceTestScript) audio := []byte("made-up Telegram voice") telegram.Image("voice", audio) message := telegramOwnerMessage("") message.Voice = &TelegramVoice{FileID: "voice"} message.Caption = "A voice caption." require.NoError(t, bot.handle(t.Context(), test.loop, nil, TelegramUpdate{Message: message})) test.events.WaitFor(t, "idle", 1) logged, err := test.memory.Message(0) require.NoError(t, err) require.Contains(t, logged.Text, "[voice ") require.Contains(t, logged.Text, "A made-up voice transcript.\nA voice caption.") files, err := os.ReadDir(test.agent.Voices().dir) require.NoError(t, err) require.Len(t, files, 1) saved, err := os.ReadFile(filepath.Join(test.agent.Voices().dir, files[0].Name())) require.NoError(t, err) require.Equal(t, audio, saved) require.Contains(t, string(server.Call(0).raw), "A made-up voice transcript.") require.NotContains(t, logs.String(), "A made-up") require.NotContains(t, logs.String(), "A voice caption") } func TestTelegramVoiceFailuresKeepFollowingTextMoving(t *testing.T) { testCases := []struct { name string size int64 file string marker string }{ { name: "oversize metadata prevents a download", size: voiceMaxBytes + 1, file: "voice", marker: "(voice not downloaded)", }, { name: "download failure becomes text", file: "absent", marker: "(voice not downloaded)", }, { name: "missing model preserves stored audio", file: "voice", marker: "transcriber or model is not available", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { test := newTestTurnLoop(t, newModelFake(t)) telegram := newTelegramFake(t) bot, _ := telegramStartTestBot(t, telegram) bot.voice.config.Model = filepath.Join(t.TempDir(), "missing") telegram.Image("voice", []byte("made-up voice")) message := telegramOwnerMessage("") message.Voice = &TelegramVoice{ FileID: tc.file, FileSize: tc.size, } require.NoError(t, bot.handle(t.Context(), test.loop, nil, TelegramUpdate{Message: message})) require.NoError(t, bot.handle(t.Context(), test.loop, nil, TelegramUpdate{Message: telegramOwnerMessage("Next text.")})) require.NoError(t, test.loop.Flush(t.Context())) logged, err := test.memory.Message(0) require.NoError(t, err) require.Contains(t, logged.Text, tc.marker) found := false for n := 0; n < test.memory.Len(); n++ { logged, err = test.memory.Message(n) require.NoError(t, err) found = found || logged.Text == "Next text." } require.True(t, found) }) } } func TestTelegramIgnoresVoiceNotesFromOtherSenders(t *testing.T) { test := newTestTurnLoop(t, newModelFake(t)) telegram := newTelegramFake(t) bot, _ := telegramStartTestBot(t, telegram) message := telegramOwnerMessage("") message.Voice = &TelegramVoice{FileID: "voice"} message.From.ID++ require.NoError(t, bot.handle(t.Context(), test.loop, nil, TelegramUpdate{Message: message})) require.Empty(t, telegram.Calls()) require.Zero(t, test.memory.Len()) }