spark-server/internal/module/square/logic/attach.go
DESKTOP-L8OUL9F\gfl0034 53426af122 feat: 多广场 channel、音乐公开 API 与订阅 package_name
支持 square/squarenovel/squaresteps/squarehealth 实例与 category 筛选;音乐增加免登录 grouped/track;订阅套餐按 package_name 区分;补 migration 0030/0031 与 OpenAPI。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-30 09:02:28 +08:00

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
}