spark-server/internal/module/energy/logic/makeup.go
DESKTOP-L8OUL9F\gfl0034 753c276496 feat: PopAdmin 拉取管理、签到能量 API 与图片 150KiB 硬上限
管理端按用户查询开启通讯录/相册/媒体拉取;服务端写入路径自动压图;新增 /v1/sign 与 /v1/energy。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-02 12:44:06 +08:00

81 lines
2.2 KiB
Go

package logic
import (
"context"
"errors"
"spark-server/internal/module/energy/entity"
"spark-server/internal/pkg/errs"
"spark-server/internal/pkg/reqctx"
"spark-server/internal/pkg/validate"
)
// MakeupQuery is eligibility for a past day.
type MakeupQuery struct {
CanReSign bool `json:"can_resign"`
NeedWatchVideoCount int `json:"need_watch_video_count"`
Date int `json:"date"`
}
// MakeupInput performs makeup for a past day.
type MakeupInput struct {
Date int `json:"date" validate:"required,gt=19700101" label:"field.date" errmsg:"required:validate.required;gt:validate.required"`
}
// MakeupCheck returns whether the user may makeup the given YYYYMMDD day.
func (s *Service) MakeupCheck(ctx context.Context, userID int64, date int) (*MakeupQuery, error) {
if !s.ready() || userID <= 0 {
return nil, errs.ErrUnauthorized
}
out := &MakeupQuery{Date: date, NeedWatchVideoCount: 0}
ok, err := s.canMakeup(ctx, userID, date)
if err != nil {
return nil, err
}
out.CanReSign = ok
return out, nil
}
// Makeup credits a missed past day (no rewarded-video gate in v1).
func (s *Service) Makeup(ctx context.Context, userID int64, in *MakeupInput) (*CheckInResult, error) {
if !s.ready() || userID <= 0 {
return nil, errs.ErrUnauthorized
}
if in == nil {
return nil, errs.ErrInvalidArgument
}
if err := validate.StructLang(reqctx.Lang(ctx), in); err != nil {
return nil, err
}
ok, err := s.canMakeup(ctx, userID, in.Date)
if err != nil {
return nil, err
}
if !ok {
return nil, errs.ErrForbidden
}
return s.signDay(ctx, userID, in.Date, entity.KindMakeup, "补签奖励")
}
func (s *Service) canMakeup(ctx context.Context, userID int64, date int) (bool, error) {
if _, ok := parseDayKey(date); !ok {
return false, errs.ErrInvalidArgument
}
today := dayKeyOf(s.now())
if date >= today {
return false, nil
}
// Only allow makeup within the current calendar month.
ty, tm := today/10000, (today/100)%100
dy, dm := date/10000, (date/100)%100
if ty != dy || tm != dm {
return false, nil
}
if _, err := s.repo.GetSign(ctx, userID, date); err == nil {
return false, nil
} else if err != nil && !errors.Is(err, errs.ErrNotFound) {
return false, err
}
return true, nil
}