diff --git a/web/service/inbound.go b/web/service/inbound.go index fce01634..92182df9 100644 --- a/web/service/inbound.go +++ b/web/service/inbound.go @@ -6,6 +6,7 @@ import ( "strconv" "strings" "time" + "sort" "x-ui/database" "x-ui/database/model" @@ -2025,3 +2026,38 @@ func (s *InboundService) MigrateDB() { func (s *InboundService) GetOnlineClients() []string { return p.GetOnlineClients() } + + +func (s *InboundService) GetValidEmails(emails []string) ([]string, []string, error) { + db := database.GetDB() + + // Step 1: Get ClientTraffic records for emails in the input list + var clients []xray.ClientTraffic + err := db.Where("email IN ?", emails).Find(&clients).Error + if err != nil && err != gorm.ErrRecordNotFound { + return nil, nil, err + } + + // Step 2: Sort clients by (Up + Down) descending + sort.Slice(clients, func(i, j int) bool { + return (clients[i].Up + clients[i].Down) > (clients[j].Up + clients[j].Down) + }) + + // Step 3: Extract sorted valid emails and track found ones + validEmails := make([]string, 0, len(clients)) + found := make(map[string]bool) + for _, client := range clients { + validEmails = append(validEmails, client.Email) + found[client.Email] = true + } + + // Step 4: Identify emails that were not found in the database + extraEmails := make([]string, 0) + for _, email := range emails { + if !found[email] { + extraEmails = append(extraEmails, email) + } + } + + return validEmails, extraEmails, nil +} diff --git a/web/service/tgbot.go b/web/service/tgbot.go index 8aa5cb90..594c3912 100644 --- a/web/service/tgbot.go +++ b/web/service/tgbot.go @@ -1456,7 +1456,38 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool } t.SendMsgToTgbot(chatId,t.I18nBot("tgbot.messages.FinishProcess"), tu.ReplyKeyboardRemove()) + case "get_sorted_traffic_usage_report": + t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) + emails, err := t.inboundService.getAllEmails() + + if err != nil { + t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation"), tu.ReplyKeyboardRemove()) + return + } + valid_emails ,extra_emails, err := t.inboundService.GetValidEmails(emails) + for _, valid_emails := range valid_emails { + traffic, err := t.inboundService.GetClientTrafficByEmail(valid_emails) + if err != nil { + logger.Warning(err) + msg := t.I18nBot("tgbot.wentWrong") + t.SendMsgToTgbot(chatId, msg) + continue + } + if traffic == nil { + msg := t.I18nBot("tgbot.noResult") + t.SendMsgToTgbot(chatId, msg) + continue + } + + output := t.clientInfoMsg(traffic, false, false, false, false, true, false) + t.SendMsgToTgbot(chatId, output, tu.ReplyKeyboardRemove()) + } + for _, extra_emails := range extra_emails { + msg := fmt.Sprintf("📧 %s\n%s", extra_emails, t.I18nBot("tgbot.noResult")) + t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove()) + + } } } @@ -1609,6 +1640,9 @@ func checkAdmin(tgId int64) bool { func (t *Tgbot) SendAnswer(chatId int64, msg string, isAdmin bool) { numericKeyboard := tu.InlineKeyboard( + tu.InlineKeyboardRow( + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.SortedTrafficUsageReport")).WithCallbackData(t.encodeQuery("get_sorted_traffic_usage_report")), + ), tu.InlineKeyboardRow( tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.serverUsage")).WithCallbackData(t.encodeQuery("get_usage")), tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.ResetAllTraffics")).WithCallbackData(t.encodeQuery("reset_all_traffics")), diff --git a/web/translation/translate.ar_EG.toml b/web/translation/translate.ar_EG.toml index fe106feb..76ab70a5 100644 --- a/web/translation/translate.ar_EG.toml +++ b/web/translation/translate.ar_EG.toml @@ -655,6 +655,9 @@ "change_password" = "⚙️🔑 كلمة السر" "change_email" = "⚙️📧 البريد الإلكتروني" "change_comment" = "⚙️💬 تعليق" +"ResetAllTraffics" = "إعادة ضبط جميع الترافيك" +"SortedTrafficUsageReport" = "تقرير استخدام الترافيك المرتب" + [tgbot.answers] "successfulOperation" = "✅ العملية نجحت!" diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml index d2c2579b..d0d81732 100644 --- a/web/translation/translate.en_US.toml +++ b/web/translation/translate.en_US.toml @@ -612,6 +612,7 @@ "FailedResetTraffic" = "📧 Email: {{ .ClientEmail }}\n🏁 Result: ❌ Failed \n\n🛠️ Error: [ {{ .ErrorMessage }} ]" "FinishProcess" = "🔚 Traffic reset process finished for all clients." + [tgbot.buttons] "closeKeyboard" = "❌ Close Keyboard" "cancel" = "❌ Cancel" @@ -655,6 +656,7 @@ "change_email" = "⚙️📧 Email" "change_comment" = "⚙️💬 Comment" "ResetAllTraffics" = "Reset All Traffics" +"SortedTrafficUsageReport" = "Sorted Traffic Usage Report" [tgbot.answers] "successfulOperation" = "✅ Operation successful!" diff --git a/web/translation/translate.es_ES.toml b/web/translation/translate.es_ES.toml index 31b655e9..9109dd99 100644 --- a/web/translation/translate.es_ES.toml +++ b/web/translation/translate.es_ES.toml @@ -658,7 +658,7 @@ "change_email" = "⚙️📧 Correo electrónico" "change_comment" = "⚙️💬 Comentario" "ResetAllTraffics" = "Reiniciar todo el tráfico" - +"SortedTrafficUsageReport" = "Informe de uso de tráfico ordenado" [tgbot.answers] diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml index daadf00d..727a0827 100644 --- a/web/translation/translate.fa_IR.toml +++ b/web/translation/translate.fa_IR.toml @@ -658,6 +658,8 @@ "change_email" = "⚙️📧 ایمیل" "change_comment" = "⚙️💬 نظر" "ResetAllTraffics" = "بازنشانی همه ترافیک‌ها" +"SortedTrafficUsageReport" = "گزارش استفاده از ترافیک مرتب‌شده" + [tgbot.answers] "successfulOperation" = "✅ انجام شد!" diff --git a/web/translation/translate.id_ID.toml b/web/translation/translate.id_ID.toml index b89f4519..19e4d050 100644 --- a/web/translation/translate.id_ID.toml +++ b/web/translation/translate.id_ID.toml @@ -658,6 +658,7 @@ "change_email" = "⚙️📧 Email" "change_comment" = "⚙️💬 Komentar" "ResetAllTraffics" = "Reset Semua Lalu Lintas" +"SortedTrafficUsageReport" = "Laporan Penggunaan Lalu Lintas yang Terurut" [tgbot.answers] diff --git a/web/translation/translate.ja_JP.toml b/web/translation/translate.ja_JP.toml index 3ac1b236..e7c4f77d 100644 --- a/web/translation/translate.ja_JP.toml +++ b/web/translation/translate.ja_JP.toml @@ -658,6 +658,7 @@ "change_email" = "⚙️📧 メールアドレス" "change_comment" = "⚙️💬 コメント" "ResetAllTraffics" = "すべてのトラフィックをリセット" +"SortedTrafficUsageReport" = "ソートされたトラフィック使用レポート" [tgbot.answers] diff --git a/web/translation/translate.pt_BR.toml b/web/translation/translate.pt_BR.toml index 2aef5ca7..27c5cf9c 100644 --- a/web/translation/translate.pt_BR.toml +++ b/web/translation/translate.pt_BR.toml @@ -658,6 +658,7 @@ "change_email" = "⚙️📧 E-mail" "change_comment" = "⚙️💬 Comentário" "ResetAllTraffics" = "Redefinir Todo o Tráfego" +"SortedTrafficUsageReport" = "Relatório de Uso de Tráfego Ordenado" [tgbot.answers] diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml index fbd39c76..0e73e623 100644 --- a/web/translation/translate.ru_RU.toml +++ b/web/translation/translate.ru_RU.toml @@ -658,6 +658,7 @@ "change_email" = "⚙️📧 Электронная почта" "change_comment" = "⚙️💬 Комментарий" "ResetAllTraffics" = "Сбросить весь трафик" +"SortedTrafficUsageReport" = "Отсортированный отчет об использовании трафика" [tgbot.answers] diff --git a/web/translation/translate.tr_TR.toml b/web/translation/translate.tr_TR.toml index ea7aba09..6baca6c9 100644 --- a/web/translation/translate.tr_TR.toml +++ b/web/translation/translate.tr_TR.toml @@ -658,6 +658,7 @@ "change_email" = "⚙️📧 E-posta" "change_comment" = "⚙️💬 Yorum" "ResetAllTraffics" = "Tüm Trafikleri Sıfırla" +"SortedTrafficUsageReport" = "Sıralı Trafik Kullanım Raporu" [tgbot.answers] diff --git a/web/translation/translate.uk_UA.toml b/web/translation/translate.uk_UA.toml index bba6aa41..84f46bc3 100644 --- a/web/translation/translate.uk_UA.toml +++ b/web/translation/translate.uk_UA.toml @@ -658,6 +658,7 @@ "change_email" = "⚙️📧 Електронна пошта" "change_comment" = "⚙️💬 Коментар" "ResetAllTraffics" = "Скинути весь трафік" +"SortedTrafficUsageReport" = "Відсортований звіт про використання трафіку" [tgbot.answers] diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml index 3df3e89e..a293a589 100644 --- a/web/translation/translate.vi_VN.toml +++ b/web/translation/translate.vi_VN.toml @@ -658,6 +658,7 @@ "change_email" = "⚙️📧 Email" "change_comment" = "⚙️💬 Bình Luận" "ResetAllTraffics" = "Đặt lại tất cả lưu lượng" +"SortedTrafficUsageReport" = "Báo cáo sử dụng lưu lượng đã sắp xếp" [tgbot.answers] diff --git a/web/translation/translate.zh_CN.toml b/web/translation/translate.zh_CN.toml index 5963d360..0cb388d9 100644 --- a/web/translation/translate.zh_CN.toml +++ b/web/translation/translate.zh_CN.toml @@ -658,6 +658,7 @@ "change_email" = "⚙️📧 邮箱" "change_comment" = "⚙️💬 评论" "ResetAllTraffics" = "重置所有流量" +"SortedTrafficUsageReport" = "排序的流量使用报告" [tgbot.answers] diff --git a/web/translation/translate.zh_TW.toml b/web/translation/translate.zh_TW.toml index 65d35905..67bf15bb 100644 --- a/web/translation/translate.zh_TW.toml +++ b/web/translation/translate.zh_TW.toml @@ -658,6 +658,7 @@ "change_email" = "⚙️📧 電子郵件" "change_comment" = "⚙️💬 評論" "ResetAllTraffics" = "重設所有流量" +"SortedTrafficUsageReport" = "排序過的流量使用報告" [tgbot.answers]