package botser import ( "bytes" "context" "errors" "fmt" "os" "stat/common/crypt" "stat/common/statutils" "stat/common/stdLog" "stat/common/tgbot" "stat/common/utils" "stat/models/appInfoMod" "stat/models/botdailyhourstat" "stat/models/botreport" "stat/models/channelmod" "stat/models/channelpackage" "stat/models/versionMod" "stat/service/crossSer" "stat/service/innerserverser" "stat/service/versionSer" "stat/skd/job/monitor" "stat/statg" "strings" "time" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/bson" "golang.org/x/exp/slices" ) func DisplayAppButtons(ctx context.Context, cmd *tgbot.Command) error { list, err := appInfoMod.GetAllAppInfoEx(ctx) if err != nil { return err } title := fmt.Sprintf("请选择您要查询%s的应用:", cmd.GetFlagStringValue("-title")) keyboard := GetAppKeyboard(list, cmd.Message().Text, 2) return cmd.SendEdit(title, keyboard) } func DisplayStatProjectButtons(ctx context.Context, cmd *tgbot.Command) error { title := fmt.Sprintf("请选择统计项目:") keyboard := GetStatProjectKeyboard(cmd.Message().Text) return cmd.SendEdit(title, keyboard) } func HandleMenuCmd(ctx context.Context, cmd *tgbot.Command) error { return cmd.SendReply("请选择命令:", MenuKeyboard) } func HandleWhatCmd(ctx context.Context, cmd *tgbot.Command) error { text := fmt.Sprintf("会话信息:\n") text += fmt.Sprintf("用户:【%s】\n", cmd.Message().From.FirstName+cmd.Message().From.LastName) text += fmt.Sprintf("UID:【%d】\n", cmd.Message().From.ID) text += fmt.Sprintf("聊天:【%s】\n", cmd.Message().Chat.Title) text += fmt.Sprintf("CID:【%d】\n", cmd.Message().Chat.ID) return cmd.SendText(text) } func HandleMenuCmd0(ctx context.Context, cmd *tgbot.Command) error { text := "前一天旧的 /recharge\n 综合统计前一天的 /rechargenew\n" + "综合从第几天到第几天/rechargedate -begin=2024-01-01 -end=2024-01-21 @bot\n 综合统计具体年月日/rechargeoneday -date=2024-01-01\n" return cmd.SendText(text) } // channel_apk func HandleChannelApkCmd(ctx context.Context, cmd *tgbot.Command) error { appIds := cmd.GetFlagInt32Slice("-app") if len(appIds) <= 0 { return tgbot.NewUserError(cmd, "请输入应用ID,格式:\n"+cmd.Help+"\n"+cmd.Desc) } channel := cmd.GetFlagStringValue("-channel") if channel == "" { return tgbot.NewUserError(cmd, "请输入渠道名称,格式:\n"+cmd.Help+"\n"+cmd.Desc) } debug := cmd.GetFlagStringValue("-debug") appNames, err := appInfoMod.GetAllAppIdNameMap(ctx) if err != nil { return err } appId := appIds[0] version, err := versionMod.ButtonClick(ctx, appId, "android", 0) if err != nil { return tgbot.NewUserError(cmd, fmt.Sprintf("获取应用【%s】(id=%d) 版本信息失败: %s\n", appNames[appId], appId, err.Error())) } pack, serr := channelpackage.FindOneChannelPackage(ctx, bson.M{ channelpackage.FN.ChannelPackage.AppId: appId, channelpackage.FN.ChannelPackage.Channel: channel, channelpackage.FN.ChannelPackage.Version: version.VersionNum, channelpackage.FN.ChannelPackage.FileName: version.Md5, }) if serr != nil && serr.Code != stdLog.DataNotExist { return tgbot.NewUserError(cmd, fmt.Sprintf("查找渠道包出错【app=%s】(id=%d) 渠道【%s】, Error:%s\n", appNames[appId], appId, channel, serr.Error())) } logBody := bytes.NewBuffer(nil) if pack != nil { if pack.Status == channelpackage.ChanApkStatusSuccess { text := fmt.Sprintf("渠道包已经存在:\n") text += fmt.Sprintf("应用:【%s】(%d)\n", appNames[appId], appId) text += fmt.Sprintf("渠道:【%s】\n", channel) text += fmt.Sprintf("版本:【%s】\n", version.VersionNum) text += fmt.Sprintf("文件:【%s】\n", version.Md5) text += fmt.Sprintf("发布:【%s】\n", version.CreatedAt.Format(time.DateTime)) text += fmt.Sprintf("生成:【%s】\n", pack.GenTime.Format(time.DateTime)) baseUrls := versionSer.GetPackageBaseDomain(appId) for index, baseUrl := range baseUrls { text += fmt.Sprintf("下载链接-%d: %s\n", index, pack.GetRandomLink([]string{baseUrl})) } return cmd.SendReply(text, nil) } if pack.Status == channelpackage.ChanApkStatusMaking && time.Now().Sub(pack.GenTime) < 10*time.Minute { return tgbot.NewUserError(cmd, fmt.Sprintf("渠道包正在生成中【app=%s】(id=%d) 渠道【%s】请稍后再试。。。\n", appNames[appId], appId, channel)) } if pack, err = versionSer.TryMakeChannelApk(ctx, appId, channel, version, pack, "渠道包不在成功状态很久了", true, logBody); err != nil { return tgbot.NewUserError(cmd, fmt.Sprintf("生成渠道包出错【app=%s】(id=%d) 渠道【%s】, Error:%s\n", appNames[appId], appId, channel, err.Error())) } text := fmt.Sprintf("渠道包生成成功:\n") text += fmt.Sprintf("应用:【%s】(%d)\n", appNames[appId], appId) text += fmt.Sprintf("渠道:【%s】\n", channel) text += fmt.Sprintf("版本:【%s】\n", version.VersionNum) text += fmt.Sprintf("文件:【%s】\n", version.Md5) text += fmt.Sprintf("发布:【%s】\n", version.CreatedAt.Format(time.DateTime)) text += fmt.Sprintf("生成:【%s】\n", pack.GenTime.Format(time.DateTime)) baseUrls := versionSer.GetPackageBaseDomain(appId) for index, baseUrl := range baseUrls { text += fmt.Sprintf("下载链接-%d: %s\n", index, pack.GetRandomLink([]string{baseUrl})) } if strings.ToLower(debug) == strings.ToLower(crypt.StrToMd5(fmt.Sprintf("#<%s>$", time.Now().Format(time.DateOnly)))) { text += logBody.String() } return cmd.SendReply(text, nil) } else { // 生成apk reason := fmt.Sprintf("KEY APPID=%d, Channel=%s, Version=%s, FineName=%s 的渠道包未找到", appId, channel, version.VersionNum, version.Md5) if pack, err = versionSer.TryMakeChannelApk(ctx, appId, channel, version, pack, reason, true, logBody); err != nil { return tgbot.NewUserError(cmd, fmt.Sprintf("生成渠道包出错【app=%s】(id=%d) 渠道【%s】, Error:%s\n", appNames[appId], appId, channel, err.Error())) } text := fmt.Sprintf("渠道包生成成功:\n") text += fmt.Sprintf("应用:【%s】(%d)\n", appNames[appId], appId) text += fmt.Sprintf("渠道:【%s】\n", channel) text += fmt.Sprintf("版本:【%s】\n", version.VersionNum) text += fmt.Sprintf("文件:【%s】\n", version.Md5) text += fmt.Sprintf("发布:【%s】\n", version.CreatedAt.Format(time.DateTime)) text += fmt.Sprintf("生成:【%s】\n", pack.GenTime.Format(time.DateTime)) baseUrls := versionSer.GetPackageBaseDomain(appId) for index, baseUrl := range baseUrls { text += fmt.Sprintf("下载链接-%d: %s\n", index, pack.GetRandomLink([]string{baseUrl})) } if strings.ToLower(debug) == strings.ToLower(crypt.StrToMd5(fmt.Sprintf("#<%s>$", time.Now().Format(time.DateOnly)))) { text += logBody.String() } return cmd.SendReply(text, nil) } } // channel_analyze func HandleChannelAnalyzeCmd(ctx context.Context, cmd *tgbot.Command) error { channel := cmd.GetFlagStringValue("-channel") if channel == "" { return tgbot.NewUserError(cmd, "请输入渠道名称,格式:\n"+cmd.Help+"\n"+cmd.Desc) } sBegin := cmd.GetFlagStringValue("-begin") if sBegin == "" { return tgbot.NewUserError(cmd, "请输入查询开始日期,格式:\n"+cmd.Help+"\n"+cmd.Desc) } sEnd := cmd.GetFlagStringValue("-end") if sEnd == "" { return tgbot.NewUserError(cmd, "请输入查询结束日期,格式:\n"+cmd.Help+"\n"+cmd.Desc) } count, err := channelmod.CountChannelInfos(ctx, bson.M{channelmod.FN.ChannelInfo.Channel: channel}) if err != nil { return tgbot.NewUserError(cmd, "查询渠道出错:"+err.Error()) } if count == 0 { return tgbot.NewUserError(cmd, "服务器没有这个渠道:"+channel) } begin, err := time.ParseInLocation("2006-01-02", sBegin, time.Local) if err != nil { return tgbot.NewUserError(cmd, "解析开始日期出错, 格式:\n"+cmd.Help+"\n"+cmd.Desc) } end, err := time.ParseInLocation("2006-01-02", sEnd, time.Local) if err != nil { return tgbot.NewUserError(cmd, "解析结束日期出错, 格式:\n"+cmd.Help+"\n"+cmd.Desc) } item, err := ChannelAnalyze(ctx, channel, begin, end) if err != nil { return tgbot.NewUserError(cmd, "分析渠道出错:"+err.Error()) } top, _ := cmd.GetFlagInt32Value("-top") if top <= 0 { top = 10 } text := fmt.Sprintf("渠道分析:%s\n", channel) text += fmt.Sprintf("开始时间:%s\n", sBegin) text += fmt.Sprintf("结束时间:%s\n", sEnd) text += "=====渠道分析结果=====\n" text += fmt.Sprintf("注册用户:%d\n", item.RegisterCount) text += fmt.Sprintf("注册IP数:%d\n", item.RegisterIpCount) text += fmt.Sprintf("访问用户:%d\n", len(item.VisitCountMap)) text += fmt.Sprintf("注册1小时后访问:%d\n", len(item.ValidVisitAfterHourMap)) text += fmt.Sprintf("注册1天后访问:%d\n", len(item.ValidVisitAfterDayMap)) text += fmt.Sprintf("注册2天后访问:%d\n", len(item.ValidVisitAfterTowDayMap)) text += fmt.Sprintf("充值次数:%d\n", item.RechargeCount) text += fmt.Sprintf("充值用户:%d\n", len(item.RegisterUserMap)) text += fmt.Sprintf("充值钱数:%d元\n", item.RechargeAmount/100) text += fmt.Sprintf("游戏充值:%d\n", item.GameRecharge/100) text += fmt.Sprintf("游戏提现:%d\n", item.GameWithdraw/100) text += "=====IP注册数前10名=====\n" ranks := item.IpRank(int(top)) for _, rank := range ranks { text += fmt.Sprintf("注册:%d, IP:%s\n", rank.Count, rank.Ip) } return cmd.SendReply(text, nil) } func HandleGameReportCmd(ctx context.Context, cmd *tgbot.Command) error { appMap, err := appInfoMod.GetAllAppIdNameMap(ctx) if err != nil { return err } if _, ok := appMap[888]; !ok { return errors.New("本服务器没有游戏统计") } back, err := cmd.GetFlagInt32Value("-back") if err != nil { return tgbot.NewUserError(cmd, "请输入回退天数,格式:\n"+cmd.Help+"\n"+cmd.Desc) } if back > 0 { back *= -1 } fileName, err := GetGameReportFile(ctx, time.Now().AddDate(0, 0, int(back))) if err != nil { return err } cmd.FilePath = fileName return cmd.SendReply("游戏统计报表文件", nil) } func HandleAutoTaskStatusCmd(ctx context.Context, cmd *tgbot.Command) error { if cmd.HasFlag("-file") { content := statutils.ServerMon.ToJson() filePath := fmt.Sprintf("/tmp/%s.json", utils.UUID()) err := os.WriteFile(filePath, []byte(content), 0666) if err != nil { return err } cmd.FilePath = filePath return cmd.SendReply("自动任务数据", nil) } else { content := statutils.ServerMon.Display() return cmd.SendReply(content, nil) } } func HandleCloseCmd(ctx context.Context, cmd *tgbot.Command) error { return cmd.SendDelete() } func HandleAppListCmd(ctx context.Context, cmd *tgbot.Command) error { list, err := appInfoMod.GetAllAppInfo(ctx) if err != nil { return err } allIds := make([]int32, 0, len(list)) dbApps := make(map[int32]*appInfoMod.AppInfo) for _, app := range list { _app := app dbApps[app.AppId] = &_app allIds = append(allIds, app.AppId) } endpoints := statg.GlobalEndpoints.GetIndexEndpoints(statg.Conf.ServerIndex) for _, endpoint := range endpoints { if _, exists := dbApps[endpoint.AppId]; !exists { allIds = append(allIds, endpoint.AppId) } } text := fmt.Sprintf("应用列表:【%s】\n", time.Now().Format("2006-01-02T15:04:05")) for _, id := range allIds { end := endpoints.GetEndpointByAppId(id) app := dbApps[id] if end != nil && app != nil { text += fmt.Sprintf("【%s】【%s】【%s】【%d】\n", end.NameFull, end.NameShort, end.NameEn, end.AppId) warns := make([]string, 0) if end.ServerUrl == "" { warns = append(warns, "服务器地址没配‼️") } if end.NameEn == "" { warns = append(warns, "名称英文缩写没配‼️") } if end.H5Config == "" { warns = append(warns, "H5Config没配‼️") } if end.H5Origin == "" { warns = append(warns, "H5Origin没配‼️") } if end.H5Target == "" { warns = append(warns, "H5Target没配‼️") } if len(warns) > 0 { text += fmt.Sprintf("【%s】", strings.Join(warns, ";")) } } else if app == nil && end != nil { text += fmt.Sprintf("【%s】【%s】【%s】【%d】数据库未添加该APP‼️\n", end.NameFull, end.NameShort, end.NameEn, end.AppId) } else if app != nil && end == nil { text += fmt.Sprintf("【%s】【%d】数据库存在该APP,但是没有配置文件没有‼️\n", app.Name, app.AppId) } } return cmd.SendBack(text) } func HandleSyncStatusCmd(ctx context.Context, cmd *tgbot.Command) error { appIds := cmd.GetFlagInt32Slice("-app") if len(appIds) <= 0 { return DisplayAppButtons(ctx, cmd) } appNames, err := appInfoMod.GetAllAppIdNameMap(ctx) if err != nil { return err } isDetail := slices.Contains(cmd.Params, "-detail") var lastAppId int32 text := fmt.Sprintf("同步状态:%s\n", time.Now().Format("2006-01-02T15:04:05")) statutils.GlobalSyncMonitor.Traverse(func(item *statutils.SyncItem) { if len(appIds) > 0 && !slices.Contains(appIds, item.AppID) { return } if item.AppID != lastAppId { lastAppId = item.AppID text += fmt.Sprintf("\U0001F7E2【%d:%s】\n", item.AppID, appNames[item.AppID]) } text += fmt.Sprintf("1️⃣描述【%s】\n", item.JobDesc) if isDetail { text += fmt.Sprintf("2️⃣名称【%s】\n", item.JobName) text += fmt.Sprintf("3️⃣开始【%s】\n", item.JobBegin().Format("2006-01-02T15:04:05")) if item.JobEnd().Before(item.JobBegin()) { // 未完成 text += fmt.Sprintf("4️⃣用时【%s】\n", fmt.Sprintf("%s", time.Now().Sub(item.JobBegin()))) text += fmt.Sprintf("5️⃣结束【正在执行...】\n") } else { text += fmt.Sprintf("4️⃣用时【%s】\n", fmt.Sprintf("%s", item.JobEnd().Sub(item.JobBegin()))) text += fmt.Sprintf("5️⃣结束【%s】\n", item.JobEnd().Format("2006-01-02T15:04:05")) } text += fmt.Sprintf("6️⃣当前【%d条】\n", item.CurrentCount) text += fmt.Sprintf("7️⃣当日【%d条】\n", item.TodayCount()) if !item.RequestBegin.Before(item.JobBegin()) { text += fmt.Sprintf("ℹ请求开始【%s】\n", item.RequestBegin.Format("2006-01-02T15:04:05")) text += fmt.Sprintf("ℹ请求用时【%s】\n", fmt.Sprintf("%s", item.RequestEnd.Sub(item.RequestBegin))) text += fmt.Sprintf("ℹ请求结束【%s】\n", item.RequestEnd.Format("2006-01-02T15:04:05")) } if !item.ProcessBegin.Before(item.JobBegin()) { text += fmt.Sprintf("ℹ处理开始【%s】\n", item.ProcessBegin.Format("2006-01-02T15:04:05")) text += fmt.Sprintf("ℹ处理用时【%s】\n", fmt.Sprintf("%s", item.ProcessEnd.Sub(item.ProcessBegin))) text += fmt.Sprintf("ℹ处理结束【%s】\n", item.ProcessEnd.Format("2006-01-02T15:04:05")) } } else { text += fmt.Sprintf("2️⃣名称【%s】\n", item.JobName) text += fmt.Sprintf("3️⃣开始【%s】\n", item.JobBegin().Format("2006-01-02T15:04:05")) if item.JobEnd().Before(item.JobBegin()) { // 未完成 text += fmt.Sprintf("4️⃣用时【%s】\n", fmt.Sprintf("%s", time.Now().Sub(item.JobBegin()))) text += fmt.Sprintf("5️⃣结束【正在执行...】\n") } else { text += fmt.Sprintf("4️⃣用时【%s】\n", fmt.Sprintf("%s", item.JobEnd().Sub(item.JobBegin()))) text += fmt.Sprintf("5️⃣结束【%s】\n", item.JobEnd().Format("2006-01-02T15:04:05")) } text += fmt.Sprintf("6️⃣当前【%d条】\n", item.CurrentCount) text += fmt.Sprintf("7️⃣当日【%d条】\n", item.TodayCount()) } if item.Error != nil { text += fmt.Sprintf("🛑错误【%s】\n", item.Error.Error()) } text += fmt.Sprintf("\n") }) return cmd.SendBack(text) } func HandleTodayStatCmd(ctx context.Context, cmd *tgbot.Command) error { appIds := cmd.GetFlagInt32Slice("-app") if len(appIds) <= 0 { return DisplayAppButtons(ctx, cmd) } back, _ := cmd.GetFlagInt32Value("-back") return DailyStat(ctx, cmd, int(back)) } func HandleYesterdayStatCmd(ctx context.Context, cmd *tgbot.Command) error { appIds := cmd.GetFlagInt32Slice("-app") if len(appIds) <= 0 { return DisplayAppButtons(ctx, cmd) } return DailyStat(ctx, cmd, -1) } func HandleDailyStatCmd(ctx context.Context, cmd *tgbot.Command) error { appIds := cmd.GetFlagInt32Slice("-app") if len(appIds) <= 0 { return DisplayAppButtons(ctx, cmd) } back, err := cmd.GetFlagInt32Value("-back") if err != nil { return tgbot.NewUserError(cmd, "请输入回退天数,格式:\n"+cmd.Help+"\n"+cmd.Desc) } return DailyStat(ctx, cmd, int(back)) } func HandleDailyHourStatCmd(ctx context.Context, cmd *tgbot.Command) error { appIds := cmd.GetFlagInt32Slice("-app") if len(appIds) <= 0 { return DisplayAppButtons(ctx, cmd) } project := cmd.GetFlagStringValue("-stat") if project == "" { return DisplayStatProjectButtons(ctx, cmd) } back, err := cmd.GetFlagInt32Value("-back") if err != nil { return tgbot.NewUserError(cmd, "请输入回退天数,格式:\n"+cmd.Help+"\n"+cmd.Desc) } return DailyHourStat(ctx, cmd, int(back)) } func HandleHourStatCmd(ctx context.Context, cmd *tgbot.Command) error { appIds := cmd.GetFlagInt32Slice("-app") if len(appIds) <= 0 { return DisplayAppButtons(ctx, cmd) } back, err := cmd.GetFlagInt32Value("-back") if err != nil { return tgbot.NewUserError(cmd, "请输入回退小时数,格式:\n"+cmd.Help+"\n"+cmd.Desc) } return HourStat(ctx, cmd, int(back)) } func DailyStat(ctx context.Context, cmd *tgbot.Command, moveBackDays int) error { appId, err := cmd.GetFlagInt32Value("-app") if err != nil { return tgbot.NewUserError(cmd, "请输入应用ID,格式:\n"+cmd.Help+"\n"+cmd.Desc) } filter := bson.M{} appMap, err := appInfoMod.GetAllAppIdMap(ctx, filter) if err != nil { return tgbot.NewUserError(cmd, "服务器错误:"+err.Error()) } appInfo := appMap[appId] if appInfo == nil { return tgbot.NewUserError(cmd, fmt.Sprintf("应用ID【%d】不存在", appId)) } if moveBackDays > 0 { moveBackDays = moveBackDays * -1 } reportTime := utils.RecentMinute(time.Now(), 60) if moveBackDays != 0 { reportTime = utils.BeginWithTime(time.Now().AddDate(0, 0, moveBackDays+1)) } 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, false) if err != nil { return tgbot.NewUserError(cmd, "服务器错误:"+err.Error()) } } else { return tgbot.NewUserError(cmd, "服务器错误:"+err.Error()) } } 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 tgbot.NewUserError(cmd, "服务器错误:"+err.Error()) } } else { return tgbot.NewUserError(cmd, "服务器错误:"+err.Error()) } } text, title, desc := report.DisplayDayHourTextWithTitle(appInfo.Name, historyReport, lastWeekHourStat(ctx, appId, reportTime)) et := tgbot.NewEntityList(title, desc, []*tgbot.Entity{ { Content: text, }, }) return cmd.SendEntity(et) } func HourStat(ctx context.Context, cmd *tgbot.Command, moveBackHours int) error { appId, err := cmd.GetFlagInt32Value("-app") if err != nil { return tgbot.NewUserError(cmd, "请输入应用ID,格式:\n"+cmd.Help+"\n"+cmd.Desc) } filter := bson.M{} appMap, err := appInfoMod.GetAllAppIdMap(ctx, filter) if err != nil { return tgbot.NewUserError(cmd, "服务器错误:"+err.Error()) } appInfo := appMap[appId] if appInfo == nil { return tgbot.NewUserError(cmd, fmt.Sprintf("应用ID【%d】不存在", appId)) } if moveBackHours > 0 { moveBackHours = moveBackHours * -1 } reportTime := utils.RecentMinute(time.Now(), 60) if moveBackHours != 0 { reportTime = reportTime.Add(time.Duration(moveBackHours) * time.Hour) } reportFilter := bson.M{ botreport.FN.BotReport.SumDate: reportTime, botreport.FN.BotReport.AppId: appId, } report, err := botreport.FindOneBotReport(ctx, reportFilter) if err != nil { return tgbot.NewUserError(cmd, "服务器错误:"+err.Error()) } if report.SumDate != reportTime { return tgbot.NewUserError(cmd, "数据记录尚未生成,请过五分钟再试") } HistoryFilter := bson.M{ botreport.FN.BotReport.SumDate: reportTime.AddDate(0, 0, -1), botreport.FN.BotReport.AppId: appId, } historyReport, err := botreport.FindOneBotReport(ctx, HistoryFilter) if err != nil { return tgbot.NewUserError(cmd, "服务器错误:"+err.Error()) } text := DisplayHourStat(report, historyReport, appInfo, GetHourDesc(moveBackHours)) return cmd.SendBack(text) } func DailyHourStat(ctx context.Context, cmd *tgbot.Command, moveBackDays int) error { appId, err := cmd.GetFlagInt32Value("-app") if err != nil { return tgbot.NewUserError(cmd, "请输入应用ID,格式:\n"+cmd.Help+"\n"+cmd.Desc) } statName := cmd.GetFlagStringValue("-stat") if statName == "" { return tgbot.NewUserError(cmd, "请输入统计项目的细分名称:\n"+cmd.Help+"\n"+cmd.Desc) } filter := bson.M{} appMap, err := appInfoMod.GetAllAppIdMap(ctx, filter) if err != nil { return tgbot.NewUserError(cmd, "服务器错误:"+err.Error()) } appInfo := appMap[appId] if appInfo == nil { return tgbot.NewUserError(cmd, fmt.Sprintf("应用ID【%d】不存在", appId)) } if moveBackDays > 0 { moveBackDays = moveBackDays * -1 } reportTime := utils.RecentMinute(time.Now(), 60) if moveBackDays != 0 { reportTime = reportTime.AddDate(0, 0, moveBackDays) } 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 { return tgbot.NewUserError(cmd, "统计记录尚未生成,请过5分钟再试") } return tgbot.NewUserError(cmd, "服务器错误:"+err.Error()) } HistoryFilter := bson.M{ botreport.FN.BotReport.AppId: appId, botreport.FN.BotReport.SumDate: reportTime.AddDate(0, 0, -1), } historyReport, _ := botdailyhourstat.FindOneBotHourStatEx(ctx, HistoryFilter) photo := fmt.Sprintf("/tmp/%s.png", utils.UUID()) var text string title := fmt.Sprintf("%s%s%s", appInfo.Name, GetDateDesc(moveBackDays), statutils.StatProjectNameDict[statName]) text, err = report.GenerateTodayTable(title, statName, photo, historyReport) if err != nil { return err } cmd.PhotoPath = photo return cmd.SendBack(text) } func HandleDistrictDataCmd(ctx context.Context, cmd *tgbot.Command) error { lanpageinfo := monitor.RunLandPageMonitor() cmd.SendReply(lanpageinfo, nil) channelMsg := monitor.ChannelMonitor() cmd.SendReply(channelMsg, nil) return nil } func HandleCrossDayStatCmd(ctx context.Context, cmd *tgbot.Command) error { project := cmd.GetFlagStringValue("-stat") if project == "" { return DisplayStatProjectButtons(ctx, cmd) } if !cmd.HasFlag("-back") { return tgbot.NewUserError(cmd, "请输入回退天数,格式:\n"+cmd.Help+"\n"+cmd.Desc) } if cmd.HasFlag("-stat") { sType := cmd.GetFlagStringValue("-stat") statMethod, ok := crossSer.CrossStatMethodMap[sType] if !ok { return tgbot.NewUserError(cmd, fmt.Sprintf("-stat=%s,没有注册对应的统计方法", sType)) } return statMethod(ctx, cmd) } else { return tgbot.NewUserError(cmd, "-stat 没有填写, 格式:\n"+cmd.Help+"\n"+cmd.Desc) } } func HandleCrossMonthStatCmd(ctx context.Context, cmd *tgbot.Command) error { if statg.Conf.ServerIndex.IsMadou() { monthStr := cmd.GetFlagStringValue("-month") if monthStr == "" { return tgbot.NewUserError(cmd, "请输入统计月份,格式:\n"+cmd.Help+"\n"+cmd.Desc) } return crossSer.CrossMonthStat(ctx, cmd) } return nil } func HandleVersionCmd(ctx context.Context, cmd *tgbot.Command) error { text := GetServerInformation() return cmd.SendReply(text, nil) } func HandleRchssendCmd(ctx context.Context, cmd *tgbot.Command) error { err := innerserverser.InnerServerDailyStat(ctx) if err != nil { fmt.Println("HandleRchssendCmd" + err.Error()) return tgbot.NewUserError(cmd, "HandleRchssendCmd:"+err.Error()) } return nil } func HandleRchsMonthBotsendCmd(ctx context.Context, cmd *tgbot.Command) error { err := innerserverser.InnerServerMonthStat2(ctx, nil, nil, cmd) if err != nil { fmt.Println("HandleRchsbotsendCmd" + err.Error()) return tgbot.NewUserError(cmd, "HandleRchsbotsendCmd:"+err.Error()) } return nil } func HandleRchsMonthBotDatetodatesendCmd(ctx context.Context, cmd *tgbot.Command) error { err := innerserverser.InnerServerBotDateMonthStat(ctx, cmd) if err != nil { fmt.Println("HandleRchsbotsendCmd" + err.Error()) return tgbot.NewUserError(cmd, "HandleRchsbotsendCmd:"+err.Error()) } return nil } func HandleRchsDateBotsendCmd(ctx context.Context, cmd *tgbot.Command) error { err := innerserverser.InnerServerBotDateDayStat(ctx, cmd) if err != nil { fmt.Println("HandleRchsbotsendCmd" + err.Error()) return tgbot.NewUserError(cmd, "HandleRchsbotsendCmd:"+err.Error()) } return nil }