package dto import ( "encoding/json" "fmt" "slices" "with_you/internal/model" ) // NewTextSegment 创建文本Segment func NewTextSegment(content string) model.MessageSegment { return model.MessageSegment{ Type: string(SegmentTypeText), Data: map[string]any{"text": content}, } } // ExtractVoteSegmentData 从消息链中提取投票Segment数据 func ExtractVoteSegmentData(segments model.MessageSegments) *VoteSegmentData { for _, segment := range segments { if segment.Type == string(SegmentTypeVote) { dataBytes, err := json.Marshal(segment.Data) if err != nil { continue } var voteData VoteSegmentData if err := json.Unmarshal(dataBytes, &voteData); err != nil { continue } return &voteData } } return nil } // HasVoteSegment 检查消息链中是否包含投票Segment func HasVoteSegment(segments model.MessageSegments) bool { return HasSegmentType(segments, SegmentTypeVote) } // ExtractTextContentFromModel 从 model.MessageSegments 中提取纯文本内容 func ExtractTextContentFromModel(segments model.MessageSegments) string { var result string for _, segment := range segments { switch segment.Type { case "text": if text, ok := segment.Data["text"].(string); ok { result += text } case "at": userID, _ := segment.Data["user_id"].(string) if userID == "all" { result += "@所有人 " } else if userID != "" { // 昵称由前端实时解析,后端文本提取仅用于推送通知兜底 result += "@某人 " } case "image": result += "[图片]" case "voice": result += "[语音]" case "video": result += "[视频]" case "file": if name, ok := segment.Data["name"].(string); ok && name != "" { result += fmt.Sprintf("[文件:%s]", name) } else { result += "[文件]" } case "face": if name, ok := segment.Data["name"].(string); ok && name != "" { result += fmt.Sprintf("[%s]", name) } else { result += "[表情]" } case "link": if title, ok := segment.Data["title"].(string); ok && title != "" { result += fmt.Sprintf("[链接:%s]", title) } else { result += "[链接]" } case "vote": result += "[投票]" case "post_ref": if title, ok := segment.Data["title"].(string); ok && title != "" { result += fmt.Sprintf("[帖子:%s]", title) } else { result += "[帖子引用]" } } } return result } // ExtractTextContent 从消息链中提取纯文本内容 // 用于搜索、通知展示等场景 func ExtractTextContent(segments model.MessageSegments) string { return ExtractTextContentFromModel(segments) } // ExtractMentionedUsers 从消息链中提取被@的用户ID列表 // 不包括 "all"(@所有人) func ExtractMentionedUsers(segments model.MessageSegments) []string { var userIDs []string seen := make(map[string]bool) for _, segment := range segments { if segment.Type == string(SegmentTypeAt) { userID, _ := segment.Data["user_id"].(string) if userID != "all" && userID != "" && !seen[userID] { userIDs = append(userIDs, userID) seen[userID] = true } } } return userIDs } // ExtractReferencedPosts 从消息链中提取所有被引用的帖子ID func ExtractReferencedPosts(segments model.MessageSegments) []string { var postIDs []string seen := make(map[string]bool) for _, segment := range segments { if segment.Type == string(SegmentTypePostRef) { postID, _ := segment.Data["post_id"].(string) if postID != "" && !seen[postID] { postIDs = append(postIDs, postID) seen[postID] = true } } } return postIDs } // HasSegmentType 检查消息链中是否包含指定类型的segment func HasSegmentType(segments model.MessageSegments, segmentType SegmentType) bool { return slices.ContainsFunc(segments, func(segment model.MessageSegment) bool { return segment.Type == string(segmentType) }) }