370 lines
14 KiB
Go
370 lines
14 KiB
Go
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
|
|
}
|