package botser import ( "context" "fmt" "stat/common/log" "stat/common/statutils" "stat/common/tgbot" "stat/common/utils" "stat/models/accessmod" "stat/models/appInfoMod" "stat/models/botdailyhourstat" "stat/models/botreport" "stat/models/downloadinfo" "stat/models/rechargemod" "stat/models/registermod" "stat/models/syncrecharge" "stat/models/syncvip" "stat/models/versionMod" "stat/service/crossSer" "stat/statg" "strings" "time" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson" ) // 当日累计详细数据 func DailyDetailBotTask(ctx context.Context, bot *tgbot.TgBot, reportTime time.Time) error { title := GetDateDesc(0) + "应用统计排名:" + reportTime.Format("2006-01-02T15:04:05") photo, _, err := crossSer.GetRankPhoto(reportTime, title, func(item *botdailyhourstat.BotHourStat) int64 { return item.TodayStat.Recharge.Value() / 100 }) if err != nil { return err } return bot.SendBroadcastMessage(fmt.Sprintf("应用统计排名:%s\n", reportTime.Format("2006-01-02T15:04:05")), photo, tgbot.FileTypePhoto) } // 当日累计总充值排行 func DailyBotRankTask(ctx context.Context, bot *tgbot.TgBot, reportTime time.Time) error { title := GetDateDesc(0) + "应用统计排名:" + reportTime.Format("2006-01-02T15:04:05") photo, _, err := crossSer.GetRankPhoto(reportTime, title, func(item *botdailyhourstat.BotHourStat) int64 { return item.TodayStat.Recharge.Value() / 100 }) if err != nil { return err } return bot.SendBroadcastMessage(fmt.Sprintf("应用统计排名:%s\n", reportTime.Format("2006-01-02T15:04:05")), photo, tgbot.FileTypePhoto) } // 当日累计总充值、单小时充值 func DailyBotReportTask(ctx context.Context, bot *tgbot.TgBot, appId int32, reportTime time.Time) error { log.Error("DailyBotReportTask start", log.Any("appid", appId), log.Any("time", reportTime)) reportFilter := bson.M{ botreport.FN.BotReport.AppId: appId, botreport.FN.BotReport.SumDate: reportTime, } report, err := botdailyhourstat.FindOneBotHourStatEx(ctx, reportFilter) if err != nil { if err == mongo.ErrNoDocuments { report, err = BotDailyHourStat(ctx, appId, reportTime, true) if err != nil { return err } } else { return err } } HistoryFilter := bson.M{ botreport.FN.BotReport.AppId: appId, botreport.FN.BotReport.SumDate: reportTime.AddDate(0, 0, -1), } historyReport, err := botdailyhourstat.FindOneBotHourStatEx(ctx, HistoryFilter) if err != nil { if err == mongo.ErrNoDocuments { historyReport, err = BotDailyHourStat(ctx, appId, reportTime.AddDate(0, 0, -1), true) if err != nil { return err } } else { return err } } appNameMap, _ := appInfoMod.GetAllAppIdNameMap(ctx) appName := appNameMap[appId] if statg.GlobalEndpoints.GetBotStatEndpoints().ExistsByAppId(appId) { //text := report.DisplayDayHourText(appName, report) //_ = bot.SendBroadcastMessage(text, "", tgbot.FileTypeNone) text, title, desc := report.DisplayDayHourTextWithTitle(appName, historyReport, lastWeekHourStat(ctx, appId, reportTime)) et := tgbot.NewEntityList(title, desc, []*tgbot.Entity{ { Content: text, }, }) _ = bot.SendBroadcastEntity(et) return nil } log.Error("DailyBotReportTask end", log.Any("appid", appId), log.Any("time", reportTime)) return nil } func DailyBotReportInfo(ctx context.Context, appId int32, reportTime time.Time) (text, title, desc string, err error) { log.Error("DailyBotReportTask start", log.Any("appid", appId), log.Any("time", reportTime)) reportFilter := bson.M{ botreport.FN.BotReport.AppId: appId, botreport.FN.BotReport.SumDate: reportTime, } report, err := botdailyhourstat.FindOneBotHourStatEx(ctx, reportFilter) if err != nil { if err == mongo.ErrNoDocuments { report, err = BotDailyHourStat(ctx, appId, reportTime, true) if err != nil { return } } else { return } } HistoryFilter := bson.M{ botreport.FN.BotReport.AppId: appId, botreport.FN.BotReport.SumDate: reportTime.AddDate(0, 0, -1), } historyReport, err := botdailyhourstat.FindOneBotHourStatEx(ctx, HistoryFilter) if err != nil { if err == mongo.ErrNoDocuments { historyReport, err = BotDailyHourStat(ctx, appId, reportTime.AddDate(0, 0, -1), true) if err != nil { return } } else { return } } appNameMap, _ := appInfoMod.GetAllAppIdNameMap(ctx) appName := appNameMap[appId] if statg.GlobalEndpoints.GetBotStatEndpoints().ExistsByAppId(appId) { text, title, desc = report.DisplayDayHourTextWithTitle(appName, historyReport, lastWeekHourStat(ctx, appId, reportTime)) } log.Error("DailyBotReportTask end", log.Any("appid", appId), log.Any("time", reportTime)) return } // 当日累计总充值排行 func DailyBotRankTaskInfo(ctx context.Context, reportTime time.Time) (photo string, buf []byte, err error) { title := GetDateDesc(0) + "应用统计排名:" + reportTime.Format("2006-01-02T15:04:05") photo, buf, err = crossSer.GetRankPhoto(reportTime, title, func(item *botdailyhourstat.BotHourStat) int64 { return item.TodayStat.Recharge.Value() / 100 }) return photo, buf, err } // 当日累计总充值、单小时充值 func BotDailyHourStat(ctx context.Context, appId int32, reportTime time.Time, saveData bool) (*botdailyhourstat.BotHourStat, error) { hourStatBegin := reportTime.Add(-60 * time.Minute) reportFilter := bson.M{ "sumDate": reportTime, "appId": appId, } //BotHourStat report, err := botdailyhourstat.FindOneBotHourStat(ctx, reportFilter) if err != nil { log.Error("FindOneBotReport", log.E(err)) return nil, err } if report.SumDate != reportTime { // 生成数据并插入 start := utils.BeginWithTime(reportTime.Add(-time.Minute)) end := reportTime report = &botdailyhourstat.BotHourStat{ ID: primitive.NewObjectID(), AppId: appId, SumDate: reportTime, UpdatedAt: time.Now(), CreatedAt: time.Now(), } // 访问 err := accessmod.VisitInfoByTimeShard(ctx, appId, start, end, utils.GlobalShardHour, func(item *accessmod.AccessMod) { client := statutils.GetClientInfo(item.SysType, item.DevType, item.DistrictCode, item.IsDirect, false, item.IsFormalUser) report.TodayStat.Visit.Add(1, client) }) if err != nil { return nil, err } // 注册 userDict := make(map[uint64]bool) err = registermod.RegisterFormalsInfoByTimeShard(ctx, appId, start, end, utils.GlobalShardHour, func(item *registermod.RegisterMod) { if item.IsFormal && statutils.IsClientH5OrLight(item.SysType, item.DevType) { if _, exists := userDict[item.UserId]; !exists { userDict[item.UserId] = true client := statutils.GetClientInfo(item.SysType, item.DevType, item.DistrictCode, item.IsDirect, item.IsDeduction, item.IsFormal) report.TodayStat.Register.Add(1, client) if item.RegisterTime.After(hourStatBegin) && item.RegisterTime.Before(reportTime) { report.HourStat.Register.Add(1, client) } } } }) if err != nil { return nil, err } err = registermod.RegisterUsersInfoByTimeShard(ctx, appId, start, end, utils.GlobalShardHour, func(item *registermod.RegisterMod) { userDict[item.UserId] = true client := statutils.GetClientInfo(item.SysType, item.DevType, item.DistrictCode, item.IsDirect, item.IsDeduction, item.IsFormal) report.TodayStat.Register.Add(1, client) if item.RegisterTime.After(hourStatBegin) && item.RegisterTime.Before(reportTime) { report.HourStat.Register.Add(1, client) } }) if err != nil { return nil, err } // 充值 rechargeMap := make(map[string]*rechargemod.RechargeMod) rechargeList, _ := rechargemod.TotalRechargeListV1(ctx, appId, start, end) for _, item := range rechargeList { client := statutils.GetClientInfo(item.SysType, item.DevType, item.DistrictCode, item.IsDirect, false, item.IsFormalUser) rechargeMap[item.OrderId] = item report.TodayStat.Recharge.Add(item.PayMoney, client) if item.RegisterTime.After(item.SuccessAt.AddDate(0, 0, -1)) { report.TodayStat.RechargeNew.Add(item.PayMoney, client) } else { report.TodayStat.RechargeOld.Add(item.PayMoney, client) } if item.SuccessAt.After(hourStatBegin) && item.SuccessAt.Before(reportTime) { report.HourStat.Recharge.Add(item.PayMoney, client) if item.RegisterTime.After(item.SuccessAt.AddDate(0, 0, -1)) { report.HourStat.RechargeNew.Add(item.PayMoney, client) } else { report.HourStat.RechargeOld.Add(item.PayMoney, client) } } } // 订单 filter := bson.M{syncrecharge.FN.SyncRechargeOrder.AppId: appId, syncrecharge.FN.SyncRechargeOrder.CreatedAt: bson.M{"$gt": start.Add(-20 * time.Minute), "$lt": end}} orderExList, _ := syncrecharge.FindManySyncRechargeOrder(ctx, filter) orderList := make([]*syncrecharge.SyncRechargeOrder, 0) for _, item := range orderExList { if recharge, ok := rechargeMap[item.OrderId]; ok { item.Money = recharge.Money item.PayMoney = recharge.PayMoney item.Status = recharge.Status item.CreatedAt = recharge.SuccessAt } if item.CreatedAt.After(start) && item.CreatedAt.Before(end) { orderList = append(orderList, item) } } for _, item := range orderList { client := statutils.GetClientInfo(item.SysType, item.DevType, item.DistrictCode, item.IsDirect, false, item.IsFormalUser) report.TodayStat.Order.Add(item.PayMoney, client) if item.Status == 3 { report.TodayStat.OrderSucc.Add(1, client) } if item.CreatedAt.After(hourStatBegin) && item.CreatedAt.Before(reportTime) { report.HourStat.Order.Add(item.PayMoney, client) if item.Status == 3 { report.HourStat.OrderSucc.Add(item.PayMoney, client) } } } // 会员 vipFilter := bson.M{syncvip.FN.SyncVip.AppId: appId, syncvip.FN.SyncVip.SuccessAt: bson.M{"$gt": start, "$lt": end}} viporderList, _ := syncvip.FindManySyncVip(ctx, vipFilter) for _, item := range viporderList { client := statutils.GetClientInfo(item.DeviceType, item.DeviceType, item.DistrictCode, item.IsDirect, false, item.IsFormalUser) report.TodayStat.RechargeVip.Add(item.Money, client) if item.SuccessAt.After(hourStatBegin) && item.SuccessAt.Before(reportTime) { report.HourStat.RechargeVip.Add(item.Money, client) } } // 金币 report.TodayStat.RechargeGold = *report.TodayStat.Recharge.Sub(&report.TodayStat.RechargeVip) report.HourStat.RechargeGold = *report.HourStat.Recharge.Sub(&report.HourStat.RechargeVip) // 游戏 if appId == 888 { gameInfo := GetGameInfo(ctx, start) if gameInfo != nil { report.TodayGame = &botdailyhourstat.GameItem{} report.TodayGame.RchgAmount = gameInfo.GameRchgAmount / 100 //充值总金额 report.TodayGame.DcRchgAmount = gameInfo.GameDCRchgAmount / 100 //代充总金额 report.TodayGame.WtdrAmount = gameInfo.GameWtdrAmount / 100 //游戏提现总金额 report.TodayGame.WtdrRealAmount = gameInfo.GameWtdrRealAmount / 100 //游戏实际提现总金额 report.TodayGame.IncAmount = -gameInfo.GameIncAmount / 100 //游戏上分总金额 report.TodayGame.DecAmount = gameInfo.GameDecAmount / 100 //游戏下分总金额 report.TodayGame.ValidBet = gameInfo.ValidBet / 100 //有效投注金额 report.TodayGame.Profit = gameInfo.Profit / 100 //系统盈利 } } // 落地页 downloadList, err := downloadinfo.GetAccessCountByTime(ctx, appId, start, end) if err != nil { return nil, err } for _, downloadInfo := range downloadList { report.TodayLandPage.LandPageTotalClick += 1 if downloadInfo.SysType == "android" { report.TodayLandPage.LandPageAndroidClick += 1 } else if strings.Contains(downloadInfo.SysType, "ios") || strings.Contains(downloadInfo.SysType, "light") { if downloadInfo.PackageType == versionMod.Shop { report.TodayLandPage.LandPageIosAppstoreClick += 1 } else if downloadInfo.PackageType == versionMod.Enterprise { report.TodayLandPage.LandPageIosFirmClick += 1 } else if downloadInfo.PackageType == versionMod.Light { report.TodayLandPage.LandPageIosLightClick += 1 } } if downloadInfo.CreatedAt.After(hourStatBegin) && downloadInfo.CreatedAt.Before(reportTime) { report.HourLandPage.LandPageTotalClick += 1 if downloadInfo.SysType == "android" { report.HourLandPage.LandPageAndroidClick += 1 } else if strings.Contains(downloadInfo.SysType, "ios") || strings.Contains(downloadInfo.SysType, "light") { if downloadInfo.PackageType == versionMod.Shop { report.HourLandPage.LandPageIosAppstoreClick += 1 } else if downloadInfo.PackageType == versionMod.Enterprise { report.HourLandPage.LandPageIosFirmClick += 1 } else if downloadInfo.PackageType == versionMod.Light { report.HourLandPage.LandPageIosLightClick += 1 } } } } report.AppId = appId if saveData { serr := botdailyhourstat.InsertOneBotHourStat(ctx, report) if serr != nil { log.Error("botdailyhourstat:InsertOneBotHourStat db.InsertOne failed", log.E(serr)) } log.Info("botdailyhourstat", log.Any("info", report.ReportTime)) } } return report, nil } // lastWeekHourStat 取上周当日同一小时的统计记录,给汇报里的"环比"做基准。 // 只查不补算: 现算一份七天前的数据要把当天的原始流水全量聚合一遍,代价高, // 而且历史原始数据可能已经被清理,算出来反而是错的。查不到就返回 nil, // 展示层会把那一行标成"无数据"。 func lastWeekHourStat(ctx context.Context, appId int32, reportTime time.Time) *botdailyhourstat.BotHourStat { filter := bson.M{ botreport.FN.BotReport.AppId: appId, botreport.FN.BotReport.SumDate: reportTime.AddDate(0, 0, -7), } report, err := botdailyhourstat.FindOneBotHourStatEx(ctx, filter) if err != nil { if err != mongo.ErrNoDocuments { log.Warn("lastWeekHourStat failed", log.E(err), log.Any("appId", appId), log.Any("sumDate", reportTime)) } return nil } return report }