From 376d0d98187f560bdee3e8cb3dbfe063b6a2666f Mon Sep 17 00:00:00 2001 From: Rogee Date: Fri, 14 Aug 2026 01:18:36 +0800 Subject: [PATCH] H-77: report missing Shangwutong source fields (#15) Co-authored-by: Rogee --- .../shangwutong/internal/delivery/mapping.go | 30 ++++++++++---- .../internal/delivery/mapping_test.go | 39 +++++++++++++++++++ 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/channels/shangwutong/internal/delivery/mapping.go b/channels/shangwutong/internal/delivery/mapping.go index 56f3ce10..0c63bce8 100644 --- a/channels/shangwutong/internal/delivery/mapping.go +++ b/channels/shangwutong/internal/delivery/mapping.go @@ -646,14 +646,26 @@ func parseSource(text string) map[string]any { } func sourceActivityContent(attributes map[string]any) string { - if len(attributes) == 0 { - return "" - } lines := []string{"访客来源信息"} + missing := make([]string, 0) fields := []struct { key string label string }{ + {"", "永久身份"}, + {"", "临时身份"}, + {"", "初次访问页面"}, + {"", "当前访问页面"}, + {"", "重复百度智能咨询页区块"}, + {"", "页面标题"}, + {"", "会话前点击内容"}, + {"", "初次访问时间"}, + {"", "上次访问时间"}, + {"", "访问次数"}, + {"", "访问页数"}, + {"", "IP 说明"}, + {"", "浏览器名称"}, + {"", "浏览器版本"}, {"swt_source_search_term", "搜索词"}, {"swt_source_purchase_term", "购买词"}, {"swt_source_keyword_id", "关键词 ID"}, @@ -668,12 +680,16 @@ func sourceActivityContent(attributes map[string]any) string { {"swt_source_url", "来源页面"}, } for _, field := range fields { - if value, ok := attributes[field.key].(string); ok && strings.TrimSpace(value) != "" { - lines = append(lines, field.label+":"+strings.TrimSpace(value)) + value, _ := attributes[field.key].(string) + value = strings.TrimSpace(value) + if field.key != "" && value != "" && value != "0" && !strings.EqualFold(value, "null") { + lines = append(lines, field.label+":"+value) + continue } + missing = append(missing, field.label) } - if len(lines) == 1 { - return "" + if len(missing) > 0 { + lines = append(lines, "以下字段商务通未提供或当前暂不支持:"+strings.Join(missing, "、")) } return strings.Join(lines, "
") } diff --git a/channels/shangwutong/internal/delivery/mapping_test.go b/channels/shangwutong/internal/delivery/mapping_test.go index 40c800f9..215a116a 100644 --- a/channels/shangwutong/internal/delivery/mapping_test.go +++ b/channels/shangwutong/internal/delivery/mapping_test.go @@ -160,6 +160,45 @@ func TestKind8ParsesLatestWakeableState(t *testing.T) { } } +func TestKind8ReportsMissingSourceFields(t *testing.T) { + t.Run("all missing", func(t *testing.T) { + mapped := mapInboundEvent(8, 44, "", "", "", "source", 10, time.Now()) + if mapped.Message == nil || mapped.Message.MessageType != "activity" { + t.Fatalf("missing source activity = %#v", mapped) + } + for _, field := range []string{"永久身份", "临时身份", "来源页面", "浏览器版本"} { + if !strings.Contains(mapped.Message.Content, field) { + t.Fatalf("missing field %q not reported: %q", field, mapped.Message.Content) + } + } + }) + + t.Run("partial", func(t *testing.T) { + content := sourceActivityContent(map[string]any{ + "swt_source_search_term": "种植牙", + "swt_source_url": "https://example.test/很长的中文路径?word=种植牙", + "swt_source_region": "null", + "swt_source_keyword_id": "0", + }) + parts := strings.Split(content, "以下字段商务通未提供或当前暂不支持:") + if len(parts) != 2 || !strings.Contains(parts[0], "搜索词:种植牙") || !strings.Contains(parts[0], "来源页面:https://example.test/很长的中文路径?word=种植牙") { + t.Fatalf("provided source fields lost: %q", content) + } + if strings.Contains(parts[1], "搜索词") || strings.Contains(parts[1], "来源页面") || !strings.Contains(parts[1], "地域") || strings.Contains(content, "地域:null") || strings.Contains(content, "关键词 ID:0") { + t.Fatalf("partial missing fields = %q", content) + } + }) + + t.Run("repeated blocks use one notice", func(t *testing.T) { + text := "https%3A%2F%2Fexample.test%2F%E4%B8%AD%E6%96%87+%3Cdiv%3E%E6%90%9C%E7%B4%A2%E8%AF%8D%EF%BC%9Afirst%3C%2Fdiv%3E" + + "%3Cdiv%3E%E6%90%9C%E7%B4%A2%E8%AF%8D%EF%BC%9Asecond%3C%2Fdiv%3E" + mapped := mapInboundEvent(8, 45, text, "", "", "source", 10, time.Now()) + if mapped.Message == nil || strings.Count(mapped.Message.Content, "商务通未提供或当前暂不支持") != 1 || !strings.Contains(mapped.Message.Content, "搜索词:first") || !strings.Contains(mapped.Message.Content, "来源页面:https://example.test/%E4%B8%AD%E6%96%87") { + t.Fatalf("repeated source activity = %#v", mapped.Message) + } + }) +} + func TestVisitorProfileMapsContactNameAndAttributes(t *testing.T) { environment := mapInboundEvent(7, 1, "220.197.4.178 %e8%b4%b5%e5%b7%9e%e8%b4%b5%e9%98%b3 5.6 1 1 393x798 zh-CN iPhone iPhone%3b+CPU+iPhone+OS+18_7+like+Mac+OS+X ", "", "", "source", 10, time.Now()) if environment.ContactName != "" {