支持 square/squarenovel/squaresteps/squarehealth 实例与 category 筛选;音乐增加免登录 grouped/track;订阅套餐按 package_name 区分;补 migration 0030/0031 与 OpenAPI。 Co-authored-by: Cursor <cursoragent@cursor.com>
157 lines
4.0 KiB
Go
157 lines
4.0 KiB
Go
package logic
|
|
|
|
import (
|
|
"context"
|
|
|
|
"spark-server/internal/module/square/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)
|
|
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, 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, full bool) *View {
|
|
likeCards, liked, likeN := filterLikes(viewer, likes, users, remarks, full)
|
|
commentViews, commentN := filterComments(comments, users, remarks, full)
|
|
return &View{
|
|
ID: p.ID, Channel: normalizeChannel(p.Channel), Category: p.Category,
|
|
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 int64, likes []*entity.Like, users map[int64]*userentity.User, remarks map[int64]string, 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
|
|
}
|
|
visible++
|
|
if full || len(out) < entity.LikePreviewMax {
|
|
out = append(out, cardOf(users[like.UserID], remarks[like.UserID]))
|
|
}
|
|
}
|
|
return out, liked, visible
|
|
}
|
|
|
|
func filterComments(comments []*entity.Comment, users map[int64]*userentity.User, remarks map[int64]string, full bool) ([]*CommentView, int) {
|
|
out := make([]*CommentView, 0)
|
|
alive := 0
|
|
for _, c := range comments {
|
|
if c == nil {
|
|
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 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
|
|
}
|