package logic import ( "context" "spark-server/internal/module/moment/entity" userentity "spark-server/internal/module/user/entity" ) func (s *Service) attachViews(ctx context.Context, viewer int64, posts []*entity.Post, full bool) ([]*View, error) { if len(posts) == 0 { return []*View{}, nil } ids := postIDs(posts) likes, err := s.repo.ListLikes(ctx, ids) if err != nil { return nil, err } comments, err := s.repo.ListComments(ctx, ids) if err != nil { return nil, err } uids := collectUIDs(posts, likes, comments, viewer) users := s.loadUsers(ctx, uids) remarks := s.loadRemarks(ctx, viewer, uids) friendIDs, err := s.friends.ListFriendIDs(ctx, viewer) if err != nil { return nil, err } friends := idSet(friendIDs) out := make([]*View, 0, len(posts)) for _, p := range posts { out = append(out, s.oneView(viewer, p, likes[p.ID], comments[p.ID], users, remarks, friends, full)) } return out, nil } func (s *Service) oneView(viewer int64, p *entity.Post, likes []*entity.Like, comments []*entity.Comment, users map[int64]*userentity.User, remarks map[int64]string, friends map[int64]bool, full bool) *View { likeCards, liked, likeN := filterLikes(viewer, p.UserID, likes, users, remarks, friends, full) commentViews, commentN := filterComments(viewer, p.UserID, comments, users, remarks, friends, full) return &View{ ID: p.ID, User: cardOf(users[p.UserID], remarks[p.UserID]), Kind: p.Kind, Text: p.Text, Content: contentJSON(p.Content), POI: poiPtr(p.POI), Visibility: p.Visibility, LikeCount: likeN, CommentCount: commentN, Liked: liked, Likes: likeCards, Comments: commentViews, CreatedAt: p.CreatedAtMS, } } func filterLikes(viewer, author int64, likes []*entity.Like, users map[int64]*userentity.User, remarks map[int64]string, friends map[int64]bool, full bool) ([]UserCard, bool, int) { out := make([]UserCard, 0) liked := false visible := 0 for _, like := range likes { if like == nil { continue } if like.UserID == viewer { liked = true } if !seeInteract(viewer, author, like.UserID, friends) { continue } visible++ if full || len(out) < entity.LikePreviewMax { out = append(out, cardOf(users[like.UserID], remarks[like.UserID])) } } return out, liked, visible } func filterComments(viewer, author int64, comments []*entity.Comment, users map[int64]*userentity.User, remarks map[int64]string, friends map[int64]bool, full bool) ([]*CommentView, int) { out := make([]*CommentView, 0) alive := 0 for _, c := range comments { if c == nil || !seeInteract(viewer, author, c.UserID, friends) { continue } cv := &CommentView{ ID: c.ID, User: cardOf(users[c.UserID], remarks[c.UserID]), ReplyToID: c.ReplyToID, ReplyToUID: c.ReplyToUID, Text: c.Text, CreatedAt: c.CreatedAtMS, } if c.Status == entity.StatusDeleted { cv.Deleted = true cv.Text = "" } else { alive++ } if full || len(out) < entity.CommentPreviewMax { out = append(out, cv) } } return out, alive } func seeInteract(viewer, author, actor int64, friends map[int64]bool) bool { if viewer == author || actor == viewer { return true } return friends[actor] } func postIDs(posts []*entity.Post) []int64 { out := make([]int64, 0, len(posts)) for _, p := range posts { if p != nil { out = append(out, p.ID) } } return out } func collectUIDs(posts []*entity.Post, likes map[int64][]*entity.Like, comments map[int64][]*entity.Comment, viewer int64) []int64 { seen := map[int64]struct{}{viewer: {}} add := func(id int64) { if id > 0 { seen[id] = struct{}{} } } for _, p := range posts { if p != nil { add(p.UserID) } } for _, rows := range likes { for _, like := range rows { if like != nil { add(like.UserID) } } } for _, rows := range comments { for _, c := range rows { if c != nil { add(c.UserID) } } } out := make([]int64, 0, len(seen)) for id := range seen { out = append(out, id) } return out } func (s *Service) loadUsers(ctx context.Context, ids []int64) map[int64]*userentity.User { out := make(map[int64]*userentity.User, len(ids)) for _, id := range ids { u, err := s.users.Get(ctx, id) if err != nil { continue } out[id] = u } return out } func (s *Service) loadRemarks(ctx context.Context, viewer int64, ids []int64) map[int64]string { out := make(map[int64]string) for _, id := range ids { if id == viewer { continue } rel, err := s.friends.Relation(ctx, viewer, id) if err != nil || rel == nil { continue } out[id] = rel.Remark } return out }