125 lines
3.3 KiB
Go
125 lines
3.3 KiB
Go
package logic
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"spark-server/internal/module/square/entity"
|
|
"spark-server/internal/pkg/errs"
|
|
)
|
|
|
|
type NoticeView struct {
|
|
ID int64 `json:"id"`
|
|
Kind entity.NoticeKind `json:"kind"`
|
|
From UserCard `json:"from"`
|
|
PostID int64 `json:"post_id"`
|
|
CommentID int64 `json:"comment_id,omitempty"`
|
|
Read bool `json:"read"`
|
|
CreatedAt int64 `json:"created_at"`
|
|
}
|
|
|
|
type NoticeList struct {
|
|
Items []*NoticeView `json:"items"`
|
|
NextCursor int64 `json:"next_cursor"`
|
|
}
|
|
|
|
type NoticeUnread struct {
|
|
HasNew bool `json:"has_new"`
|
|
LatestID int64 `json:"latest_id"`
|
|
}
|
|
|
|
type NoticeReadInput struct {
|
|
Cursor int64 `json:"cursor" validate:"omitempty,gte=0" label:"field.square_notice_cursor"`
|
|
}
|
|
|
|
func (s *Service) ListNotices(ctx context.Context, userID, cursor int64, limit int) (*NoticeList, error) {
|
|
if !s.ready() || userID <= 0 {
|
|
return nil, errs.ErrUnauthorized
|
|
}
|
|
limit = entity.ClampLimit(limit)
|
|
rows, err := s.repo.ListNotices(ctx, userID, cursor, limit)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
uids := make([]int64, 0, len(rows))
|
|
for _, n := range rows {
|
|
uids = append(uids, n.FromUserID)
|
|
}
|
|
users := s.loadUsers(ctx, uids)
|
|
remarks := s.loadRemarks(ctx, userID, uids)
|
|
items := make([]*NoticeView, 0, len(rows))
|
|
next := int64(0)
|
|
for _, n := range rows {
|
|
items = append(items, &NoticeView{
|
|
ID: n.ID, Kind: n.Kind, From: cardOf(users[n.FromUserID], remarks[n.FromUserID]),
|
|
PostID: n.PostID, CommentID: n.CommentID, Read: n.ReadAtMS > 0, CreatedAt: n.CreatedAtMS,
|
|
})
|
|
next = n.ID
|
|
}
|
|
return &NoticeList{Items: items, NextCursor: next}, nil
|
|
}
|
|
|
|
func (s *Service) ReadNotices(ctx context.Context, userID int64, in *NoticeReadInput) error {
|
|
if !s.ready() || userID <= 0 {
|
|
return errs.ErrUnauthorized
|
|
}
|
|
cursor := int64(0)
|
|
if in != nil {
|
|
cursor = in.Cursor
|
|
}
|
|
if err := s.repo.MarkNoticesRead(ctx, userID, cursor); err != nil {
|
|
return err
|
|
}
|
|
if cursor > 0 {
|
|
return s.repo.AdvanceNoticeRead(ctx, userID, cursor)
|
|
}
|
|
latest, err := s.repo.LatestNoticeID(ctx, userID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if latest > 0 {
|
|
return s.repo.AdvanceNoticeRead(ctx, userID, latest)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) NoticeUnread(ctx context.Context, userID int64) (*NoticeUnread, error) {
|
|
if !s.ready() || userID <= 0 {
|
|
return nil, errs.ErrUnauthorized
|
|
}
|
|
st, err := s.repo.GetNoticeState(ctx, userID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
latest, err := s.repo.LatestNoticeID(ctx, userID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &NoticeUnread{HasNew: latest > st.LastReadNoticeID, LatestID: latest}, nil
|
|
}
|
|
|
|
func (s *Service) notify(ctx context.Context, rows []*entity.Notice) error {
|
|
out := make([]*entity.Notice, 0, len(rows))
|
|
now := time.Now().UnixMilli()
|
|
for _, n := range rows {
|
|
if n == nil || n.ToUserID <= 0 || n.ToUserID == n.FromUserID {
|
|
continue
|
|
}
|
|
id, err := s.ids.NextID()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
n.ID = id
|
|
n.CreatedAtMS = now
|
|
out = append(out, n)
|
|
}
|
|
return s.repo.CreateNotices(ctx, out)
|
|
}
|
|
|
|
func (s *Service) newNotice(to, from int64, kind entity.NoticeKind, postID, commentID int64) *entity.Notice {
|
|
if to <= 0 || to == from {
|
|
return nil
|
|
}
|
|
return &entity.Notice{ToUserID: to, FromUserID: from, Kind: kind, PostID: postID, CommentID: commentID}
|
|
}
|