171 lines
4.5 KiB
Go
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
|
|
}
|