package main import ( "fmt" "strings" "time" "github.com/samber/lo" tele "gopkg.in/telebot.v3" "git.gensokyo.cafe/kkyy/tgbot_misaka_5882f7/stats" ) var ( trafficMenu = &tele.ReplyMarkup{} trafficBtnDays, trafficBtnMonths tele.Btn ) func init() { trafficBtnDays = trafficMenu.Data("🌝 Days", "btn_traffic_days") trafficBtnMonths = trafficMenu.Data("🗓️ Months", "btn_traffic_months") trafficMenu.Inline(trafficMenu.Row(trafficBtnDays, trafficBtnMonths)) } func handleTrafficCmd(c tele.Context) error { dailyTraffic, err := stats.VnstatDailyTraffic(config.WatchedInterface) if err != nil { _ = c.Reply(stickerFromID(stickerPanic), tele.Silent) return err } monthlyTraffic, err := stats.VnstatMonthlyTraffic(config.WatchedInterface) if err != nil { _ = c.Reply(stickerFromID(stickerPanic), tele.Silent) return err } var responseParts = []string{"*Traffic Usage Summaries*\n"} // Yesterday's traffic if present if len(dailyTraffic) > 1 { row := dailyTraffic[len(dailyTraffic)-2] day := fmt.Sprintf("%d-%02d-%02d", row.Date.Year, row.Date.Month, row.Date.Day) responseParts = append(responseParts, fmt.Sprintf("Yesterday (%s):` %s`", day, fmtTraffic(row))) } // Today's traffic if present if len(dailyTraffic) > 0 { row := dailyTraffic[len(dailyTraffic)-1] responseParts = append(responseParts, fmt.Sprintf("Today so far:` %s`\n", fmtTraffic(row))) } // Last month's traffic, if present if len(monthlyTraffic) > 1 { row := monthlyTraffic[len(monthlyTraffic)-2] month := fmt.Sprintf("%d-%02d", row.Date.Year, row.Date.Month) responseParts = append(responseParts, fmt.Sprintf("Last month (%s):` %s`", month, fmtTraffic(row))) } // This month's traffic, if present if len(monthlyTraffic) > 0 { row := monthlyTraffic[len(monthlyTraffic)-1] responseParts = append(responseParts, fmt.Sprintf("This month so far:` %s`", fmtTraffic(row))) responseParts = append(responseParts, drawBarForTrafficRecord(row)) } var respText string if len(responseParts) == 1 { respText = "No traffic data available." } else { respText = strings.Join(responseParts, "\n") } return c.Reply(respText, &tele.SendOptions{ParseMode: tele.ModeMarkdown}, tele.Silent, trafficMenu) } func fmtTraffic(r stats.VnstatTrafficRecord) string { effective := lo.Max([]uint64{r.Rx, r.Tx}) return fmt.Sprintf("%.2f GiB", float64(effective)/1024/1024/1024) } func drawBarForTrafficRecord(r stats.VnstatTrafficRecord) string { effective := lo.Max([]uint64{r.Rx, r.Tx}) max := config.MonthlyTrafficLimitGiB ratio := float64(effective) / 1024 / 1024 / 1024 / float64(max) return fmt.Sprintf("`%s %2.0f%%`", drawBar(ratio, 16), ratio*100) } func handleTrafficBtnDays(c tele.Context) error { dailyTraffic, err := stats.VnstatDailyTraffic(config.WatchedInterface) if err != nil { _ = c.Reply(stickerFromID(stickerPanic), tele.Silent) return err } var responseParts = []string{ "*Traffic usage of recent days*", fmt.Sprintf("_updated at %s_\n", time.Now().Format("15:04:05")), } offset := lo.Max([]int{0, len(dailyTraffic) - 14}) for _, tr := range dailyTraffic[offset:] { day := time.Date(int(tr.Date.Year), time.Month(tr.Date.Month), int(tr.Date.Day), 0, 0, 0, 0, time.Local) dayStr := fmt.Sprintf("%s (%s)", day.Format("01-02"), day.Weekday().String()[0:3]) responseParts = append(responseParts, fmt.Sprintf("`%s: %10s`", dayStr, fmtTraffic(tr))) } var respText string if len(responseParts) == 1 { respText = "No daily traffic data available." } else { respText = strings.Join(responseParts, "\n") } return c.Edit(respText, &tele.SendOptions{ParseMode: tele.ModeMarkdown}, trafficMenu) } func handleTrafficBtnMonths(c tele.Context) error { monthlyTraffic, err := stats.VnstatMonthlyTraffic(config.WatchedInterface) if err != nil { _ = c.Reply(stickerFromID(stickerPanic), tele.Silent) return err } var responseParts = []string{ "*Traffic usage of recent months*", fmt.Sprintf("_updated at %s_\n", time.Now().Format("15:04:05")), } for _, tr := range monthlyTraffic { responseParts = append( responseParts, fmt.Sprintf("`%d-%02d: %10s`", tr.Date.Year, tr.Date.Month, fmtTraffic(tr)), ) } var respText string if len(responseParts) == 1 { respText = "No monthly traffic data available." } else { respText = strings.Join(responseParts, "\n") } return c.Edit(respText, &tele.SendOptions{ParseMode: tele.ModeMarkdown}, trafficMenu) }