Files
larksuite-cli/shortcuts/im/convert_lib/text.go
梁硕 83dfb068ad feat: open-source lark-cli — the official CLI for Lark/Feishu
Change-Id: I113d9cdb5403cec347efe4595415e34a18b7decf
2026-03-28 10:36:25 +08:00

141 lines
3.1 KiB
Go

// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package convertlib
import (
"fmt"
"sort"
"strings"
)
type textConverter struct{}
func (textConverter) Convert(ctx *ConvertContext) string {
parsed, err := ParseJSONObject(ctx.RawContent)
if err != nil {
return invalidJSONPlaceholder("text")
}
text, _ := parsed["text"].(string)
if text == "" {
return ctx.RawContent
}
return ResolveMentionKeys(text, ctx.MentionMap)
}
type postConverter struct{}
func (postConverter) Convert(ctx *ConvertContext) string {
parsed, err := ParseJSONObject(ctx.RawContent)
if err != nil || parsed == nil {
return invalidJSONPlaceholder("rich text")
}
body := unwrapPostLocale(parsed)
if body == nil {
return "[Rich text message]"
}
var parts []string
if title, _ := body["title"].(string); title != "" {
parts = append(parts, title)
}
if blocks, _ := body["content"].([]interface{}); len(blocks) > 0 {
for _, para := range blocks {
elems, _ := para.([]interface{})
var line strings.Builder
for _, el := range elems {
elem, _ := el.(map[string]interface{})
line.WriteString(renderPostElem(elem))
}
parts = append(parts, line.String())
}
}
result := strings.TrimSpace(strings.Join(parts, "\n"))
if result == "" {
return "[Rich text message]"
}
return ResolveMentionKeys(result, ctx.MentionMap)
}
func unwrapPostLocale(parsed map[string]interface{}) map[string]interface{} {
if _, ok := parsed["content"]; ok {
return parsed
}
if _, ok := parsed["title"]; ok {
return parsed
}
for _, locale := range []string{"zh_cn", "en_us", "ja_jp"} {
if v, ok := parsed[locale]; ok {
if m, ok := v.(map[string]interface{}); ok {
return m
}
}
}
keys := make([]string, 0, len(parsed))
for key := range parsed {
keys = append(keys, key)
}
sort.Strings(keys)
for _, key := range keys {
v := parsed[key]
if m, ok := v.(map[string]interface{}); ok {
return m
}
}
return nil
}
func renderPostElem(el map[string]interface{}) string {
tag, _ := el["tag"].(string)
switch tag {
case "text":
text, _ := el["text"].(string)
return text
case "a":
text, _ := el["text"].(string)
href, _ := el["href"].(string)
if href != "" && text != "" {
return fmt.Sprintf("[%s](%s)", escapeMDLinkText(text), href)
}
if href != "" {
return href
}
return text
case "at":
userId, _ := el["user_id"].(string)
if userId == "@_all" || userId == "all" {
return "@all"
}
name, _ := el["user_name"].(string)
if name != "" {
return "@" + name
}
return "@" + userId
case "img":
key, _ := el["image_key"].(string)
if key != "" {
return fmt.Sprintf("[Image: %s]", key)
}
return "[Image]"
case "media":
key, _ := el["file_key"].(string)
if key != "" {
return fmt.Sprintf("[Media: %s]", key)
}
return "[Media]"
case "code_block":
lang, _ := el["language"].(string)
code, _ := el["text"].(string)
if lang != "" {
return fmt.Sprintf("\n```%s\n%s\n```\n", lang, code)
}
return fmt.Sprintf("\n```\n%s\n```\n", code)
case "hr":
return "\n---\n"
default:
text, _ := el["text"].(string)
return text
}
}