spark-server/internal/module/moment/logic/attach.go
2026-09-18 17:51:42 +08:00

171 lines
4.5 KiB
Go

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
}