feat: 积分质押功能

This commit is contained in:
2025-04-03 16:17:20 +08:00
parent 229f1d181b
commit 8119bcefdc
40 changed files with 2552 additions and 108 deletions

126
internal/svc/game_action.go Normal file
View File

@@ -0,0 +1,126 @@
package svc
import (
"bytes"
"context"
"database/sql"
"encoding/json"
"fmt"
"github.com/spf13/cast"
"github.com/zeromicro/go-zero/core/logx"
"io"
"math"
"net/http"
"nova_task/internal/model"
"nova_task/internal/pkg/encrypt/md5"
"strconv"
"strings"
"time"
)
// GetGameServerAddress 获取游戏服地址
func (s *ServiceContext) GetGameServerAddress(ctx context.Context, roleID int64) (string, map[string]any, error) {
agentIDServerID := math.Floor(float64(roleID)/100000000) / 100000
splitStr := cast.ToString(agentIDServerID)
splitParts := []string{"0", "0"}
if parts := strings.Split(splitStr, "."); len(parts) == 2 {
splitParts = parts
}
serverInfo := map[string]any{}
originalAgentID, _ := strconv.ParseInt(splitParts[0], 10, 64)
originalServerID, _ := strconv.ParseInt(splitParts[1], 10, 64)
serverInfo["original_agent_id"] = originalAgentID
serverInfo["original_server_id"] = originalServerID
agentId, serverServerId, err := s.MergeServerModel.FinalServer(ctx, originalAgentID, originalServerID)
if err != nil {
return "", serverInfo, err
}
serverInfo["agent_id"] = agentId
serverInfo["server_id"] = serverServerId
gs, err := s.ServersModel.GetGameServer(ctx, agentId, serverServerId)
if err != nil {
return "", serverInfo, err
}
serverInfo["web_port"] = gs.WebPort
serverInfo["server_ip"] = gs.ServerIP
serverInfo["public_server_ip"] = gs.PublicServerIP
return fmt.Sprintf("http://%s:%d", gs.PublicServerIP, gs.WebPort), serverInfo, nil
}
func (s *ServiceContext) GameAction(ctx context.Context, roleId int64, action string, args map[string]any) (any, error) {
//return map[string]any{
// "data": 1,
// "ret": 1,
//}, nil
addr, serverInfo, err := s.GetGameServerAddress(ctx, roleId)
if err != nil {
return nil, err
}
now := time.Now().Unix()
request := map[string]any{
"nova_time": now,
"nova_token": md5.Md5str(fmt.Sprintf("%d%s", now, s.Config.NovaToken)),
"nova_action": action,
"role_id": roleId,
}
for k, v := range args {
if _, ok := request[k]; ok {
continue
}
request[k] = v
}
data, _ := json.Marshal(request)
httpReq, err := http.NewRequest(http.MethodPost, addr, bytes.NewReader(data))
if err != nil {
return nil, err
}
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("Accept", "application/json")
httpResp, err := http.DefaultClient.Do(httpReq)
if err != nil {
s.ErrLog(ctx, action, addr, serverInfo, request, nil)
return nil, err
}
respData, _ := io.ReadAll(httpResp.Body)
resp := map[string]any{}
if err := json.Unmarshal(respData, &resp); err != nil {
s.ErrLog(ctx, action, addr, serverInfo, request, string(respData))
return nil, err
}
if cast.ToInt64(resp["ret"]) != 1 {
s.ErrLog(ctx, action, addr, serverInfo, request, resp)
return resp, fmt.Errorf("game action msg= %s, data=%v", cast.ToString(resp["msg"]), cast.ToString(resp["data"]))
}
return resp, nil
}
func (s *ServiceContext) ErrLog(ctx context.Context, action, url string, serverInfo, req, resp any) {
var marshal = func(v any) string {
if v == nil {
return ""
}
if vv, ok := v.(string); ok {
return vv
}
data, _ := json.Marshal(v)
return string(data)
}
_, err := s.RequestServerLogModel.Insert(ctx, &model.NhRequestServerLog{
Action: action,
Url: url,
ServerInfo: marshal(serverInfo),
ReqData: marshal(req),
ResData: marshal(resp),
CreateTime: sql.NullTime{Valid: true, Time: time.Now()},
})
if err != nil {
logx.Errorw("insert request server log error", logx.Field("err", err), logx.Field("action", action), logx.Field("url", url), logx.Field("server_info", serverInfo), logx.Field("req", req), logx.Field("resp", resp))
}
}

84
internal/svc/model.go Normal file
View File

@@ -0,0 +1,84 @@
package svc
import (
"github.com/zeromicro/go-zero/core/stores/sqlx"
"nova_task/internal/model"
)
type dbModel struct {
TaskModel model.NhTaskModel
taskAssetModel model.NhTaskAssetModel
taskAssetRecordModel model.NhTaskAssetRecordModel
TaskProgressModel model.NhTaskProgressModel
TwitterModel model.NhTwitterModel
PromoteBindModel model.NhPromoteBindModel
TouristBindModel model.NhTouristBindModel
CommunityModel model.NhTaskCommunityModel
UserModel model.NhUserModel
WalletModel model.NhWalletModel
ConfigModel model.NhSystemConfigModel
NftHolderModel model.NhNftHolderModel
NftHolderChangeLogModel model.NhNftHolderChangeLogModel
StakeNftModel model.NhTaskNftStakeModel
OldStakeNftModel model.NhNftStakeModel
StakeNftLogModel model.NhTaskNftStakeLogModel
StakeRewardModel model.NhTaskNftStakeRewardModel
GamePitModel model.NhGamePitModel
StakePropertyModel model.NhNftStakePropertyModel
EmailRewardModel model.NhEmailRewardModel
AmbassadorModel model.NhTaskAmbassadorModel
GameReportModel model.NhGameReportModel
RoleModel model.NhRoleModel
GamesPropertyModel model.NhGamesPropertyLogsModel
AirdropModel model.NhAirdropLogModel
PioneerRewardsModel model.NhPioneerRewardsModel
MergeServerModel model.MsMergeServersModel
GameServerModel model.MsGameServerModel
ServersModel model.MgServersModel
GameServerNotifyModel model.NhGameServerNotifyModel
RequestServerLogModel model.NhRequestServerLogModel
StakePointConfigModel model.NhStakeHomePointConfigModel
StakePointsModel model.NhStakePointsModel
}
func newDBModel(dbConn, gameConn sqlx.SqlConn, configModel model.NhSystemConfigModel) *dbModel {
return &dbModel{
TaskModel: model.NewNhTaskModel(dbConn),
taskAssetModel: model.NewNhTaskAssetModel(dbConn),
taskAssetRecordModel: model.NewNhTaskAssetRecordModel(dbConn),
TaskProgressModel: model.NewNhTaskProgressModel(dbConn),
TwitterModel: model.NewNhTwitterModel(dbConn),
PromoteBindModel: model.NewNhPromoteBindModel(dbConn),
CommunityModel: model.NewNhTaskCommunityModel(dbConn),
UserModel: model.NewNhUserModel(dbConn),
TouristBindModel: model.NewNhTouristBindModel(dbConn),
WalletModel: model.NewNhWalletModel(dbConn),
ConfigModel: configModel,
NftHolderModel: model.NewNhNftHolderModel(dbConn),
NftHolderChangeLogModel: model.NewNhNftHolderChangeLogModel(dbConn),
StakeNftModel: model.NewNhTaskNftStakeModel(dbConn),
OldStakeNftModel: model.NewNhNftStakeModel(dbConn),
StakeRewardModel: model.NewNhTaskNftStakeRewardModel(dbConn),
GamePitModel: model.NewNhGamePitModel(dbConn),
StakePropertyModel: model.NewNhNftStakePropertyModel(dbConn),
EmailRewardModel: model.NewNhEmailRewardModel(dbConn),
AmbassadorModel: model.NewNhTaskAmbassadorModel(dbConn),
GameReportModel: model.NewNhGameReportModel(dbConn),
RoleModel: model.NewNhRoleModel(dbConn),
GamesPropertyModel: model.NewNhGamesPropertyLogsModel(dbConn),
AirdropModel: model.NewNhAirdropLogModel(dbConn),
PioneerRewardsModel: model.NewNhPioneerRewardsModel(dbConn),
StakePointConfigModel: model.NewNhStakeHomePointConfigModel(dbConn),
StakePointsModel: model.NewNhStakePointsModel(dbConn),
GameServerNotifyModel: model.NewNhGameServerNotifyModel(dbConn),
RequestServerLogModel: model.NewNhRequestServerLogModel(dbConn),
MergeServerModel: model.NewMsMergeServersModel(gameConn),
GameServerModel: model.NewMsGameServerModel(gameConn),
ServersModel: model.NewMgServersModel(gameConn),
}
}

View File

@@ -22,32 +22,7 @@ import (
type ServiceContext struct {
Config config.Config
TaskModel model.NhTaskModel
taskAssetModel model.NhTaskAssetModel
taskAssetRecordModel model.NhTaskAssetRecordModel
TaskProgressModel model.NhTaskProgressModel
TwitterModel model.NhTwitterModel
PromoteBindModel model.NhPromoteBindModel
TouristBindModel model.NhTouristBindModel
CommunityModel model.NhTaskCommunityModel
UserModel model.NhUserModel
WalletModel model.NhWalletModel
ConfigModel model.NhSystemConfigModel
NftHolderModel model.NhNftHolderModel
NftHolderChangeLogModel model.NhNftHolderChangeLogModel
StakeNftModel model.NhTaskNftStakeModel
OldStakeNftModel model.NhNftStakeModel
StakeNftLogModel model.NhTaskNftStakeLogModel
StakeRewardModel model.NhTaskNftStakeRewardModel
GamePitModel model.NhGamePitModel
StakePropertyModel model.NhNftStakePropertyModel
EmailRewardModel model.NhEmailRewardModel
AmbassadorModel model.NhTaskAmbassadorModel
GameReportModel model.NhGameReportModel
RoleModel model.NhRoleModel
GamesPropertyModel model.NhGamesPropertyLogsModel
AirdropModel model.NhAirdropLogModel
PioneerRewardsModel model.NhPioneerRewardsModel
*dbModel
ApiKeyCheck rest.Middleware
AdminSecretCheck rest.Middleware
@@ -61,44 +36,18 @@ type ServiceContext struct {
func NewServiceContext(c config.Config) *ServiceContext {
dbConn := c.MySql.Conn()
gameConn := c.GameDB.Conn()
configModel := model.NewNhSystemConfigModel(dbConn, c.Cache)
return &ServiceContext{
Config: c,
TaskModel: model.NewNhTaskModel(dbConn),
taskAssetModel: model.NewNhTaskAssetModel(dbConn),
taskAssetRecordModel: model.NewNhTaskAssetRecordModel(dbConn),
TaskProgressModel: model.NewNhTaskProgressModel(dbConn),
TwitterModel: model.NewNhTwitterModel(dbConn),
PromoteBindModel: model.NewNhPromoteBindModel(dbConn),
CommunityModel: model.NewNhTaskCommunityModel(dbConn),
UserModel: model.NewNhUserModel(dbConn),
TouristBindModel: model.NewNhTouristBindModel(dbConn),
WalletModel: model.NewNhWalletModel(dbConn),
ConfigModel: configModel,
NftHolderModel: model.NewNhNftHolderModel(dbConn),
NftHolderChangeLogModel: model.NewNhNftHolderChangeLogModel(dbConn),
StakeNftModel: model.NewNhTaskNftStakeModel(dbConn),
OldStakeNftModel: model.NewNhNftStakeModel(dbConn),
StakeRewardModel: model.NewNhTaskNftStakeRewardModel(dbConn),
GamePitModel: model.NewNhGamePitModel(dbConn),
StakePropertyModel: model.NewNhNftStakePropertyModel(dbConn),
EmailRewardModel: model.NewNhEmailRewardModel(dbConn),
AmbassadorModel: model.NewNhTaskAmbassadorModel(dbConn),
GameReportModel: model.NewNhGameReportModel(dbConn),
RoleModel: model.NewNhRoleModel(dbConn),
GamesPropertyModel: model.NewNhGamesPropertyLogsModel(dbConn),
AirdropModel: model.NewNhAirdropLogModel(dbConn),
PioneerRewardsModel: model.NewNhPioneerRewardsModel(dbConn),
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,
Earn: c.Earn.BuildEarnClient(),
DBConn: dbConn,
Redis: redis.MustNewRedis(c.Redis),
DBConn: dbConn,
Earn: c.Earn.BuildEarnClient(),
Redis: redis.MustNewRedis(c.Redis),
}
}
@@ -173,6 +122,35 @@ func (s *ServiceContext) AddUserAssetWithSession(ctx context.Context, session sq
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:
@@ -186,7 +164,7 @@ func (s *ServiceContext) AddUserAssetWithSession(ctx context.Context, session sq
case consts.AssetType_Property:
_, err = gamesPropertyModel.Insert(ctx, &model.NhGamesPropertyLogs{
Uid: uid,
RoleId: int64(role),
RoleId: role,
PropertyId: assetId,
PropertyNum: uint(amount.IntPart()),
})
@@ -234,6 +212,7 @@ func (s *ServiceContext) AddUserAssetWithSession(ctx context.Context, session sq
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)
}