feat(posts): add post reference/internal linking functionality
Add support for referencing other posts within messages through a new post_ref segment type. Includes new PostReference model to track relationships, PostRefService for processing references, and new endpoints for post suggestions, related posts, and reference click tracking.
This commit is contained in:
@@ -250,8 +250,9 @@ const (
|
||||
SegmentTypeAt SegmentType = "at"
|
||||
SegmentTypeReply SegmentType = "reply"
|
||||
SegmentTypeFace SegmentType = "face"
|
||||
SegmentTypeLink SegmentType = "link"
|
||||
SegmentTypeVote SegmentType = "vote"
|
||||
SegmentTypeLink SegmentType = "link"
|
||||
SegmentTypeVote SegmentType = "vote"
|
||||
SegmentTypePostRef SegmentType = "post_ref"
|
||||
)
|
||||
|
||||
// TextSegmentData 文本数据
|
||||
@@ -325,6 +326,23 @@ type VoteOptionData struct {
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
// PostRefSegmentData 帖子内链Segment数据
|
||||
type PostRefSegmentData struct {
|
||||
PostID string `json:"post_id"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Author *UserResponse `json:"author,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Accessible bool `json:"accessible"`
|
||||
ClickCount int `json:"click_count,omitzero"`
|
||||
}
|
||||
|
||||
// PostRefBrief 帖子内链简要信息 (用于搜索联想)
|
||||
type PostRefBrief struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Channel string `json:"channel,omitempty"`
|
||||
}
|
||||
|
||||
// VoteSegmentData 投票Segment数据
|
||||
type VoteSegmentData struct {
|
||||
Options []VoteOptionData `json:"options"`
|
||||
|
||||
@@ -145,6 +145,17 @@ func NewLinkSegment(url, title, description, image string) model.MessageSegment
|
||||
}
|
||||
}
|
||||
|
||||
// NewPostRefSegment 创建帖子内链Segment
|
||||
func NewPostRefSegment(postID, title string) model.MessageSegment {
|
||||
return model.MessageSegment{
|
||||
Type: string(SegmentTypePostRef),
|
||||
Data: map[string]any{
|
||||
"post_id": postID,
|
||||
"title": title,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ExtractVoteSegmentData 从消息链中提取投票Segment数据
|
||||
func ExtractVoteSegmentData(segments model.MessageSegments) *VoteSegmentData {
|
||||
for _, segment := range segments {
|
||||
@@ -227,6 +238,12 @@ func ExtractTextContentFromModel(segments model.MessageSegments) string {
|
||||
}
|
||||
case "vote":
|
||||
result += "[投票]"
|
||||
case "post_ref":
|
||||
if title, ok := segment.Data["title"].(string); ok && title != "" {
|
||||
result += fmt.Sprintf("[帖子:%s]", title)
|
||||
} else {
|
||||
result += "[帖子引用]"
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
@@ -256,6 +273,28 @@ func ExtractMentionedUsers(segments model.MessageSegments) []string {
|
||||
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
|
||||
}
|
||||
|
||||
// HasPostRefSegment 检查消息链中是否包含帖子引用
|
||||
func HasPostRefSegment(segments model.MessageSegments) bool {
|
||||
return HasSegmentType(segments, SegmentTypePostRef)
|
||||
}
|
||||
|
||||
// IsAtAll 检查消息是否@了所有人
|
||||
func IsAtAll(segments model.MessageSegments) bool {
|
||||
return slices.ContainsFunc(segments, func(segment model.MessageSegment) bool {
|
||||
|
||||
Reference in New Issue
Block a user