Files
novatask/internal/svc/service_context.go
2025-04-03 16:17:20 +08:00

219 lines
6.7 KiB
Go

package svc
import (
"context"
"errors"
"fmt"
ea "github.com/earn-alliance/earnalliance-go"
"github.com/shopspring/decimal"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/rest"
"nova_task/internal/config"
"nova_task/internal/consts"
"nova_task/internal/middleware"
"nova_task/internal/model"
"nova_task/internal/pkg/errs"
"nova_task/internal/types"
"time"
)
type ServiceContext struct {
Config config.Config
*dbModel
ApiKeyCheck rest.Middleware
AdminSecretCheck rest.Middleware
Game7ApiKeyCheck rest.Middleware
KGeNApiKeyCheck rest.Middleware
Earn *ea.Client
DBConn sqlx.SqlConn
Redis *redis.Redis
}
func NewServiceContext(c config.Config) *ServiceContext {
dbConn := c.MySql.Conn()
gameConn := c.GameDB.Conn()
configModel := model.NewNhSystemConfigModel(dbConn, c.Cache)
return &ServiceContext{
Config: c,
dbModel: newDBModel(dbConn, gameConn, configModel),
ApiKeyCheck: middleware.NewApiKeyCheckMiddleware(configModel).Handle,
AdminSecretCheck: middleware.NewAdminSecretCheckMiddleware(configModel).Handle,
Game7ApiKeyCheck: middleware.NewGame7ApiKeyCheckMiddleware(configModel).Handle,
KGeNApiKeyCheck: middleware.NewKGeNApiKeyCheckMiddleware(configModel).Handle,
DBConn: dbConn,
Earn: c.Earn.BuildEarnClient(),
Redis: redis.MustNewRedis(c.Redis),
}
}
func (s *ServiceContext) Close() {
err := s.Earn.Flush()
if err != nil {
logx.Errorw("flush earn error", logx.Field("err", err))
}
s.Earn.Close()
}
func (s *ServiceContext) IsAmbassador(ctx context.Context, uid uint, stage int8) bool {
u, err := s.UserModel.FindOne(ctx, uid)
if err != nil {
if !errors.Is(err, model.ErrNotFound) {
logx.Errorw("find user error", logx.Field("err", err), logx.Field("uid", uid), logx.Field("stage", stage))
}
return false
}
_, err = s.AmbassadorModel.FindOneByEmailStage(ctx, u.Email, stage)
if err != nil {
if !errors.Is(err, model.ErrNotFound) {
logx.Errorw("find ambassador error", logx.Field("err", err), logx.Field("uid", uid), logx.Field("stage", stage))
}
return false
}
return true
}
func (s *ServiceContext) HasBindTwitter(ctx context.Context, uid uint) bool {
tw, err := s.TwitterModel.FindOneByUid(ctx, uid)
if err != nil {
if !errors.Is(err, model.ErrNotFound) {
logx.Errorw("find twitter error", logx.Field("err", err), logx.Field("uid", uid))
}
return false
}
return tw.TwitterId != ""
}
func (s *ServiceContext) GetUidByEmail(ctx context.Context, email string) (uint, *types.CarvResult) {
u, err := s.UserModel.FindOneByEmail(ctx, email)
if err != nil {
if !errors.Is(err, model.ErrNotFound) {
return 0, &types.CarvResult{
Error: &types.Error{
Code: int(errs.ErrDatabaseOperate),
Message: "system error",
},
}
}
return 0, &types.CarvResult{
Error: &types.Error{
Code: int(errs.ErrUserNotFound),
Message: "email not exist",
},
}
}
return u.Id, nil
}
func (s *ServiceContext) AddUserAssetWithSession(ctx context.Context, session sqlx.Session, uid uint, role int64, asset consts.AssetType, assetId string, amount decimal.Decimal, remark string, eventId uint64, provideUid uint, referralReward bool) error {
var assetModel model.NhTaskAssetModel
var recordModel model.NhTaskAssetRecordModel
var gamesPropertyModel model.NhGamesPropertyLogsModel
if session != nil {
assetModel = s.taskAssetModel.WithSession(session)
recordModel = s.taskAssetRecordModel.WithSession(session)
gamesPropertyModel = s.GamesPropertyModel.WithSession(session)
} else {
assetModel = s.taskAssetModel
recordModel = s.taskAssetRecordModel
gamesPropertyModel = s.GamesPropertyModel
}
if amount.LessThan(decimal.Zero) {
uAsset, err := assetModel.FindOneByUid(ctx, int(uid))
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return errs.New(errs.ErrInsufficientPoints, "insufficient point")
}
return errs.New(errs.ErrDatabaseOperate, err)
}
switch asset {
case consts.AssetType_Points:
if uAsset.Points.LessThan(amount.Abs()) {
return errs.New(errs.ErrInsufficientPoints, "insufficient point")
}
case consts.AssetType_Castile:
if uAsset.Castile.LessThan(amount.Abs()) {
return errs.New(errs.ErrInsufficientCastile, "insufficient castile")
}
case consts.AssetType_Elite_Points:
if uAsset.ElitePoints.LessThan(amount.Abs()) {
return errs.New(errs.ErrInsufficientElitePoints, "insufficient elite points")
}
case consts.AssetType_Keys:
if uAsset.Keys < int(amount.IntPart()) {
return errs.New(errs.ErrInsufficientKeys, "insufficient keys")
}
default:
return errors.New("unknown asset type")
}
}
var err error
switch asset {
case consts.AssetType_Points:
err = assetModel.AddPoint(ctx, uid, amount)
case consts.AssetType_Castile:
err = assetModel.AddCastile(ctx, uid, amount)
case consts.AssetType_Elite_Points:
err = assetModel.AddElitePoints(ctx, uid, amount)
case consts.AssetType_Keys:
err = assetModel.AddKeys(ctx, uid, int(amount.IntPart()))
case consts.AssetType_Property:
_, err = gamesPropertyModel.Insert(ctx, &model.NhGamesPropertyLogs{
Uid: uid,
RoleId: role,
PropertyId: assetId,
PropertyNum: uint(amount.IntPart()),
})
return err
default:
return errors.New("unknown asset type")
}
if err != nil {
return err
}
_, err = recordModel.Insert(ctx, &model.NhTaskAssetRecord{
Uid: int(uid),
EventId: eventId,
AssetField: string(asset),
Count: amount.InexactFloat64(),
Remark: remark,
ProvideUid: provideUid,
CreateTime: int(time.Now().Unix()),
})
if err != nil {
return err
}
if !referralReward {
return nil
}
// 返利给上级
pb, err := s.PromoteBindModel.FindOneByInvitedUid(ctx, uid)
if err != nil {
if !errors.Is(err, model.ErrNotFound) {
logx.Errorw("find promote bind error", logx.Field("err", err), logx.Field("uid", uid))
}
return nil
}
if pb.ShareUid == 0 {
return nil
}
var rate = 5
if s.NftHolderModel.HoldNft(ctx, pb.ShareUid) {
rate = 15
} else if s.AmbassadorModel.IsAmbassador(ctx, pb.ShareUid) {
rate = 10
}
rated := decimal.NewFromFloat(float64(rate) / 100)
rewardAmount := amount.Mul(rated)
return s.AddUserAssetWithSession(ctx, session, pb.ShareUid, 0, asset, assetId, rewardAmount, fmt.Sprintf("分享返利,比例%s", rated.String()), 7, uid, false)
}
// AddUserAsset 增加用户资产
func (s *ServiceContext) AddUserAsset(ctx context.Context, uid uint, role int64, asset consts.AssetType, assetId string, amount decimal.Decimal, remark string, eventId uint64, provideUid uint, referralReward bool) error {
return s.AddUserAssetWithSession(ctx, nil, uid, role, asset, assetId, amount, remark, eventId, provideUid, referralReward)
}