mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-17 15:47:14 +00:00
fix(tgbot): send the admin traffic reports as one message (#6490)
Reset all traffics and the sorted usage report replied with one Telegram message per client. A panel with a few hundred clients therefore fired a burst of sendMessage calls that trips Telegram's per-chat rate limit and throttles the bot for every user, not just the admin who tapped. Both reports are now assembled into one string and handed to SendMsgToTgbot, which already pages long messages. Two details the batching would otherwise lose: the reset report still answers (with the reply keyboard removed) when the panel has no clients, and both reports are HTML-escaped as a whole, because a single stray "<" in a remark or an email now costs the ~15-client page it lands on instead of one client's message.
This commit is contained in:
@@ -1268,18 +1268,22 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
return
|
||||
}
|
||||
|
||||
// One report per tap, not one message per client: a large panel would
|
||||
// otherwise burst past Telegram's rate limit. SendMsgToTgbot pages it.
|
||||
var report strings.Builder
|
||||
for _, email := range emails {
|
||||
err := t.inboundService.ResetClientTrafficByEmail(email)
|
||||
if err == nil {
|
||||
msg := t.I18nBot("tgbot.messages.SuccessResetTraffic", "ClientEmail=="+email)
|
||||
t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove())
|
||||
if err := t.inboundService.ResetClientTrafficByEmail(email); err == nil {
|
||||
report.WriteString(t.I18nBot("tgbot.messages.SuccessResetTraffic", "ClientEmail=="+email))
|
||||
} else {
|
||||
msg := t.I18nBot("tgbot.messages.FailedResetTraffic", "ClientEmail=="+email, "ErrorMessage=="+err.Error())
|
||||
t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove())
|
||||
report.WriteString(t.I18nBot("tgbot.messages.FailedResetTraffic", "ClientEmail=="+email, "ErrorMessage=="+err.Error()))
|
||||
}
|
||||
report.WriteString("\r\n\r\n")
|
||||
}
|
||||
report.WriteString(t.I18nBot("tgbot.messages.FinishProcess"))
|
||||
|
||||
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.FinishProcess"), tu.ReplyKeyboardRemove())
|
||||
// Escaped whole: one stray "<" in a remark or email otherwise makes
|
||||
// Telegram reject the page it landed on, losing ~15 clients at once.
|
||||
t.SendMsgToTgbot(chatId, html.EscapeString(report.String()), tu.ReplyKeyboardRemove())
|
||||
case "get_sorted_traffic_usage_report":
|
||||
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
||||
emails, err := t.inboundService.GetAllEmails()
|
||||
@@ -1287,33 +1291,36 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation"), tu.ReplyKeyboardRemove())
|
||||
return
|
||||
}
|
||||
valid_emails, extra_emails, err := t.inboundService.FilterAndSortClientEmails(emails)
|
||||
validEmails, missingEmails, err := t.inboundService.FilterAndSortClientEmails(emails)
|
||||
if err != nil {
|
||||
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation"), tu.ReplyKeyboardRemove())
|
||||
return
|
||||
}
|
||||
|
||||
for _, valid_emails := range valid_emails {
|
||||
traffic, err := t.inboundService.GetClientTrafficByEmail(valid_emails)
|
||||
// Batched for the same reason as the reset report above: one message
|
||||
// per client hits Telegram's rate limit on a large panel.
|
||||
var report strings.Builder
|
||||
for _, email := range validEmails {
|
||||
traffic, err := t.inboundService.GetClientTrafficByEmail(email)
|
||||
if err != nil {
|
||||
logger.Warning(err)
|
||||
msg := t.I18nBot("tgbot.wentWrong")
|
||||
t.SendMsgToTgbot(chatId, msg)
|
||||
report.WriteString(t.I18nBot("tgbot.wentWrong"))
|
||||
report.WriteString("\r\n\r\n")
|
||||
continue
|
||||
}
|
||||
if traffic == nil {
|
||||
msg := t.I18nBot("tgbot.noResult")
|
||||
t.SendMsgToTgbot(chatId, msg)
|
||||
report.WriteString(t.I18nBot("tgbot.noResult"))
|
||||
report.WriteString("\r\n\r\n")
|
||||
continue
|
||||
}
|
||||
|
||||
output := t.clientInfoMsg(traffic, false, false, false, false, true, false)
|
||||
t.SendMsgToTgbot(chatId, output, tu.ReplyKeyboardRemove())
|
||||
report.WriteString(t.clientInfoMsg(traffic, false, false, false, false, true, false))
|
||||
report.WriteString("\r\n\r\n")
|
||||
}
|
||||
for _, extra_emails := range extra_emails {
|
||||
msg := fmt.Sprintf("📧 %s\n%s", extra_emails, t.I18nBot("tgbot.noResult"))
|
||||
t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove())
|
||||
|
||||
for _, email := range missingEmails {
|
||||
fmt.Fprintf(&report, "📧 %s\r\n%s\r\n\r\n", email, t.I18nBot("tgbot.noResult"))
|
||||
}
|
||||
if report.Len() > 0 {
|
||||
t.SendMsgToTgbot(chatId, html.EscapeString(report.String()), tu.ReplyKeyboardRemove())
|
||||
}
|
||||
default:
|
||||
action, email, ok := splitClientLinkCallback(callbackQuery.Data)
|
||||
|
||||
Reference in New Issue
Block a user