package service import ( "context" "math" "sort" "time" mhayaTime "github.com/mhaya/extend/time" cutils "github.com/mhaya/extend/utils" "github.com/mhaya/game/game_cluster/internal/code" "github.com/mhaya/game/game_cluster/internal/constant" "github.com/mhaya/game/game_cluster/internal/mdb" "github.com/mhaya/game/game_cluster/internal/mdb/eventmodels" "github.com/mhaya/game/game_cluster/internal/mdb/models" "github.com/mhaya/game/game_cluster/nodes/webadmin/common" "github.com/mhaya/game/game_cluster/nodes/webadmin/entity" "github.com/mhaya/game/game_cluster/nodes/webadmin/model" mhayaLogger "github.com/mhaya/logger" "github.com/spf13/cast" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "gorm.io/gorm" ) type Synthesis struct { nodeId string db *mongo.Database } func NewSynthesis(nodeId string) *Synthesis { return &Synthesis{ nodeId: nodeId, db: mdb.MDB, } } // 综合统计 func (s *Synthesis) Overview(req entity.OverviewReq) (*entity.OverviewResp, *code.Result) { page, pageSize := checkPageParam(req.Page, req.Size) playerMgr := NewPlayerManage() // 根据条件查询 if req.UserName != "" { detail, codeResult := s.getOverviewDetail(req.UserName) if codeResult != nil { mhayaLogger.Warnf("Overview getOverviewDetail error:%v", codeResult) return nil, codeResult } if detail == nil { return nil, nil } var results []*entity.OverviewDetail results = append(results, detail) return &entity.OverviewResp{ Details: results, Total: 1, }, nil } // 查询列表 listResp, codeResult := playerMgr.List(context.Background(), entity.PlayerListReq{ Page: page, Size: pageSize, }) if codeResult != nil { mhayaLogger.Warnf("Overview List error:%v", codeResult) return nil, codeResult } var results []*entity.OverviewDetail for _, detail := range listResp.Details { detail, codeResult := s.getOverviewDetail(detail.UserName) if codeResult != nil { mhayaLogger.Warnf("Overview getOverviewDetail error:%v", codeResult) return nil, codeResult } if detail != nil { results = append(results, detail) } } count, codeResult := playerMgr.GetPlayerTotalCount() if codeResult != nil { mhayaLogger.Warnf("Overview GetPlayerTotalCount codeResult:%v", codeResult) return nil, codeResult } return &entity.OverviewResp{ Details: results, Total: count, }, nil } func (s *Synthesis) getOverviewDetail(userName string) (*entity.OverviewDetail, *code.Result) { userDetail, codeResult := s.getUserDetail(userName) if codeResult != nil { mhayaLogger.Warnf("getOverviewDetail getUserDetail error:%v", codeResult) return nil, codeResult } activeDetail, codeResult := s.getActive(userName) if codeResult != nil { mhayaLogger.Warnf("getOverviewDetail getActive error:%v", codeResult) return nil, codeResult } assetDetail, codeResult := s.getAsset(userName) if codeResult != nil { mhayaLogger.Warnf("getOverviewDetail getAsset error:%v", codeResult) return nil, codeResult } playerMgr := NewPlayerManage() // 获取最新的用户骰子投掷记录 diceRecord, codeResult := playerMgr.GetPlayerLastestDiceRecord(userName) if codeResult != nil { mhayaLogger.Warnf("getOverviewDetail GetPlayerLastestDiceRecord error:%v", codeResult) return nil, codeResult } // 获取最新的用户登录记录 loginRecord, codeResult := playerMgr.GetPlayerLastestLoginRecord(userName) if codeResult != nil { mhayaLogger.Warnf("getOverviewDetail GetPlayerLastestLoginRecord error:%v", codeResult) return nil, codeResult } return &entity.OverviewDetail{ UserName: userName, OpenId: userDetail.OpenId, FirstLoginDate: userDetail.FirstLoginDate, CreateTime: userDetail.CreateTime, LastLoginTime: userDetail.LastLoginTime, MaxSuccessions: activeDetail.MaxSuccessions, DieRoll: int64(diceRecord.Count), CurrentIntegral: assetDetail.PointsValue, SuccessfulInvitations: activeDetail.SuccessfulInvitations, Withdrawals: activeDetail.Withdrawals, CumulativeWithdrawalAmount: activeDetail.CumulativeWithdrawalAmount, TurntableRuns: activeDetail.TurntableRuns, PointsRanking: func() int64 { if loginRecord != nil { return loginRecord.PointsRankSeq } return 0 }(), RankingOfDiceRolls: func() int64 { if loginRecord != nil { return loginRecord.ThrowDiceRankSeq } return 0 }(), InvitesRanking: func() int64 { if loginRecord != nil { return loginRecord.InviteUserRankSeq } return 0 }(), TonValue: assetDetail.TonValue, UsdtValue: assetDetail.UsdtValue, }, nil } // 统计用户相关信息 func (s *Synthesis) UserList(req entity.UserListReq) (*entity.UserListResp, *code.Result) { page, pageSize := checkPageParam(req.Page, req.Size) playerMgr := NewPlayerManage() // 根据条件查询 if req.UserName != "" { detail, codeResult := s.getUserDetail(req.UserName) if codeResult != nil { mhayaLogger.Warnf("UserList getUserDetail error:%v", codeResult) return nil, codeResult } if detail == nil { return nil, nil } var results []*entity.UserListDetail results = append(results, detail) return &entity.UserListResp{ Details: results, Total: 1, }, nil } // 查询列表 listResp, codeResult := playerMgr.List(context.Background(), entity.PlayerListReq{ Page: page, Size: pageSize, }) if codeResult != nil { mhayaLogger.Warnf("UserList List error:%v", codeResult) return nil, codeResult } var results []*entity.UserListDetail for _, detail := range listResp.Details { ret, codeResult := s.getUserDetail(detail.UserName) if codeResult != nil { mhayaLogger.Warnf("UserList getUserDetail error:%v", codeResult) return nil, codeResult } if detail != nil { results = append(results, ret) } } count, codeResult := playerMgr.GetPlayerTotalCount() if codeResult != nil { mhayaLogger.Warnf("UserList GetPlayerTotalCount codeResult:%v", codeResult) return nil, codeResult } return &entity.UserListResp{ Details: results, Total: int64(count), }, nil } func (s *Synthesis) getUserDetail(userName string) (*entity.UserListDetail, *code.Result) { playerMgr := NewPlayerManage() // 获取注册记录 registerRecord, codeResult := playerMgr.GetRegisterRecord(userName) if codeResult != nil { mhayaLogger.Warnf("getUserDetail GetRegisterRecord error:%v", codeResult) return nil, codeResult } if registerRecord == nil { mhayaLogger.Warnf("getUserDetail registerRecord:%v", registerRecord) return nil, nil } // 获取用户的首次登录记录 firstLoginRecord, codeResult := playerMgr.GetPlayerFirstLoginRecord(userName) if codeResult != nil { mhayaLogger.Warnf("getUserDetail GetPlayerFirstLoginRecord error:%v", codeResult) return nil, codeResult } // 获取最新的用户登录记录 loginRecord, codeResult := playerMgr.GetPlayerLastestLoginRecord(userName) if codeResult != nil { mhayaLogger.Warnf("getUserDetail GetPlayerLastestLoginRecord error:%v", codeResult) return nil, codeResult } return &entity.UserListDetail{ UserName: userName, OpenId: func() string { if loginRecord != nil { return loginRecord.TgId } return "" }(), CreateTime: registerRecord.CreateAt, FirstLoginDate: func() int64 { if firstLoginRecord != nil { return firstLoginRecord.CreateAt } return 0 }(), LoginIP: func() string { if loginRecord != nil { return loginRecord.Ip } return "" }(), LastLoginTime: func() int64 { if loginRecord != nil { return loginRecord.CreateAt } return 0 }(), TonWall: func() string { if loginRecord != nil { return loginRecord.TonWall } return "" }(), Fingerprint: func() string { if loginRecord != nil { return loginRecord.Fingerprint } return "" }(), }, nil } func (s *Synthesis) FindMDBUserLogDaily(req entity.UserLogDailyReq) (*entity.UserLogDailyResp, *code.Result) { page, pageSize := checkPageParam(req.Page, req.Size) // 定义上下文 ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second) defer cancel() // 指定集合 collection := mdb.MDB.Collection(constant.CNamePlayerDailyRecord) // 构建查询条件 - 如果查询值为空那就不添加查询条件 filter := bson.M{} if req.StartTime != 0 { filter["daily"] = bson.M{ "$gte": req.StartTime, "$lte": req.EndTime, } } if req.Platform != "" && req.Platform != "all" { filter["platform"] = req.Platform } if req.Channel != "" { filter["channel"] = req.Channel } // 计算总数 count, err := collection.CountDocuments(ctx, filter) if err != nil { mhayaLogger.Warnf("FindMDBUserLogDaily CountDocuments error:%v", err) return nil, common.NewResult(code.InternalError) } // 执行查询 opts := options.Find() opts.SetSkip(int64((page - 1) * pageSize)) opts.SetLimit(int64(pageSize)) opts.SetSort(bson.D{{"daily", -1}}) cursor, err := collection.Find(ctx, filter, opts) if err != nil { mhayaLogger.Warnf("FindMDBUserLogDaily Find error:%v", err) return nil, common.NewResult(code.InternalError) } defer cursor.Close(ctx) // 解析查询结果 var results []*entity.UserLogDailyDetail for cursor.Next(ctx) { var result *entity.UserLogDailyDetail err := cursor.Decode(&result) if err != nil { mhayaLogger.Warnf("FindMDBUserLogDaily Decode error:%v", err) return nil, common.NewResult(code.InternalError) } results = append(results, result) } // 同一天的数据全部放到platform= ALl 且数据累加 // 如果没有platform=all 的那就新增一个 同一个时间段只能有一个 platform=all // 将同一天的数据累加到platform=all的记录中 allPlatformRecordMap := make(map[int64]*entity.UserLogDailyDetail) for _, result := range results { allPlatformRecordMap[result.Timestamp] = &entity.UserLogDailyDetail{ Timestamp: result.Timestamp, Platform: "all", } } for _, v := range results { if v.Timestamp == allPlatformRecordMap[v.Timestamp].Timestamp { allPlatformRecordMap[v.Timestamp].Registered += v.Registered allPlatformRecordMap[v.Timestamp].LoggedIn += v.LoggedIn allPlatformRecordMap[v.Timestamp].NewActive += v.NewActive allPlatformRecordMap[v.Timestamp].OldActive += v.OldActive allPlatformRecordMap[v.Timestamp].TotalPoints += v.TotalPoints allPlatformRecordMap[v.Timestamp].UProduced += v.UProduced allPlatformRecordMap[v.Timestamp].UCashout += v.UCashout allPlatformRecordMap[v.Timestamp].NewLogin += v.NewLogin allPlatformRecordMap[v.Timestamp].OldLogin += v.OldLogin } } // 替换原有结果 for _, record := range allPlatformRecordMap { results = append(results, record) } return &entity.UserLogDailyResp{ Details: results, Total: count, }, nil } // FindWithdrawal 根据请求查询提现记录 func (s *Synthesis) FindWithdrawal(req entity.UserWithdrawalReq) (*entity.UserWithdrawalResp, *code.Result) { page, pageSize := checkPageParam(req.Page, req.Size) if req.Currency != "" && !constant.CurrencyValid(req.Currency) { mhayaLogger.Warnf("FindWithdrawal unknow currency:%v", req.Currency) return nil, common.NewResult(code.ParamError) } var records []*eventmodels.UserWithdrawEventContent where := &eventmodels.UserWithdrawEventContent{ UserBasic: eventmodels.UserBasic{ UserId: req.UserName, UserName: req.NickName, }, EventBasic: eventmodels.EventBasic{ Status: req.Withdrawal, }, WithdrawId: req.ID, Currency: req.Currency, Address: req.Address, State: req.State, } db := mdb.LogstashDB.Model(&eventmodels.UserWithdrawEventContent{}).Where(where).Order("create_at") if req.StartTime > 0 && req.EndTime > 0 && req.StartTime <= req.EndTime { db = db.Where("create_at >= ? and create_at <= ?", req.StartTime, req.EndTime) } if req.AmountMin > 0 && req.AmountMax > 0 && req.AmountMin <= req.AmountMax { db = db.Where("amount >= ? and amount <= ?", req.AmountMin, req.AmountMax) } if req.AfterAmountMin > 0 && req.AfterAmountMax > 0 && req.AfterAmountMin <= req.AfterAmountMax { db = db.Where("after_balance >= ? and after_balance <= ?", req.AfterAmountMin, req.AfterAmountMax) } pages := Paginate(db, page, pageSize) err := db.Scopes(pages.Limit).Find(&records).Error if err != nil && err != gorm.ErrRecordNotFound { mhayaLogger.Warnf("FindWithdrawal Find error:%v", err) return nil, common.NewResult(code.InternalError) } var results []*entity.UserWithdrawalDetail for _, v := range records { results = append(results, &entity.UserWithdrawalDetail{ Id: v.WithdrawId, UserName: v.UserId, NickName: v.UserName, OpenId: v.TgId, Status: v.State, Reason: v.Reason, Withdrawal: v.Status, Amount: int(v.Amount), AfterAmount: int(v.AfterBalance), Type: v.Currency, Address: v.Address, CreateAt: v.CreateAt, UpdateAt: v.CreateAt, }) } return &entity.UserWithdrawalResp{ Details: results, Total: pages.Count, }, nil } // 导出提现记录 func (s *Synthesis) WithdrawalExport(req entity.UserWithdrawalExportReq) (*entity.UserWithdrawalResp, *code.Result) { ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second) defer cancel() collection := mdb.MDB.Collection(constant.CNameCashOutRecord) // 构建过滤器 filter := bson.M{} if req.UserName != "" { filter["userName"] = req.UserName } if req.NickName != "" { filter["nickName"] = req.NickName } if req.ID != "" { filter["_id"], _ = primitive.ObjectIDFromHex(req.ID) } if req.Address != "" { filter["address"] = req.Address } if req.State > 0 { filter["state"] = req.State } if req.Withdrawal > 0 { filter["withdrawal"] = req.Withdrawal } if req.StartTime > 0 && req.EndTime > 0 && req.StartTime <= req.EndTime { filter["createAt"] = bson.M{ "$gte": req.StartTime, "$lte": req.EndTime, } } if req.AmountMin > 0 && req.AmountMax > 0 && req.AmountMin <= req.AmountMax { filter["amount"] = bson.M{ "$gte": req.AmountMin, "$lte": req.AmountMax, } } if req.AfterAmountMin > 0 && req.AfterAmountMax > 0 && req.AfterAmountMin <= req.AfterAmountMax { filter["after_amount"] = bson.M{ "$gte": req.AfterAmountMin, "$lte": req.AfterAmountMax, } } findOptions := options.Find() findOptions.SetSort(bson.D{{"createAt", -1}}) // 获取总数total count, err := collection.CountDocuments(ctx, filter) if err != nil { mhayaLogger.Warnf("WithdrawalExportData CountDocuments error:%v", err) return nil, common.NewResult(code.InternalError) } // 查询数据 var results []*entity.UserWithdrawalDetail cursor, err := collection.Find(ctx, filter, findOptions) if err != nil { mhayaLogger.Warnf("WithdrawalExportData Find error:%v", err) return nil, common.NewResult(code.InternalError) } defer cursor.Close(ctx) // 解析结果 for cursor.Next(ctx) { var result entity.UserWithdrawalDetail if err := cursor.Decode(&result); err != nil { mhayaLogger.Warnf("WithdrawalExportData Decode error:%v", err) return nil, common.NewResult(code.InternalError) } results = append(results, &result) } if err := cursor.Err(); err != nil { mhayaLogger.Warnf("WithdrawalExportData cursor error:%v", err) return nil, common.NewResult(code.InternalError) } return &entity.UserWithdrawalResp{ Details: results, Total: count, }, nil } // WithdrawalStatus 更新提现状态 func (s *Synthesis) WithdrawalStatus(req entity.UserWithdrawalStatus) *code.Result { // ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second) // defer cancel() collection := mdb.MDB.Collection(constant.CNameCashOutRecord) // 更新条件 updateCondition := bson.M{"userName": req.UserName} // 更新内容 updateContent := bson.M{"$set": bson.M{"status": req.Status}} // 设置更新选项 updateOptions := options.Update() // 设置 upsert 选项 // 执行更新操作 _, err := collection.UpdateOne(context.TODO(), updateCondition, updateContent, updateOptions) if err != nil { mhayaLogger.Warnf("WithdrawalStatus UpdateOne error:%v", err) return common.NewResult(code.InternalError) } return nil } // WithdrawalStatusBatch 更新提现状态 func (s *Synthesis) WithdrawalStatusBatch(req entity.UserWithdrawalStatusBatch) *code.Result { collection := mdb.MDB.Collection(constant.CNameCashOutRecord) if len(req.ID) == 0 { return common.NewResult(code.ParamError) } for _, id := range req.ID { objID := primitive.ObjectID{} objID, _ = primitive.ObjectIDFromHex(id) updateCondition := bson.M{"_id": objID} updateContent := bson.M{} withdrawal := models.CashOutRecord{} err := collection.FindOne(context.TODO(), updateCondition).Decode(&withdrawal) if err != nil { mhayaLogger.Warnf("WithdrawalStatusBatch FindOne error:%v", err) continue } if req.Withdrawal != 0 { if withdrawal.Status == 1 { updateContent = bson.M{"$set": bson.M{"withdrawal": req.Withdrawal}} } else { continue } } if req.Status > 0 { if withdrawal.Status != 0 { continue } updateContent = bson.M{"$set": bson.M{"status": req.Status}} } updateOptions := options.Update().SetUpsert(true) _, err = collection.UpdateOne(context.TODO(), updateCondition, updateContent, updateOptions) if err != nil { mhayaLogger.Warnf("WithdrawalStatusBatch UpdateOne error:%v", err) continue } } return nil } // FindUserCountryCount 查询用户国家分布 // // 返回值为 UserCountryResp 的切片和错误。 func (s *Synthesis) FindUserCountryCount() (*entity.UserCountryResp, *code.Result) { // 选择数据库和集合 collection := mdb.MDB.Collection(constant.CNamePlayerCountryByIPStat) // 定义聚合管道 // 定义聚合管道 pipeline := []bson.D{ { {Key: "$project", Value: bson.D{ {Key: "playerRegisterCountry", Value: bson.D{{Key: "$objectToArray", Value: "$playerRegisterCountry"}}}, }}, }, { {Key: "$unwind", Value: "$playerRegisterCountry"}, }, { {Key: "$group", Value: bson.D{ {Key: "_id", Value: "$playerRegisterCountry.k"}, {Key: "totalValue", Value: bson.D{{Key: "$sum", Value: "$playerRegisterCountry.v"}}}, }}, }, { {Key: "$project", Value: bson.D{ {Key: "_id", Value: 0}, {Key: "countryKey", Value: "$_id"}, {Key: "totalValue", Value: 1}, }}, }, } // 执行聚合查询 cursor, err := collection.Aggregate(context.TODO(), pipeline) if err != nil { mhayaLogger.Warnf("FindUserCountryCount Aggregate error:%v", err) return nil, common.NewResult(code.InternalError) } defer cursor.Close(context.TODO()) // 遍历查询结果 var results []bson.M if err := cursor.All(context.TODO(), &results); err != nil { mhayaLogger.Warnf("FindUserCountryCount All error:%v", err) return nil, common.NewResult(code.InternalError) } var totalIPCount int64 var data []*entity.UserCountryDetail // 将结果转换为 UserCountryDetail for _, r := range results { var resp entity.UserCountryDetail resp.Country = r["countryKey"].(string) resp.IPCount = int(r["totalValue"].(int32)) totalIPCount += int64(resp.IPCount) data = append(data, &resp) } for _, v := range data { // 保留小数点后两位 v.Percentage = math.Round(float64(v.IPCount)/float64(totalIPCount)*10000) / 100 } // 根据阈值过滤结果 otherCount := 0 otherPercentage := 0.00 filteredResults := make([]*entity.UserCountryDetail, 0) threshold := 1.00 for _, r := range data { if r.Percentage >= threshold { filteredResults = append(filteredResults, r) // 保留小数点后两位 r.Percentage = math.Round(r.Percentage*100) / 100 otherPercentage += r.Percentage } else { otherCount += r.IPCount } } // 将其他国家添加到过滤后的结果中 if otherCount > 0 { p := 100.00 - math.Round(otherPercentage*100)/100 filteredResults = append(filteredResults, &entity.UserCountryDetail{ Country: "other", IPCount: otherCount, Percentage: math.Round(p*100) / 100, }) } return &entity.UserCountryResp{ Details: filteredResults, }, nil } // FindUserRetention UserRetentionResp 用户留存率 // 1. 获取指定日期范围内的注册用户数量 // 2. 获取指定日期范围内的活跃用户数量 // 3. 计算留存率 // 4. 返回结果 func (s *Synthesis) FindUserRetention(req entity.UserRetentionReq) (*entity.UserRetentionResp, *code.Result) { playerPreserve := models.GetPlayerPreserve(req.StartTime, req.EndTime) // 查询数据 var results []*entity.UserRetentionDetail for key, v := range playerPreserve { var retention entity.Retention for _, vv := range v { if vv.ID == 1 { retention.Day1 = entity.DayRetention{ LoggedIn: vv.Ratio, LoginDate: key, } } if vv.ID == 3 { retention.Day3 = entity.DayRetention{ LoggedIn: vv.Ratio, LoginDate: key, } } if vv.ID == 7 { retention.Day7 = entity.DayRetention{ LoggedIn: vv.Ratio, LoginDate: key, } } if vv.ID == 14 { retention.Day14 = entity.DayRetention{ LoggedIn: vv.Ratio, LoginDate: key, } } if vv.ID == 30 { retention.Day30 = entity.DayRetention{ LoggedIn: vv.Ratio, LoginDate: key, } } } results = append(results, &entity.UserRetentionDetail{ RegistrationDate: key, RetentionData: retention, }) } return &entity.UserRetentionResp{ Details: results, }, nil } // FindUserLevel 用户等级统计 func (s *Synthesis) FindUserLevel() (*entity.UserLevelCountResp, *code.Result) { ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second) defer cancel() collection := mdb.MDB.Collection(constant.CNamePlayerLevelStat) // 查询所有文档 cursor, err := collection.Find(ctx, bson.M{}) if err != nil { mhayaLogger.Warnf("FindUserLevel Find error:%v", err) return nil, common.NewResult(code.InternalError) } defer cursor.Close(ctx) var results []*entity.UserLevelCountDetail var reData []*models.PlayerLevelStat for cursor.Next(ctx) { var result models.PlayerLevelStat if err := cursor.Decode(&result); err != nil { mhayaLogger.Warnf("FindUserLevel Decode error:%v", err) return nil, common.NewResult(code.InternalError) } reData = append(reData, &result) } if err := cursor.Err(); err != nil { mhayaLogger.Warnf("FindUserLevel cursor error:%v", err) return nil, common.NewResult(code.InternalError) } dataMap := make(map[string]int) for _, v := range reData { for key, v1 := range v.ServerLevel { dataMap[key] += v1 } } keys := make([]string, 0, len(dataMap)) for k := range dataMap { keys = append(keys, k) } sort.Strings(keys) for _, v := range keys { results = append(results, &entity.UserLevelCountDetail{ Level: cast.ToInt(v), UserCount: dataMap[v], }) } return &entity.UserLevelCountResp{ Details: results, }, nil } func (s *Synthesis) InsertRecord(param model.UserOperationLog) { mhayaLogger.Warnf("InsertRecord param:%#v", param) record := new(model.UserOperationLog) collection := mdb.MDB.Collection(record.TableName()) insertData := bson.M{} insertData["user_name"] = param.Username insertData["role_id"] = param.RoleId insertData["url"] = param.Path insertData["method"] = param.Method insertData["status_code"] = param.StatusCode insertData["dur"] = param.Dur insertData["client_ip"] = param.ClientIP insertData["error_message"] = param.ErrorMessage insertData["created_at"] = mhayaTime.Now().Unix() _, err := collection.InsertOne(context.Background(), insertData) if err != nil { mhayaLogger.Warnf("InsertRecord InsertOne error:%v", err) return } } func (s *Synthesis) RecordList(req entity.RecordListReq) (*entity.RecordListResp, *code.Result) { page, pageSize := checkPageParam(req.Page, req.Size) var records []*eventmodels.BackendOperationEventContent where := &eventmodels.BackendOperationEventContent{ UserBasic: eventmodels.UserBasic{ UserName: req.UserName, }, RoleId: req.RoleId, Path: req.Path, StatusCode: req.StatusCode, ClientIP: req.ClientIP, } db := mdb.LogstashDB.Model(&eventmodels.BackendOperationEventContent{}).Where(where).Order("create_at") if req.StartTime > 0 && req.EndTime > 0 && req.StartTime <= req.EndTime { db = db.Where("create_at >= ? and create_at <= ?", req.StartTime, req.EndTime) } if req.DurMin > 0 && req.DurMax > 0 && req.DurMin <= req.DurMax { db = db.Where("dur >= ? and dur <= ?", req.DurMin, req.DurMax) } pages := Paginate(db, page, pageSize) err := db.Scopes(pages.Limit).Find(&records).Error if err != nil && err != gorm.ErrRecordNotFound { mhayaLogger.Warnf("RecordList Find error:%v", err) return nil, common.NewResult(code.InternalError) } var results []*entity.RecordListDetail for _, v := range records { results = append(results, &entity.RecordListDetail{ Username: v.UserName, RoleId: v.RoleId, Path: v.Path, Method: v.Method, StatusCode: v.StatusCode, Dur: v.Dur, ClientIP: v.ClientIP, ErrorMessage: v.ErrorMessage, CreatedAt: v.CreateAt, }) } return &entity.RecordListResp{ Details: results, Total: pages.Count, }, nil } // 转盘统计 func (s *Synthesis) Turntable(req entity.TurntableReq) (*entity.TurntableResp, *code.Result) { page, pageSize := checkPageParam(req.Page, req.Size) var records []*eventmodels.TurntableEventContent where := &eventmodels.TurntableEventContent{ UserBasic: eventmodels.UserBasic{ UserId: req.UserName, }, } db := mdb.LogstashDB.Model(&eventmodels.TurntableEventContent{}).Where(where).Order("create_at") if req.StartTime > 0 && req.EndTime > 0 && req.StartTime <= req.EndTime { db = db.Where("create_at >= ? and create_at <= ?", req.StartTime, req.EndTime) } pages := Paginate(db, page, pageSize) err := db.Scopes(pages.Limit).Find(&records).Error if err != nil && err != gorm.ErrRecordNotFound { mhayaLogger.Warnf("Turntable Find error:%v", err) return nil, common.NewResult(code.InternalError) } var results []*entity.TurntableDetail for _, v := range records { results = append(results, &entity.TurntableDetail{ UserName: v.UserName, OpenId: v.TgId, TurntableExecutionTime: v.CreateAt, PrizeName: v.PrizeName, PrizeNumber: v.PrizeNumber, }) } return &entity.TurntableResp{ Details: results, Total: pages.Count, }, nil } // 资产统计 func (s *Synthesis) Assets(req entity.AssetsReq) (*entity.AssetsResp, *code.Result) { page, pageSize := checkPageParam(req.Page, req.Size) playerMgr := NewPlayerManage() // 根据条件查询 if req.UserName != "" { registerRecord, codeResult := playerMgr.GetRegisterRecord(req.UserName) if codeResult != nil { mhayaLogger.Warnf("Assets GetRegisterRecord error:%v", codeResult) return nil, codeResult } if registerRecord == nil { mhayaLogger.Warnf("Assets registerRecord:%v", registerRecord) return nil, nil } var results []*entity.AssetsDetail detail, codeResult := s.getAsset(req.UserName) if codeResult != nil { mhayaLogger.Warnf("Assets getAsset error:%v", codeResult) return nil, codeResult } results = append(results, detail) return &entity.AssetsResp{ Details: results, Total: 1, }, nil } // 查询列表 listResp, codeResult := playerMgr.List(context.Background(), entity.PlayerListReq{ Page: page, Size: pageSize, }) if codeResult != nil { mhayaLogger.Warnf("Assets List error:%v", codeResult) return nil, codeResult } var results []*entity.AssetsDetail for _, detail := range listResp.Details { ret, codeResult := s.getAsset(detail.UserName) if codeResult != nil { mhayaLogger.Warnf("Assets getAsset error:%v", codeResult) return nil, codeResult } results = append(results, ret) } count, codeResult := playerMgr.GetPlayerTotalCount() if codeResult != nil { mhayaLogger.Warnf("Assets GetPlayerTotalCount codeResult:%v", codeResult) return nil, codeResult } return &entity.AssetsResp{ Details: results, Total: int64(count), }, nil } func (s *Synthesis) getAsset(userName string) (*entity.AssetsDetail, *code.Result) { var totalUsdtAmount int64 where := &eventmodels.AssetsEventContent{ UserBasic: eventmodels.UserBasic{ UserId: userName, }, } where.Currency = string(constant.UsdtCurrency) err := mdb.LogstashDB.Model(&eventmodels.AssetsEventContent{}).Where(where).Pluck("SUM(amount) as total_amount", &totalUsdtAmount).Error if err != nil { mhayaLogger.Warnf("getAsset Pluck UsdtCurrency error:%v", err) return nil, common.NewResult(code.InternalError) } var totalTonAmount int64 where.Currency = string(constant.TonCurrency) err = mdb.LogstashDB.Model(&eventmodels.AssetsEventContent{}).Where(where).Pluck("SUM(amount) as total_amount", &totalTonAmount).Error if err != nil { mhayaLogger.Warnf("getAsset Pluck TonCurrency error:%v", err) return nil, common.NewResult(code.InternalError) } var totalPointsAmount int64 where.Currency = string(constant.PointsCurrency) err = mdb.LogstashDB.Model(&eventmodels.AssetsEventContent{}).Where(where).Pluck("SUM(amount) as total_amount", &totalPointsAmount).Error if err != nil { mhayaLogger.Warnf("getAsset Pluck PointsCurrency error:%v", err) return nil, common.NewResult(code.InternalError) } return &entity.AssetsDetail{ UserName: userName, TonValue: cutils.QuoInt64ByRatioToFloat64(totalTonAmount, constant.MoneyRatio), UsdtValue: cutils.QuoInt64ByRatioToFloat64(totalUsdtAmount, constant.MoneyRatio), PointsValue: totalPointsAmount, StatisticalDate: mhayaTime.Now().Unix(), }, nil } // 资产变动记录 func (s *Synthesis) AssetsRecord(req entity.AssetsRecordReq) (*entity.AssetsRecordResp, *code.Result) { page, pageSize := checkPageParam(req.Page, req.Size) if req.Currency != "" && !constant.CurrencyValid(req.Currency) { mhayaLogger.Warnf("AssetsRecord unknow currency:%v", req.Currency) return nil, common.NewResult(code.ParamError) } if req.OperationType != "" && req.OperationType != string(constant.IncreaseOp) && req.OperationType != string(constant.DecreaseOp) { mhayaLogger.Warnf("AssetsRecord unknow OperationType:%v", req.OperationType) return nil, common.NewResult(code.ParamError) } var records []*eventmodels.AssetsEventContent where := &eventmodels.AssetsEventContent{ UserBasic: eventmodels.UserBasic{ UserId: req.UserName, }, OperationType: req.OperationType, Currency: req.Currency, Amount: req.Amount, } db := mdb.LogstashDB.Model(&eventmodels.AssetsEventContent{}).Where(where).Order("create_at") if req.StartTime > 0 && req.EndTime > 0 && req.StartTime <= req.EndTime { db = db.Where("create_at >= ? and create_at <= ?", req.StartTime, req.EndTime) } pages := Paginate(db, page, pageSize) err := db.Scopes(pages.Limit).Find(&records).Error if err != nil && err != gorm.ErrRecordNotFound { mhayaLogger.Warnf("Invite Find error:%v", err) return nil, common.NewResult(code.InternalError) } var results []*entity.AssetsRecordDetail for _, v := range records { results = append(results, &entity.AssetsRecordDetail{ UserName: v.UserId, AssetType: string(v.Currency), AssetsGrowth: v.Amount, AcquisitionTime: v.CreateAt, SourceOfAssetAcquisition: v.Reason, }) } return &entity.AssetsRecordResp{ Details: results, Total: pages.Count, }, nil } // 邀请统计 func (s *Synthesis) Invite(req entity.InviteReq) (*entity.InviteResp, *code.Result) { page, pageSize := checkPageParam(req.Page, req.Size) var records []*eventmodels.InviteEventContent where := &eventmodels.InviteEventContent{ UserBasic: eventmodels.UserBasic{ UserId: req.UserName, }, } db := mdb.LogstashDB.Model(&eventmodels.InviteEventContent{}).Where(where).Order("create_at") pages := Paginate(db, page, pageSize) err := db.Scopes(pages.Limit).Find(&records).Error if err != nil && err != gorm.ErrRecordNotFound { mhayaLogger.Warnf("Invite Find error:%v", err) return nil, common.NewResult(code.InternalError) } var results []*entity.InviteDetail for _, v := range records { results = append(results, &entity.InviteDetail{ UserName: v.UserName, OpenId: v.TgId, InviteID: v.UserId, IfInviteVIP: v.IfInviteUserTgVip, InviteTime: v.CreateAt, SuccessfulInvitationsLV2: int64(v.InviteUserLevel2), CumulativesuccessfulInvitations: int64(v.ContinuousInviteUserCount), InvitationChannel: v.Channel, }) } return &entity.InviteResp{ Details: results, Total: pages.Count, }, nil } // 活跃统计 func (s *Synthesis) Active(req entity.ActiveReq) (*entity.ActiveResp, *code.Result) { page, pageSize := checkPageParam(req.Page, req.Size) playerMgr := NewPlayerManage() // 根据条件查询 if req.UserName != "" { detail, codeResult := s.getActive(req.UserName) if codeResult != nil { mhayaLogger.Warnf("Active getActive error:%v", codeResult) return nil, codeResult } if detail == nil { return nil, nil } var results []*entity.ActiveDetail results = append(results, detail) return &entity.ActiveResp{ Details: results, Total: 1, }, nil } // 查询列表 listResp, codeResult := playerMgr.List(context.Background(), entity.PlayerListReq{ Page: page, Size: pageSize, }) if codeResult != nil { mhayaLogger.Warnf("Active List error:%v", codeResult) return nil, codeResult } var results []*entity.ActiveDetail for _, detail := range listResp.Details { detail, codeResult := s.getActive(detail.UserName) if codeResult != nil { mhayaLogger.Warnf("Active getActive error:%v", codeResult) return nil, codeResult } if detail != nil { results = append(results, detail) } } count, codeResult := playerMgr.GetPlayerTotalCount() if codeResult != nil { mhayaLogger.Warnf("Active GetPlayerTotalCount codeResult:%v", codeResult) return nil, codeResult } return &entity.ActiveResp{ Details: results, Total: count, }, nil } func (s *Synthesis) getActive(userName string) (*entity.ActiveDetail, *code.Result) { playerMgr := NewPlayerManage() // 获取注册记录 registerRecord, codeResult := playerMgr.GetRegisterRecord(userName) if codeResult != nil { mhayaLogger.Warnf("getActive GetRegisterRecord error:%v", codeResult) return nil, codeResult } if registerRecord == nil { mhayaLogger.Warnf("getActive registerRecord:%v", registerRecord) return nil, nil } // 获取最新的用户登录记录 loginRecord, codeResult := playerMgr.GetPlayerLastestLoginRecord(userName) if codeResult != nil { mhayaLogger.Warnf("getActive GetPlayerLastestLoginRecord error:%v", codeResult) return nil, codeResult } // 邀请成功人数 inviteCount, codeResult := playerMgr.GetSuccessfulInvitations(userName, 0) if codeResult != nil { mhayaLogger.Warnf("getActive GetSuccessfulInvitations error:%v", codeResult) return nil, codeResult } // 提现次数 withdrawCount, codeResult := playerMgr.GetWithdrawalCount(userName, -1) if codeResult != nil { mhayaLogger.Warnf("getActive GetWithdrawalCount error:%v", codeResult) return nil, codeResult } // 累计提现金额 // TODO 暂定USDT cumulativeWithdrawalAmount, codeResult := playerMgr.GetCumulativeWithdrawalAmount(userName, string(constant.UsdtCurrency), -1) if codeResult != nil { mhayaLogger.Warnf("getActive GetCumulativeWithdrawalAmount error:%v", codeResult) return nil, codeResult } // 转盘实际抽奖次数 turntableRuns, codeResult := playerMgr.GetTurntableRuns(userName) if codeResult != nil { mhayaLogger.Warnf("getActive GetTurntableRuns error:%v", codeResult) return nil, codeResult } return &entity.ActiveDetail{ UserName: userName, IfUserVip: func() bool { if loginRecord != nil { return loginRecord.IfTgVip } return false }(), CreateTime: registerRecord.CreateAt, LastLoginTime: func() int64 { if loginRecord != nil { return loginRecord.CreateAt } return 0 }(), MaxSuccessions: func() int { if loginRecord != nil { return loginRecord.ContinuousDaysMax } return 0 }(), SuccessfulInvitations: inviteCount, Withdrawals: withdrawCount, CumulativeWithdrawalAmount: cumulativeWithdrawalAmount, TurntableRuns: turntableRuns, }, nil } // 任务完成度统计 func (s *Synthesis) TaskCompletion(req entity.TaskCompletionReq) (*entity.TaskCompletionResp, *code.Result) { page, pageSize := checkPageParam(req.Page, req.Size) playerMgr := NewPlayerManage() // 根据条件查询 if req.UserName != "" { detail, codeResult := s.getTaskCompletionDetail(req.UserName) if codeResult != nil { mhayaLogger.Warnf("TaskCompletion getTaskCompletionDetail error:%v", codeResult) return nil, codeResult } if detail == nil { return nil, nil } var results []*entity.TaskCompletionDetail results = append(results, detail) return &entity.TaskCompletionResp{ Details: results, Total: 1, }, nil } // 查询列表 listResp, codeResult := playerMgr.List(context.Background(), entity.PlayerListReq{ Page: page, Size: pageSize, }) if codeResult != nil { mhayaLogger.Warnf("TaskCompletion List error:%v", codeResult) return nil, codeResult } var results []*entity.TaskCompletionDetail for _, detail := range listResp.Details { ret, codeResult := s.getTaskCompletionDetail(detail.UserName) if codeResult != nil { mhayaLogger.Warnf("TaskCompletion getTaskCompletionDetail error:%v", codeResult) return nil, codeResult } if detail != nil { results = append(results, ret) } } count, codeResult := playerMgr.GetPlayerTotalCount() if codeResult != nil { mhayaLogger.Warnf("TaskCompletion GetPlayerTotalCount codeResult:%v", codeResult) return nil, codeResult } return &entity.TaskCompletionResp{ Details: results, Total: int64(count), }, nil } func (s *Synthesis) getTaskCompletionDetail(userName string) (*entity.TaskCompletionDetail, *code.Result) { playerMgr := NewPlayerManage() // 获取注册记录 registerRecord, codeResult := playerMgr.GetRegisterRecord(userName) if codeResult != nil { mhayaLogger.Warnf("getTaskCompletionDetail GetRegisterRecord error:%v", codeResult) return nil, codeResult } if registerRecord == nil { mhayaLogger.Warnf("getTaskCompletionDetail registerRecord:%v", registerRecord) return nil, nil } // 获取用户加入频道的记录 joinTgRecord, codeResult := playerMgr.GetJoinRecord(userName, string(constant.TGJoinName)) if codeResult != nil { mhayaLogger.Warnf("getTaskCompletionDetail GetJoinRecord error:%v", codeResult) return nil, codeResult } joinDcRecord, codeResult := playerMgr.GetJoinRecord(userName, string(constant.DCJoinName)) if codeResult != nil { mhayaLogger.Warnf("getTaskCompletionDetail GetJoinRecord error:%v", codeResult) return nil, codeResult } // 获取用户关注的记录 followTwitterRecord, codeResult := playerMgr.GetFollowRecord(userName, string(constant.TwitterFollowName)) if codeResult != nil { mhayaLogger.Warnf("getTaskCompletionDetail GetFollowRecord error:%v", codeResult) return nil, codeResult } followYoutubeRecord, codeResult := playerMgr.GetFollowRecord(userName, string(constant.YoutubeFollowName)) if codeResult != nil { mhayaLogger.Warnf("getTaskCompletionDetail GetFollowRecord error:%v", codeResult) return nil, codeResult } // 获取最新的用户信息更新记录 updateRecord, codeResult := playerMgr.GetPlayerLastestUpdateRecord(userName) if codeResult != nil { mhayaLogger.Warnf("getTaskCompletionDetail GetPlayerLastestUpdateRecord error:%v", codeResult) return nil, codeResult } // 邀请成功人数 inviteCount, codeResult := playerMgr.GetSuccessfulInvitations(userName, 0) if codeResult != nil { mhayaLogger.Warnf("getTaskCompletionDetail GetSuccessfulInvitations error:%v", codeResult) return nil, codeResult } return &entity.TaskCompletionDetail{ UserName: userName, DicePerDay: 0, // TODO 每日骰子数量 IsJoinTgChannel: func() bool { return joinTgRecord != nil }(), IsFollowTwitter: func() bool { return followTwitterRecord != nil }(), IsJoinDcChannel: func() bool { return joinDcRecord != nil }(), IsBindTwitter: func() bool { if updateRecord != nil { return updateRecord.XId == "" } return false }(), IsFollowYoutube: func() bool { return followYoutubeRecord != nil }(), InviteNumber: inviteCount, }, nil } // 用户行为检测 func (s *Synthesis) BehaviorMonitoring(req entity.BehaviorMonitoringReq) (*entity.BehaviorMonitoringResp, *code.Result) { page, pageSize := checkPageParam(req.Page, req.Size) var records []*eventmodels.DiceEventContent where := &eventmodels.DiceEventContent{ UserBasic: eventmodels.UserBasic{ UserId: req.UserName, }, } db := mdb.LogstashDB.Model(&eventmodels.DiceEventContent{}).Where(where).Order("create_at") pages := Paginate(db, page, pageSize) err := db.Scopes(pages.Limit).Find(&records).Error if err != nil && err != gorm.ErrRecordNotFound { mhayaLogger.Warnf("BehaviorMonitoring Find error:%v", err) return nil, common.NewResult(code.InternalError) } var results []*entity.BehaviorMonitoringDetail for _, v := range records { results = append(results, &entity.BehaviorMonitoringDetail{ UserName: v.UserId, DieExecutionTime: v.CreateAt, }) } return &entity.BehaviorMonitoringResp{ Details: results, Total: pages.Count, }, nil }