219 lines
6.7 KiB
Go
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)
|
|
}
|