spark-server/internal/module/square/logic/view.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

111 lines
2.9 KiB
Go

package logic
import (
"context"
"encoding/json"
"spark-server/internal/module/square/entity"
userentity "spark-server/internal/module/user/entity"
"spark-server/internal/pkg/errs"
)
type UserCard struct {
UID int64 `json:"uid"`
SparkID string `json:"spark_id"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
Remark string `json:"remark"`
}
type CommentView struct {
ID int64 `json:"id"`
User UserCard `json:"user"`
ReplyToID int64 `json:"reply_to_id,omitempty"`
ReplyToUID int64 `json:"reply_to_uid,omitempty"`
Text string `json:"text"`
Deleted bool `json:"deleted,omitempty"`
CreatedAt int64 `json:"created_at"`
}
type View struct {
ID int64 `json:"id"`
Channel entity.Channel `json:"channel"`
Category entity.Category `json:"category,omitempty"`
User UserCard `json:"user"`
Kind entity.Kind `json:"kind"`
Text string `json:"text"`
Content json.RawMessage `json:"content"`
POI *entity.POI `json:"poi,omitempty"`
Visibility entity.Visibility `json:"visibility"`
LikeCount int `json:"like_count"`
CommentCount int `json:"comment_count"`
Liked bool `json:"liked"`
Likes []UserCard `json:"likes"`
Comments []*CommentView `json:"comments"`
CreatedAt int64 `json:"created_at"`
}
type ListResult struct {
Items []*View `json:"items"`
NextCursor int64 `json:"next_cursor"`
HasMore bool `json:"has_more"`
}
func (s *Service) Get(ctx context.Context, viewerID, postID int64, channel entity.Channel) (*View, error) {
if !s.ready() || viewerID <= 0 {
return nil, errs.ErrUnauthorized
}
if postID <= 0 {
return nil, errs.ErrInvalidArgument
}
channel = normalizeChannel(channel)
post, err := s.repo.GetPost(ctx, postID)
if err != nil {
return nil, err
}
if normalizeChannel(post.Channel) != channel {
return nil, errs.ErrNotFound
}
vis, err := s.visFor(ctx, viewerID, []*entity.Post{post})
if err != nil {
return nil, err
}
if !vis.canSee(post) {
return nil, errs.ErrNotFound
}
return s.viewOf(ctx, viewerID, post, true)
}
func (s *Service) viewOf(ctx context.Context, viewer int64, post *entity.Post, full bool) (*View, error) {
views, err := s.attachViews(ctx, viewer, []*entity.Post{post}, full)
if err != nil {
return nil, err
}
if len(views) == 0 {
return nil, errs.ErrNotFound
}
return views[0], nil
}
func cardOf(u *userentity.User, remark string) UserCard {
if u == nil {
return UserCard{Remark: remark}
}
return UserCard{UID: u.ID, SparkID: u.SparkID, Nickname: u.Nickname, Avatar: u.Avatar, Remark: remark}
}
func poiPtr(p entity.POI) *entity.POI {
if !p.Set() {
return nil
}
cp := p
return &cp
}
func contentJSON(raw []byte) json.RawMessage {
if len(raw) == 0 {
return json.RawMessage(`{}`)
}
return json.RawMessage(raw)
}