feat(通知模板): 支持 case 取值映射与事件名匹配渲染
Motivation: 让通知模板能够将 action、event 等原始枚举值映射为可读中文文案,并支持按事件名后缀匹配;同时简化 SafeW 消息发送格式,避免 Markdown 转义引入的显示问题。 Changes: * 新增 `case` 模板函数,按值匹配 key/文案并支持末尾奇数参数作为默认值 * `case` 匹配兼容事件名后缀(如 trade.close 匹配 .close) * `line` 前缀自动去除末尾冒号,避免重复冒号 * 模板渲染前自动注入 event 字段,便于模板按事件名取值 * SafeW 消息改为纯文本发送,移除 MarkdownV2 转义
This commit is contained in:
@@ -26,7 +26,7 @@ type safewConfig struct {
|
||||
type safewMessage struct {
|
||||
ChatID string `json:"chat_id"`
|
||||
Text string `json:"text"`
|
||||
ParseMode string `json:"parse_mode"`
|
||||
ParseMode string `json:"parse_mode,omitempty"`
|
||||
}
|
||||
|
||||
type safewAPIResponse struct {
|
||||
@@ -52,9 +52,8 @@ func (s *SafeWSender) Send(title, content string, config json.RawMessage) error
|
||||
}
|
||||
|
||||
payload := safewMessage{
|
||||
ChatID: chatID,
|
||||
Text: "*" + escapeMarkdownV2(title) + "*\n" + escapeMarkdownV2(content),
|
||||
ParseMode: "MarkdownV2",
|
||||
ChatID: chatID,
|
||||
Text: title + "\n" + content,
|
||||
}
|
||||
body, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
@@ -235,19 +234,6 @@ func safewErrorDescription(body []byte) string {
|
||||
}
|
||||
}
|
||||
|
||||
func escapeMarkdownV2(s string) string {
|
||||
var b strings.Builder
|
||||
b.Grow(len(s))
|
||||
for _, r := range s {
|
||||
switch r {
|
||||
case '_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!', '\\':
|
||||
b.WriteByte('\\')
|
||||
}
|
||||
b.WriteRune(r)
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
type SafewChat struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
|
||||
@@ -11,32 +11,6 @@ import (
|
||||
"aiaa-notification-service/internal/config"
|
||||
)
|
||||
|
||||
func TestEscapeMarkdownV2(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
in string
|
||||
want string
|
||||
}{
|
||||
{name: "underscore and dot", in: "hello_world.", want: `hello\_world\.`},
|
||||
{name: "empty", in: "", want: ""},
|
||||
{name: "no specials", in: "hello", want: "hello"},
|
||||
{name: "backslash first", in: `a\b`, want: `a\\b`},
|
||||
{
|
||||
name: "all specials",
|
||||
in: "_*[]()~`>#+-=|{}.!\\",
|
||||
want: "\\_\\*\\[\\]\\(\\)\\~\\`\\>\\#\\+\\-\\=\\|\\{\\}\\.\\!\\\\",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := escapeMarkdownV2(tt.in)
|
||||
if got != tt.want {
|
||||
t.Fatalf("escapeMarkdownV2(%q) = %q, want %q", tt.in, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewSenderSafew(t *testing.T) {
|
||||
s, err := NewSender("safew", &config.SMTPConfig{}, nil)
|
||||
if err != nil {
|
||||
@@ -72,10 +46,10 @@ func TestSafeWSenderSendSuccess(t *testing.T) {
|
||||
if gotBody["chat_id"] != "123456789" {
|
||||
t.Fatalf("chat_id = %#v, want \"123456789\"", gotBody["chat_id"])
|
||||
}
|
||||
if gotBody["parse_mode"] != "MarkdownV2" {
|
||||
t.Fatalf("parse_mode = %#v, want MarkdownV2", gotBody["parse_mode"])
|
||||
if gotBody["parse_mode"] != nil && gotBody["parse_mode"] != "" {
|
||||
t.Fatalf("parse_mode = %#v, want omitted/plain", gotBody["parse_mode"])
|
||||
}
|
||||
wantText := "*" + escapeMarkdownV2("hello_world.") + "*\n" + escapeMarkdownV2("price=1.5")
|
||||
wantText := "hello_world.\nprice=1.5"
|
||||
if gotBody["text"] != wantText {
|
||||
t.Fatalf("text = %#v, want %#v", gotBody["text"], wantText)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user