Files
AskaEth 7d2ff74cfc
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
test(telegram): 补语音内联回归测试(上一条语音切片提交时被 grep 过滤漏掉)
2026-10-05 08:37:23 +08:00

79 lines
2.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package telegram
// 本文件锁定 **Telegram 入站语音**的字节内联(切片 IM-ASR):「渠道零改动」这条承诺要
// 在**真适配器**上被验证一次 —— 语音只有 `file_id` + `audio/ogg`(没有文件名、没有
// 扩展名),因此音频白名单必须能靠平台声明的 MIME 命中,否则 telegram 语音会被整条
// 挡掉。夹具复用 media_test.go 的假 Bot API。
import (
"context"
"encoding/json"
"fmt"
"testing"
)
// voiceUpdate 构造一条 Telegram 语音消息的原始 update(无 caption:纯语音)。
func voiceUpdate(fileID, mime string, size int64) []byte {
body := map[string]any{
"update_id": 3,
"message": map[string]any{
"message_id": 44,
"date": 1700000002,
"chat": map[string]any{"id": 7, "type": "private"},
"from": map[string]any{"id": 9, "first_name": "主人"},
"voice": map[string]any{"file_id": fileID, "file_size": size, "mime_type": mime, "duration": 3},
},
}
raw, err := json.Marshal(body)
if err != nil {
panic(fmt.Sprintf("marshal update: %v", err))
}
return raw
}
// TestInboundVoiceIsInlined 是正向用例:语音 ⇒ getFile ⇒ 下载 ⇒ Data 被填,
// 且本切片**一行适配器代码都没改**(因此它同时是「渠道零改动」的回归保护)。
func TestInboundVoiceIsInlined(t *testing.T) {
t.Parallel()
s := newTGAssetServer(t)
a, h, _ := newInlineAdapter(t, s)
if _, err := a.ProcessUpdate(context.Background(), voiceUpdate("voice-id", "audio/ogg", 1024)); err != nil {
t.Fatalf("ProcessUpdate: %v", err)
}
msg := h.message(t)
if msg.Content != "" {
t.Fatalf("Content = %q, want 空(纯语音没有 caption,转写由桥接器负责)", msg.Content)
}
if len(msg.Media) != 1 || string(msg.Media[0].Data) != "附件的正文\n" {
t.Fatalf("Media.Data = %q, want 下载到的语音字节", msg.Media[0].Data)
}
if msg.Media[0].URL != "voice-id" || msg.Media[0].MIMEType != "audio/ogg" {
t.Fatalf("内联改动了媒体元数据:%+v", msg.Media[0])
}
if s.getFile.Load() != 1 || s.fileHits.Load() != 1 {
t.Fatalf("getFile=%d fileHits=%d, want 1/1(MIME 兜底必须命中音频白名单)", s.getFile.Load(), s.fileHits.Load())
}
}
// TestInboundVoiceWithoutMIMEIsNotDownloaded 钉住 deny-by-default:平台既没给文件名也
// 没给类型时**不发起任何请求**(宁可诚实说读不到,也不猜一份类型不明的音频)。
func TestInboundVoiceWithoutMIMEIsNotDownloaded(t *testing.T) {
t.Parallel()
s := newTGAssetServer(t)
a, h, _ := newInlineAdapter(t, s)
if _, err := a.ProcessUpdate(context.Background(), voiceUpdate("voice-id", "", 1024)); err != nil {
t.Fatalf("ProcessUpdate: %v", err)
}
msg := h.message(t)
if len(msg.Media[0].Data) != 0 {
t.Fatalf("类型不明的语音被内联了(%d 字节)", len(msg.Media[0].Data))
}
if s.allHits.Load() != 0 {
t.Fatalf("类型不明的语音仍发起了请求:all=%d", s.allHits.Load())
}
}