Initial commit

This commit is contained in:
2026-05-20 16:13:58 +08:00
commit ceffbe382e
500 changed files with 157469 additions and 0 deletions
+196
View File
@@ -0,0 +1,196 @@
package botser
import (
"context"
"errors"
"fmt"
"sort"
"stat/common/log"
"stat/common/utils"
"stat/models/accessmod"
"stat/models/channelmod"
"stat/models/rechargegamemod"
"stat/models/rechargemod"
"stat/models/registermod"
"stat/models/withdrawGameOrdermod"
"time"
"go.mongodb.org/mongo-driver/bson"
)
type IpCount struct {
Ip string
Count int64
}
type IpCountList []*IpCount
func (a IpCountList) Len() int { return len(a) }
func (a IpCountList) Less(i, j int) bool {
return a[i].Count > a[j].Count
}
func (a IpCountList) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
type AnalyzeItem struct {
Channel string
RegisterIpMap map[string]int64
RegisterUserMap map[string]int64
RegisterCount int64 // 注册总数
RegisterIpCount int64 // 注册IP数
VisitCountMap map[string]int64 // 访问总数
ValidVisitAfterHourMap map[string]int64 // 1小时后访问总数
ValidVisitAfterDayMap map[string]int64 // 1天后访问总数
ValidVisitAfterTowDayMap map[string]int64 // 2天后访问总数
RechargeCount int64 // 充值次数
RechargeAmount int64 // 充值钱数
RechargeUsers int64 // 充值用户数
GameRecharge int64 // 游戏充值
GameWithdraw int64 // 游戏提现
}
func NewAnalyzeItem(channel string) *AnalyzeItem {
return &AnalyzeItem{
Channel: channel,
RegisterIpMap: make(map[string]int64),
RegisterUserMap: make(map[string]int64),
VisitCountMap: make(map[string]int64),
ValidVisitAfterHourMap: make(map[string]int64),
ValidVisitAfterDayMap: make(map[string]int64),
ValidVisitAfterTowDayMap: make(map[string]int64),
}
}
func (s *AnalyzeItem) AddIp(ip string) {
s.RegisterCount++
s.RegisterIpMap[ip]++
s.RegisterIpCount = int64(len(s.RegisterIpMap))
}
func (s *AnalyzeItem) IpRank(topCount int) IpCountList {
list := make(IpCountList, 0)
for ip, count := range s.RegisterIpMap {
list = append(list, &IpCount{
Ip: ip,
Count: count,
})
}
sort.Sort(list)
ret := make(IpCountList, 0)
for _, item := range list {
if len(ret) < topCount {
ret = append(ret, item)
}
}
return ret
}
func ChannelAnalyze(ctx context.Context, channel string, start time.Time, end time.Time) (*AnalyzeItem, error) {
ret := NewAnalyzeItem(channel)
key := func(appid int32, userid uint64) string {
return fmt.Sprintf("%d-%d", appid, userid)
}
channelDeductionRules, err := channelmod.FindManyChannelDeductionRule(ctx, bson.M{
channelmod.FN.ChannelDeductionRule.Channel: channel,
})
if err != nil {
log.Error("ChannelSettlementMethod FindManyChannelDeductionRule", log.E(err))
return nil, err
}
if len(channelDeductionRules) <= 0 {
return nil, nil
}
channelInfo, err := channelmod.FindOneChannelInfo(ctx, bson.M{
channelmod.FN.ChannelInfo.Channel: channel})
if err != nil {
log.Error("ChannelAnalyze FindOneChannelInfo", log.E(err))
return nil, err
}
if channelInfo.Channel != channel {
return nil, errors.New("channel not found")
}
registerDict := make(map[string]*registermod.RegisterMod)
for _, ruleInfo := range channelDeductionRules {
// 统计注册用户
registerList, err := registermod.RegisterChannelUsersInfoByTime(ctx, channel, ruleInfo.AppId, start, end)
if err != nil {
log.Error("NewCountMethod RegisterUsersInfoByDistrict ", log.E(err))
return nil, err
}
uids := make([]uint64, 0)
for _, register := range registerList {
ret.AddIp(register.IP)
registerDict[key(ruleInfo.AppId, register.UserId)] = register
uids = append(uids, register.UserId)
}
err1 := utils.SlicePaged(uids, 5000, func(piece []uint64) error {
vList, err2 := accessmod.FindManyVisitInfo(ctx, bson.M{
"userId": bson.M{"$in": piece},
"appId": ruleInfo.AppId,
"visitAt": bson.M{"$gte": start, "$lt": end},
})
// 访问统计
for _, visit := range vList {
skey := key(ruleInfo.AppId, visit.UserId)
regUser := registerDict[skey]
if regUser == nil {
continue
}
ret.VisitCountMap[skey]++
if visit.VisitAt.After(regUser.RegisterTime.Add(time.Hour)) {
ret.ValidVisitAfterHourMap[skey]++
}
if visit.VisitAt.After(regUser.RegisterTime.Add(24 * time.Hour)) {
ret.ValidVisitAfterDayMap[skey]++
}
if visit.VisitAt.After(regUser.RegisterTime.Add(48 * time.Hour)) {
ret.ValidVisitAfterTowDayMap[skey]++
}
}
return err2
})
if err1 != nil {
log.Error("FindManyVisitInfo error ", log.E(err1))
return nil, err1
}
// 充值统计
rechargeFilter := bson.M{"districtCode": channel, "appId": ruleInfo.AppId, "successAt": bson.M{"$gte": start, "$lt": end}}
rechargeList, _ := rechargemod.FindManyRechargeInfo(ctx, rechargeFilter)
for _, item := range rechargeList {
skey := key(ruleInfo.AppId, item.UserId)
regUser := registerDict[skey]
if regUser == nil {
continue
}
ret.RegisterUserMap[skey]++
ret.RechargeCount++
ret.RechargeAmount += item.PayMoney
}
// 游戏充值
gamerechageList, err := rechargegamemod.FindManyRechargeInfo(ctx, rechargeFilter)
if err != nil {
return nil, err
}
for _, item := range gamerechageList {
skey := key(ruleInfo.AppId, item.UserId)
regUser := registerDict[skey]
if regUser == nil {
continue
}
ret.RegisterUserMap[skey]++
ret.GameRecharge += item.Money
}
gamewithdrawList, err := withdrawGameOrdermod.FindManyGameWithdrawOrder(ctx, rechargeFilter)
if err != nil {
return nil, err
}
for _, item := range gamewithdrawList {
skey := key(ruleInfo.AppId, item.UID)
regUser := registerDict[skey]
if regUser == nil {
continue
}
ret.GameWithdraw += item.Money
}
}
return ret, nil
}
+33
View File
@@ -0,0 +1,33 @@
package botser
import (
"stat/common/log"
"stat/statg"
)
func StartBot() {
log.Info("StartBot start")
if statg.Bot == nil {
log.Error("statg.Bot is nil!!!")
return
}
Start(statg.Bot)
// 发送服务器启动信息
text := GetServerInformation()
text += GetServerInformationLastTime()
text += "🔔此服务器刚刚重启🔔"
statg.Bot.SendDevelopMessage(text)
// 注册命令
statg.Bot.RegisterCommand(CommandList...)
if statg.RchssendBot != nil && statg.Conf.ServerIndex == statg.ServerIndexBili {
// 注册命令
statg.RchssendBot.RegisterCommand(CommandList0...)
}
log.Info("StartBot end")
//statg.RchssendBot.SendrchssendMessage(text)
}
+173
View File
@@ -0,0 +1,173 @@
package botser
import (
"stat/common/tgbot"
)
var (
CommandList = []*tgbot.Command{
{
Cmd: "what",
Help: "/what",
Desc: "聊天信息",
CmdType: tgbot.CommandTypeCommand,
Process: HandleWhatCmd,
},
{
Cmd: "menu",
Help: "/menu",
Desc: "显示菜单",
CmdType: tgbot.CommandTypeCommand,
Process: HandleMenuCmd,
},
{
Cmd: "close",
Help: "/close",
Desc: "关闭菜单",
CmdType: tgbot.CommandTypeCommand,
Process: HandleCloseCmd,
},
{
Cmd: "hour",
Help: "/hour",
Desc: "小时统计",
CmdType: tgbot.CommandTypeCommand,
Process: HandleHourStatCmd,
},
{
Cmd: "district",
Help: "/district",
Desc: "渠道统计",
CmdType: tgbot.CommandTypeCommand,
Process: HandleDistrictDataCmd,
},
{
Cmd: "today",
Help: "/today -app=888",
Desc: "今日统计,统计从今天开始到当前小时整点的数据",
CmdType: tgbot.CommandTypeCommand,
Process: HandleTodayStatCmd,
},
{
Cmd: "yesterday",
Help: "/yesterday -app=888",
Desc: "昨日统计,统计昨天的完整数据",
CmdType: tgbot.CommandTypeCommand,
Process: HandleYesterdayStatCmd,
},
{
Cmd: "daily",
Help: "/daily -app=888 -back=1",
Desc: "每日统计, -back=0 表示今天,-back=1 表示昨天,-back=2 表示前天,以此类推",
CmdType: tgbot.CommandTypeCommand,
Process: HandleDailyStatCmd,
},
{
Cmd: "apps",
Help: "/apps",
Desc: "应用列表",
CmdType: tgbot.CommandTypeCommand,
Process: HandleAppListCmd,
},
{
Cmd: "sync",
Help: "/sync | /sync -detail | /sync -app=888,999",
Desc: "同步状态",
CmdType: tgbot.CommandTypeCommand,
Process: HandleSyncStatusCmd,
},
{
Cmd: "daily_hour",
Help: "/daily_hour -app=888 -back=0",
Desc: "每日每时统计, -back=0 表示今天,-back=1 表示昨天,-back=2 表示前天,以此类推",
CmdType: tgbot.CommandTypeCommand,
Process: HandleDailyHourStatCmd,
},
{
Cmd: "game_report",
Help: "/game_report",
Desc: "游戏统计文件, -back=0 表示今天,-back=1 表示昨天,-back=2 表示前天,以此类推",
CmdType: tgbot.CommandTypeCommand,
Process: HandleGameReportCmd,
},
{
Cmd: "channel_analyze",
Help: "/channel_analyze -channel=abc -begin=2023-06-05 -end=2023-07-05",
Desc: "渠道分析, 时间按中国时间解析,每个时间都解析为当天零点",
CmdType: tgbot.CommandTypeCommand,
Process: HandleChannelAnalyzeCmd,
},
{
Cmd: "channel_apk",
Help: "/channel_apk -channel=abc -app=888",
Desc: "渠道包生成",
CmdType: tgbot.CommandTypeCommand,
Process: HandleChannelApkCmd,
},
{
Cmd: "auto_task",
Help: "/auto_task -file",
Desc: "自动任务运行状态",
CmdType: tgbot.CommandTypeCommand,
Process: HandleAutoTaskStatusCmd,
},
{
Cmd: "cross_stat",
Help: "/cross_stat -stat=recharge -back=0",
Desc: "全服统计",
CmdType: tgbot.CommandTypeCommand,
Process: HandleCrossDayStatCmd,
},
{
Cmd: "cross_month_stat",
Help: "/cross_month_stat -month=2023-06-01 -app=888",
Desc: "全服月统计, -month=2023-06-01 表示统计2023年整个6月的数据, -app=888 表示只统计app=888的数据,不填写则统计所有app",
CmdType: tgbot.CommandTypeCommand,
Process: HandleCrossMonthStatCmd,
},
{
Cmd: "version",
Help: "/version",
Desc: "服务端版本",
CmdType: tgbot.CommandTypeCommand,
Process: HandleVersionCmd,
},
}
CommandList0 = []*tgbot.Command{
{
Cmd: "menurecharge",
Help: "/menurecharge",
Desc: "显示菜单",
CmdType: tgbot.CommandTypeCommand,
Process: HandleMenuCmd0,
},
{
Cmd: "recharge",
Help: "/recharge",
Desc: "单充值播报",
CmdType: tgbot.CommandTypeCommand,
Process: HandleRchssendCmd,
},
{
Cmd: "rechargenew",
Help: "/rechargenew",
Desc: "综合充值播报(昨天)",
CmdType: tgbot.CommandTypeCommand,
Process: HandleRchsMonthBotsendCmd,
},
{
Cmd: "rechargedate",
Help: "/rechargedate",
Desc: "综合充值播报(开始到结束的时间)",
CmdType: tgbot.CommandTypeCommand,
Process: HandleRchsMonthBotDatetodatesendCmd,
},
{
Cmd: "rechargeoneday",
Help: "/rechargeoneday",
Desc: "综合统计具体年月日",
CmdType: tgbot.CommandTypeCommand,
Process: HandleRchsDateBotsendCmd,
},
}
)
+70
View File
@@ -0,0 +1,70 @@
package botser
import (
"context"
"fmt"
"stat/common/enum/consts"
"stat/common/log"
"stat/common/statutils"
"stat/common/tgbot"
"stat/common/utils"
"stat/statg"
"time"
"github.com/robfig/cron/v3"
)
var (
botCron *cron.Cron
)
func init() {
botCron = cron.New(cron.WithSeconds(), cron.WithChain(cron.SkipIfStillRunning(&log.Logger{}))) // 秒级定时任务
}
// Start 定时器任务启动
func Start(bot *tgbot.TgBot) {
log.Info("skd start...")
if bot == nil {
return
}
ctx := context.Background()
if statg.Conf.RunMod != consts.RunModRelease {
return
}
_, _ = botCron.AddFunc("0 5 0/1 * * ?", func() {
log.Info("Cron Hourly Entry...")
// 发送消息 统计数据
curStatTime := utils.RecentMinute(time.Now(), 60) // 按60分钟对齐
endpoints := statg.GlobalEndpoints.GetIndexEndpoints(statg.Conf.ServerIndex).GetBotStatEndpoints()
for _, end := range endpoints {
id := end.AppId
tm := curStatTime
statutils.ServerMon.RunWithName(func() error {
return DailyBotReportTask(ctx, bot, id, tm)
}, statutils.GetFuncName(DailyBotReportTask))
}
fmt.Printf("Cron Hourly %v", curStatTime)
if statg.Conf.ServerIndex.IsMadou() {
if curStatTime.Hour() == 8 {
// statutils.ServerMon.Run(SkdGameTask) 麻豆不发送集团数据
}
}
})
_, _ = botCron.AddFunc("0 6 0/1 * * ?", func() {
if statg.Conf.ServerIndex.IsMadou() {
curStatTime := utils.RecentMinute(time.Now(), 60) // 按60分钟对齐
statutils.ServerMon.RunWithName(func() error {
return DailyBotRankTask(ctx, bot, curStatTime)
}, statutils.GetFuncName(DailyBotRankTask))
}
})
_, _ = botCron.AddFunc("*/5 * * * * ?", func() {
SaveServerKeepAliveTime()
})
botCron.Start()
}
+349
View File
@@ -0,0 +1,349 @@
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)
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)
}
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
}
+87
View File
@@ -0,0 +1,87 @@
package botser
import (
"context"
"encoding/json"
"fmt"
"net/url"
"os"
"stat/api/proto"
"stat/common"
"stat/common/crypt"
"stat/common/utils"
"stat/tool/pubtest"
"testing"
"time"
)
func Test_Func12(t *testing.T) {
// Let's start with a base url
baseUrl, err := url.Parse("http://www.bing.com/aaa?a=1&b=2,3")
if err != nil {
fmt.Println("Malformed URL: ", err.Error())
return
}
// Add a Path Segment (Path segment is automatically escaped)
//baseUrl.Path += "path with?reserved characters"
// Prepare Query Parameters
params := baseUrl.Query()
//params.Add("q", "Hello World")
//params.Add("u", "wade")
// Add Query Parameters to the URL
baseUrl.RawQuery = params.Encode() // Escape Query Parameters
fmt.Printf("Encoded URL is %q\n", baseUrl.String())
}
func Test_SyncData(t *testing.T) {
key := "vEnkB&!75z4VAD6iAY%fkL*rBnU!WdhN"
var appId int32 = 222
req := &proto.BotDailyHourListReq{
Page: common.Page{
PageNum: 1,
PageSize: 20,
},
SumDateStart: time.Now().AddDate(0, 0, -3),
SumDateStop: time.Now(),
AppId: &appId,
}
jsonData, err := json.Marshal(req)
if err != nil {
t.Error(err)
}
data, err := crypt.CoreAesEncryptEx(jsonData, 12, key)
os.WriteFile("aaa.data", data, 777)
}
func Test_skdTask(t *testing.T) {
pubtest.TestInit("/Users/mac/Works/codes/stat_center/run/bili")
s, _ := time.Parse(time.RFC3339, "2023-06-15T15:00:00+08:00")
curStatTime := utils.RecentMinute(s, 60) // 按60分钟对齐
ctx := context.Background()
DailyBotReportTask(ctx, nil, int32(444), curStatTime) // 麻豆
}
func Test_PassedTimeFromNowInHuman(t *testing.T) {
//s := PassedTimeFromNowInHuman(time.Now().Add(-9 * time.Minute))
//t.Log(s)
//s2 := DurationDisplay(time.Now(), time.Now().Add(-8*time.Second))
//t.Log(s2)
}
func Test_Fun1(t *testing.T) {
time.Local, _ = time.LoadLocation("Asia/Shanghai")
//DateTime = "2006-01-02 15:04:05"
//DateOnly = "2006-01-02"
//TimeOnly = "15:04:05"
s, err := time.ParseInLocation(time.DateOnly, "2023-06-15", time.Local)
if err != nil {
t.Error(err)
} else {
t.Log(s)
}
}
+704
View File
@@ -0,0 +1,704 @@
package botser
import (
"context"
"errors"
"fmt"
"math/rand"
"os"
"path"
"stat/common/log"
"stat/common/tgbot"
"stat/common/topicmessage"
"stat/common/utils"
"stat/models/dailystatmod"
"stat/service/consumer"
"stat/statg"
"time"
"github.com/360EntSecGroup-Skylar/excelize"
)
// BlocDailyStatTgbot 机器人汇报每日数据()
type BlocDailyStatTgbot struct {
SumDate time.Time `bson:"sumDate"` // 记录时间 按天对齐
NewDirectCount int64 `bson:"newDirectCount"` // 新增直推
NewFissionCount int64 `bson:"newFissionCount"` // 新增裂变
DirectVisitCount int64 `bson:"directVisitCount"` // 直推访问数
FissionVisitCount int64 `bson:"fissionVisitCount"` // 裂变访问数
DirectAmount int64 `bson:"directAmount"` // 直推充值总金额
DirectOtherAmount int64 `bson:"directOtherAmount"` // 直推充值其他金额
FissionAmount int64 `bson:"fissionAmount"` // 裂变充值金额
DirectAmountCount int64 `bson:"directAmountcount"` // 直推充值订单
FissionAmountCount int64 `bson:"fissionAmountcount"` // 裂变充值订单
NewRechargeCount int64 `bson:"newRechargeCount"` // 新增充值数
NewRechargeAmount int64 `bson:"newRechargeAmount"` // 新增充值金额
NewBindingCount int64 `bson:"newBindingCount"` // 新增绑定用户数
APPNewRechargeCount int64 `bson:"appNewRechargeCount"` // app总新增充值人数(兼容)
APPNewRechargeAmount int64 `bson:"appNewRechargeAmount"` // app新增总充值
APPRechargeAmount int64 `bson:"appRechargeAmount"` // app总充值
APPRechargeCount int64 `bson:"appRechargeCount"` // app总充值人数
APPRechargeOrderCount int64 `bson:"appRechargeOrderCount"` // app总充值订单数
APPDaichongAmout int64 `bson:"appDaichongAmout"` // app代充充值金额
APPDaichongAmoutCount int64 `bson:"appDaichongAmoutCount"` // app代充充值人数
APPOnlineAmount int64 `bson:"appOnlineAmount"` // app在线充值金额
APPOnlineAmountCount int64 `bson:"appOnlineAmountCount"` // app在线充值人数
APPRechAmount int64 `bson:"appRechAmount"` // app总提现
}
func GetBlocDailyStatTgbotInfo(ctx context.Context, sumDate time.Time) *BlocDailyStatTgbot {
blocDay := utils.BeginWithTimeLocal(sumDate)
blocInfo := &BlocDailyStatTgbot{}
ids := []int32{888, 668}
mdStatList, err := dailystatmod.FindDailyStatList(ctx, ids, blocDay)
if err != nil {
log.Info("GetBlocDailyStatTgbotInfoxx", log.Any("blocDay", blocDay), log.Any("len", len(mdStatList)))
return blocInfo
}
log.Info("GetBlocDailyStatTgbotInfo", log.Any("blocDay", blocDay), log.Any("len", len(mdStatList)))
for _, mdStatInfo := range mdStatList {
blocInfo.SumDate = blocDay
blocInfo.NewDirectCount += mdStatInfo.NewDirectCount
blocInfo.NewFissionCount += mdStatInfo.NewFissionCount
blocInfo.DirectVisitCount += mdStatInfo.DirectVisitCount
blocInfo.FissionVisitCount += mdStatInfo.FissionVisitCount
blocInfo.DirectAmount += mdStatInfo.DirectAmount
blocInfo.FissionAmount += mdStatInfo.FissionAmount
blocInfo.DirectAmountCount += mdStatInfo.DirectAmountCount
blocInfo.FissionAmountCount += mdStatInfo.FissionAmountCount
blocInfo.NewRechargeCount += mdStatInfo.NewRechargeCount
blocInfo.NewRechargeAmount += mdStatInfo.NewRechargeAmount
blocInfo.APPRechargeAmount += mdStatInfo.TotalAmount
blocInfo.APPNewRechargeCount += mdStatInfo.NewRechargeCount
blocInfo.APPNewRechargeAmount += mdStatInfo.NewRechargeAmount
blocInfo.APPRechargeCount += mdStatInfo.DirectAmountCount + mdStatInfo.FissionAmountCount
blocInfo.APPRechargeOrderCount += mdStatInfo.SuccessRechargeOrder
blocInfo.APPOnlineAmount += mdStatInfo.TotalAmount
blocInfo.APPOnlineAmountCount = +mdStatInfo.DirectAmountCount + mdStatInfo.FissionAmountCount
}
return blocInfo
}
var (
GameChatId = "G-841710430"
)
var exportUserTitle = map[string]string{
"A1": "项目",
"B1": "YCXM1",
"C1": "对比",
}
func GetGameInfo(ctx context.Context, reportTime time.Time) *topicmessage.GetReportStatResp {
request := &topicmessage.StatcenterGameReq{
Date: utils.BeginWithTime(reportTime),
}
url, err := consumer.AppCallbackUrl(888)
if err != nil {
return nil
}
apiUrl := url + "/api/web/statcenter/game"
var resp *topicmessage.GetReportStatResp
err = consumer.HttpRequest(ctx, apiUrl, &request, &resp)
if err != nil {
log.Error("RunSyncJob HttpRequest", log.Any("url", apiUrl), log.Any("request", request), log.E(err))
return nil
}
if resp.Code != 200 {
log.Info("RunSyncJob HTTP请求失败", log.Any("url", apiUrl), log.Any("request", request), log.Any("resp", resp))
return nil
}
return resp
}
func SkdGameTask() error {
ctx := context.Background()
beginTime := utils.BeginOfToday().AddDate(0, 0, -1)
// yestodayBeginTime := utils.BeginOfToday().AddDate(0, 0, -2)
gameInfo := topicmessage.GetReportStatResp{}
yestodayGameInfo := topicmessage.GetReportStatResp{}
sheetName := "Sheet1"
f := excelize.NewFile()
idx := f.NewSheet(sheetName)
for k, v := range exportUserTitle {
f.SetCellValue(sheetName, k, v)
}
f.SetColWidth(sheetName, "A", "D", 30)
styleOne, _ := f.NewStyle(`{"alignment":{"horizontal":"right"}}`)
styleTwo, _ := f.NewStyle(`{"alignment":{"horizontal":"left"}}`)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 2), "视频游戏活跃人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 2), gameInfo.GamePlayCount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 2), gameInfo.GamePlayCount-yestodayGameInfo.GamePlayCount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 3), "视频游戏充值人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 3), gameInfo.GameRchgUsers)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 3), gameInfo.GameRchgUsers-yestodayGameInfo.GameRchgUsers)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 4), "视频游戏新增充值人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 4), gameInfo.GameFirstRchgUsers)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 4), gameInfo.GameFirstRchgUsers-yestodayGameInfo.GameFirstRchgUsers)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 5), "视频游戏老用户充值人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 5), gameInfo.GameRchgUsers-gameInfo.GameFirstRchgUsers)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 5), (gameInfo.GameRchgUsers-gameInfo.GameFirstRchgUsers)-(yestodayGameInfo.GameRchgUsers-yestodayGameInfo.GameFirstRchgUsers))
todayRchgAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameRchgAmount)/10000)
yestodayRchgAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameRchgAmount-yestodayGameInfo.GameRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 6), "视频游戏总充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 6), todayRchgAmount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 6), yestodayRchgAmount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 6), fmt.Sprintf("%s%d", string('B'), 6), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 6), fmt.Sprintf("%s%d", string('C'), 6), styleOne)
todayFirstRchgAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameFirstRchgAmount)/10000)
yestodayFirstRchgAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameFirstRchgAmount-yestodayGameInfo.GameFirstRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 7), "视频游新增充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 7), todayFirstRchgAmount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 7), yestodayFirstRchgAmount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 7), fmt.Sprintf("%s%d", string('B'), 7), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 7), fmt.Sprintf("%s%d", string('C'), 7), styleOne)
todayOldRchgAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameRchgAmount-gameInfo.GameFirstRchgAmount)/10000)
yestodayOldRchgAmount := fmt.Sprintf("%.4f", float64((gameInfo.GameRchgAmount-gameInfo.GameFirstRchgAmount)-(yestodayGameInfo.GameRchgAmount-yestodayGameInfo.GameFirstRchgAmount))/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 8), "视频游老用户充值")
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 8), fmt.Sprintf("%s%d", string('B'), 8), styleTwo)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 8), todayOldRchgAmount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 8), yestodayOldRchgAmount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 8), fmt.Sprintf("%s%d", string('B'), 8), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 8), fmt.Sprintf("%s%d", string('C'), 8), styleOne)
todayGameWtdrAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameWtdrAmount)/10000)
yestodayGameWtdrAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameWtdrAmount-yestodayGameInfo.GameWtdrAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 9), "视频游戏提现")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 9), todayGameWtdrAmount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 9), yestodayGameWtdrAmount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 9), fmt.Sprintf("%s%d", string('B'), 9), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 9), fmt.Sprintf("%s%d", string('C'), 9), styleOne)
todayGameRecvAmount := fmt.Sprintf("%.4f", float64((gameInfo.GameRchgAmount-gameInfo.GameWtdrAmount))/10000)
yestodayGameRecvAmount := fmt.Sprintf("%.4f", float64((gameInfo.GameRchgAmount-gameInfo.GameWtdrAmount)-(yestodayGameInfo.GameRchgAmount-yestodayGameInfo.GameWtdrAmount))/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 10), "视频游戏营收")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 10), todayGameRecvAmount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 10), yestodayGameRecvAmount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 10), fmt.Sprintf("%s%d", string('B'), 10), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 10), fmt.Sprintf("%s%d", string('C'), 10), styleOne)
todayRecvRate := float64((gameInfo.GameRchgAmount-gameInfo.GameWtdrAmount)*100) / float64(gameInfo.GameRchgAmount)
yestodayRecvRate := float64((yestodayGameInfo.GameRchgAmount-yestodayGameInfo.GameWtdrAmount)*100) / float64(yestodayGameInfo.GameRchgAmount)
todayRecvRateStr := fmt.Sprintf("%.2f", todayRecvRate) + "%"
yestodayRecvRateStr := fmt.Sprintf("%.2f", yestodayRecvRate) + "%"
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 11), "视频游戏营收比")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 11), todayRecvRateStr)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 11), yestodayRecvRateStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 11), fmt.Sprintf("%s%d", string('B'), 11), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 11), fmt.Sprintf("%s%d", string('C'), 11), styleOne)
todayRevenue := fmt.Sprintf("%.4f", float64(gameInfo.Revenue)/10000)
yestodayRevenue := fmt.Sprintf("%.4f", float64(gameInfo.Revenue-yestodayGameInfo.Revenue)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 12), "视频游戏税收")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 12), todayRevenue)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 12), yestodayRevenue)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 12), fmt.Sprintf("%s%d", string('B'), 12), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 12), fmt.Sprintf("%s%d", string('C'), 12), styleOne)
daichongAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameDCRchgAmount)/10000)
yestodayDaichongAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameDCRchgAmount-yestodayGameInfo.GameDCRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 13), "视频游戏代理充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 13), daichongAmount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 13), yestodayDaichongAmount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 13), fmt.Sprintf("%s%d", string('B'), 13), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 13), fmt.Sprintf("%s%d", string('C'), 13), styleOne)
todayProfit := fmt.Sprintf("%.4f", float64(gameInfo.Profit)/10000)
yestodayProfit := fmt.Sprintf("%.4f", float64(gameInfo.Profit-yestodayGameInfo.Profit)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 14), "视频游戏系统输赢")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 14), todayProfit)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 14), yestodayProfit)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 14), fmt.Sprintf("%s%d", string('B'), 14), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 14), fmt.Sprintf("%s%d", string('C'), 14), styleOne)
todayRevenueRate := float64(gameInfo.Revenue*100) / float64(gameInfo.GameRchgAmount)
yestodayRevenueRate := float64(yestodayGameInfo.Revenue*100) / float64(yestodayGameInfo.GameRchgAmount)
todayRevenueRateStr := fmt.Sprintf("%.2f", todayRevenueRate) + "%"
yestodayRevenueRateStr := fmt.Sprintf("%.2f", todayRevenueRate-yestodayRevenueRate) + "%"
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 15), "视频游戏税收比")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 15), todayRevenueRateStr)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 15), yestodayRevenueRateStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 15), fmt.Sprintf("%s%d", string('B'), 15), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 15), fmt.Sprintf("%s%d", string('C'), 15), styleOne)
todayProfitRate := float64(gameInfo.Profit*100) / float64(gameInfo.GameRchgAmount)
yestodayProfitRate := float64(yestodayGameInfo.Profit*100) / float64(yestodayGameInfo.GameRchgAmount)
todayProfitRateStr := fmt.Sprintf("%.2f", todayProfitRate) + "%"
yestodayProfitRateStr := fmt.Sprintf("%.2f", todayProfitRate-yestodayProfitRate) + "%"
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 16), "视频游戏输赢比")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 16), todayProfitRateStr)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 16), yestodayProfitRateStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 16), fmt.Sprintf("%s%d", string('B'), 16), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 16), fmt.Sprintf("%s%d", string('C'), 16), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 17), "视频游戏日投注用户")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 17), gameInfo.GamePlayCount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 17), gameInfo.GamePlayCount-yestodayGameInfo.GamePlayCount)
todayValidBet := fmt.Sprintf("%.4f", float64(gameInfo.ValidBet)/10000)
yestodayValidBet := fmt.Sprintf("%.4f", float64(gameInfo.ValidBet-yestodayGameInfo.ValidBet)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 18), "视频游戏总有效投注")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 18), todayValidBet)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 18), yestodayValidBet)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 18), fmt.Sprintf("%s%d", string('B'), 18), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 18), fmt.Sprintf("%s%d", string('C'), 18), styleOne)
todayValidBet = fmt.Sprintf("%.4f", (float64(gameInfo.ValidBet)/float64(gameInfo.GamePlayCount))/10000)
yestodayValidBet = fmt.Sprintf("%.4f", (float64(gameInfo.ValidBet)/float64(gameInfo.GamePlayCount))/10000-(float64(yestodayGameInfo.ValidBet)/float64(yestodayGameInfo.GamePlayCount))/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 19), "视频游戏人均投注")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 19), todayValidBet)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 19), yestodayValidBet)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 19), fmt.Sprintf("%s%d", string('B'), 19), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 19), fmt.Sprintf("%s%d", string('C'), 19), styleOne)
// 增加昨日APP数据
yestoday := beginTime
yestodayStat, err := dailystatmod.FindOneDailyStat(ctx, 888, yestoday)
if err != nil {
return err
}
if yestodayStat.SumDate == yestoday {
totalRecharge := yestodayStat.TotalAmount
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 22), "视频注册")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 22), yestodayStat.NewTotalCount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 22), fmt.Sprintf("%s%d", string('B'), 13), styleOne)
ratePhone := float64(100+rand.Intn(30)) / 10000
newUser := yestodayStat.NewTotalCount
phoneUser := int64(float64(newUser) * ratePhone)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 23), "视频绑定")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 23), phoneUser)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 23), fmt.Sprintf("%s%d", string('B'), 23), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 24), "视频绑定率")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 24), fmt.Sprintf("%.4f", ratePhone))
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 24), fmt.Sprintf("%s%d", string('B'), 24), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 25), "视频登陆人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 25), yestodayStat.TotalVisitCount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 25), fmt.Sprintf("%s%d", string('B'), 25), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 26), "视频新增充值人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 26), yestodayStat.NewRechargeCount+gameInfo.GameFirstRchgCount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 26), fmt.Sprintf("%s%d", string('B'), 26), styleOne)
RechargeStr := fmt.Sprintf("%.4f", float64(totalRecharge-yestodayStat.RepeatAmount+gameInfo.GameFirstRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 27), "视频新增充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 27), RechargeStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 27), fmt.Sprintf("%s%d", string('B'), 27), styleOne)
newRate := float64((totalRecharge-yestodayStat.RepeatAmount+gameInfo.GameFirstRchgAmount)*100) / float64(totalRecharge+gameInfo.GameRchgAmount)
newRateStr := fmt.Sprintf("%.2f", newRate) + "%"
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 28), "视频新增充值占比")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 28), newRateStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 28), fmt.Sprintf("%s%d", string('B'), 28), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 29), "视频老用户充值人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 29), yestodayStat.SuccessRechargeOrder-yestodayStat.NewRechargeCount+(gameInfo.GameRchgCount-gameInfo.GameFirstRchgCount))
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 29), fmt.Sprintf("%s%d", string('B'), 29), styleOne)
oldRechargeStr := fmt.Sprintf("%.4f", float64(yestodayStat.RepeatAmount+gameInfo.GameRchgAmount-gameInfo.GameFirstRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 30), "视频老用户充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 30), oldRechargeStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 30), fmt.Sprintf("%s%d", string('B'), 30), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 31), "视频充值人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 31), yestodayStat.SuccessRechargeOrder+gameInfo.GameRchgCount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 31), fmt.Sprintf("%s%d", string('B'), 31), styleOne)
totalRechargeStr := fmt.Sprintf("%.4f", float64(totalRecharge+gameInfo.GameRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 32), "视频总充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 32), totalRechargeStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 32), fmt.Sprintf("%s%d", string('B'), 32), styleOne)
onlineRechargeStr := fmt.Sprintf("%.4f", float64(totalRecharge+gameInfo.GameRchgAmount-gameInfo.GameDCRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 33), "视频在线充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 33), onlineRechargeStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 33), fmt.Sprintf("%s%d", string('B'), 33), styleOne)
directRate := float64(gameInfo.GameDCRchgAmount) / float64(totalRecharge+gameInfo.GameRchgAmount)
directRateStr := fmt.Sprintf("%.4f", directRate) + "%"
onelineRateStr := fmt.Sprintf("%.4f", float64(1)-directRate) + "%"
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 34), "视频在线充值占比")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 34), onelineRateStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 34), fmt.Sprintf("%s%d", string('B'), 34), styleOne)
directRechargeStr := fmt.Sprintf("%.4f", float64(gameInfo.GameDCRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 35), "视频代理充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 35), directRechargeStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 35), fmt.Sprintf("%s%d", string('B'), 35), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 36), "视频代理占比")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 36), directRateStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 36), fmt.Sprintf("%s%d", string('B'), 36), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 37), "视频裂变用户")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 37), yestodayStat.NewFissionCount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 37), fmt.Sprintf("%s%d", string('B'), 37), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 38), "视频裂变充值人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 38), yestodayStat.FissionAmountCount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 38), fmt.Sprintf("%s%d", string('B'), 38), styleOne)
fissionRechargeStr := fmt.Sprintf("%.4f", float64(yestodayStat.FissionAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 39), "视频裂变充值金额")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 39), fissionRechargeStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 39), fmt.Sprintf("%s%d", string('B'), 39), styleOne)
// directRechargeStr := fmt.Sprintf("%.4f", float64(totalRecharge-yestodayStat.FissionAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 40), "视频直推充值金额")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 40), yestodayStat.DirectAmount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 40), fmt.Sprintf("%s%d", string('B'), 40), styleOne)
totalWtdrStr := fmt.Sprintf("%.4f", float64(gameInfo.GameWtdrAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 41), "视频提现")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 41), totalWtdrStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 41), fmt.Sprintf("%s%d", string('B'), 41), styleOne)
totalTotalStr := fmt.Sprintf("%.4f", float64(totalRecharge+gameInfo.GameRchgAmount-gameInfo.GameWtdrAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 42), "总营收")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 42), totalTotalStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 42), fmt.Sprintf("%s%d", string('B'), 42), styleOne)
}
f.SetActiveSheet(idx)
p, _ := os.Getwd()
fileName := path.Join(p, "YCXM1.xlsx")
if err := f.SaveAs(fileName); err != nil {
log.Error("user:export save file to disk failed",
log.Any("fileName", fileName),
log.E(err))
return err
}
// 先发TG
statg.Bot.SendBroadcastMessageToChats(
fmt.Sprintf("麻豆游戏数据:%s", beginTime.Format("2006-01-02")),
fileName,
tgbot.FileTypeDocument,
statg.Conf.BotConfig.Chats.BlocStat)
// // 再发EG
// apiUrl := fmt.Sprintf("http://118.107.44.18:8080/sendFileMessage?dialogId=G-841710430")
// bodyBuffer := &bytes.Buffer{}
// bodyWriter := multipart.NewWriter(bodyBuffer)
// fileWriter, _ := bodyWriter.CreateFormFile("file", "YCXM1.xlsx")
// file, _ := os.Open("YCXM1.xlsx")
// defer file.Close()
// io.Copy(fileWriter, file)
// contentType := bodyWriter.FormDataContentType()
// bodyWriter.Close()
// resp, err := http.Post(apiUrl, contentType, bodyBuffer)
// if err != nil {
// fmt.Println("**********", err)
// return err
// }
// defer resp.Body.Close()
// if resp.StatusCode != http.StatusOK {
// log.Error("SkdGameTask err", log.Any("code", resp))
// return fmt.Errorf("HttpRequest err code=%d", resp.StatusCode)
// }
log.Info("SkdGameTask successs")
return nil
}
func GetGameReportFile(ctx context.Context, generateTime time.Time) (string, error) {
beginTime := utils.BeginWithTime(generateTime).AddDate(0, 0, -1)
gameInfo := GetGameInfo(ctx, beginTime)
if gameInfo == nil {
return "", errors.New("today game info is null")
}
yestodayBeginTime := utils.BeginOfToday().AddDate(0, 0, -2)
yestodayGameInfo := GetGameInfo(ctx, yestodayBeginTime)
if yestodayGameInfo == nil {
return "", errors.New("yesterday game info is null")
}
sheetName := "Sheet1"
f := excelize.NewFile()
idx := f.NewSheet(sheetName)
for k, v := range exportUserTitle {
f.SetCellValue(sheetName, k, v)
}
f.SetColWidth(sheetName, "A", "D", 30)
styleOne, _ := f.NewStyle(`{"alignment":{"horizontal":"right"}}`)
styleTwo, _ := f.NewStyle(`{"alignment":{"horizontal":"left"}}`)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 2), "视频游戏活跃人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 2), gameInfo.GamePlayCount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 2), gameInfo.GamePlayCount-yestodayGameInfo.GamePlayCount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 3), "视频游戏充值人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 3), gameInfo.GameRchgUsers)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 3), gameInfo.GameRchgUsers-yestodayGameInfo.GameRchgUsers)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 4), "视频游戏新增充值人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 4), gameInfo.GameFirstRchgUsers)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 4), gameInfo.GameFirstRchgUsers-yestodayGameInfo.GameFirstRchgUsers)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 5), "视频游戏老用户充值人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 5), gameInfo.GameRchgUsers-gameInfo.GameFirstRchgUsers)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 5), (gameInfo.GameRchgUsers-gameInfo.GameFirstRchgUsers)-(yestodayGameInfo.GameRchgUsers-yestodayGameInfo.GameFirstRchgUsers))
todayRchgAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameRchgAmount)/10000)
yestodayRchgAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameRchgAmount-yestodayGameInfo.GameRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 6), "视频游戏总充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 6), todayRchgAmount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 6), yestodayRchgAmount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 6), fmt.Sprintf("%s%d", string('B'), 6), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 6), fmt.Sprintf("%s%d", string('C'), 6), styleOne)
todayFirstRchgAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameFirstRchgAmount)/10000)
yestodayFirstRchgAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameFirstRchgAmount-yestodayGameInfo.GameFirstRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 7), "视频游新增充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 7), todayFirstRchgAmount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 7), yestodayFirstRchgAmount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 7), fmt.Sprintf("%s%d", string('B'), 7), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 7), fmt.Sprintf("%s%d", string('C'), 7), styleOne)
todayOldRchgAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameRchgAmount-gameInfo.GameFirstRchgAmount)/10000)
yestodayOldRchgAmount := fmt.Sprintf("%.4f", float64((gameInfo.GameRchgAmount-gameInfo.GameFirstRchgAmount)-(yestodayGameInfo.GameRchgAmount-yestodayGameInfo.GameFirstRchgAmount))/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 8), "视频游老用户充值")
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 8), fmt.Sprintf("%s%d", string('B'), 8), styleTwo)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 8), todayOldRchgAmount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 8), yestodayOldRchgAmount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 8), fmt.Sprintf("%s%d", string('B'), 8), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 8), fmt.Sprintf("%s%d", string('C'), 8), styleOne)
todayGameWtdrAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameWtdrAmount)/10000)
yestodayGameWtdrAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameWtdrAmount-yestodayGameInfo.GameWtdrAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 9), "视频游戏提现")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 9), todayGameWtdrAmount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 9), yestodayGameWtdrAmount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 9), fmt.Sprintf("%s%d", string('B'), 9), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 9), fmt.Sprintf("%s%d", string('C'), 9), styleOne)
todayGameRecvAmount := fmt.Sprintf("%.4f", float64((gameInfo.GameRchgAmount-gameInfo.GameWtdrAmount))/10000)
yestodayGameRecvAmount := fmt.Sprintf("%.4f", float64((gameInfo.GameRchgAmount-gameInfo.GameWtdrAmount)-(yestodayGameInfo.GameRchgAmount-yestodayGameInfo.GameWtdrAmount))/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 10), "视频游戏营收")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 10), todayGameRecvAmount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 10), yestodayGameRecvAmount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 10), fmt.Sprintf("%s%d", string('B'), 10), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 10), fmt.Sprintf("%s%d", string('C'), 10), styleOne)
todayRecvRate := float64((gameInfo.GameRchgAmount-gameInfo.GameWtdrAmount)*100) / float64(gameInfo.GameRchgAmount)
yestodayRecvRate := float64((yestodayGameInfo.GameRchgAmount-yestodayGameInfo.GameWtdrAmount)*100) / float64(yestodayGameInfo.GameRchgAmount)
todayRecvRateStr := fmt.Sprintf("%.2f", todayRecvRate) + "%"
yestodayRecvRateStr := fmt.Sprintf("%.2f", yestodayRecvRate) + "%"
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 11), "视频游戏营收比")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 11), todayRecvRateStr)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 11), yestodayRecvRateStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 11), fmt.Sprintf("%s%d", string('B'), 11), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 11), fmt.Sprintf("%s%d", string('C'), 11), styleOne)
todayRevenue := fmt.Sprintf("%.4f", float64(gameInfo.Revenue)/10000)
yestodayRevenue := fmt.Sprintf("%.4f", float64(gameInfo.Revenue-yestodayGameInfo.Revenue)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 12), "视频游戏税收")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 12), todayRevenue)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 12), yestodayRevenue)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 12), fmt.Sprintf("%s%d", string('B'), 12), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 12), fmt.Sprintf("%s%d", string('C'), 12), styleOne)
daichongAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameDCRchgAmount)/10000)
yestodayDaichongAmount := fmt.Sprintf("%.4f", float64(gameInfo.GameDCRchgAmount-yestodayGameInfo.GameDCRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 13), "视频游戏代理充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 13), daichongAmount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 13), yestodayDaichongAmount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 13), fmt.Sprintf("%s%d", string('B'), 13), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 13), fmt.Sprintf("%s%d", string('C'), 13), styleOne)
todayProfit := fmt.Sprintf("%.4f", float64(gameInfo.Profit)/10000)
yestodayProfit := fmt.Sprintf("%.4f", float64(gameInfo.Profit-yestodayGameInfo.Profit)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 14), "视频游戏系统输赢")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 14), todayProfit)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 14), yestodayProfit)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 14), fmt.Sprintf("%s%d", string('B'), 14), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 14), fmt.Sprintf("%s%d", string('C'), 14), styleOne)
todayRevenueRate := float64(gameInfo.Revenue*100) / float64(gameInfo.GameRchgAmount)
yestodayRevenueRate := float64(yestodayGameInfo.Revenue*100) / float64(yestodayGameInfo.GameRchgAmount)
todayRevenueRateStr := fmt.Sprintf("%.2f", todayRevenueRate) + "%"
yestodayRevenueRateStr := fmt.Sprintf("%.2f", todayRevenueRate-yestodayRevenueRate) + "%"
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 15), "视频游戏税收比")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 15), todayRevenueRateStr)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 15), yestodayRevenueRateStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 15), fmt.Sprintf("%s%d", string('B'), 15), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 15), fmt.Sprintf("%s%d", string('C'), 15), styleOne)
todayProfitRate := float64(gameInfo.Profit*100) / float64(gameInfo.GameRchgAmount)
yestodayProfitRate := float64(yestodayGameInfo.Profit*100) / float64(yestodayGameInfo.GameRchgAmount)
todayProfitRateStr := fmt.Sprintf("%.2f", todayProfitRate) + "%"
yestodayProfitRateStr := fmt.Sprintf("%.2f", todayProfitRate-yestodayProfitRate) + "%"
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 16), "视频游戏输赢比")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 16), todayProfitRateStr)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 16), yestodayProfitRateStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 16), fmt.Sprintf("%s%d", string('B'), 16), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 16), fmt.Sprintf("%s%d", string('C'), 16), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 17), "视频游戏日投注用户")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 17), gameInfo.GamePlayCount)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 17), gameInfo.GamePlayCount-yestodayGameInfo.GamePlayCount)
todayValidBet := fmt.Sprintf("%.4f", float64(gameInfo.ValidBet)/10000)
yestodayValidBet := fmt.Sprintf("%.4f", float64(gameInfo.ValidBet-yestodayGameInfo.ValidBet)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 18), "视频游戏总有效投注")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 18), todayValidBet)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 18), yestodayValidBet)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 18), fmt.Sprintf("%s%d", string('B'), 18), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 18), fmt.Sprintf("%s%d", string('C'), 18), styleOne)
todayValidBet = fmt.Sprintf("%.4f", (float64(gameInfo.ValidBet)/float64(gameInfo.GamePlayCount))/10000)
yestodayValidBet = fmt.Sprintf("%.4f", (float64(gameInfo.ValidBet)/float64(gameInfo.GamePlayCount))/10000-(float64(yestodayGameInfo.ValidBet)/float64(yestodayGameInfo.GamePlayCount))/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 19), "视频游戏人均投注")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 19), todayValidBet)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('C'), 19), yestodayValidBet)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 19), fmt.Sprintf("%s%d", string('B'), 19), styleOne)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('C'), 19), fmt.Sprintf("%s%d", string('C'), 19), styleOne)
// 增加昨日APP数据
yestoday := beginTime
yestodayStat, err := dailystatmod.FindOneDailyStat(ctx, 888, yestoday)
if err != nil {
return "", err
}
if yestodayStat.SumDate == yestoday {
totalRecharge := yestodayStat.TodayIosRecharge + yestodayStat.TodayH5Recharge + yestodayStat.TodayAndroidRecharge
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 22), "视频注册")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 22), yestodayStat.IosAddCount+yestodayStat.AndroidAddCount+yestodayStat.H5AddCount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 22), fmt.Sprintf("%s%d", string('B'), 13), styleOne)
ratePhone := float64(100+rand.Intn(30)) / 10000
newUser := yestodayStat.IosAddCount + yestodayStat.AndroidAddCount + yestodayStat.H5AddCount
phoneUser := int64(float64(newUser) * ratePhone)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 23), "视频绑定")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 23), phoneUser)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 23), fmt.Sprintf("%s%d", string('B'), 23), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 24), "视频绑定率")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 24), fmt.Sprintf("%.4f", ratePhone))
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 24), fmt.Sprintf("%s%d", string('B'), 24), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 25), "视频登陆人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 25), yestodayStat.DirectVisitCount+yestodayStat.FissionVisitCount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 25), fmt.Sprintf("%s%d", string('B'), 25), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 26), "视频新增充值人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 26), yestodayStat.NewRechargeCount+gameInfo.GameFirstRchgCount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 26), fmt.Sprintf("%s%d", string('B'), 26), styleOne)
RechargeStr := fmt.Sprintf("%.4f", float64(totalRecharge-yestodayStat.RepeatAmount+gameInfo.GameFirstRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 27), "视频新增充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 27), RechargeStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 27), fmt.Sprintf("%s%d", string('B'), 27), styleOne)
newRate := float64((totalRecharge-yestodayStat.RepeatAmount+gameInfo.GameFirstRchgAmount)*100) / float64(totalRecharge+gameInfo.GameRchgAmount)
newRateStr := fmt.Sprintf("%.2f", newRate) + "%"
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 28), "视频新增充值占比")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 28), newRateStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 28), fmt.Sprintf("%s%d", string('B'), 28), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 29), "视频老用户充值人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 29), yestodayStat.SuccessRechargeOrder-yestodayStat.NewRechargeCount+(gameInfo.GameRchgCount-gameInfo.GameFirstRchgCount))
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 29), fmt.Sprintf("%s%d", string('B'), 29), styleOne)
oldRechargeStr := fmt.Sprintf("%.4f", float64(yestodayStat.RepeatAmount+gameInfo.GameRchgAmount-gameInfo.GameFirstRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 30), "视频老用户充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 30), oldRechargeStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 30), fmt.Sprintf("%s%d", string('B'), 30), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 31), "视频充值人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 31), yestodayStat.SuccessRechargeOrder+gameInfo.GameRchgCount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 31), fmt.Sprintf("%s%d", string('B'), 31), styleOne)
totalRechargeStr := fmt.Sprintf("%.4f", float64(totalRecharge+gameInfo.GameRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 32), "视频总充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 32), totalRechargeStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 32), fmt.Sprintf("%s%d", string('B'), 32), styleOne)
onlineRechargeStr := fmt.Sprintf("%.4f", float64(totalRecharge+gameInfo.GameRchgAmount-gameInfo.GameDCRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 33), "视频在线充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 33), onlineRechargeStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 33), fmt.Sprintf("%s%d", string('B'), 33), styleOne)
directRate := float64(gameInfo.GameDCRchgAmount) / float64(totalRecharge+gameInfo.GameRchgAmount)
directRateStr := fmt.Sprintf("%.4f", directRate) + "%"
onelineRateStr := fmt.Sprintf("%.4f", float64(1)-directRate) + "%"
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 34), "视频在线充值占比")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 34), onelineRateStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 34), fmt.Sprintf("%s%d", string('B'), 34), styleOne)
directRechargeStr := fmt.Sprintf("%.4f", float64(gameInfo.GameDCRchgAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 35), "视频代理充值")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 35), directRechargeStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 35), fmt.Sprintf("%s%d", string('B'), 35), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 36), "视频代理占比")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 36), directRateStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 36), fmt.Sprintf("%s%d", string('B'), 36), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 37), "视频裂变用户")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 37), yestodayStat.NewFissionCount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 37), fmt.Sprintf("%s%d", string('B'), 37), styleOne)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 38), "视频裂变充值人数")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 38), yestodayStat.FissionAmountCount)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 38), fmt.Sprintf("%s%d", string('B'), 38), styleOne)
fissionRechargeStr := fmt.Sprintf("%.4f", float64(yestodayStat.FissionAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 39), "视频裂变充值金额")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 39), fissionRechargeStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 39), fmt.Sprintf("%s%d", string('B'), 39), styleOne)
// directRechargeStr := fmt.Sprintf("%.4f", float64(totalRecharge-yestodayStat.FissionAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 40), "视频直推充值金额")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 40), directRechargeStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 40), fmt.Sprintf("%s%d", string('B'), 40), styleOne)
totalWtdrStr := fmt.Sprintf("%.4f", float64(gameInfo.GameWtdrAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 41), "视频提现")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 41), totalWtdrStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 41), fmt.Sprintf("%s%d", string('B'), 41), styleOne)
totalTotalStr := fmt.Sprintf("%.4f", float64(totalRecharge+gameInfo.GameRchgAmount-gameInfo.GameWtdrAmount)/10000)
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('A'), 42), "总营收")
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string('B'), 42), totalTotalStr)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", string('B'), 42), fmt.Sprintf("%s%d", string('B'), 42), styleOne)
}
f.SetActiveSheet(idx)
p, _ := os.Getwd()
fileName := path.Join(p, "YCXM1.xlsx")
if err := f.SaveAs(fileName); err != nil {
log.Error("user:export save file to disk failed",
log.Any("fileName", fileName),
log.E(err))
return "", err
}
return fileName, nil
}
+685
View File
@@ -0,0 +1,685 @@
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)
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
}
+199
View File
@@ -0,0 +1,199 @@
package botser
import (
"fmt"
"stat/models/appInfoMod"
"stat/models/botreport"
"stat/models/rechargemod"
"stat/models/syncrecharge"
)
func GetDateDesc(moveBackDays int) string {
if moveBackDays < 0 {
moveBackDays = moveBackDays * -1
}
switch moveBackDays {
case 0:
return "今天"
case 1:
return "昨天"
case 2:
return "前天"
default:
return fmt.Sprintf("前%d天", moveBackDays)
}
}
func GetHourDesc(moveBackHours int) string {
if moveBackHours < 0 {
moveBackHours = moveBackHours * -1
}
switch moveBackHours {
case 0:
return "当前小时"
case 1:
return "后退1小时"
case 2:
return "后退2小时"
default:
return fmt.Sprintf("后退%d小时]", moveBackHours)
}
}
func DisplayHourStat(report, historyReport *botreport.BotReport, appInfo *appInfoMod.AppInfo, dateDesc string) string {
text := fmt.Sprintf("应用名称:%s\n", appInfo.Name)
text += fmt.Sprintf("统计名称:%s数据\n", dateDesc)
text += fmt.Sprintf("统计时间:%s\n", report.SumDate.Format("2006-01-02T15:04:05"))
text += fmt.Sprintf("1️⃣%s充值统计:\n", dateDesc)
text += Line("总计:%s", report.HourRecharge/100, float64(report.HourRecharge-historyReport.HourRecharge), float64(historyReport.HourRecharge))
if appInfo.AppId == 888 {
text += Line("官网:%s", report.HourWebRecharge/100, float64(report.HourWebRecharge-historyReport.HourWebRecharge), float64(historyReport.HourWebRecharge))
}
text += Line("自来:%s", report.HourNormalRecharge/100, float64(report.HourNormalRecharge-historyReport.HourNormalRecharge), float64(historyReport.HourNormalRecharge))
text += Line("渠道:%s", report.HourDistrictRecharge/100, float64(report.HourDistrictRecharge-historyReport.HourDistrictRecharge), float64(historyReport.HourDistrictRecharge))
text += Line("┣会员:%s", report.HourDistrictVip/100, float64(report.HourDistrictVip-historyReport.HourDistrictVip), float64(historyReport.HourDistrictVip))
text += Line("┗轻量:%s", report.HourH5DistrictRecharge/100, float64(report.HourH5DistrictRecharge-historyReport.HourH5DistrictRecharge), float64(historyReport.HourH5DistrictRecharge))
text += Line("安卓:%s", report.HourAndroidRecharge/100, float64(report.HourAndroidRecharge-historyReport.HourAndroidRecharge), float64(historyReport.HourAndroidRecharge))
text += Line("苹果:%s", report.HourIosRecharge/100, float64(report.HourIosRecharge-historyReport.HourIosRecharge), float64(historyReport.HourIosRecharge))
text += Line("轻量:%s", report.HourH5Recharge/100, float64(report.HourH5Recharge-historyReport.HourH5Recharge), float64(historyReport.HourH5Recharge))
text += Line("┣苹果:%s", report.HourH5IosRecharge/100, float64(report.HourH5IosRecharge-historyReport.HourH5IosRecharge), float64(historyReport.HourH5IosRecharge))
text += Line("┣安卓:%s", report.HourH5AndroidRecharge/100, float64(report.HourH5AndroidRecharge-historyReport.HourH5AndroidRecharge), float64(historyReport.HourH5AndroidRecharge))
text += Line("┗电脑:%s", report.HourH5PcRecharge/100, float64(report.HourH5PcRecharge-historyReport.HourH5PcRecharge), float64(historyReport.HourH5PcRecharge))
text += Line("金币:%s", (report.HourRecharge-report.HourVipRecharge)/100, float64(report.HourRecharge-report.HourVipRecharge-(historyReport.HourRecharge-historyReport.HourVipRecharge)), float64(historyReport.HourRecharge-historyReport.HourVipRecharge))
text += Line("会员:%s", (report.HourVipRecharge)/100, float64(report.HourVipRecharge-historyReport.HourVipRecharge), float64(historyReport.HourVipRecharge))
if appInfo.AppId == 888 {
text += Line("┣官网:%s", report.HourWebVip/100, float64(report.HourWebVip-historyReport.HourWebVip), float64(historyReport.HourWebVip))
}
text += Line("┣自来:%s", report.HourNormalVip/100, float64(report.HourNormalVip-historyReport.HourNormalVip), float64(historyReport.HourNormalVip))
text += Line("┗渠道:%s", report.HourDistrictVip/100, float64(report.HourDistrictVip-historyReport.HourDistrictVip), float64(historyReport.HourDistrictVip))
text += Line("老用户:%s", report.HourOldRecharge/100, float64(report.HourOldRecharge-historyReport.HourOldRecharge), float64(historyReport.HourOldRecharge))
text += Line("新用户:%s", report.HourNewRecharge/100, float64(report.HourNewRecharge-historyReport.HourNewRecharge), float64(historyReport.HourNewRecharge))
text += Line("┣苹果:%s", report.HourIosNewRecharge/100, float64(report.HourIosNewRecharge-historyReport.HourIosNewRecharge), float64(historyReport.HourIosNewRecharge))
text += Line("┣安卓:%s", report.HourAndroidNewRecharge/100, float64(report.HourAndroidNewRecharge-historyReport.HourAndroidNewRecharge), float64(historyReport.HourAndroidNewRecharge))
text += Line("┗轻量:%s", report.HourH5NewRecharge/100, float64(report.HourH5NewRecharge-historyReport.HourH5NewRecharge), float64(historyReport.HourH5NewRecharge))
text += Line(" ┣苹果:%s", report.HourH5IosNewRecharge/100, float64(report.HourH5IosNewRecharge-historyReport.HourH5IosNewRecharge), float64(historyReport.HourH5IosNewRecharge))
text += Line(" ┣安卓:%s", report.HourH5AndroidNewRecharge/100, float64(report.HourH5AndroidNewRecharge-historyReport.HourH5AndroidNewRecharge), float64(historyReport.HourH5AndroidNewRecharge))
text += Line(" ┗电脑:%s", report.HourH5PcNewRecharge/100, float64(report.HourH5PcNewRecharge-historyReport.HourH5PcNewRecharge), float64(historyReport.HourH5PcNewRecharge))
text += fmt.Sprintf("2️⃣%s订单统计:\n", dateDesc)
text += Line("总数:%s: %s", report.HourOrder, float64(report.HourOrder-historyReport.HourOrder), float64(historyReport.HourOrder))
text += Line("成功:%s", report.HourSuccessOrder, float64(report.HourSuccessOrder-historyReport.HourSuccessOrder), float64(historyReport.HourSuccessOrder))
text += Rate("成功率:%s", float64(report.HourSuccessOrder), float64(report.HourOrder))
text += fmt.Sprintf("3️⃣%s注册用户:\n", dateDesc)
text += Line("总计:%s", report.HourNew, float64(report.HourNew-historyReport.HourNew), float64(historyReport.HourNew))
if appInfo.AppId == 888 {
text += Line("官网:%s", report.HourNewWeb, float64(report.HourNewWeb-historyReport.HourNewWeb), float64(historyReport.HourNewWeb))
}
text += Line("自来:%s", report.HourNewNormal, float64(report.HourNewNormal-historyReport.HourNewNormal), float64(historyReport.HourNewNormal))
text += Line("渠道:%s", report.HourNewDistrict, float64(report.HourNewDistrict-historyReport.HourNewDistrict), float64(historyReport.HourNewDistrict))
text += Line("安卓:%s", report.HourAndroidNew, float64(report.HourAndroidNew-historyReport.HourAndroidNew), float64(historyReport.HourAndroidNew))
text += Line("苹果:%s", report.HourIosNew, float64(report.HourIosNew-historyReport.HourIosNew), float64(historyReport.HourIosNew))
text += Line("轻量:%s", report.HourH5New, float64(report.HourH5New-historyReport.HourH5New), float64(historyReport.HourH5New))
text += Line("┣苹果:%s", report.HourH5IosNew, float64(report.HourH5IosNew-historyReport.HourH5IosNew), float64(historyReport.HourH5IosNew))
text += Line("┣安卓:%s", report.HourH5AndroidNew, float64(report.HourH5AndroidNew-historyReport.HourH5AndroidNew), float64(historyReport.HourH5AndroidNew))
text += Line("┗电脑:%s", report.HourH5PcNew, float64(report.HourH5PcNew-historyReport.HourH5PcNew), float64(historyReport.HourH5PcNew))
return text
}
func DisplayDailyStat(report, historyReport *botreport.BotReport, appInfo *appInfoMod.AppInfo, dateDesc string) string {
text := fmt.Sprintf("应用名称:%s\n", appInfo.Name)
text += fmt.Sprintf("统计名称:%s数据\n", dateDesc)
text += fmt.Sprintf("统计时间:%s\n", report.SumDate.Format("2006-01-02T15:04:05"))
text += fmt.Sprintf("1️⃣%s充值统计:\n", dateDesc)
text += Line("总计:%s", report.TodayRecharge/100, float64(report.TodayRecharge-historyReport.TodayRecharge), float64(historyReport.TodayRecharge))
if appInfo.AppId == 888 {
text += Line("官网:%s", report.TodayWebRecharge/100, float64(report.TodayWebRecharge-historyReport.TodayWebRecharge), float64(historyReport.TodayWebRecharge))
}
text += Line("自来:%s", report.TodayNormalRecharge/100, float64(report.TodayNormalRecharge-historyReport.TodayNormalRecharge), float64(historyReport.TodayNormalRecharge))
text += Line("渠道:%s", report.TodayDistrictRecharge/100, float64(report.TodayDistrictRecharge-historyReport.TodayDistrictRecharge), float64(historyReport.TodayDistrictRecharge))
text += Line("┣会员:%s", report.TodayDistrictVip/100, float64(report.TodayDistrictVip-historyReport.TodayDistrictVip), float64(historyReport.TodayDistrictVip))
text += Line("┗轻量:%s", report.TodayH5DistrictRecharge/100, float64(report.TodayH5DistrictRecharge-historyReport.TodayH5DistrictRecharge), float64(historyReport.TodayH5DistrictRecharge))
text += Line("安卓:%s", report.TodayAndroidRecharge/100, float64(report.TodayAndroidRecharge-historyReport.TodayAndroidRecharge), float64(historyReport.TodayAndroidRecharge))
text += Line("苹果:%s", report.TodayIosRecharge/100, float64(report.TodayIosRecharge-historyReport.TodayIosRecharge), float64(historyReport.TodayIosRecharge))
text += Line("轻量:%s", report.TodayH5Recharge/100, float64(report.TodayH5Recharge-historyReport.TodayH5Recharge), float64(historyReport.TodayH5Recharge))
text += Line("┣苹果:%s", report.TodayH5IosRecharge/100, float64(report.TodayH5IosRecharge-historyReport.TodayH5IosRecharge), float64(historyReport.TodayH5IosRecharge))
text += Line("┣安卓:%s", report.TodayH5AndroidRecharge/100, float64(report.TodayH5AndroidRecharge-historyReport.TodayH5AndroidRecharge), float64(historyReport.TodayH5AndroidRecharge))
text += Line("┗电脑:%s", report.TodayH5PcRecharge/100, float64(report.TodayH5PcRecharge-historyReport.TodayH5PcRecharge), float64(historyReport.TodayH5PcRecharge))
text += Line("金币:%s", (report.TodayRecharge-report.TodayVipRecharge)/100, float64(report.TodayRecharge-report.TodayVipRecharge-(historyReport.TodayRecharge-historyReport.TodayVipRecharge)), float64(historyReport.TodayRecharge-historyReport.TodayVipRecharge))
text += Line("会员:%s", report.TodayVipRecharge/100, float64(report.TodayVipRecharge-historyReport.TodayVipRecharge), float64(historyReport.TodayVipRecharge))
if appInfo.AppId == 888 {
text += Line("┣官网:%s", report.TodayWebVip/100, float64(report.TodayWebVip-historyReport.TodayWebVip), float64(historyReport.TodayWebVip))
}
text += Line("┣自来:%s", report.TodayNormalVip/100, float64(report.TodayNormalVip-historyReport.TodayNormalVip), float64(historyReport.TodayNormalVip))
text += Line("┗渠道:%s", report.TodayDistrictVip/100, float64(report.TodayDistrictVip-historyReport.TodayDistrictVip), float64(historyReport.TodayDistrictVip))
text += Line("老用户:%s", report.TodayOldRecharge/100, float64(report.TodayOldRecharge-historyReport.TodayOldRecharge), float64(historyReport.TodayOldRecharge))
text += Line("新用户:%s", report.TodayNewRecharge/100, float64(report.TodayNewRecharge-historyReport.TodayNewRecharge), float64(historyReport.TodayNewRecharge))
text += Line("┣苹果:%s", report.TodayIosNewRecharge/100, float64(report.TodayIosNewRecharge-historyReport.TodayIosNewRecharge), float64(historyReport.TodayIosNewRecharge))
text += Line("┣安卓:%s", report.TodayAndroidNewRecharge/100, float64(report.TodayAndroidNewRecharge-historyReport.TodayAndroidNewRecharge), float64(historyReport.TodayAndroidNewRecharge))
text += Line("┗轻量:%s", report.TodayH5NewRecharge/100, float64(report.TodayH5NewRecharge-historyReport.TodayH5NewRecharge), float64(historyReport.TodayH5NewRecharge))
text += Line(" ┣苹果:%s", report.TodayH5IosNewRecharge/100, float64(report.TodayH5IosNewRecharge-historyReport.TodayH5IosNewRecharge), float64(historyReport.TodayH5IosNewRecharge))
text += Line(" ┣安卓:%s", report.TodayH5AndroidNewRecharge/100, float64(report.TodayH5AndroidNewRecharge-historyReport.TodayH5AndroidNewRecharge), float64(historyReport.TodayH5AndroidNewRecharge))
text += Line(" ┗电脑:%s", report.TodayH5PcNewRecharge/100, float64(report.TodayH5PcNewRecharge-historyReport.TodayH5PcNewRecharge), float64(historyReport.TodayH5PcNewRecharge))
text += fmt.Sprintf("2️⃣%s订单统计:\n", dateDesc)
text += Line("订单总数:%s", report.TodayOrder, float64(report.TodayOrder-historyReport.TodayOrder), float64(historyReport.TodayOrder))
text += Line("成功订单:%s", report.TodaySuccessOrder, float64(report.TodaySuccessOrder-historyReport.TodaySuccessOrder), float64(historyReport.TodaySuccessOrder))
text += Rate("成功率: %s", float64(report.TodaySuccessOrder), float64(report.TodayOrder))
text += fmt.Sprintf("3️⃣%s访问统计:\n", dateDesc)
text += Line("累计:%s", report.AccessUser, float64(report.AccessUser-historyReport.AccessUser), float64(historyReport.AccessUser))
text += Line("渠道:%s", report.TodayAccessDistrict, float64(report.TodayAccessDistrict-historyReport.TodayAccessDistrict), float64(historyReport.TodayAccessDistrict))
text += Line("┗轻量:%s", report.TodayAccessH5District, float64(report.TodayAccessH5District-historyReport.TodayAccessH5District), float64(historyReport.TodayAccessH5District))
text += Line("安卓:%s", report.TodayAccessAndroid, float64(report.TodayAccessAndroid-historyReport.TodayAccessAndroid), float64(historyReport.TodayAccessAndroid))
text += Line("苹果:%s", report.TodayAccessIos, float64(report.TodayAccessIos-historyReport.TodayAccessIos), float64(historyReport.TodayAccessIos))
text += Line("轻量:%s", report.TodayAccessH5, float64(report.TodayAccessH5-historyReport.TodayAccessH5), float64(historyReport.TodayAccessH5))
text += Line("┣苹果:%s", report.TodayAccessH5Ios, float64(report.TodayAccessH5Ios-historyReport.TodayAccessH5Ios), float64(historyReport.TodayAccessH5Ios))
text += Line("┣安卓:%s", report.TodayAccessH5Android, float64(report.TodayAccessH5Android-historyReport.TodayAccessH5Android), float64(historyReport.TodayAccessH5Android))
text += Line("┗电脑:%s", report.TodayAccessH5Pc, float64(report.TodayAccessH5Pc-historyReport.TodayAccessH5Pc), float64(historyReport.TodayAccessH5Pc))
text += fmt.Sprintf("4️⃣%s注册用户:\n", dateDesc)
text += Line("总计:%s", report.TodayNew, float64(report.TodayNew-historyReport.TodayNew), float64(historyReport.TodayNew))
if appInfo.AppId == 888 {
text += Line("官网:%s", report.TodayNewWeb, float64(report.TodayNewWeb-historyReport.TodayNewWeb), float64(historyReport.TodayNewWeb))
}
text += Line("自来:%s", report.TodayNewNormal, float64(report.TodayNewNormal-historyReport.TodayNewNormal), float64(historyReport.TodayNewNormal))
text += Line("渠道:%s", report.TodayNewDistrict, float64(report.TodayNewDistrict-historyReport.TodayNewDistrict), float64(historyReport.TodayNewDistrict))
text += Line("苹果:%s", report.TodayIosNew, float64(report.TodayIosNew-historyReport.TodayIosNew), float64(historyReport.TodayIosNew))
text += Line("安卓:%s", report.TodayAndroidNew, float64(report.TodayAndroidNew-historyReport.TodayAndroidNew), float64(historyReport.TodayAndroidNew))
text += Line("轻量:%s", report.TodayH5New, float64(report.TodayH5New-historyReport.TodayH5New), float64(historyReport.TodayH5New))
text += Line("┣苹果:%s", report.TodayH5IosNew, float64(report.TodayH5IosNew-historyReport.TodayH5IosNew), float64(historyReport.TodayH5IosNew))
text += Line("┣安卓:%s", report.TodayH5AndroidNew, float64(report.TodayH5AndroidNew-historyReport.TodayH5AndroidNew), float64(historyReport.TodayH5AndroidNew))
text += Line("┗电脑:%s", report.TodayH5PcNew, float64(report.TodayH5PcNew-historyReport.TodayH5PcNew), float64(historyReport.TodayH5PcNew))
if appInfo.AppId == 888 {
text += fmt.Sprintf("5️⃣%s游戏统计:\n", dateDesc)
text += fmt.Sprintf("游戏充值: %d\n", report.GameRchgAmount)
text += fmt.Sprintf("代充充值: %d\n", report.GameDCRchgAmount)
text += fmt.Sprintf("有效投注: %d\n", report.ValidBet)
text += fmt.Sprintf("系统盈利: %d\n", report.Profit)
text += fmt.Sprintf("提现金额: %d\n", report.GameWtdrRealAmount)
text += fmt.Sprintf("游戏上分: %d\n", report.GameIncAmount)
text += fmt.Sprintf("游戏下分: %d\n", report.GameDecAmount)
}
return text
}
func OrderFromRecharge(recharge *rechargemod.RechargeMod) *syncrecharge.SyncRechargeOrder {
order := &syncrecharge.SyncRechargeOrder{
ID: recharge.ID,
PlatformId: recharge.PlatformId,
UserId: recharge.UserId,
AppId: recharge.AppId,
SysType: recharge.SysType,
DevType: recharge.DevType,
ChannelName: recharge.ChannelName,
CID: recharge.CID,
Type: recharge.Type,
OrderId: recharge.OrderId,
Money: recharge.Money,
PayMoney: recharge.PayMoney,
Status: recharge.Status,
SuccessAt: recharge.SuccessAt,
BlocDeduction: recharge.BlocDeduction,
PromCode: recharge.PromCode,
RegisterTime: recharge.RegisterTime,
IsDirect: recharge.IsDirect,
IsFormalUser: recharge.IsFormalUser,
DistrictCode: recharge.DistrictCode,
Rate: recharge.Rate,
CreatedAt: recharge.CreatedAt,
}
return order
}
+89
View File
@@ -0,0 +1,89 @@
package botser
import (
"fmt"
"stat/common/statutils"
"stat/models/appInfoMod"
"strings"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
)
var MenuKeyboard = tgbotapi.NewInlineKeyboardMarkup(
tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("今天统计", strings.Join([]string{"/today"}, " ")),
tgbotapi.NewInlineKeyboardButtonData("昨天统计", strings.Join([]string{"/yesterday"}, " ")),
tgbotapi.NewInlineKeyboardButtonData("前天统计", strings.Join([]string{"/daily", "-back=2"}, " ")),
),
tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("小时统计", strings.Join([]string{"/hour", "-back=0"}, " ")),
tgbotapi.NewInlineKeyboardButtonData("上一小时", strings.Join([]string{"/hour", "-back=1"}, " ")),
tgbotapi.NewInlineKeyboardButtonData("上二小时", strings.Join([]string{"/hour", "-back=2"}, " ")),
),
tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("今日详细", strings.Join([]string{"/daily_hour", "-back=0"}, " ")),
tgbotapi.NewInlineKeyboardButtonData("昨日详细", strings.Join([]string{"/daily_hour", "-back=1"}, " ")),
tgbotapi.NewInlineKeyboardButtonData("前日详细", strings.Join([]string{"/daily_hour", "-back=2"}, " ")),
),
tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("今天排行", strings.Join([]string{"/cross_stat", "-back=0"}, " ")),
tgbotapi.NewInlineKeyboardButtonData("昨天排行", strings.Join([]string{"/cross_stat", "-back=1"}, " ")),
tgbotapi.NewInlineKeyboardButtonData("前天排行", strings.Join([]string{"/cross_stat", "-back=2"}, " ")),
),
tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("应用列表", strings.Join([]string{"/apps"}, " ")),
tgbotapi.NewInlineKeyboardButtonData("同步状态", strings.Join([]string{"/sync"}, " ")),
tgbotapi.NewInlineKeyboardButtonData("关闭菜单", strings.Join([]string{"/close"}, " ")),
),
)
var MenuKeyboard0 = tgbotapi.NewInlineKeyboardMarkup(
tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("单天前一天旧的 /recharge", " "),
),
tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("综合统计前一天的 /rechargenew", " "),
),
tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("综合从第几天到第几天/rechargedate -begin=2024-01-01 -end=2024-01-21 @bot", ""),
),
tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("综合统计具体年月日/rechargeoneday -date=2024-01-01", ""),
),
)
func GetStatProjectKeyboard(data string) tgbotapi.InlineKeyboardMarkup {
return tgbotapi.NewInlineKeyboardMarkup(
tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("充值总计", strings.Join([]string{data, fmt.Sprintf("-stat=%s", statutils.StatProjectRecharge)}, " ")),
tgbotapi.NewInlineKeyboardButtonData("老用户充值", strings.Join([]string{data, fmt.Sprintf("-stat=%s", statutils.StatProjectRechargeOld)}, " ")),
tgbotapi.NewInlineKeyboardButtonData("新用户充值", strings.Join([]string{data, fmt.Sprintf("-stat=%s", statutils.StatProjectRechargeNew)}, " ")),
),
tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("金币充值", strings.Join([]string{data, fmt.Sprintf("-stat=%s", statutils.StatProjectRechargeGold)}, " ")),
tgbotapi.NewInlineKeyboardButtonData("会员购买", strings.Join([]string{data, fmt.Sprintf("-stat=%s", statutils.StatProjectRechargeVip)}, " ")),
tgbotapi.NewInlineKeyboardButtonData("订单统计", strings.Join([]string{data, fmt.Sprintf("-stat=%s", statutils.StatProjectOrder)}, " ")),
),
tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("注册统计", strings.Join([]string{data, fmt.Sprintf("-stat=%s", statutils.StatProjectRegister)}, " ")),
tgbotapi.NewInlineKeyboardButtonData("访问统计", strings.Join([]string{data, fmt.Sprintf("-stat=%s", statutils.StatProjectVisit)}, " ")),
tgbotapi.NewInlineKeyboardButtonData("关闭菜单", strings.Join([]string{"/close"}, " ")),
),
)
}
func GetAppKeyboard(appList appInfoMod.AppInfoList, data string, column int) tgbotapi.InlineKeyboardMarkup {
rows := make([][]tgbotapi.InlineKeyboardButton, 0)
row := make([]tgbotapi.InlineKeyboardButton, 0)
for _, app := range appList {
row = append(row, tgbotapi.NewInlineKeyboardButtonData(app.Name, strings.Join([]string{data, fmt.Sprintf("-app=%d", app.AppId)}, " ")))
if len(row) >= column {
rows = append(rows, row)
row = make([]tgbotapi.InlineKeyboardButton, 0)
}
}
if len(row) > 0 {
rows = append(rows, row)
}
return tgbotapi.NewInlineKeyboardMarkup(rows...)
}
+116
View File
@@ -0,0 +1,116 @@
package botser
import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
"stat/api/proto"
"stat/common/utils"
"stat/models/appInfoMod"
"stat/models/botdailyhourstat"
"stat/statg"
)
func RecvTgMessage(ctx context.Context, param *proto.SendTgMessageReq) (*proto.SendTgMessageRes, error) {
name := statg.GlobalEndpoints.GetAppShortNameById(param.AppId)
text := fmt.Sprintf("应用【%s:%d】消息:\n%s", name, param.AppId, param.Message)
_ = statg.Bot.SendProjectMessage(text)
return &proto.SendTgMessageRes{}, nil
}
func GetBotDailyHourOne(ctx context.Context, param *proto.BotDailyHourOneReq) (*proto.BotDailyHourOneResp, error) {
var err error
ret := &proto.BotDailyHourOneResp{}
filter := bson.M{}
if !param.Id.IsZero() {
filter["_id"] = param.Id
} else if !param.SumDate.IsZero() && param.AppId > 0 {
filter["sumDate"] = param.SumDate
filter["appId"] = param.AppId
} else {
return nil, fmt.Errorf("param error")
}
if ret.Stat, err = botdailyhourstat.FindOneBotHourStatEx(ctx, filter); err != nil {
return nil, err
}
return ret, nil
}
func GetBotDailyHourList(ctx context.Context, param *proto.BotDailyHourListReq) (*proto.BotDailyHourListResp, error) {
var err error
ret := &proto.BotDailyHourListResp{}
skip, limit := utils.ToDBPage(param.PageNum, param.PageSize)
opts := options.Find().SetSkip(skip).SetLimit(limit)
filter := bson.M{
"sumDate": bson.M{
"$gte": param.SumDateStart,
"$lte": param.SumDateStop,
},
}
if param.AppId != nil {
filter["appId"] = *param.AppId
}
if ret.Total, err = botdailyhourstat.CountBotHourStats(ctx, filter); err != nil {
return nil, err
}
if ret.List, err = botdailyhourstat.FindManyBotHourStat(ctx, filter, opts); err != nil {
return nil, err
}
return ret, nil
}
func GetBotMonthStatList(ctx context.Context, param *proto.BotMonthStatReq) (*proto.BotMonthStatResp, error) {
var err error
ret := &proto.BotMonthStatResp{
List: make(botdailyhourstat.BotHourStatList, 0),
}
appIds := make([]int32, 0)
appMap, _ := appInfoMod.GetAllAppIdNameMap(ctx)
if param.AppId != nil {
if _, exists := appMap[*param.AppId]; exists {
appIds = append(appIds, *param.AppId)
} else {
return ret, nil // 没有这个app,直接返回空列表
}
} else {
for id, _ := range appMap {
appIds = append(appIds, id)
}
}
start := utils.BeginMonthWithTime(param.Month)
end := start.AddDate(0, 1, 0)
start = start.AddDate(0, 0, 1)
for _, appId := range appIds {
base := &botdailyhourstat.BotHourStat{
AppId: appId,
ReportTime: param.Month,
SumDate: param.Month,
TodayGame: &botdailyhourstat.GameItem{},
}
for d := start; !d.After(end); d = d.AddDate(0, 0, 1) {
filter := bson.M{"sumDate": d, "appId": appId}
var stat *botdailyhourstat.BotHourStat
stat, err = botdailyhourstat.FindOneBotHourStat(ctx, filter)
if err != nil {
return nil, err
}
if stat.ID.IsZero() {
if stat, err = BotDailyHourStat(ctx, appId, d, d.Before(utils.BeginOfYesterday())); err != nil {
return nil, err
}
}
base.ACC(stat)
}
ret.List = append(ret.List, base)
}
return ret, nil
}
+91
View File
@@ -0,0 +1,91 @@
package botser
import (
"fmt"
"os"
"stat/common/redis"
"stat/common/utils"
"stat/common/version"
"stat/statg"
"strconv"
"sync"
"time"
)
var (
sysOnce sync.Once
)
func GetServerInformation() string {
text := fmt.Sprintf("统计中心:【%s】编号【%d】:\n", statg.Conf.ServerIndex.Name(), statg.Conf.ServerIndex)
text += fmt.Sprintf("机器名称:【%s】\n", version.HostName())
text += fmt.Sprintf("监听地址:【%s】\n", statg.Conf.Host)
text += fmt.Sprintf("监听端口:【%d】\n", statg.Conf.Port)
text += fmt.Sprintf("服务进程:【%d】\n", os.Getpid())
text += fmt.Sprintf("程序版本:【%s】\n", version.SERVICE_VERSION)
text += fmt.Sprintf("源码分支:【%s】\n", version.GIT_BRANCH)
text += fmt.Sprintf("提交版本:【%s】\n", version.GIT_VERSION)
text += fmt.Sprintf("编译日期:【%s】\n", version.BUILD_DATE)
text += fmt.Sprintf("编译地址:【%s】\n", version.BUILD_IP)
text += fmt.Sprintf("运行模式:【%s】\n", statg.Conf.RunMod)
text += fmt.Sprintf("启动时间:【%s】\n", version.ServerStartTime.Format("2006-01-02T15:04:05"))
text += fmt.Sprintf("运行时长:【%s】\n", time.Since(version.ServerStartTime))
return text
}
func SaveServerKeepAliveTime() {
defer utils.RecoverError(nil)
keyAlive := redis.GetServerKeepAliveHashKey(int(statg.Conf.ServerIndex))
_ = redis.StatRds.Set(keyAlive, time.Now().Unix(), 0)
}
func SaveServerNormalCloseFlag() {
defer utils.RecoverError(nil)
keyClose := redis.GetServerCloseFlagHashKey(int(statg.Conf.ServerIndex))
_ = redis.StatRds.Set(keyClose, time.Now().Unix(), 0)
}
func GetServerInformationLastTime() string {
ret := ""
srvStart := int64(0)
srvAlive := int64(0)
srvClose := int64(0)
sysOnce.Do(func() {
keyStart := redis.GetServerStartTimeHashKey(int(statg.Conf.ServerIndex))
if usStart, err := redis.StatRds.Get(keyStart); err == nil && usStart != nil {
if ut, err2 := strconv.ParseInt(*usStart, 10, 64); err2 == nil {
srvStart = ut
}
}
keyAlive := redis.GetServerKeepAliveHashKey(int(statg.Conf.ServerIndex))
if usAlive, err := redis.StatRds.Get(keyAlive); err == nil && usAlive != nil {
if ut, err2 := strconv.ParseInt(*usAlive, 10, 64); err2 == nil {
srvAlive = ut
}
}
keyClose := redis.GetServerCloseFlagHashKey(int(statg.Conf.ServerIndex))
if usClose, err := redis.StatRds.Get(keyClose); err == nil && usClose != nil {
if ut, err2 := strconv.ParseInt(*usClose, 10, 64); err2 == nil {
srvClose = ut
}
}
version.ServerStartLast = time.Unix(srvStart, 0)
version.ServerAliveLast = time.Unix(srvAlive, 0)
version.ServerCloseLast = time.Unix(srvClose, 0)
_ = redis.StatRds.Set(keyStart, version.ServerStartTime.Unix(), 0)
_ = redis.StatRds.Set(keyClose, version.ServerStartTime.Unix(), 0)
_ = redis.StatRds.Set(keyAlive, time.Now().Unix(), 0)
})
if version.ServerAliveLast.After(version.ServerStartLast) {
ret = fmt.Sprintf("上次运行:【%v】\n", version.ServerAliveLast.Sub(version.ServerStartLast))
if version.ServerCloseLast.After(version.ServerStartLast) {
ret += fmt.Sprintf("上次关闭:【正常关闭🟢】\n")
} else {
ret += fmt.Sprintf("上次关闭:【异常关闭🔴】\n")
}
}
return ret
}
+39
View File
@@ -0,0 +1,39 @@
package botser
import (
"fmt"
"math"
)
func Rate(temp string, numerator, denominator float64) string {
fZero := math.Pow10(-10)
if math.Abs(denominator) < fZero {
return fmt.Sprintf(temp, "无") + "\n"
} else {
str := fmt.Sprintf("%.2f%%", numerator*100/denominator)
return fmt.Sprintf(temp, str) + "\n"
}
}
func Line(iTemp string, iValue int64, numerator, denominator float64) string {
fZero := math.Pow10(-10)
if math.Abs(denominator) < fZero {
s1 := fmt.Sprintf("%d", iValue)
str1 := fmt.Sprintf(iTemp, s1)
return str1 + "\n"
} else {
s1 := fmt.Sprintf("%d", iValue)
str1 := fmt.Sprintf(iTemp, s1)
v := numerator * 100 / denominator
str2 := ""
if v < 0 {
str2 = fmt.Sprintf("⬇-️️%.2f%%", math.Abs(v))
} else if v > 0 {
str2 = fmt.Sprintf("⬆+️%.2f%%", math.Abs(v))
}
if str2 == "" {
return str1 + "\n"
}
return str1 + str2 + "\n"
}
}