mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-05-17 22:54:50 +08:00
feishu inbound: convert post JSON to markdown and surface media keys as attachments
This commit is contained in:
@@ -191,7 +191,7 @@ func (c *FeishuChannel) handleMessageReceive(_ context.Context, event *larkim.P2
|
|||||||
senderID = "unknown"
|
senderID = "unknown"
|
||||||
}
|
}
|
||||||
|
|
||||||
content := extractFeishuMessageContent(message)
|
content, mediaPaths := extractFeishuMessageContent(message)
|
||||||
if content == "" {
|
if content == "" {
|
||||||
content = "[empty message]"
|
content = "[empty message]"
|
||||||
}
|
}
|
||||||
@@ -223,7 +223,7 @@ func (c *FeishuChannel) handleMessageReceive(_ context.Context, event *larkim.P2
|
|||||||
logger.FieldPreview: truncateString(content, 80),
|
logger.FieldPreview: truncateString(content, 80),
|
||||||
})
|
})
|
||||||
|
|
||||||
c.HandleMessage(senderID, chatID, content, nil, metadata)
|
c.HandleMessage(senderID, chatID, content, mediaPaths, metadata)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -830,21 +830,100 @@ func extractFeishuSenderID(sender *larkim.EventSender) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractFeishuMessageContent(message *larkim.EventMessage) string {
|
func extractFeishuMessageContent(message *larkim.EventMessage) (string, []string) {
|
||||||
if message == nil || message.Content == nil || *message.Content == "" {
|
if message == nil || message.Content == nil || *message.Content == "" {
|
||||||
return ""
|
return "", nil
|
||||||
|
}
|
||||||
|
raw := strings.TrimSpace(*message.Content)
|
||||||
|
msgType := ""
|
||||||
|
if message.MessageType != nil {
|
||||||
|
msgType = strings.ToLower(strings.TrimSpace(*message.MessageType))
|
||||||
}
|
}
|
||||||
|
|
||||||
if message.MessageType != nil && *message.MessageType == larkim.MsgTypeText {
|
switch msgType {
|
||||||
var textPayload struct {
|
case strings.ToLower(string(larkim.MsgTypeText)):
|
||||||
Text string `json:"text"`
|
var textPayload struct { Text string `json:"text"` }
|
||||||
|
if err := json.Unmarshal([]byte(raw), &textPayload); err == nil {
|
||||||
|
return textPayload.Text, nil
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal([]byte(*message.Content), &textPayload); err == nil {
|
case strings.ToLower(string(larkim.MsgTypePost)):
|
||||||
return textPayload.Text
|
md, media := parseFeishuPostToMarkdown(raw)
|
||||||
|
if strings.TrimSpace(md) != "" || len(media) > 0 {
|
||||||
|
return md, media
|
||||||
|
}
|
||||||
|
case strings.ToLower(string(larkim.MsgTypeImage)):
|
||||||
|
var img struct { ImageKey string `json:"image_key"` }
|
||||||
|
if err := json.Unmarshal([]byte(raw), &img); err == nil && strings.TrimSpace(img.ImageKey) != "" {
|
||||||
|
return "[image]", []string{"feishu:image:" + img.ImageKey}
|
||||||
|
}
|
||||||
|
case strings.ToLower(string(larkim.MsgTypeFile)):
|
||||||
|
var f struct { FileKey string `json:"file_key"`; FileName string `json:"file_name"` }
|
||||||
|
if err := json.Unmarshal([]byte(raw), &f); err == nil && strings.TrimSpace(f.FileKey) != "" {
|
||||||
|
name := strings.TrimSpace(f.FileName)
|
||||||
|
if name == "" { name = f.FileKey }
|
||||||
|
return "[file] " + name, []string{"feishu:file:" + f.FileKey}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return *message.Content
|
return raw, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseFeishuPostToMarkdown(raw string) (string, []string) {
|
||||||
|
var obj map[string]interface{}
|
||||||
|
if err := json.Unmarshal([]byte(raw), &obj); err != nil {
|
||||||
|
return raw, nil
|
||||||
|
}
|
||||||
|
lang, _ := obj["zh_cn"].(map[string]interface{})
|
||||||
|
if lang == nil {
|
||||||
|
for _, v := range obj {
|
||||||
|
if m, ok := v.(map[string]interface{}); ok { lang = m; break }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if lang == nil {
|
||||||
|
return raw, nil
|
||||||
|
}
|
||||||
|
lines := make([]string, 0, 32)
|
||||||
|
media := make([]string, 0, 8)
|
||||||
|
if title, _ := lang["title"].(string); strings.TrimSpace(title) != "" {
|
||||||
|
lines = append(lines, "# "+strings.TrimSpace(title))
|
||||||
|
}
|
||||||
|
rows, _ := lang["content"].([]interface{})
|
||||||
|
for _, row := range rows {
|
||||||
|
elems, _ := row.([]interface{})
|
||||||
|
if len(elems) == 0 { lines = append(lines, ""); continue }
|
||||||
|
line := ""
|
||||||
|
for _, ev := range elems {
|
||||||
|
em, _ := ev.(map[string]interface{})
|
||||||
|
if em == nil { continue }
|
||||||
|
tag := strings.ToLower(strings.TrimSpace(fmt.Sprintf("%v", em["tag"])))
|
||||||
|
switch tag {
|
||||||
|
case "text":
|
||||||
|
line += fmt.Sprintf("%v", em["text"])
|
||||||
|
case "a":
|
||||||
|
line += fmt.Sprintf("[%v](%v)", em["text"], em["href"])
|
||||||
|
case "at":
|
||||||
|
uid := strings.TrimSpace(fmt.Sprintf("%v", em["user_id"]))
|
||||||
|
if uid == "" { uid = strings.TrimSpace(fmt.Sprintf("%v", em["open_id"])) }
|
||||||
|
line += "@" + uid
|
||||||
|
case "img":
|
||||||
|
k := strings.TrimSpace(fmt.Sprintf("%v", em["image_key"]))
|
||||||
|
if k != "" { media = append(media, "feishu:image:"+k); line += " " }
|
||||||
|
case "code_block":
|
||||||
|
lang := strings.TrimSpace(fmt.Sprintf("%v", em["language"]))
|
||||||
|
code := fmt.Sprintf("%v", em["text"])
|
||||||
|
if line != "" {
|
||||||
|
lines = append(lines, strings.TrimSpace(line))
|
||||||
|
line = ""
|
||||||
|
}
|
||||||
|
lines = append(lines, "```"+lang+"\n"+code+"\n```")
|
||||||
|
case "hr":
|
||||||
|
if line != "" { lines = append(lines, strings.TrimSpace(line)); line = "" }
|
||||||
|
lines = append(lines, "---")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(line) != "" { lines = append(lines, strings.TrimSpace(line)) }
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(strings.Join(lines, "\n")), media
|
||||||
}
|
}
|
||||||
|
|
||||||
func stringValue(v *string) string {
|
func stringValue(v *string) string {
|
||||||
|
|||||||
Reference in New Issue
Block a user