diff --git a/bin/conf/backend/conf.toml b/bin/conf/backend/conf.toml index 7ef3d19..142db1f 100644 --- a/bin/conf/backend/conf.toml +++ b/bin/conf/backend/conf.toml @@ -1,10 +1,18 @@ [Backend] Addr=":7616" Release=false -DB="root:d47a98e748ccaf1f@tcp(172.105.117.6:3306)/backend" +DB="root:123456@tcp(192.168.10.101:3306)/backend" [Web.ZYPay] ZYPayURL="https://in.zyhws.com/tablegames/singleton/orderPay" ZYWithdrawURL="https://in.zyhws.com/tablegames/singleton/orderdraw" PayNotifyURL="http://192.168.1.141:7615/balance/recharge/ZYPayCallback" WithdrawNotifyURL="http://192.168.1.141:7615/balance/withdraw/ZYWithdrawCallback" -WhiteIPs = ["47.241.254.165","8.214.46.27"] \ No newline at end of file +WhiteIPs = ["47.241.254.165","8.214.46.27"] +[Backend.Oss] +Endpoint="oss-ap-south-1.aliyuncs.com" +AccessKeyId="LTAI5tLaYWuRVz7BiQ7m666Z" +AccessKeySecret="6s7mMexYbVmZSLXEv3kdJwxXThMN4T" +BucketName="xpggame" +ObjectName="res/" + + diff --git a/bin/conf/baseConf.toml b/bin/conf/baseConf.toml index cdb1fb6..b6973d6 100644 --- a/bin/conf/baseConf.toml +++ b/bin/conf/baseConf.toml @@ -1,23 +1,23 @@ [net] -registry="127.0.0.1:8500" # consul 地址 -nats="nats://127.0.0.1:4222" # nats地址 +registry="192.168.10.101:8500" # consul 地址 +nats="nats://192.168.10.101:4222" # nats地址 [redis] -addr="127.0.0.1:6379" +addr="192.168.10.101:6379" name="" passwd="" tls=false -db=0 +db=2 cluster=false [es] #urls=["http://127.0.0.1:9200"] -urls=["http://elastic:joyyu7XRwlpJtXFEIw80@47.112.119.250:9400"] +urls=["http://elastic:ZyepQWx5QRO2oGzSJCz5@47.106.150.32:9400"] sniff=false [mysql] #dsn="xh_rwuser:!Xhwlkj2018@tcp(127.0.0.1:3306)/game" -dsn="root:d9JaXnG5QuuZLIrY@tcp(47.112.119.250:3306)/slotsgame" +dsn="root:123456@tcp(192.168.10.101:3306)/brl_game" debug=true [facebook] diff --git a/bin/conf/pay/conf.toml b/bin/conf/pay/conf.toml index defb144..8a0c4b8 100644 --- a/bin/conf/pay/conf.toml +++ b/bin/conf/pay/conf.toml @@ -14,18 +14,21 @@ PaySuccessWeight = 50 BaseSuccess = 10 WithdrawScanTime = 10 [Pay.IGeek] -APIURL = "http://api.test.igeekpay.com/gateway" -APPID = "H4RIKR" -MID = "RSRV686X" -Key = "2YHPVB8DZKTALVVI" +#APIURL = "https://api.test.payasaan.com/gateway" +APIURL = "https://api.igeekpay.com/gateway" +APPID = "TJ7V2H" +MID = "Z61CRKK2" +Key = "29AR9288DULM53QD" [Web.Adjust] URL = "https://s2s.adjust.com/event" APIURL = "https://api.adjust.com/device_service/api/v1/inspect_device" APIToken = "_2ZGYezfdZ7yD2he-zWx" +[Web.FB] +APIURL = "https://graph.facebook.com/v18.0/" [Pay.BestPay] APIURL = "https://very.goodrummy.co.in" [Pay.GrePay] -Key = "" -WithdrawAccount = "" -MIDAmount = 3000 +Key = "FF5D557F6AC9EF26212B482B23AD7F07" +WithdrawAccount = "2208100000250402110" +MIDAmount = 50000 BigChannel = "0452" \ No newline at end of file diff --git a/bin/conf/web/conf.toml b/bin/conf/web/conf.toml index e21d172..bc54d6e 100644 --- a/bin/conf/web/conf.toml +++ b/bin/conf/web/conf.toml @@ -13,7 +13,7 @@ TestWithdraw=-1 TestPay=3 FetchTime = 60 OldChannels = [] -FreeSpinFirst = 500000000 +FreeSpinFirst = 2000 TotalWithdrawPer = 50 BreakLimit = 100000000 SelectID = 2 diff --git a/call/config.go b/call/config.go index 15cce45..9c0bb26 100644 --- a/call/config.go +++ b/call/config.go @@ -710,6 +710,7 @@ func GetConfigGameList(num int, cond ...int) []*common.ConfigGameList { return ret } } + GetGameInfo(ret) return ret } @@ -1072,7 +1073,7 @@ func GetConfigTaskByTaskID(taskID int) *common.ConfigTask { func GetConfigTaskByTaskType(t int) (ret []*common.ConfigTask) { for _, v := range configTask { - if v.Type == t { + if int(v.Type) == t { ret = append(ret, v) } } diff --git a/call/game.go b/call/game.go index 4bd8d30..c3571b2 100644 --- a/call/game.go +++ b/call/game.go @@ -1,11 +1,15 @@ package call import ( + "context" + "errors" "fmt" "server/common" "server/db" "server/util" + "time" + "github.com/go-redis/redis/v8" "github.com/liangdas/mqant/log" "gorm.io/gorm" ) @@ -44,3 +48,48 @@ func UpdateGameSort(provider, gameID int) { db.Mysql().Update(&common.ConfigGameList{GameProvider: provider, GameID: gameID}, map[string]interface{}{"sort": gorm.Expr("sort + 1")}) }) } + +// GetGameInfo 获取游戏信息 +func GetGameInfo(gameInfos []*common.ConfigGameList) { + ctx := context.Background() + rdb := db.Redis().GetRedis() + pipeline := rdb.Pipeline() + maxRewardField := "maxReward" + rtpField := "rtp" + maxRewardTimeField := "maxRewardTime" + for _, game := range gameInfos { + key := fmt.Sprintf("firstpage:games:%d_%d", game.GameProvider, game.GameID) + pipeline.HGet(ctx, key, maxRewardField) + pipeline.HGet(ctx, key, maxRewardTimeField) + pipeline.HGet(ctx, key, rtpField) + } + cmds, err := pipeline.Exec(ctx) + now := time.Now() + for i := 0; i < 2*len(gameInfos); i = i + 2 { + game := gameInfos[i/2] + maxRewardCmd := cmds[i] + maxRewardTimeCmd := cmds[i+1] + key := fmt.Sprintf("firstpage:games:%d_%d", game.GameProvider, game.GameID) + game.MaxReward, err = maxRewardCmd.(*redis.StringCmd).Int64() + if errors.Is(err, redis.Nil) { + val := util.RandBetween64(100, 9999) + rtp := util.RandBetween64(93, 104) + game.RTP = rtp + game.MaxReward = val + pipeline.HSet(ctx, key, maxRewardField, val, maxRewardTimeField, time.Now(), rtpField, rtp) + } else { + maxRewardTime, _ := maxRewardTimeCmd.(*redis.StringCmd).Time() + if now.Sub(maxRewardTime).Hours() >= 1 { + val := util.RandBetween64(game.MaxReward, 9999) + rtp := util.RandBetween64(93, 104) + game.RTP = rtp + game.MaxReward = val + pipeline.HSet(ctx, key, maxRewardField, val, maxRewardTimeField, time.Now(), rtpField, rtp) + } + } + } + _, err = pipeline.Exec(ctx) + if err != nil { + log.Error("GetGameInfo err:%v", err) + } +} diff --git a/call/pay.go b/call/pay.go index 4a6ddb6..edec42a 100644 --- a/call/pay.go +++ b/call/pay.go @@ -502,7 +502,7 @@ func PayActivity(r *common.RechargeOrder, notCharge bool, user *common.PlayerDBI // VIP UpdateVip(r.UID, r.Amount, 0, 0) // 检查任务 - CheckTask(r) + CheckTask(Task{Uid: r.UID, Value: r.Amount, Types: []common.TaskType{common.TaskTypeOnceRecharge}}) // 检查所有活动 CheckAllActivity(r) @@ -515,28 +515,6 @@ func PayActivity(r *common.RechargeOrder, notCharge bool, user *common.PlayerDBI return nil } -func CheckTask(r *common.RechargeOrder) { - now := time.Now().Unix() - con := GetConfigTask() - for _, v := range con { - if (v.Type == common.TaskTypeOnceRecharge || v.Type == common.TaskTypeFirstRecharge) && r.Amount >= v.Target { // 单次充值任务 || 首次充值任务 - data := GetUserTaskDataByTaskID(r.UID, v.TaskID) - if data.ID == 0 { - db.Mysql().Create(&common.TaskData{UID: r.UID, TaskID: v.TaskID, Time: now, Progress: v.Target}) - } else if data.Progress == 0 { - db.Mysql().Update(&common.TaskData{UID: r.UID, TaskID: v.TaskID}, map[string]interface{}{"progress": v.Target, "time": now}) - } - } else if v.Type == common.TaskTypeTotalRecharge { // 累充任务 - data := GetUserTaskDataByTaskID(r.UID, v.TaskID) - if data.ID == 0 { - db.Mysql().Create(&common.TaskData{UID: r.UID, TaskID: v.TaskID, Time: now, Progress: r.Amount}) - } else if data.Progress >= 0 { - db.Mysql().Update(&common.TaskData{UID: r.UID, TaskID: v.TaskID}, map[string]interface{}{"progress": gorm.Expr("progress + ?", r.Amount), "time": now}) - } - } - } -} - func ActivityFirstRechargeBack(r *common.RechargeOrder) { now := time.Now().Unix() if IsActivityValid(common.ActivityIDFirstRechargeBack) { diff --git a/call/share.go b/call/share.go index 3bd3c98..9a31850 100644 --- a/call/share.go +++ b/call/share.go @@ -57,6 +57,9 @@ func ShareBind(share string, isOld bool, uid, cid int) { // 更新上级邀请玩家数 db.Mysql().Update(&common.ShareInfo{UID: upInfo.UID}, map[string]interface{}{"invites": gorm.Expr("invites + 1")}) + + // 完成邀请任务 + CheckTask(Task{Uid: uid, Value: 1, Types: []common.TaskType{common.TaskTypeInvite}}) } // 判断分享,发放有效用户奖励 diff --git a/call/task.go b/call/task.go new file mode 100644 index 0000000..12b980d --- /dev/null +++ b/call/task.go @@ -0,0 +1,45 @@ +package call + +import ( + "server/common" + "server/db" + "time" + + "github.com/liangdas/mqant/log" + "gorm.io/gorm" +) + +type Task struct { + Uid int // uid + Types []common.TaskType // 任务类型 + Value int64 // 进度值 +} + +func CheckTask(task Task) { + log.Info("checkTask task:%v", task) + now := time.Now().Unix() + con := GetConfigTask() + uid := task.Uid + for _, v := range con { + for _, t := range task.Types { + if (t == common.TaskTypeOnceRecharge || t == common.TaskTypeInvite || t == common.TaskTypePlayGame) && v.Type == t { // 单次充值任务 || 首次充值任务 || v.Type == common.TaskTypeFirstRecharge) + data := GetUserTaskDataByTaskID(task.Uid, v.TaskID) + if data.ID == 0 { + db.Mysql().Create(&common.TaskData{UID: uid, TaskID: v.TaskID, Time: now, Progress: v.Target}) + } else if data.Progress == 0 { + db.Mysql().Update(&common.TaskData{UID: uid, TaskID: v.TaskID}, map[string]interface{}{"progress": v.Target, "time": now}) + } + break + } else if (t == common.TaskTypeBet1000 || t == common.TaskTypeBet10000) && v.Type == t { + data := GetUserTaskDataByTaskID(task.Uid, v.TaskID) + if data.ID == 0 { + db.Mysql().Create(&common.TaskData{UID: uid, TaskID: v.TaskID, Time: now, Progress: task.Value}) + } else { + db.Mysql().Update(&common.TaskData{UID: uid, TaskID: v.TaskID}, map[string]interface{}{"progress": gorm.Expr("progress + ?", task.Value), "time": now}) + } + break + } + } + + } +} diff --git a/call/user.go b/call/user.go index 5c0e471..850ce01 100644 --- a/call/user.go +++ b/call/user.go @@ -171,7 +171,6 @@ func NewUser(info *common.PlayerDBInfo, ip, share, fbc, fbp, agent string) error initPlayer(uid, cid) UploadAdjust(common.AdjustEventNewPlayer, info, nil) ShareBind(share, isOld, uid, cid) - // 新手赠送 first := config.GetConfig().Web.FreeSpinFirst if first > 0 { @@ -589,6 +588,8 @@ func UpdatePlayerProfile(data *common.ESGameData) error { util.Go(func() { // 更新vip UpdateVip(uid, 0, bet, settle) + // 检查任务 + CheckTask(Task{Uid: uid, Value: bet / 100, Types: []common.TaskType{common.TaskTypePlayGame, common.TaskTypeBet1000, common.TaskTypeBet10000}}) }) // 写入es @@ -635,7 +636,7 @@ func GetUserTaskData(uid int) (ret []common.TaskData) { func GetUserTaskDataByTaskID(uid, taskID int) *common.TaskData { data := &common.TaskData{UID: uid, TaskID: taskID} - db.Mysql().Get(data) + db.Mysql().GetLast(data) return data } @@ -709,7 +710,6 @@ func GetGameRecord(uid int) (gameList []*common.ConfigGameList) { if gameConf != nil { gameList = append(gameList, gameConf) } - } } return diff --git a/common/config.go b/common/config.go index d9e4f8f..cdefaae 100644 --- a/common/config.go +++ b/common/config.go @@ -347,8 +347,9 @@ type ConfigGameList struct { Demo int `gorm:"column:demo;type:int(11);default:1;comment:是否支持demo 1支持 2不支持" web:"demo"` SubID string `gorm:"column:subid;type:varchar(255);default:'';comment:一些游戏有子id" web:"subid"` Jackpot int64 `gorm:"-" web:"-"` - MaxReward int64 `gorm:"-" web:"-" json:"max_reward"` // 最大奖励 - Number int64 `gorm:"-" web:"-" json:"number"` // 游玩人数 + MaxReward int64 `gorm:"-" web:"-" redis:"maxReward"` // 最大奖励 + PlayerNumber int64 `gorm:"-" web:"-" redis:"number"` // 游玩人数 + RTP int64 `gorm:"-" web:"-" redis:"rtp"` // rtp } func (c *ConfigGameList) TableName() string { diff --git a/common/currency.go b/common/currency.go index 0b17b8e..dce9c92 100644 --- a/common/currency.go +++ b/common/currency.go @@ -197,7 +197,7 @@ func GetGameOutEvents() []interface{} { func RoundCurrency(t CurrencyType, amount int64) int64 { switch t { case CurrencyINR: - return amount / 100 * 100 + return amount case CurrencyUSDT: return amount / 100 * 100 default: diff --git a/common/platform.go b/common/platform.go index b00c09b..bf0cb59 100644 --- a/common/platform.go +++ b/common/platform.go @@ -45,7 +45,7 @@ const ( ) const ( - DecimalDigits = 100000000 // 计算时精确到小数点后8位 + DecimalDigits = 100 // 计算时精确到小数点后2位 ) var ( diff --git a/common/share.go b/common/share.go index 90f86c1..c6f8ba2 100644 --- a/common/share.go +++ b/common/share.go @@ -15,11 +15,11 @@ func (c *ConfigShare) TableName() string { // 分享配置 type ConfigShareSys struct { ID int `gorm:"primarykey"` - WithdrawLimit int64 `gorm:"column:withdraw_limit;type:bigint(20);default:100000000;comment:最低领取数额" web:"withdraw_limit"` - ShareRecharge int64 `gorm:"column:share_recharge;type:bigint(20);default:2000000000;comment:有效玩家充值需求" web:"share_recharge"` - ShareReward int64 `gorm:"column:share_reward;type:bigint(20);default:1000000000;comment:分享有效玩家奖励" web:"share_reward"` - FakeInviteReward int64 `gorm:"column:fake_invite_reward;type:bigint(20);default:1250000000000000;comment:虚拟邀请奖励" web:"fake_invite_reward"` - FakeBetReward int64 `gorm:"column:fake_bet_reward;type:bigint(20);default:980000000000000;comment:虚拟投注奖励" web:"fake_bet_reward"` + WithdrawLimit int64 `gorm:"column:withdraw_limit;type:bigint(20);default:100;comment:最低领取数额" web:"withdraw_limit"` + ShareRecharge int64 `gorm:"column:share_recharge;type:bigint(20);default:2000;comment:有效玩家充值需求" web:"share_recharge"` + ShareReward int64 `gorm:"column:share_reward;type:bigint(20);default:1000;comment:分享有效玩家奖励" web:"share_reward"` + FakeInviteReward int64 `gorm:"column:fake_invite_reward;type:bigint(20);default:1250000000;comment:虚拟邀请奖励" web:"fake_invite_reward"` + FakeBetReward int64 `gorm:"column:fake_bet_reward;type:bigint(20);default:980000000;comment:虚拟投注奖励" web:"fake_bet_reward"` } func (c *ConfigShareSys) TableName() string { @@ -84,6 +84,7 @@ type ShareActivityCode struct { ShareCode string `gorm:"column:share_code;type:varchar(255);index:idx_share;comment:分享码" json:"share_code"` ActivityId int `gorm:"column:activity_id;type:int(11);index:idx_share;comment:关联活动ID" json:"activity_id"` Reward string `gorm:"column:reward;type:varchar(255);index:idx_share;comment:分享码" json:"reward"` + ValidNum int `gorm:"column:valid_num;type:int(11);index:idx_share;comment:有效次数" json:"valid_num"` CreateAt int64 `gorm:"column:create_at;type:bigint(20);comment:创建时间" json:"create_at"` ExpireAt int64 `gorm:"column:expire_at;type:bigint(20);comment:过期时间" json:"expire_at"` } diff --git a/common/task.go b/common/task.go index 35324e8..aab37ae 100644 --- a/common/task.go +++ b/common/task.go @@ -1,18 +1,36 @@ package common +type TaskType int + const ( - TaskTypeZero = iota - TaskTypeRegist // 注册任务 - TaskTypeDownload // 下载app任务 - TaskTypeTotalRecharge // 累充任务 - TaskTypeOnceRecharge // 单次充值任务 - TaskTypeFirstRecharge // 首次充值任务 + TaskTypeZero TaskType = iota + TaskTypeOnceRecharge // 单次充值任务 + TaskTypeInvite // 邀请好友 + TaskTypePlayGame // 参与一次牌局 + TaskTypeBet1000 // 累计下注1000 + TaskTypeBet10000 // 累计下注10000 TaskTypeAll ) +// TaskTypeFirstRecharge // 首次充值任务 +// TaskTypeRegist // 注册任务 +// TaskTypeDownload // 下载app任务 +// TaskTypeTotalRecharge // 累充任务 +// 完成任意一次充值 +// (每日重置一次) +// 完成一次好友邀请 +// (每日重置一次,这里要有效好友才可完成,有效好友意思是只邀请的玩家充值了200卢比) +// 参与一次牌局 +// (任务每日重置一次) +// 累记下注到1000 +// (每日任务重置一次) +// 累记下注到10000 +// (每日任务重置一次) + // 判读任务的目标是否是次数 func IsNumTaskType(t int) bool { - return t == TaskTypeRegist || t == TaskTypeDownload + // return t == TaskTypeOnceRecharge || t == TaskTypeInvite || t == TaskTypePlayGame + return false } func GetTaskTitle(task *ConfigTask) string { @@ -36,17 +54,17 @@ const ( // Kind 1单次 2循环 // Type 1注册 2下载 3累充 4单次充 type ConfigTask struct { - ID int `gorm:"primary_key;AUTO_INCREMENT;column:id"` - TaskID int `gorm:"column:task_id;type:int(11);default:0;uniqueIndex:task_id;comment:任务id" web:"task_id"` - Target int64 `gorm:"column:target;type:bigint(20);default:0;comment:任务目标" web:"target"` - Reward int64 `gorm:"column:reward;type:bigint(20);default:0;comment:奖励" web:"reward"` - Open int `gorm:"column:open;type:int(11);default:1;comment:开关 1打开" web:"open"` - Kind int `gorm:"column:kind;type:int(11);default:1;comment:1单次 2循环" web:"kind"` - Type int `gorm:"column:type;type:int(11);default:1;comment:1注册 2下载" web:"type"` - Title string `gorm:"column:title;type:varchar(256);default:'';comment:标题" web:"title"` - Icon string `gorm:"column:icon;type:varchar(256);default:'';comment:图标" web:"icon"` - Sort int `gorm:"column:sort;type:int(11);default:0;comment:排序" web:"sort"` - Action int `gorm:"column:action;type:int(11);default:1;comment:跳转类型" web:"action"` + ID int `gorm:"primary_key;AUTO_INCREMENT;column:id"` + TaskID int `gorm:"column:task_id;type:int(11);default:0;uniqueIndex:task_id;comment:任务id" web:"task_id"` + Target int64 `gorm:"column:target;type:bigint(20);default:0;comment:任务目标" web:"target"` + Reward int64 `gorm:"column:reward;type:bigint(20);default:0;comment:奖励" web:"reward"` + Open int `gorm:"column:open;type:int(11);default:1;comment:开关 1打开" web:"open"` + Kind int `gorm:"column:kind;type:int(11);default:1;comment:1单次 2循环" web:"kind"` + Type TaskType `gorm:"column:type;type:int(11);default:1;comment:1注册 2下载" web:"type"` + Title string `gorm:"column:title;type:varchar(256);default:'';comment:标题" web:"title"` + Icon string `gorm:"column:icon;type:varchar(256);default:'';comment:图标" web:"icon"` + Sort int `gorm:"column:sort;type:int(11);default:0;comment:排序" web:"sort"` + Action int `gorm:"column:action;type:int(11);default:1;comment:跳转类型" web:"action"` } func (c *ConfigTask) TableName() string { diff --git a/config/config.go b/config/config.go index 75f8b0d..77f5f9d 100644 --- a/config/config.go +++ b/config/config.go @@ -1,5 +1,13 @@ package config +type OssParams struct { + Endpoint string + AccessKeyId string + AccessKeySecret string + BucketName string + ObjectName string +} + type FacebookParams struct { Prefix string AppKey string @@ -118,6 +126,7 @@ type Configure struct { Backend struct { Addr string DB string + Oss OssParams } Rummy struct { SettleTime int diff --git a/go.mod b/go.mod index 00b6096..9aaabfe 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.16 require ( github.com/BurntSushi/toml v1.1.0 + github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible // indirect github.com/bwmarrin/snowflake v0.3.0 github.com/fbsobreira/gotron-sdk v0.0.0-20230418195951-b7bfbf1c0ade github.com/gin-gonic/gin v1.7.4 diff --git a/go.sum b/go.sum index 22aaff6..e9ef1f1 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,8 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBA github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g= +github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= diff --git a/main.go b/main.go index a375ac3..3717981 100644 --- a/main.go +++ b/main.go @@ -36,7 +36,6 @@ func main() { log.Info("启动游戏服务器 ...") rand.Seed(time.Now().UTC().UnixNano()) runtime.GOMAXPROCS(runtime.NumCPU()) - modulefile := flag.String("module", "module.json", "module configure file") logdir := flag.String("log", "logs", "log file directory") wddir := flag.String("wd", ".", "Server work directory") @@ -47,7 +46,7 @@ func main() { conf := flag.String("conf", "conf.toml", "server configure file") - //flag.String("rule", "rule.toml", "rule config toml file") + // flag.String("rule", "rule.toml", "rule config toml file") // flag.String("Game_config", "Game_config.xlsx", "excel game configure file") // flag.String("robot_config", "robot_config.xlsx", "excel robot configure file") @@ -106,16 +105,16 @@ func main() { module.ProcessID(*processID), module.BILogDir(*bidir), module.KillWaitTTL(1*time.Minute), - module.Debug(*debug), //只有是在调试模式下才会在控制台打印日志, 非调试模式下只在日志文件中输出日志 - module.Nats(nc), //指定nats rpc - module.Registry(rs), //指定服务发现 + module.Debug(*debug), // 只有是在调试模式下才会在控制台打印日志, 非调试模式下只在日志文件中输出日志 + module.Nats(nc), // 指定nats rpc + module.Registry(rs), // 指定服务发现 module.RegisterTTL(20*time.Second), module.RegisterInterval(10*time.Second), module.Selector(selector.NewSelector(selector.Registry(rs))), ) err = app.Run( - //已实现的模块都应该在此处传入 + // 已实现的模块都应该在此处传入 hall.Module(), common.Module(), mgate.Module(), diff --git a/modules/backend/handler/common/common.go b/modules/backend/handler/common/common.go index bfba2cd..d692429 100644 --- a/modules/backend/handler/common/common.go +++ b/modules/backend/handler/common/common.go @@ -1,17 +1,24 @@ package handler import ( + "fmt" "server/call" "server/common" + "server/config" "server/modules/backend/app" "server/modules/backend/bdb" "server/modules/backend/values" "server/util" + "github.com/aliyun/aliyun-oss-go-sdk/oss" "github.com/gin-gonic/gin" "github.com/liangdas/mqant/log" ) +var ( + bucket *oss.Bucket +) + func ProductList(c *gin.Context) { a := app.NewApp(c) defer func() { @@ -66,7 +73,7 @@ func AccountList(c *gin.Context) { } resp := &values.AccountListResp{} a.Data = resp - list := []values.User{} + var list []values.User if err := bdb.BackDB.C().Find(&list).Error; err != nil { log.Error("err:%v", err) a.Code = values.CodeRetry @@ -76,3 +83,49 @@ func AccountList(c *gin.Context) { resp.List = append(resp.List, v.Account) } } + +func UploadOSS(c *gin.Context) { + a := app.NewApp(c) + defer func() { + a.Response() + }() + ossConf := config.GetConfig().Backend.Oss + req := new(values.UploadOSSReq) + req.ObjectName = c.PostForm("ObjectName") + rsp := new(values.UploadOSSResp) + a.Data = rsp + file, err := c.FormFile("file") + if err != nil { + a.Code = values.CodeRetry + log.Error("UploadOSS err:%v", err) + return + } + f, err := file.Open() + if err != nil { + a.Code = values.CodeRetry + log.Error("UploadOSS err:%v", err) + return + } + defer f.Close() + if bucket == nil { + client, err := oss.New(ossConf.Endpoint, ossConf.AccessKeyId, ossConf.AccessKeySecret) + if err != nil { + a.Code = values.CodeRetry + log.Error("UploadOSS New err:%v", err) + return + } + bucket, err = client.Bucket(ossConf.BucketName) + if err != nil { + a.Code = values.CodeRetry + log.Error("UploadOSS Bucket err:%v", err) + return + } + } + err = bucket.PutObject(ossConf.ObjectName+file.Filename, f) + if err != nil { + a.Code = values.CodeRetry + log.Error("UploadOSS PutObject err:%v", err) + return + } + rsp.Url = fmt.Sprintf("https://%s.%s/%s", ossConf.BucketName, ossConf.Endpoint, ossConf.ObjectName+file.Filename) +} diff --git a/modules/backend/handler/examine/examine.go b/modules/backend/handler/examine/examine.go index 908daf9..b993b3b 100644 --- a/modules/backend/handler/examine/examine.go +++ b/modules/backend/handler/examine/examine.go @@ -30,7 +30,7 @@ func WithdrawList(c *gin.Context) { table1 := `(SELECT id,uid,channel_id,pay_channel,orderid,apipayid,payaccount,amount,create_time,callback_time,status,operator from withdraw_order %s)a` table2 := `(SELECT id,platform,mobile,tag from users %s)b` - table3 := `(SELECT uid,brl from player_currency)c` + table3 := `(SELECT uid,inr from player_currency)c` table4 := `(SELECT uid,total_recharge,total_recharge_count,total_withdraw,total_withdraw_count FROM recharge_info)d` // 表1的查询条件 @@ -76,7 +76,7 @@ func WithdrawList(c *gin.Context) { sqlCount := " SELECT COUNT(*) AS count from" sqlList := `SELECT a.id,a.uid,a.channel_id,a.pay_channel,a.orderid as OrderID,a.apipayid as APIPayID,a.payaccount,a.amount,a.create_time,a.callback_time, - a.status,a.operator,b.platform,b.mobile,b.tag,c.brl,d.total_recharge,d.total_recharge_count,d.total_withdraw,d.total_withdraw_count from ` + a.status,a.operator,b.platform,b.mobile,b.tag,c.inr,d.total_recharge,d.total_recharge_count,d.total_withdraw,d.total_withdraw_count from ` querySql := fmt.Sprintf(table1, table1Condition) + " inner join " + fmt.Sprintf(table2, table2Condition) + " on a.uid = b.id inner join " + table3 + " on a.uid = c.uid inner join " + table4 + " on a.uid = d.uid " diff --git a/modules/backend/handler/guser/getGameUserList.go b/modules/backend/handler/guser/getGameUserList.go index 457cec5..1e32f37 100644 --- a/modules/backend/handler/guser/getGameUserList.go +++ b/modules/backend/handler/guser/getGameUserList.go @@ -87,9 +87,9 @@ func GetGameUserList(c *gin.Context) { } } if len(req.Cash) > 0 { - cashSql = append(cashSql, fmt.Sprintf("brl >= %d", req.Cash[0])) + cashSql = append(cashSql, fmt.Sprintf("inr >= %d", req.Cash[0])) if len(req.Cash) > 1 { - cashSql = append(cashSql, fmt.Sprintf("brl <= %d", req.Cash[1])) + cashSql = append(cashSql, fmt.Sprintf("inr <= %d", req.Cash[1])) } } @@ -118,7 +118,7 @@ func GetGameUserList(c *gin.Context) { (SELECT uid,total_recharge,total_recharge_count,total_withdraw,total_withdraw_count,total_recharge-total_withdraw as diff from recharge_info %s)d on a.id = d.uid INNER JOIN - (SELECT uid,brl from player_currency %s)e + (SELECT uid,inr from player_currency %s)e on a.id = e.uid `, models.LinkMysqlCondi(userSql), linkB, models.LinkMysqlCondi(shareInfoSql), linkC, models.LinkMysqlCondi(vipSql), linkD, models.LinkMysqlCondi(rechargeInfoSql), models.LinkMysqlCondi(cashSql)) @@ -126,7 +126,7 @@ func GetGameUserList(c *gin.Context) { // 拉列表语句 sql := `SELECT a.id as UID,a.channel_id as ChannelID,a.country as Country,c.level as Level,a.mobile as Mobile,b.up1 as Up,a.status as Status, a.platform as Platform,a.online as Online,d.total_recharge as TotalRecharge,d.total_recharge_count as TotalRechargeCount,d.total_withdraw as TotalWithdraw, - d.total_withdraw_count as TotalWithdrawCount,e.brl as Brl,d.diff as Diff,a.last_login as LastLogin,a.birth as Birth,a.tag as Tag From ` + baseSql + d.total_withdraw_count as TotalWithdrawCount,e.inr as Brl,d.diff as Diff,a.last_login as LastLogin,a.birth as Birth,a.tag as Tag From ` + baseSql // 求和语句 sqlCount := `SELECT count(*) From ` + baseSql @@ -143,7 +143,7 @@ func GetGameUserList(c *gin.Context) { case 3: orderSql += " d.total_withdraw" case 4: - orderSql += " e.brl" + orderSql += " e.inr" case 5: orderSql += " d.diff" case 6: diff --git a/modules/backend/routers/routers_common.go b/modules/backend/routers/routers_common.go index 6d48479..60db64d 100644 --- a/modules/backend/routers/routers_common.go +++ b/modules/backend/routers/routers_common.go @@ -14,4 +14,5 @@ func common(e *gin.Engine) { e.GET("/common/userInfo", handler.UserInfo) // e.GET("/common/getGameInfo", handler.GameInfo) e.GET("/common/accountList", handler.AccountList) + e.POST("/common/uploadOSS", handler.UploadOSS) } diff --git a/modules/backend/values/protocol.go b/modules/backend/values/protocol.go index 62bea30..eeef714 100644 --- a/modules/backend/values/protocol.go +++ b/modules/backend/values/protocol.go @@ -264,3 +264,15 @@ type UserInfoResp struct { type AccountListResp struct { List []string } + +type UploadOSSReq struct { + Endpoint string + AccessKeyId string + AccessKeySecret string + BucketName string + ObjectName string +} + +type UploadOSSResp struct { + Url string +} diff --git a/modules/web/app/activity.go b/modules/web/app/activity.go index a4ad412..ba3b95b 100644 --- a/modules/web/app/activity.go +++ b/modules/web/app/activity.go @@ -5,8 +5,11 @@ import ( "server/common" "server/db" "server/modules/web/values" + "server/util" "sort" "time" + + "github.com/liangdas/mqant/log" ) // 从数据库中读取数据 @@ -24,6 +27,7 @@ func (g *Gin) CheckActivityExpire(id int) (pass bool) { return } +// GetUserTaskStatus 获取任务状态 func (a *Gin) GetUserTaskStatus() (ret []*values.OneTask) { tasks := call.GetConfigTask() for _, v := range tasks { @@ -33,49 +37,47 @@ func (a *Gin) GetUserTaskStatus() (ret []*values.OneTask) { Target: v.Target, Reward: v.Reward, Kind: v.Kind, - Type: v.Type, + Type: int(v.Type), Icon: v.Icon, Title: common.GetTaskTitle(v), Action: v.Action, } // 非次数任务,需转换目标数值 - if !common.IsNumTaskType(v.Type) { - one.Target /= common.DecimalDigits - } + // if !common.IsNumTaskType(v.Type) { + // one.Target /= common.DecimalDigits + // } ret = append(ret, one) } if a.UID <= 0 { return } - + now := time.Now() task := call.GetUserTaskData(a.UID) - now := time.Now().Unix() for _, v := range ret { - tag := false for _, k := range task { if v.TaskID == k.TaskID { v.Progess = k.Progress - tag = true - break - } - } - if !tag { - if v.Type == common.TaskTypeRegist { // 已注册且注册任务还没标记完成 - db.Mysql().Create(&common.TaskData{UID: a.UID, TaskID: v.TaskID, Progress: v.Target, Time: now}) - v.Progess = v.Target - } else if v.Type == common.TaskTypeDownload { // 已下载直接标记为完成 - if a.DeviceType == common.DeviceTypeWebview || a.DeviceType == common.DeviceTypePWA { - db.Mysql().Create(&common.TaskData{UID: a.UID, TaskID: v.TaskID, Progress: v.Target, Time: now}) - v.Progess = v.Target + taskTime := time.Unix(k.Time, 0) + // 跨天清空数据 + if !util.IsSameDay(now, taskTime) { + v.Status = 0 + v.Progess = 0 + err := db.Mysql().Update(&k, map[string]interface{}{ + "status": 0, + "progress": 0, + "time": now.Unix(), + }) + if err != nil { + log.Error("GetUserTaskStatus err:%v", err) + } } + break } } - // 非次数任务,需转换目标数值 - if !common.IsNumTaskType(v.Type) && v.Progess > 0 { - v.Progess /= common.DecimalDigits - } - + // if !common.IsNumTaskType(v.Type) && v.Progess > 0 { + // v.Progess /= common.DecimalDigits + // } if v.Progess < 0 { v.Progess = v.Target v.Status = 2 @@ -87,14 +89,5 @@ func (a *Gin) GetUserTaskStatus() (ret []*values.OneTask) { sort.SliceStable(ret, func(i, j int) bool { return ret[i].Status > ret[j].Status }) - // 完成的任务隐藏 - index := 0 - for i := range ret { - if ret[i].Status != 2 { - index = i - break - } - } - ret = ret[index:] return } diff --git a/modules/web/handler/activity.go b/modules/web/handler/activity.go index 95cfba1..ae1b420 100644 --- a/modules/web/handler/activity.go +++ b/modules/web/handler/activity.go @@ -453,8 +453,14 @@ func ActivityFreeSpinInfo(c *gin.Context) { // data.LastSpin = now // } db.Mysql().Create(data) + resp.Count = data.SpinNum } else if !util.IsSameDayTimeStamp(time.Now().Unix(), freeSpin.LastSpin) { resp.Count = common.DefaultFreeSpinNum + _, err := db.Mysql().UpdateRes(&common.ActivityFreeSpinData{UID: a.UID, LastSpin: freeSpin.LastSpin}, + map[string]interface{}{"spin_num": common.DefaultFreeSpinNum}) + if err != nil { + log.Error("ActivityFreeSpinInfo err:%v", err) + } } else { resp.Count = freeSpin.SpinNum } @@ -472,8 +478,7 @@ func ActivityFreeSpinDraw(c *gin.Context) { return } freeSpin := call.GetUserFreeSpinData(a.UID) - now := time.Now().Unix() - if util.IsSameDayTimeStamp(now, freeSpin.LastSpin) && freeSpin.SpinNum <= 0 { + if freeSpin.SpinNum <= 0 { a.Code = values.CodeRetry return } diff --git a/modules/web/handler/firstpage.go b/modules/web/handler/firstpage.go index 348ccb9..12baac4 100644 --- a/modules/web/handler/firstpage.go +++ b/modules/web/handler/firstpage.go @@ -1,8 +1,9 @@ package handler import ( + "context" + "errors" "fmt" - "math/rand" "server/call" "server/common" "server/db" @@ -13,6 +14,8 @@ import ( "time" "github.com/gin-gonic/gin" + "github.com/go-redis/redis/v8" + "github.com/liangdas/mqant/log" "github.com/olivere/elastic/v7" ) @@ -80,15 +83,84 @@ func FirstPage(c *gin.Context) { if len(list) > 0 { resp.Esport = list[0] } - task := call.GetConfigTaskByTaskType(common.TaskTypeDownload) - if len(task) > 0 { - resp.DownloadAppReward = task[0].Reward + // task := call.GetConfigTaskByTaskType(common.TaskTypeDownload) + // if len(task) > 0 { + // resp.DownloadAppReward = task[0].Reward + // } + + resp.ShowData = GetFirstShowData() +} + +// GetFirstShowData 首页展示数据 +func GetFirstShowData() values.ShowInfo { + ctx := context.Background() + // step: 平均提现时长 + now := time.Now() + currentHour := now.Format("2006-01-02-15") // 年-月-日-小时 + rdb := db.Redis().GetRedis() + pipeline := db.Redis().GetRedis().Pipeline() + keyPrefix := "firstpage:showdata:" + // 使用哈希存储平均提现时长 + key := keyPrefix + "average_withdrawal_time:" + currentHour + averageWithdrawalTime, err := rdb.HGet(ctx, key, "value").Int64() + if errors.Is(err, redis.Nil) { + averageWithdrawalTime = util.RandBetween64(15, 30) // 15-30之间 + pipeline.HSet(ctx, key, "value", averageWithdrawalTime) + pipeline.Expire(ctx, key, time.Hour) // 设置过期时间为1小时 + } + + // step: 今日平台提现总额 + withdrawalKey := keyPrefix + "withdrawal_info" + startTime, err := rdb.HGet(ctx, withdrawalKey, "start_time").Time() + withdrawal := int64(999*10 + 1000) + if err != nil || now.Day() != startTime.Day() { + startTime = now + pipeline.HSet(ctx, withdrawalKey, "start_time", startTime) + pipeline.HSet(ctx, withdrawalKey, "total_withdrawal", withdrawal) + } else { + elapsed := int(now.Sub(startTime).Hours()) + withdrawal = int64(elapsed * (999*10 + 1000)) + pipeline.HSet(ctx, withdrawalKey, "total_withdrawal", withdrawal) } - resp.ShowData = values.ShowInfo{ - Reward: rand.Int63n(1000000), - AverWithdraw: rand.Int63n(1000000), - MaxBet: rand.Int63n(1000000), - WithdrawCount: rand.Int63n(1000000), + // step: 当前累计奖金 + bonusKey := keyPrefix + "bonus_info" + totalBonus, err := rdb.HGet(ctx, bonusKey, "total_bonus").Int64() + if errors.Is(err, redis.Nil) { + totalBonus = 1549661 + pipeline.HSet(ctx, bonusKey, "total_bonus", totalBonus) + pipeline.HSet(ctx, bonusKey, "last_bonus_update_time", now) + } else { + lastUpdate, _ := rdb.HGet(ctx, bonusKey, "last_bonus_update_time").Time() + intervals := (now.Unix() - lastUpdate.Unix()) / 10 + totalBonus += util.RandBetween64(10, 2000) * intervals + pipeline.HSet(ctx, bonusKey, "total_bonus", totalBonus) + pipeline.HSet(ctx, bonusKey, "last_bonus_update_time", now) + } + + // step: 下注总额 + maxBetKey := keyPrefix + "max_bet_info" + maxBetStartTime, err := rdb.HGet(ctx, maxBetKey, "start_time").Time() + maxBet := int64(500) + if err != nil || now.Sub(maxBetStartTime) > 24*time.Hour { + maxBetStartTime = now + pipeline.HSet(ctx, maxBetKey, "start_time", maxBetStartTime) + pipeline.HSet(ctx, maxBetKey, "max_bet_amount", maxBet) + } else { + elapsed := now.Sub(startTime).Minutes() / 10 * 3 + maxBet = int64(500 * elapsed) + pipeline.HSet(ctx, maxBetKey, "max_bet_amount", maxBet) + } + // 执行Pipeline + _, err = pipeline.Exec(ctx) + if err != nil { + log.Error("Pipeline exec error: %v", err) + } + // 返回结果 + return values.ShowInfo{ + AverWithdraw: averageWithdrawalTime, + WithdrawCount: withdrawal, + Reward: totalBonus * 100, + MaxBet: maxBet * 100, } } diff --git a/modules/web/handler/game.go b/modules/web/handler/game.go index 033b855..bcc124a 100644 --- a/modules/web/handler/game.go +++ b/modules/web/handler/game.go @@ -29,8 +29,16 @@ func GameList(c *gin.Context) { resp := &values.GameListResp{Provider: req.Provider} a.Data = resp var list, tmp []*common.ConfigGameList + if req.Provider == -1 { + req.Provider = 0 + } + if req.Mark == -1 { + req.Mark = 0 + } + if req.Type == -1 || req.Type == 1 { + req.Type = 0 + } tmp = call.GetConfigGameList(0, req.Provider, req.Mark, req.Type) - if len(req.Name) > 0 { reqName := strings.ToLower(req.Name) for _, v := range tmp { diff --git a/modules/web/handler/share.go b/modules/web/handler/share.go index e2edbfa..957149b 100644 --- a/modules/web/handler/share.go +++ b/modules/web/handler/share.go @@ -84,6 +84,12 @@ func ShareInfo(c *gin.Context) { channel := call.GetChannelByID(a.Channel) if channel != nil { resp.ShareLink += channel.URL + "?code=" + "xxxxxx" + if a.Prefix != "" { + resp.ShareLink = a.Prefix + "." + resp.ShareLink + } else { + resp.ShareLink = "www." + resp.ShareLink + } + resp.ShareLink = "https://" + resp.ShareLink } a.GetUID() if a.UID <= 0 { @@ -105,6 +111,7 @@ func ShareInfo(c *gin.Context) { } else { resp.ShareLink = "www." + resp.ShareLink } + resp.ShareLink = "https://" + resp.ShareLink } } diff --git a/modules/web/handler/vip.go b/modules/web/handler/vip.go index 88c43c7..eedf6dc 100644 --- a/modules/web/handler/vip.go +++ b/modules/web/handler/vip.go @@ -93,6 +93,9 @@ func GetVipInfo(c *gin.Context) { resp.NextCashback = util.GetNext5MinUnix() - now.Unix() } } + if resp.Info.Cashback < 0 { + resp.Info.Cashback = 0 + } resp.CashbackList = []common.CurrencyBalance{} q := elastic.NewBoolQuery() q.Filter(elastic.NewTermQuery("uid", a.UID)) diff --git a/modules/web/handler/withdraw.go b/modules/web/handler/withdraw.go index e0b9e16..275ebad 100644 --- a/modules/web/handler/withdraw.go +++ b/modules/web/handler/withdraw.go @@ -183,7 +183,7 @@ func PlayerWithdrawBlock(c *gin.Context) { } } - orderID := "USDT" + util.NewOrderID(int(uid)) + orderID := "USDT" + util.NewOrderID(uid) // 第一步,先扣钱 err := call.MineCurrencyProReal(&common.UpdateCurrency{ CurrencyBalance: &common.CurrencyBalance{ @@ -210,7 +210,7 @@ func PlayerWithdrawBlock(c *gin.Context) { } order := &common.WithdrawOrder{ - UID: int(uid), + UID: uid, OrderID: orderID, APIPayID: "", // ProductID: one.ID, @@ -329,7 +329,7 @@ func PlayerWithdraw(c *gin.Context) { } } - orderID := util.NewOrderID(int(uid)) + orderID := util.NewOrderID(uid) // 第一步,先扣钱 pro := call.MineCurrencyProReal(&common.UpdateCurrency{ CurrencyBalance: &common.CurrencyBalance{ @@ -350,7 +350,7 @@ func PlayerWithdraw(c *gin.Context) { con := call.GetVipCon(uid) realAmount := need // 实际打款 if con != nil && con.Fee > 0 { - realAmount = common.RoundCurrency(req.CurrencyType, con.Fee) * realAmount + realAmount = common.RoundCurrency(req.CurrencyType, (1000-int64(con.Fee))*realAmount/1000) } var shouldAuto = false @@ -371,7 +371,7 @@ func PlayerWithdraw(c *gin.Context) { } order := &common.WithdrawOrder{ - UID: int(uid), + UID: uid, OrderID: orderID, APIPayID: "", // ProductID: one.ID, @@ -414,6 +414,7 @@ func NewWithdraw(req *values.WithdrawReq, uid int, ip string, uuid string) (stri log.Error("NewWithdrawImp err:%v,one:%+v", err, one) return "", values.CodeParam } + one.PayType = common.PayTypeBank if one.PayType == common.PayTypeUPI { return "The UPI channel is closed, please use the bank channel to withdraw cash.", values.CodeParam } diff --git a/modules/web/values/firstpage.go b/modules/web/values/firstpage.go index edc4d14..e22907b 100644 --- a/modules/web/values/firstpage.go +++ b/modules/web/values/firstpage.go @@ -1,6 +1,9 @@ package values -import "server/common" +import ( + "server/common" + "time" +) // GameNum 子项游戏请求个数 type FirstPageReq struct { @@ -20,10 +23,14 @@ type FirstPageResp struct { } type ShowInfo struct { - Reward int64 // 奖金 - AverWithdraw int64 // 平均提现市场 - MaxBet int64 // 今日最大下注 - WithdrawCount int64 // 今日提现总额 + Reward int64 `redis:"Reward"` // 奖金 + RewardTime time.Time `redis:"RewardTime"` + AverWithdraw int64 `redis:"AverWithdraw"` // 平均提现时间 + AverWithdrawTime time.Time `redis:"AverWithdrawTime"` + MaxBet int64 `redis:"MaxBet"` // 今日最大下注 + MaxBetTime time.Time `redis:"MaxBetTime"` + WithdrawCount int64 `redis:"WithdrawCount"` // 今日提现总额 + WithdrawCountTime int64 `redis:"WithdrawCountTime"` } type OneCurrency struct { ID common.CurrencyType diff --git a/modules/web/values/share.go b/modules/web/values/share.go index a32ac56..d3e0865 100644 --- a/modules/web/values/share.go +++ b/modules/web/values/share.go @@ -28,6 +28,7 @@ type ShareInfoResp struct { PlatformBetReward int64 PlatformTotalReward int64 Rank []*OneShareRank + Msg string // 后台配置消息 } type SharePlatformResp struct { diff --git a/util/util.go b/util/util.go index a4a2db1..4d0a5d8 100644 --- a/util/util.go +++ b/util/util.go @@ -844,3 +844,124 @@ func RandomOneEleFromSlice(slice interface{}, name string) int { } return 0 } + +func RandBetween64(min, max int64) int64 { + return rand.Int63n(max-min+1) + min +} + +func RandBetween(min, max int) int { + return rand.Intn(max-min+1) + min +} + +// HashMarshal 用于将结构体序列化为Redis哈希 +func HashMarshal(v interface{}) (map[string]interface{}, error) { + result := make(map[string]interface{}) + vType := reflect.TypeOf(v) + vValue := reflect.ValueOf(v) + + if vType.Kind() != reflect.Struct { + return nil, fmt.Errorf("HashMarshal: expected a struct type, got %v", vType.Kind()) + } + + for i := 0; i < vType.NumField(); i++ { + field := vType.Field(i) + fieldValue := vValue.Field(i) + redisTag := field.Tag.Get("redis") + if redisTag == "" || redisTag == "-" { + continue + } + + var value interface{} + switch fieldValue.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + value = fieldValue.Int() + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + value = fieldValue.Uint() + case reflect.Float32, reflect.Float64: + value = fieldValue.Float() + case reflect.String: + value = fieldValue.String() + case reflect.Bool: + value = fieldValue.Bool() + case reflect.Struct: + if t, ok := fieldValue.Interface().(time.Time); ok { + value = t.Format(time.RFC3339) + } else { + return nil, fmt.Errorf("HashMarshal: unsupported struct type %v for field %s", fieldValue.Kind(), field.Name) + } + default: + return nil, fmt.Errorf("HashMarshal: unsupported type %v for field %s", fieldValue.Kind(), field.Name) + } + + result[redisTag] = value + } + + return result, nil +} + +// HashUnmarshal 用于从Redis哈希反序列化为结构体 +func HashUnmarshal(data map[string]string, v interface{}) error { + vType := reflect.TypeOf(v).Elem() + vValue := reflect.ValueOf(v).Elem() + + if vType.Kind() != reflect.Struct { + return fmt.Errorf("HashUnmarshal: expected a struct type, got %v", vType.Kind()) + } + + for i := 0; i < vType.NumField(); i++ { + field := vType.Field(i) + fieldValue := vValue.Field(i) + redisTag := field.Tag.Get("redis") + if redisTag == "" || redisTag == "-" { + continue + } + + strValue, ok := data[redisTag] + if !ok { + continue + } + + switch fieldValue.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + intValue, err := strconv.ParseInt(strValue, 10, 64) + if err != nil { + return err + } + fieldValue.SetInt(intValue) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + uintValue, err := strconv.ParseUint(strValue, 10, 64) + if err != nil { + return err + } + fieldValue.SetUint(uintValue) + case reflect.Float32, reflect.Float64: + floatValue, err := strconv.ParseFloat(strValue, 64) + if err != nil { + return err + } + fieldValue.SetFloat(floatValue) + case reflect.String: + fieldValue.SetString(strValue) + case reflect.Bool: + boolValue, err := strconv.ParseBool(strValue) + if err != nil { + return err + } + fieldValue.SetBool(boolValue) + case reflect.Struct: + if fieldValue.Type() == reflect.TypeOf(time.Time{}) { + t, err := time.Parse(time.RFC3339, strValue) + if err != nil { + return err + } + fieldValue.Set(reflect.ValueOf(t)) + } else { + return fmt.Errorf("HashUnmarshal: unsupported struct type %v for field %s", fieldValue.Kind(), field.Name) + } + default: + return fmt.Errorf("HashUnmarshal: unsupported type %v for field %s", fieldValue.Kind(), field.Name) + } + } + + return nil +}