84 lines
1.7 KiB
Go
84 lines
1.7 KiB
Go
package logic
|
|
|
|
import (
|
|
"context"
|
|
|
|
"spark-server/internal/module/square/entity"
|
|
)
|
|
|
|
type visCtx struct {
|
|
viewer int64
|
|
blocked map[int64]bool
|
|
audience map[int64][]int64
|
|
}
|
|
|
|
func (v *visCtx) canSee(p *entity.Post) bool {
|
|
if p == nil || p.Status != entity.StatusNormal || p.AuditStatus != entity.AuditApproved {
|
|
return false
|
|
}
|
|
if p.UserID != v.viewer && v.blocked[p.UserID] {
|
|
return false
|
|
}
|
|
return visibilityOK(p, v.viewer, v.audience[p.ID])
|
|
}
|
|
|
|
func visibilityOK(p *entity.Post, viewer int64, peers []int64) bool {
|
|
if p.UserID == viewer {
|
|
return true
|
|
}
|
|
switch p.Visibility {
|
|
case entity.VisibilityPublic:
|
|
return true
|
|
case entity.VisibilityPrivate:
|
|
return false
|
|
case entity.VisibilityInclude:
|
|
return containsID(peers, viewer)
|
|
case entity.VisibilityExclude:
|
|
return !containsID(peers, viewer)
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func containsID(ids []int64, want int64) bool {
|
|
for _, id := range ids {
|
|
if id == want {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (s *Service) visFor(ctx context.Context, viewer int64, posts []*entity.Post) (*visCtx, error) {
|
|
v := &visCtx{viewer: viewer, blocked: map[int64]bool{}, audience: map[int64][]int64{}}
|
|
seen := map[int64]struct{}{}
|
|
for _, p := range posts {
|
|
if p == nil || p.UserID == viewer {
|
|
continue
|
|
}
|
|
if _, ok := seen[p.UserID]; ok {
|
|
continue
|
|
}
|
|
seen[p.UserID] = struct{}{}
|
|
blocked, err := s.friends.BlockedEither(ctx, viewer, p.UserID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if blocked {
|
|
v.blocked[p.UserID] = true
|
|
}
|
|
}
|
|
needAud := make([]int64, 0)
|
|
for _, p := range posts {
|
|
if p != nil && p.Visibility.NeedsAudience() {
|
|
needAud = append(needAud, p.ID)
|
|
}
|
|
}
|
|
aud, err := s.repo.ListAudience(ctx, needAud)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
v.audience = aud
|
|
return v, nil
|
|
}
|