From c66399eedcc59504b7aefee2e07a5f3f0d31dc3a Mon Sep 17 00:00:00 2001 From: ryan Date: Sat, 29 Aug 2026 08:20:43 +0800 Subject: [PATCH] autoresearch iter 7: share body field extraction across push channels email, telegram and lark each re-implemented the title/content/level lookup with only their markup differing, and each carried a dead content := "" initialization that every branch overwrote. Three small helpers in template.go now own that logic. --- .../domain/message_gateway/push/email.go | 18 ++---------- .../domain/message_gateway/push/lark.go | 24 ++------------- .../domain/message_gateway/push/telegram.go | 21 ++------------ .../domain/message_gateway/push/template.go | 29 +++++++++++++++++++ 4 files changed, 37 insertions(+), 55 deletions(-) diff --git a/backend/plugins/domain/message_gateway/push/email.go b/backend/plugins/domain/message_gateway/push/email.go index 48e501bc..2948c577 100644 --- a/backend/plugins/domain/message_gateway/push/email.go +++ b/backend/plugins/domain/message_gateway/push/email.go @@ -37,22 +37,8 @@ func (p *EmailPusher) Send(ctx context.Context, cfg Config, target string, body return "", errors.New("email: target email address is required") } - title := defaultTitle - if t, ok := body["title"].(string); ok && t != "" { - title = t - } - - content := "" - if c, ok := body["content"].(string); ok && c != "" { - content = c - } else { - // 自动格式化 map - var parts []string - for k, v := range body { - parts = append(parts, fmt.Sprintf("

%s: %v

", k, v)) - } - content = strings.Join(parts, "") - } + title := bodyTitle(body) + content := bodyContent(body, "

%s: %v

", "") // 邮件头和体 from := cfg.Key diff --git a/backend/plugins/domain/message_gateway/push/lark.go b/backend/plugins/domain/message_gateway/push/lark.go index de15d83b..afa2cd58 100644 --- a/backend/plugins/domain/message_gateway/push/lark.go +++ b/backend/plugins/domain/message_gateway/push/lark.go @@ -154,27 +154,9 @@ func (p *LarkPusher) Send(ctx context.Context, cfg Config, _ string, body map[st } } else { // 2. 如果无模板,默认生成一个精美的飞书互动卡片 - title := defaultTitle - if t, ok := body["title"].(string); ok && t != "" { - title = t - } - - content := "" - if c, ok := body["content"].(string); ok && c != "" { - content = c - } else { - // 兜底:如果连 content 都没有,把 body 里的所有值拼成 markdown - var parts []string - for k, v := range body { - parts = append(parts, fmt.Sprintf("**%s**: %v", k, v)) - } - content = strings.Join(parts, "\n") - } - - level := levelInfo - if l, ok := body["level"].(string); ok && l != "" { - level = strings.ToUpper(l) - } + title := bodyTitle(body) + content := bodyContent(body, "**%s**: %v", "\n") + level := bodyLevel(body) // 根据级别确定飞书卡片头部的背景色模板 headerColor := "blue" diff --git a/backend/plugins/domain/message_gateway/push/telegram.go b/backend/plugins/domain/message_gateway/push/telegram.go index 65aeae0f..11162763 100644 --- a/backend/plugins/domain/message_gateway/push/telegram.go +++ b/backend/plugins/domain/message_gateway/push/telegram.go @@ -55,24 +55,9 @@ func (p *TelegramPusher) Send(ctx context.Context, cfg Config, target string, bo } baseURL = strings.TrimSuffix(baseURL, "/") - title := defaultTitle - if t, ok := body["title"].(string); ok && t != "" { - title = t - } - content := "" - if c, ok := body["content"].(string); ok && c != "" { - content = c - } else { - var parts []string - for k, v := range body { - parts = append(parts, fmt.Sprintf("%s: %v", k, v)) - } - content = strings.Join(parts, "\n") - } - level := levelInfo - if l, ok := body["level"].(string); ok && l != "" { - level = strings.ToUpper(l) - } + title := bodyTitle(body) + content := bodyContent(body, "%s: %v", "\n") + level := bodyLevel(body) var text string if template != "" { diff --git a/backend/plugins/domain/message_gateway/push/template.go b/backend/plugins/domain/message_gateway/push/template.go index 161dca06..7592409d 100644 --- a/backend/plugins/domain/message_gateway/push/template.go +++ b/backend/plugins/domain/message_gateway/push/template.go @@ -76,3 +76,32 @@ func formatValue(v any) string { return fmt.Sprintf("%v", v) } } + +// bodyTitle returns the notification title, falling back to the default. +func bodyTitle(body map[string]any) string { + if t, ok := body["title"].(string); ok && t != "" { + return t + } + return defaultTitle +} + +// bodyContent returns the notification body, rendering every entry with format +// (a "%s … %v" pair) and joining them with sep when no content field is given. +func bodyContent(body map[string]any, format, sep string) string { + if c, ok := body["content"].(string); ok && c != "" { + return c + } + parts := make([]string, 0, len(body)) + for k, v := range body { + parts = append(parts, fmt.Sprintf(format, k, v)) + } + return strings.Join(parts, sep) +} + +// bodyLevel returns the upper-cased notification level, falling back to INFO. +func bodyLevel(body map[string]any) string { + if l, ok := body["level"].(string); ok && l != "" { + return strings.ToUpper(l) + } + return levelInfo +}