package call import ( "encoding/json" "errors" "fmt" "math/rand" "reflect" "server/common" "server/config" "server/db" "server/natsClient" "server/pb" "server/util" "strconv" "time" "github.com/liangdas/mqant/log" "gorm.io/gorm" ) // 查询用户的信息 func GetUserInfo(uid int) (ret *common.PlayerDBInfo, err error) { ret = db.Redis().GetUserData(uid) if ret != nil { return } ret = &common.PlayerDBInfo{Id: uid} err = db.Mysql().Get(ret) return } // 查询用户的信息 func GetUserXInfo(uid int, fields ...string) (ret *common.PlayerDBInfo, err error) { ret = new(common.PlayerDBInfo) err = db.Redis().GetUserXInfo(uid, ret, fields...) if err == nil { return } // sqlFields := []string{} // for _, v := range fields { // sqlFields = append(sqlFields, v) // } ret = &common.PlayerDBInfo{Id: uid} err = db.Mysql().SelectField(ret, fields...) return } // 查询用户的信息 func GetUserXInfoByDB(uid int, fields ...string) (ret *common.PlayerDBInfo, err error) { ret = &common.PlayerDBInfo{Id: uid} err = db.Mysql().SelectField(ret, fields...) return } // UpdateUserXinfo更新玩家信息 func UpdateUserXInfo(p *common.PlayerDBInfo, update map[string]interface{}) error { if err := db.Mysql().Update(p, update); err != nil { log.Error("err:%v", err) return err } if err := db.Redis().UpdateUserFields(p.Id, update); err != nil { log.Error("err:%v", err) return err } return nil } // AddUserXInfo 更新玩家某个字段 func AddUserXInfo(uid int, field string, value int64, tx ...*gorm.DB) error { p := &common.PlayerDBInfo{Id: uid} dbUpdate := map[string]interface{}{field: gorm.Expr(fmt.Sprintf("%v + ?", field), value)} if tx == nil { if err := db.Mysql().Update(p, dbUpdate); err != nil { log.Error("err:%v", err) return err } } else { if err := tx[0].Model(p).Where(p).Updates(dbUpdate).Error; err != nil { log.Error("err:%v", err) return err } } if err := db.Redis().HIncrBy(common.GetRedisKeyUser(uid), field, value); err != nil { log.Error("err:%v", err) return err } return nil } func initPlayer(uid, channel int) { db.Mysql().Create(&common.PlayerData{UID: uid}) initCoin := GetConfigPlatform().NewPlayerGift if initCoin < 0 { initCoin = 0 } db.Mysql().Create(&common.PlayerCurrency{UID: uid, ChannelID: channel, BRL: initCoin}) // db.Mysql().C().Table(common.PlayerRechargeTableName).Create(&common.PlayerCurrency{UID: uid, ChannelID: channel}) db.Mysql().Create(&common.PlayerProfile{UID: uid, ChannelID: channel, NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, initCoin)}) } func NewUser(info *common.PlayerDBInfo, ip, share, fbc, fbp, agent string) error { // if info.AreaCode == "" { // i, err := call.SearchIP(ip) // log.Debug("searchip:%v,res:%v", ip, i) // if err != nil { // log.Error("err:%v", err) // } // id := call.GetCountryIDByCName(i.Country) // log.Debug("i.Country:%v", i.Country) // if id == "" { // id = "US" // } // info.AreaCode = id // } isOld := false if config.GetBase().Release && !IsWhite(ip, "") { // 首先判断ip // if db.Mysql().Count(&common.PlayerDBInfo{}, fmt.Sprintf("ip = '%s' and channel_id = %d", ip, info.ChannelID)) >= int64(config.GetConfig().Web.MaxPlayerAccountIP) { // log.Debug("ip:%v 创建过多账号", ip) // return errors.New("ip") // } if info.DeviceId != "" { if IsBlackListPlayer(&common.BlackList{DeviceID: info.DeviceId, Phone: info.Mobile}) { log.Debug("deviceid:%v 在黑名单里", info.DeviceId) return errors.New("ip") } count := db.Mysql().Count(&common.PlayerDBInfo{}, fmt.Sprintf("deviceid = '%v' and channel_id = %d", info.DeviceId, info.ChannelID)) isOld = count > 1 if count >= int64(config.GetConfig().Web.MaxPlayerAccountIP) { log.Debug("deviceid:%v 创建过多账号", info.DeviceId) return errors.New("ip") } } } r := []rune(info.Nick) if len(r) > 13 { info.Nick = string(r[:13]) } if info.Avatar == "" { info.Avatar = RandomUserAvatar() } info.Status = common.AccountStatusNormal info.Birth = time.Now().Unix() info.Country = GetCountry(ip) // initCoin := GetConfigPlatform().NewPlayerGift // if info.AccountType == common.PlatformPhone { // initCoin += GetConfigPlatform().BindPhoneGift // } // info.BindCash = initCoin if err := db.Mysql().Create(info); err != nil { return err } // 游客昵称 if len(r) < 2 { info.Nick = fmt.Sprintf("User%v", info.Id) if err := db.Mysql().Update(&common.PlayerDBInfo{Id: info.Id}, map[string]interface{}{"nick": info.Nick}); err != nil { log.Error("err:%v", err) return err } } uid := info.Id cid := info.ChannelID // balance := &common.CurrencyBalance{UID: uid, Type: common.CurrencyTypeBindCash, // Event: common.CurrencyEventNewPlayer, Value: initCoin, ChannelID: info.ChannelID, // Balance: initCoin, Time: time.Now().Unix(), Exs1: "NewPlayer"} util.Go(func() { initPlayer(uid, cid) UploadAdjust(common.AdjustEventNewPlayer, info, nil) ShareBind(share, isOld, uid, cid) // 新手赠送 first := config.GetConfig().Web.FreeSpinFirst if first > 0 { UpdateCurrencyPro(&common.UpdateCurrency{ CurrencyBalance: &common.CurrencyBalance{ UID: uid, Value: first, ChannelID: info.ChannelID, Type: common.CurrencyBrazil, Event: common.CurrencyEventActivityFreeSpin, NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, first), }, }) } FBBind(ip, uid, cid, fbc, fbp, agent) UploadFB(uid, FBEventRegist, 0) UploadKwai(uid, KwaiEventRegist, 0) }) return nil } // fb绑定 func FBBind(ip string, uid, cid int, fbc, fbp, agent string) { // 优先ip绑定 pa := &common.PlayerADData{IP: ip, ChannelID: cid} db.Mysql().GetLast(pa) if pa.ID != 0 { if pa.UID == 0 { db.Mysql().Update(pa, map[string]interface{}{"uid": uid}) } else { newPa := &common.PlayerADData{UID: uid, IP: ip, ChannelID: cid, FBC: pa.FBC, FBP: pa.FBP, UserAgent: agent} db.Mysql().Create(newPa) } return } // 绑定fb数据 if len(fbc) != 0 || len(fbp) != 0 { pa := &common.PlayerADData{ChannelID: cid, FBC: fbc, FBP: fbp} db.Mysql().GetLast(pa) if pa.ID == 0 { newPa := &common.PlayerADData{UID: uid, IP: ip, ChannelID: cid, FBC: pa.FBC, FBP: pa.FBP, UserAgent: agent} db.Mysql().Create(newPa) return } if pa.UID == 0 { db.Mysql().Update(pa, map[string]interface{}{"uid": uid}) return } newPa := &common.PlayerADData{UID: uid, IP: ip, ChannelID: cid, FBC: pa.FBC, FBP: pa.FBP, UserAgent: agent} db.Mysql().Create(newPa) return } } func RandomUserAvatar() string { max := GetConfigPlatform().AvatarCount if max <= 0 { max = 15 } ran := rand.Intn(max) + 1 return strconv.Itoa(ran) } func RandomRobotAvatar() string { ranMethod := rand.Intn(100) // 30%使用卡通头像 if ranMethod < 30 { return RandomUserAvatar() } max := GetConfigPlatform().AvatarCount if max <= 0 { max = 200 } ran := rand.Intn(max) return strconv.Itoa(ran) } func IsUserNickValid(nick string) bool { n := []rune(nick) if len(n) < 1 || len(n) > 15 { return false } return true } func InsertLoginRecord(uid, channel int, ip string, birth int64, deviceType int) { date := time.Now().Format("20060102") one := &common.LoginRecord{UID: uid, ChannelID: channel, Date: date} db.Mysql().Get(one) re := GetRechargeInfo(uid) isRecharge := 2 if re.TotalRecharge > 0 { isRecharge = 1 } if one.ID > 0 { u := &common.LoginRecord{} u.ID = one.ID db.Mysql().Update(u, map[string]interface{}{"time": time.Now().Unix(), "platform": deviceType, "ip": ip, "is_recharge": isRecharge}) return } one.IP = ip one.UID = uid one.Date = date one.ChannelID = channel one.Time = time.Now().Unix() one.Platform = deviceType one.FirstTime = util.GetZeroTime(time.Unix(birth, 0)).Unix() one.IsRecharge = isRecharge if util.IsSameDayTimeStamp(birth, one.Time) { one.Status = common.NewUser } else { one.Status = common.OldUser } db.Mysql().Create(one) } func GetVIP(uid int) *common.VipData { data := &common.VipData{UID: uid} err := db.Mysql().Get(data) if err == gorm.ErrRecordNotFound { re := &common.RechargeInfo{UID: uid} db.Mysql().Get(re) data.Exp = re.TotalRecharge if data.Exp > 0 { cons := GetConfigVIP() for i := len(cons) - 1; i >= 0; i-- { if data.Exp >= cons[i].Exp && cons[i].Exp >= 0 { data.Level = cons[i].Level + 1 break } } } util.Go(func() { db.Mysql().Create(data) }) } else { level := GetVipLevel(data.Exp, data.Bet) if level != data.Level { data.Level = level db.Mysql().UpdateRes(&common.VipData{UID: uid}, map[string]interface{}{"level": level}) } } return data } func GetVipCon(uid int) *common.ConfigVIP { data := &common.VipData{UID: uid} err := db.Mysql().Get(data) if err == gorm.ErrRecordNotFound { util.Go(func() { db.Mysql().Create(data) }) } return GetConfigVIPByLevel(data.Level) } func GetVipLevel(exp, bet int64) int { con := GetConfigVIP() for i := len(con) - 2; i >= 0; i-- { if con[i].Exp > 0 && exp >= con[i].Exp && con[i].Bet > 0 && bet >= con[i].Bet { // 升级 return con[i].Level } } return 0 } // UpdateVip 增加vip经验 func UpdateVip(uid int, exp, bet, settle int64) { for i := 0; i < 3; i++ { vip := GetVIP(uid) update := map[string]interface{}{} if exp > 0 { update["exp"] = gorm.Expr("exp + ?", exp) } if bet > 0 { update["bet"] = gorm.Expr("bet + ?", bet) } con := GetVipCon(uid) win := bet - settle // 刷新返利盈利 now := time.Now().Unix() reset := false if config.GetBase().Release { reset = !util.IsSameDayTimeStamp(now, vip.ProfitTime) } else { reset = util.GetNext5MinUnix()-vip.ProfitTime >= 5*60 } if reset { if con != nil && vip.ProfitTime != 0 { update["cashback"] = vip.Profit * con.Cashback / 1000 } update["profit"] = win update["profit_time"] = now } else { update["profit"] = gorm.Expr("profit + ?", win) } level := GetVipLevel(vip.Exp+exp, vip.Bet+bet) if level != vip.Level { // 升级 update["level"] = level } res := db.Mysql().C().Model(&common.VipData{}).Where("uid = ? and exp = ? and bet = ?", uid, vip.Exp, vip.Bet).Updates(update) if res.Error != nil { log.Error("err:%v", res.Error) } if res.RowsAffected > 0 { // 通知客户端等级变动 if update["level"] != nil { SendNR(uid, int(pb.ServerCommonResp_CommonVipResp), &pb.ConfigChangeResp{Type: pb.ConfigChangeType_ConfigVipLevel}, "common") } break } } } // IsBlackListPlayer 判断用户是否是黑名单用户 func IsBlackListPlayer(data *common.BlackList) bool { if GetConfigPlatform().BlackList == 0 { return false } phone := data.Phone payAccount := data.PayAccount email := data.Email deviceID := data.DeviceID if phone == "" && payAccount == "" && email == "" && deviceID == "" { return false } sql := "" if len(phone) > 0 { sql += fmt.Sprintf("phone = '%s' ", phone) } if len(payAccount) > 0 { if len(sql) > 0 { sql += fmt.Sprintf("or pay_account = '%s' ", payAccount) } else { sql += fmt.Sprintf("pay_account = '%s' ", payAccount) } } if len(deviceID) > 0 { if len(sql) > 0 { sql += fmt.Sprintf("or deviceid = '%s' ", deviceID) } else { sql += fmt.Sprintf("deviceid = '%s' ", deviceID) } } if len(email) > 0 { if len(sql) > 0 { sql += fmt.Sprintf("or email = '%s' ", email) } else { sql += fmt.Sprintf("email = '%s' ", email) } } if len(sql) == 0 { return false } var count int64 db.Mysql().C().Model(&common.BlackList{}).Where(sql).Limit(1).Count(&count) return count > 0 } // 封号 func KickPlayer(uid int) { UpdateUserXInfo(&common.PlayerDBInfo{Id: uid}, map[string]interface{}{"status": 2}) player, _ := GetUserXInfo(uid, "token") if player.Token != "" { db.Redis().Delkey(common.GetRedisKeyToken(player.Token)) } db.Redis().Delkey(common.GetRedisKeyUser(uid)) Publish(natsClient.TopicInnerOptPlayer, &pb.InnerOptPlayer{UID: uint32(uid), Opt: common.OptPlayerTypeKick}) } // BlackListAndKick 判断用户是否是黑名单用户并且直接封号 func BlackListAndKick(uid int, data *common.BlackList) bool { if IsBlackListPlayer(data) { KickPlayer(uid) db.ES().InsertToESGO(common.ESIndexBackBlackList, &common.ESBlackList{UID: uid, Name: data.Name, PayAccount: data.PayAccount, Email: data.Email, Phone: data.Phone, Time: time.Now().Unix()}) return true } return false } // GetItems 拉取用户道具 func GetItems(uid int) *common.PlayerItems { data := &common.PlayerItems{UID: uid} err := db.Mysql().Get(data) if err == gorm.ErrRecordNotFound { util.Go(func() { db.Mysql().Create(data) }) } return data } // IsUserBan 判断用户是否被禁 func IsUserBan(uid int) bool { p, _ := GetUserXInfo(uid, "status") return p.Status == common.AccountStatusLimit } // 赢钱账户的总额 func GetUserCurrency(uid int, t common.CurrencyType) int64 { var ret int64 db.Mysql().C().Model(&common.PlayerCurrency{UID: uid}).Select(t.GetCurrencyName()).Scan(&ret) return ret } // 获取充值账户的总额 func GetUserCurrencyRecharge(uid int, t common.CurrencyType) int64 { var pcr int64 db.Mysql().C().Table(common.PlayerRechargeTableName).Where("uid = ?", uid).Select(t.GetCurrencyName()).Scan(&pcr) return pcr } // 获取充值账户+赢钱账户的总额 func GetUserCurrencyTotal(uid int, t common.CurrencyType) int64 { var pc, pcr int64 db.Mysql().C().Model(&common.PlayerCurrency{UID: uid}).Select(t.GetCurrencyName()).Scan(&pc) db.Mysql().C().Table(common.PlayerRechargeTableName).Where("uid = ?", uid).Select(t.GetCurrencyName()).Scan(&pcr) return pc + pcr } func GetUserCurrencyFloat(uid int, t common.CurrencyType, num int) float64 { var pc, pcr int64 if err := db.Mysql().C().Model(&common.PlayerCurrency{UID: uid}).Select(t.GetCurrencyName()).Scan(&pc).Error; err != nil { log.Error("err:%v", err) } if err := db.Mysql().C().Table(common.PlayerRechargeTableName).Where("uid = ?", uid).Select(t.GetCurrencyName()).Scan(&pcr).Error; err != nil { log.Error("err:%v", err) } return util.Decimal(float64(pc+pcr)/common.DecimalDigits, num) } func GetUserCurrencyByName(uid int, currencyName string) int64 { pc := &common.PlayerCurrency{UID: uid} db.Mysql().Get(pc) ref := reflect.ValueOf(pc).Elem().FieldByName(currencyName) if ref.IsValid() { return ref.Int() } return 0 } func IsNewPlayer(birth int64) bool { return time.Now().Unix()-birth < 24*60*60 } func GetPlayerRechargeInfoByCurrency(uid int, t common.CurrencyType) *common.RechargeInfoCurrency { reu := &common.RechargeInfoCurrency{} tableName := fmt.Sprintf("recharge_info_%s", t.GetCurrencyName()) db.Mysql().C().Table(tableName).Where("uid = ?", uid).Scan(reu) return reu } func UpdatePlayerRechargeInfoCurrency(uid int, t common.CurrencyType, u map[string]interface{}, tx ...*gorm.DB) error { tableName := fmt.Sprintf("recharge_info_%s", t.GetCurrencyName()) if len(tx) > 0 { return tx[0].Table(tableName).Where("uid = ?", uid).Updates(u).Error } return db.Mysql().C().Table(tableName).Where("uid = ?", uid).Updates(u).Error } func GetPlayerProfileByCurrency(uid int, t common.CurrencyType) *common.PlayerProfile { pp := &common.PlayerProfile{} tableName := fmt.Sprintf("player_profile_%s", t.GetCurrencyName()) db.Mysql().C().Table(tableName).Where("uid = ?", uid).Scan(pp) return pp } func UpdatePlayerProfile(data *common.ESGameData) error { t := data.Type bet := data.BetAmount settle := data.SettleAmount uid := data.UID var err error if data.Channel == 0 || data.Birth == 0 { p, _ := GetUserXInfo(uid, "channel_id", "birth") data.Channel = p.ChannelID data.Birth = p.Birth } log.Debug("UpdatePlayerProfile:%+v", data) u := map[string]interface{}{"total_bet": gorm.Expr("total_bet + ?", bet), "total_settle": gorm.Expr("total_settle + ?", settle), "total_counts": gorm.Expr("total_counts + 1")} if db.Mysql().Exist(&common.PlayerProfile{UID: uid}) { // 先更新总数据 db.Mysql().Update(&common.PlayerProfile{UID: uid}, u) } else { db.Mysql().Create(&common.PlayerProfile{UID: uid, ChannelID: data.Channel, TotalBet: bet, TotalCounts: 1, TotalSettle: settle}) } // if err != nil { // log.Error("err:%v", err) // return err // } UpdateUserNeedBet(uid, data.BetAmount) // 更新货币数据 tableName := fmt.Sprintf("player_profile_%s", t.GetCurrencyName()) var count int64 db.Mysql().C().Table(tableName).Where("uid = ?", uid).Count(&count) if count > 0 { u["total_bet"] = gorm.Expr("total_bet + ?", bet) u["total_settle"] = gorm.Expr("total_settle + ?", settle) err = db.Mysql().C().Table(tableName).Where("uid = ?", uid).Updates(u).Error } else { err = db.Mysql().C().Table(tableName).Create(&common.PlayerProfile{UID: uid, ChannelID: data.Channel, TotalBet: bet, TotalCounts: 1, TotalSettle: settle}).Error } if err != nil { log.Error("err:%v", err) } util.Go(func() { // 更新vip UpdateVip(uid, 0, bet, settle) }) // 写入es data.Time = time.Now().Unix() data.IsNew = util.IsSameDayTimeStamp(data.Time, data.Birth) db.ES().InsertToESGO(common.ESIndexGameData, data) return nil } func GetPlayerData(uid int) *common.PlayerData { data := &common.PlayerData{UID: uid} db.Mysql().Get(data) return data } func GetPlayerPayData(uid int) *common.PlayerPayData { data := &common.PlayerPayData{UID: uid} db.Mysql().Get(data) if data.ID == 0 { db.Mysql().Create(data) } if data.BreakGift != "" { err := json.Unmarshal([]byte(data.BreakGift), &data.SubBreakGift) if err != nil { log.Error("err:%v", err) } } return data } func GetUserNeedBet(uid int) int64 { pro := &common.PlayerProfile{UID: uid} db.Mysql().Get(pro) return pro.NeedBet } func GetUserTaskData(uid int) (ret []common.TaskData) { if uid == 0 { return } db.Mysql().QueryAll(fmt.Sprintf("uid = %d", uid), "", &common.TaskData{}, &ret) return } func GetUserTaskDataByTaskID(uid, taskID int) *common.TaskData { data := &common.TaskData{UID: uid, TaskID: taskID} db.Mysql().Get(data) return data } func UpdateUserNeedBet(uid int, amount int64) { util.Go(func() { for i := 0; i < 3; i++ { pro := &common.PlayerProfile{UID: uid} db.Mysql().Get(pro) if pro.NeedBet == 0 { return } var rows int64 var err error if pro.NeedBet < amount { rows, err = db.Mysql().UpdateResW(&common.PlayerProfile{}, map[string]interface{}{"need_bet": 0}, fmt.Sprintf("uid = %d and need_bet = %d", uid, pro.NeedBet)) } else { rows, err = db.Mysql().UpdateResW(&common.PlayerProfile{}, map[string]interface{}{"need_bet": gorm.Expr("need_bet - ?", amount)}, fmt.Sprintf("uid = %d and need_bet = %d", uid, pro.NeedBet)) } if rows == 0 || err != nil { log.Error("err:%v", err) time.Sleep(time.Second) continue } return } }) }