diff options
| author | somebodywashere <68244480+somebodywashere@users.noreply.github.com> | 2024-01-01 18:07:56 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-01 18:07:56 +0300 |
| commit | ceee1e4277953b68aeded8af01cf2eddfee2fbd5 (patch) | |
| tree | 7ff9f21d8c300ffd45473500337cff4a45ab7b65 /web | |
| parent | b725ea7de5ed73a36a9cd2c23bb247ca6b587573 (diff) | |
Major changes to tgbot, also small changes for panel (#1463)
* Reduce outage time on Xray errors
* Improved logs clearing, added previous logs
File name change: 3xipl-access-persistent.log -> 3xipl-ap.log
All previous logs have .prev suffix
* Preparations for tgbot additions
* [tgbot] Improvements, Additions and Fixes
* Changed interaction with Expire Date for Clients
* Added more info and interactions with Online Clients
* Added a way to get Ban Logs (also added them to backup)
* Few fixes and optimizations in code
* Fixed RU translation
* [tgbot] More updates and fixes
* [tgbot] Quick Fix
* [tgbot] Quick Fix 2
* [tgbot] Big Updates
Added Notifications for Clients throught Tgbot (when Expire)
Added compability for Usernames both w/wo @
Added more buttons overall for admins
* [tgbot] Fixes
* [tbot] Fixes 2
* [tgbot] Removed usernames support for Notifications to work
* [tgbot] Fix
* [tgbot] Fix Notify
* [tgbot] small fixes
* [tgbot] replyMarkup only for last message on big messages
* [tgbot] Fixed last message is empty
* [tgbot] Fix messages split
Diffstat (limited to 'web')
| -rw-r--r-- | web/job/check_client_ip_job.go | 3 | ||||
| -rw-r--r-- | web/job/check_xray_running_job.go | 21 | ||||
| -rw-r--r-- | web/job/clear_logs_job.go | 31 | ||||
| -rw-r--r-- | web/service/inbound.go | 42 | ||||
| -rw-r--r-- | web/service/tgbot.go | 698 | ||||
| -rw-r--r-- | web/service/xray.go | 2 | ||||
| -rw-r--r-- | web/translation/translate.en_US.toml | 34 | ||||
| -rw-r--r-- | web/translation/translate.es_ES.toml | 38 | ||||
| -rw-r--r-- | web/translation/translate.fa_IR.toml | 32 | ||||
| -rw-r--r-- | web/translation/translate.ru_RU.toml | 34 | ||||
| -rw-r--r-- | web/translation/translate.vi_VN.toml | 34 | ||||
| -rw-r--r-- | web/translation/translate.zh_Hans.toml | 30 | ||||
| -rw-r--r-- | web/web.go | 8 |
13 files changed, 628 insertions, 379 deletions
diff --git a/web/job/check_client_ip_job.go b/web/job/check_client_ip_job.go index b15473c5..65257170 100644 --- a/web/job/check_client_ip_job.go +++ b/web/job/check_client_ip_job.go @@ -22,8 +22,11 @@ var job *CheckClientIpJob var disAllowedIps []string var ipFiles = []string{ xray.GetIPLimitLogPath(), +xray.GetIPLimitPrevLogPath(), xray.GetIPLimitBannedLogPath(), +xray.GetIPLimitBannedPrevLogPath(), xray.GetAccessPersistentLogPath(), +xray.GetAccessPersistentPrevLogPath(), } func NewCheckClientIpJob() *CheckClientIpJob { diff --git a/web/job/check_xray_running_job.go b/web/job/check_xray_running_job.go index f1a848bf..d9ffeb7a 100644 --- a/web/job/check_xray_running_job.go +++ b/web/job/check_xray_running_job.go @@ -1,6 +1,9 @@ package job -import "x-ui/web/service" +import ( + "x-ui/logger" + "x-ui/web/service" +) type CheckXrayRunningJob struct { xrayService service.XrayService @@ -15,11 +18,15 @@ func NewCheckXrayRunningJob() *CheckXrayRunningJob { func (j *CheckXrayRunningJob) Run() { if j.xrayService.IsXrayRunning() { j.checkTime = 0 - return + } else { + j.checkTime++ + //only restart if it's down 2 times in a row + if j.checkTime > 1 { + err := j.xrayService.RestartXray(false) + j.checkTime = 0 + if err != nil { + logger.Error("Restart xray failed:", err) + } + } } - j.checkTime++ - if j.checkTime < 2 { - return - } - j.xrayService.SetToNeedRestart() } diff --git a/web/job/clear_logs_job.go b/web/job/clear_logs_job.go index 34f13eaa..5ceb5a75 100644 --- a/web/job/clear_logs_job.go +++ b/web/job/clear_logs_job.go @@ -15,10 +15,37 @@ func NewClearLogsJob() *ClearLogsJob { // Here Run is an interface method of the Job interface func (j *ClearLogsJob) Run() { logFiles := []string{xray.GetIPLimitLogPath(), xray.GetIPLimitBannedLogPath(), xray.GetAccessPersistentLogPath()} + logFilesPrev := []string{xray.GetIPLimitPrevLogPath(), xray.GetIPLimitBannedPrevLogPath(), xray.GetAccessPersistentPrevLogPath()} - // clear log files + // clear old previous logs + for i := 0; i < len(logFilesPrev); i++ { + if err := os.Truncate(logFilesPrev[i], 0); err != nil { + logger.Warning("clear logs job err:", err) + } + } + + // clear log files and copy to previous logs for i := 0; i < len(logFiles); i++ { - if err := os.Truncate(logFiles[i], 0); err != nil { + + // copy to previous logs + logFilePrev, err := os.OpenFile(logFilesPrev[i], os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644) + if err != nil { + logger.Warning("clear logs job err:", err) + } + + logFile, err := os.ReadFile(logFiles[i]) + if err != nil { + logger.Warning("clear logs job err:", err) + } + + _, err = logFilePrev.Write(logFile) + if err != nil { + logger.Warning("clear logs job err:", err) + } + defer logFilePrev.Close() + + err = os.Truncate(logFiles[i], 0) + if err != nil { logger.Warning("clear logs job err:", err) } } diff --git a/web/service/inbound.go b/web/service/inbound.go index 01d4eb57..30619791 100644 --- a/web/service/inbound.go +++ b/web/service/inbound.go @@ -1146,6 +1146,8 @@ func (s *InboundService) SetClientTelegramUserID(trafficId int, tgId string) err if oldClient.Email == clientEmail { if inbound.Protocol == "trojan" { clientId = oldClient.Password + } else if inbound.Protocol == "shadowsocks" { + clientId = oldClient.Email } else { clientId = oldClient.ID } @@ -1184,6 +1186,32 @@ func (s *InboundService) SetClientTelegramUserID(trafficId int, tgId string) err return nil } +func (s *InboundService) checkIsEnabledByEmail(clientEmail string) (bool, error) { + _, inbound, err := s.GetClientInboundByEmail(clientEmail) + if err != nil { + return false, err + } + if inbound == nil { + return false, common.NewError("Inbound Not Found For Email:", clientEmail) + } + + clients, err := s.GetClients(inbound) + if err != nil { + return false, err + } + + isEnable := false + + for _, client := range clients { + if client.Email == clientEmail { + isEnable = client.Enable + break + } + } + + return isEnable, err +} + func (s *InboundService) ToggleClientEnableByEmail(clientEmail string) (bool, error) { _, inbound, err := s.GetClientInboundByEmail(clientEmail) if err != nil { @@ -1205,6 +1233,8 @@ func (s *InboundService) ToggleClientEnableByEmail(clientEmail string) (bool, er if oldClient.Email == clientEmail { if inbound.Protocol == "trojan" { clientId = oldClient.Password + } else if inbound.Protocol == "shadowsocks" { + clientId = oldClient.Email } else { clientId = oldClient.ID } @@ -1266,6 +1296,8 @@ func (s *InboundService) ResetClientIpLimitByEmail(clientEmail string, count int if oldClient.Email == clientEmail { if inbound.Protocol == "trojan" { clientId = oldClient.Password + } else if inbound.Protocol == "shadowsocks" { + clientId = oldClient.Email } else { clientId = oldClient.ID } @@ -1324,6 +1356,8 @@ func (s *InboundService) ResetClientExpiryTimeByEmail(clientEmail string, expiry if oldClient.Email == clientEmail { if inbound.Protocol == "trojan" { clientId = oldClient.Password + } else if inbound.Protocol == "shadowsocks" { + clientId = oldClient.Email } else { clientId = oldClient.ID } @@ -1385,6 +1419,8 @@ func (s *InboundService) ResetClientTrafficLimitByEmail(clientEmail string, tota if oldClient.Email == clientEmail { if inbound.Protocol == "trojan" { clientId = oldClient.Password + } else if inbound.Protocol == "shadowsocks" { + clientId = oldClient.Email } else { clientId = oldClient.ID } @@ -1613,10 +1649,10 @@ func (s *InboundService) DelDepletedClients(id int) (err error) { return nil } -func (s *InboundService) GetClientTrafficTgBot(tguname string) ([]*xray.ClientTraffic, error) { +func (s *InboundService) GetClientTrafficTgBot(tgId string) ([]*xray.ClientTraffic, error) { db := database.GetDB() var inbounds []*model.Inbound - err := db.Model(model.Inbound{}).Where("settings like ?", fmt.Sprintf(`%%"tgId": "%s"%%`, tguname)).Find(&inbounds).Error + err := db.Model(model.Inbound{}).Where("settings like ?", fmt.Sprintf(`%%"tgId": "%s"%%`, tgId)).Find(&inbounds).Error if err != nil && err != gorm.ErrRecordNotFound { return nil, err } @@ -1627,7 +1663,7 @@ func (s *InboundService) GetClientTrafficTgBot(tguname string) ([]*xray.ClientTr logger.Error("Unable to get clients from inbound") } for _, client := range clients { - if client.TgID == tguname { + if client.TgID == tgId { emails = append(emails, client.Email) } } diff --git a/web/service/tgbot.go b/web/service/tgbot.go index 0847e418..9f11c19d 100644 --- a/web/service/tgbot.go +++ b/web/service/tgbot.go @@ -7,6 +7,7 @@ import ( "os" "strconv" "strings" + "slices" "time" "x-ui/config" "x-ui/database" @@ -218,7 +219,7 @@ func (t *Tgbot) answerCommand(message *telego.Message, chatId int64, isAdmin boo if isAdmin { t.searchClient(chatId, commandArgs[0]) } else { - t.searchForClient(chatId, commandArgs[0]) + t.getClientUsage(chatId, strconv.FormatInt(message.From.ID, 10), commandArgs[0]) } } else { msg += t.I18nBot("tgbot.commands.usage") @@ -234,11 +235,14 @@ func (t *Tgbot) answerCommand(message *telego.Message, chatId int64, isAdmin boo msg += t.I18nBot("tgbot.commands.unknown") } - if onlyMessage { - t.SendMsgToTgbot(chatId, msg) - return + if msg != ""{ + if onlyMessage { + t.SendMsgToTgbot(chatId, msg) + return + } else { + t.SendAnswer(chatId, msg, isAdmin) + } } - t.SendAnswer(chatId, msg, isAdmin) } func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool) { @@ -257,6 +261,9 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool if len(dataArray) >= 2 && len(dataArray[1]) > 0 { email := dataArray[1] switch dataArray[0] { + case "client_get_usage": + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.messages.email", "Email=="+email)) + t.searchClient(chatId, email) case "client_refresh": t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.clientRefreshSuccess", "Email=="+email)) t.searchClient(chatId, email, callbackQuery.Message.MessageID) @@ -352,7 +359,7 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool inputNumber = 0 } else if num == -1 { if inputNumber > 0 { - inputNumber = (inputNumber / 10) ^ 0 + inputNumber = (inputNumber / 10) } } else { inputNumber = (inputNumber * 10) + num @@ -372,7 +379,7 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("client_cancel "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumber", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" "+strconv.Itoa(inputNumber))), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumberAdd", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" "+strconv.Itoa(inputNumber))), ), tu.InlineKeyboardRow( tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 1")), @@ -411,20 +418,20 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("reset_exp_in "+email+" 0")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("1 "+t.I18nBot("tgbot.month")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 30")), - tu.InlineKeyboardButton("2 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 60")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 7 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 7")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 10 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 10")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("3 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 90")), - tu.InlineKeyboardButton("6 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 180")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 14 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 14")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 20 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 20")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("9 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 270")), - tu.InlineKeyboardButton("12 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 360")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 1 "+t.I18nBot("tgbot.month")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 30")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 3 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 90")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("10 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 10")), - tu.InlineKeyboardButton("20 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 20")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 6 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 180")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 12 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 365")), ), ) t.editMessageCallbackTgBot(chatId, callbackQuery.Message.MessageID, inlineKeyboard) @@ -434,7 +441,29 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool if err == nil { var date int64 = 0 if days > 0 { - date = int64(-(days * 24 * 60 * 60000)) + traffic, err := t.inboundService.GetClientTrafficByEmail(email) + if err != nil { + logger.Warning(err) + msg := t.I18nBot("tgbot.wentWrong") + t.SendMsgToTgbot(chatId, msg) + return + } + if traffic == nil { + msg := t.I18nBot("tgbot.noResult") + t.SendMsgToTgbot(chatId, msg) + return + } + + if traffic.ExpiryTime > 0 { + if traffic.ExpiryTime-time.Now().Unix()*1000 < 0 { + date = -int64(days * 24 * 60 * 60000) + } else { + date = traffic.ExpiryTime + int64(days*24*60*60000) + } + } else { + date = traffic.ExpiryTime - int64(days*24*60*60000) + } + } err := t.inboundService.ResetClientExpiryTimeByEmail(email, date) if err == nil { @@ -459,7 +488,7 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool inputNumber = 0 } else if num == -1 { if inputNumber > 0 { - inputNumber = (inputNumber / 10) ^ 0 + inputNumber = (inputNumber / 10) } } else { inputNumber = (inputNumber * 10) + num @@ -564,7 +593,7 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool inputNumber = 0 } else if num == -1 { if inputNumber > 0 { - inputNumber = (inputNumber / 10) ^ 0 + inputNumber = (inputNumber / 10) } } else { inputNumber = (inputNumber * 10) + num @@ -661,6 +690,16 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) } case "toggle_enable": + inlineKeyboard := tu.InlineKeyboard( + tu.InlineKeyboardRow( + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("client_cancel "+email)), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmToggle")).WithCallbackData(t.encodeQuery("toggle_enable_c "+email)), + ), + ) + t.editMessageCallbackTgBot(chatId, callbackQuery.Message.MessageID, inlineKeyboard) + case "toggle_enable_c": enabled, err := t.inboundService.ToggleClientEnableByEmail(email) if err == nil { t.xrayService.SetToNeedRestart() @@ -678,24 +717,36 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool } } - // Respond to the callback query, telling Telegram to show the user - // a message with the data received. - t.sendCallbackAnswerTgBot(callbackQuery.ID, callbackQuery.Data) - switch callbackQuery.Data { case "get_usage": + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.serverUsage")) t.SendMsgToTgbot(chatId, t.getServerUsage()) case "inbounds": + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.getInbounds")) t.SendMsgToTgbot(chatId, t.getInboundUsages()) case "deplete_soon": - t.SendMsgToTgbot(chatId, t.getExhausted()) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.depleteSoon")) + t.getExhausted(chatId) case "get_backup": + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.dbBackup")) t.sendBackup(chatId) + case "get_banlogs": + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.getBanLogs")) + t.sendBanLogs(chatId, true) case "client_traffic": - t.getClientUsage(chatId, callbackQuery.From.Username, strconv.FormatInt(callbackQuery.From.ID, 10)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.clientUsage")) + t.getClientUsage(chatId, strconv.FormatInt(callbackQuery.From.ID, 10)) case "client_commands": + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.commands")) t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.helpClientCommands")) + case "onlines": + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.onlines")) + t.onlineClients(chatId) + case "onlines_refresh": + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) + t.onlineClients(chatId, callbackQuery.Message.MessageID) case "commands": + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.commands")) t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.helpAdminCommands")) } } @@ -713,7 +764,10 @@ func (t *Tgbot) SendAnswer(chatId int64, msg string, isAdmin bool) { numericKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.serverUsage")).WithCallbackData(t.encodeQuery("get_usage")), + ), + tu.InlineKeyboardRow( tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.dbBackup")).WithCallbackData(t.encodeQuery("get_backup")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.getBanLogs")).WithCallbackData(t.encodeQuery("get_banlogs")), ), tu.InlineKeyboardRow( tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.getInbounds")).WithCallbackData(t.encodeQuery("inbounds")), @@ -721,6 +775,7 @@ func (t *Tgbot) SendAnswer(chatId int64, msg string, isAdmin bool) { ), tu.InlineKeyboardRow( tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.commands")).WithCallbackData(t.encodeQuery("commands")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.onlines")).WithCallbackData(t.encodeQuery("onlines")), ), ) numericKeyboardClient := tu.InlineKeyboard( @@ -754,7 +809,7 @@ func (t *Tgbot) SendMsgToTgbot(chatId int64, msg string, replyMarkup ...telego.R // paging message if it is big if len(msg) > limit { - messages := strings.Split(msg, "\r\n \r\n") + messages := strings.Split(msg, "\r\n\r\n") lastIndex := -1 for _, message := range messages { @@ -762,19 +817,23 @@ func (t *Tgbot) SendMsgToTgbot(chatId int64, msg string, replyMarkup ...telego.R allMessages = append(allMessages, message) lastIndex++ } else { - allMessages[lastIndex] += "\r\n \r\n" + message + allMessages[lastIndex] += "\r\n\r\n" + message } } + if strings.TrimSpace(allMessages[len(allMessages)-1]) == "" { + allMessages = allMessages[:len(allMessages)-1] + } } else { allMessages = append(allMessages, msg) } - for _, message := range allMessages { + for n, message := range allMessages { params := telego.SendMessageParams{ ChatID: tu.ID(chatId), Text: message, ParseMode: "HTML", } - if len(replyMarkup) > 0 { + //only add replyMarkup to last message + if len(replyMarkup) > 0 && n == (len(allMessages)-1) { params.ReplyMarkup = replyMarkup[0] } _, err := bot.SendMessage(¶ms) @@ -785,9 +844,15 @@ func (t *Tgbot) SendMsgToTgbot(chatId int64, msg string, replyMarkup ...telego.R } } -func (t *Tgbot) SendMsgToTgbotAdmins(msg string) { - for _, adminId := range adminIds { - t.SendMsgToTgbot(adminId, msg) +func (t *Tgbot) SendMsgToTgbotAdmins(msg string, replyMarkup ...telego.ReplyMarkup) { + if len(replyMarkup) > 0 { + for _, adminId := range adminIds { + t.SendMsgToTgbot(adminId, msg, replyMarkup[0]) + } + } else { + for _, adminId := range adminIds { + t.SendMsgToTgbot(adminId, msg) + } } } @@ -803,8 +868,8 @@ func (t *Tgbot) SendReport() { info := t.getServerUsage() t.SendMsgToTgbotAdmins(info) - exhausted := t.getExhausted() - t.SendMsgToTgbotAdmins(exhausted) + t.sendExhaustedToAdmins() + t.notifyExhausted() backupEnable, err := t.settingService.GetTgBotBackup() if err == nil && backupEnable { @@ -821,6 +886,15 @@ func (t *Tgbot) SendBackupToAdmins() { } } +func (t *Tgbot) sendExhaustedToAdmins() { + if !t.IsRunning() { + return + } + for _, adminId := range adminIds { + t.getExhausted(int64(adminId)) + } +} + func (t *Tgbot) getServerUsage() string { info, ipv4, ipv6 := "", "", "" info += t.I18nBot("tgbot.messages.hostname", "Hostname=="+hostname) @@ -831,7 +905,7 @@ func (t *Tgbot) getServerUsage() string { if err != nil { logger.Error("net.Interfaces failed, err: ", err.Error()) info += t.I18nBot("tgbot.messages.ip", "IP=="+t.I18nBot("tgbot.unknown")) - info += " \r\n" + info += "\r\n" } else { for i := 0; i < len(netInterfaces); i++ { if (netInterfaces[i].Flags & net.FlagUp) != 0 { @@ -855,9 +929,11 @@ func (t *Tgbot) getServerUsage() string { // get latest status of server t.lastStatus = t.serverService.GetStatus(t.lastStatus) + onlines := p.GetOnlineClients() info += t.I18nBot("tgbot.messages.serverUpTime", "UpTime=="+strconv.FormatUint(t.lastStatus.Uptime/86400, 10), "Unit=="+t.I18nBot("tgbot.days")) info += t.I18nBot("tgbot.messages.serverLoad", "Load1=="+strconv.FormatFloat(t.lastStatus.Loads[0], 'f', 2, 64), "Load2=="+strconv.FormatFloat(t.lastStatus.Loads[1], 'f', 2, 64), "Load3=="+strconv.FormatFloat(t.lastStatus.Loads[2], 'f', 2, 64)) info += t.I18nBot("tgbot.messages.serverMemory", "Current=="+common.FormatTraffic(int64(t.lastStatus.Mem.Current)), "Total=="+common.FormatTraffic(int64(t.lastStatus.Mem.Total))) + info += t.I18nBot("tgbot.messages.onlinesCount", "Count=="+fmt.Sprint(len(onlines))) info += t.I18nBot("tgbot.messages.tcpCount", "Count=="+strconv.Itoa(t.lastStatus.TcpCount)) info += t.I18nBot("tgbot.messages.udpCount", "Count=="+strconv.Itoa(t.lastStatus.UdpCount)) info += t.I18nBot("tgbot.messages.traffic", "Total=="+common.FormatTraffic(int64(t.lastStatus.NetTraffic.Sent+t.lastStatus.NetTraffic.Recv)), "Upload=="+common.FormatTraffic(int64(t.lastStatus.NetTraffic.Sent)), "Download=="+common.FormatTraffic(int64(t.lastStatus.NetTraffic.Recv))) @@ -914,85 +990,136 @@ func (t *Tgbot) getInboundUsages() string { } else { info += t.I18nBot("tgbot.messages.expire", "Time=="+time.Unix((inbound.ExpiryTime/1000), 0).Format("2006-01-02 15:04:05")) } + info += "\r\n" } } return info } -func (t *Tgbot) getClientUsage(chatId int64, tgUserName string, tgUserID string) { - traffics, err := t.inboundService.GetClientTrafficTgBot(tgUserID) +func (t *Tgbot) clientInfoMsg(traffic *xray.ClientTraffic, printEnabled bool, printOnline bool, printActive bool, + printDate bool, printTraffic bool, printRefreshed bool) string { + + now := time.Now().Unix() + expiryTime := "" + flag := false + diff := traffic.ExpiryTime/1000 - now + if traffic.ExpiryTime == 0 { + expiryTime = t.I18nBot("tgbot.unlimited") + } else if diff > 172800 || !traffic.Enable { + expiryTime = time.Unix((traffic.ExpiryTime / 1000), 0).Format("2006-01-02 15:04:05") + } else if traffic.ExpiryTime < 0 { + expiryTime = fmt.Sprintf("%d %s", traffic.ExpiryTime/-86400000, t.I18nBot("tgbot.days")) + flag = true + } else { + expiryTime = fmt.Sprintf("%d %s", diff/3600, t.I18nBot("tgbot.hours")) + flag = true + } + + total := "" + if traffic.Total == 0 { + total = t.I18nBot("tgbot.unlimited") + } else { + total = common.FormatTraffic((traffic.Total)) + } + + enabled := "" + isEnabled, err := t.inboundService.checkIsEnabledByEmail(traffic.Email) if err != nil { logger.Warning(err) - msg := t.I18nBot("tgbot.wentWrong") - t.SendMsgToTgbot(chatId, msg) - return + enabled = t.I18nBot("tgbot.wentWrong") + } else if isEnabled { + enabled = t.I18nBot("tgbot.messages.yes") + } else { + enabled = t.I18nBot("tgbot.messages.no") } - if len(traffics) == 0 { - if len(tgUserName) == 0 { - msg := t.I18nBot("tgbot.answers.askToAddUserId", "TgUserID=="+tgUserID) - t.SendMsgToTgbot(chatId, msg) - return + active := "" + if traffic.Enable { + active = t.I18nBot("tgbot.messages.yes") + } else { + active = t.I18nBot("tgbot.messages.no") + } + + status := t.I18nBot("tgbot.offline") + if p.IsRunning() { + for _, online := range p.GetOnlineClients() { + if online == traffic.Email { + status = t.I18nBot("tgbot.online") + break + } + } + } + + output := "" + output += t.I18nBot("tgbot.messages.email", "Email=="+traffic.Email) + if printEnabled { + output += t.I18nBot("tgbot.messages.enabled", "Enable=="+enabled) + } + if printOnline { + output += t.I18nBot("tgbot.messages.online", "Status=="+status) + } + if printActive { + output += t.I18nBot("tgbot.messages.active", "Enable=="+active) + } + if printDate { + if flag { + output += t.I18nBot("tgbot.messages.expireIn", "Time=="+expiryTime) + } else { + output += t.I18nBot("tgbot.messages.expire", "Time=="+expiryTime) } - traffics, err = t.inboundService.GetClientTrafficTgBot(tgUserName) } + if printTraffic { + output += t.I18nBot("tgbot.messages.upload", "Upload=="+common.FormatTraffic(traffic.Up)) + output += t.I18nBot("tgbot.messages.download", "Download=="+common.FormatTraffic(traffic.Down)) + output += t.I18nBot("tgbot.messages.total", "UpDown=="+common.FormatTraffic((traffic.Up+traffic.Down)), "Total=="+total) + } + if printRefreshed { + output += t.I18nBot("tgbot.messages.refreshedOn", "Time=="+time.Now().Format("2006-01-02 15:04:05")) + } + + return output +} + +func (t *Tgbot) getClientUsage(chatId int64, tgUserID string, email ...string) { + traffics, err := t.inboundService.GetClientTrafficTgBot(tgUserID) if err != nil { logger.Warning(err) msg := t.I18nBot("tgbot.wentWrong") t.SendMsgToTgbot(chatId, msg) return } + if len(traffics) == 0 { - msg := t.I18nBot("tgbot.answers.askToAddUserName", "TgUserName=="+tgUserName, "TgUserID=="+tgUserID) - t.SendMsgToTgbot(chatId, msg) + t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.askToAddUserId", "TgUserID=="+tgUserID)) return } - now := time.Now().Unix() - for _, traffic := range traffics { - expiryTime := "" - flag := false - diff := traffic.ExpiryTime/1000 - now - if traffic.ExpiryTime == 0 { - expiryTime = t.I18nBot("tgbot.unlimited") - } else if diff > 172800 || !traffic.Enable { - expiryTime = time.Unix((traffic.ExpiryTime / 1000), 0).Format("2006-01-02 15:04:05") - } else if traffic.ExpiryTime < 0 { - expiryTime = fmt.Sprintf("%d %s", traffic.ExpiryTime/-86400000, t.I18nBot("tgbot.days")) - flag = true - } else { - expiryTime = fmt.Sprintf("%d %s", diff/3600, t.I18nBot("tgbot.hours")) - flag = true - } - - total := "" - if traffic.Total == 0 { - total = t.I18nBot("tgbot.unlimited") - } else { - total = common.FormatTraffic((traffic.Total)) - } + output := "" - output := "" - output += t.I18nBot("tgbot.messages.email", "Email=="+traffic.Email) - if traffic.Enable { - output += t.I18nBot("tgbot.messages.active") - if flag { - output += t.I18nBot("tgbot.messages.expireIn", "Time=="+expiryTime) - } else { - output += t.I18nBot("tgbot.messages.expire", "Time=="+expiryTime) + if len(traffics) > 0 { + if len(email) > 0 { + for _, traffic := range traffics { + if traffic.Email == email[0] { + output := t.clientInfoMsg(traffic, true, true, true, true, true, true) + t.SendMsgToTgbot(chatId, output) + return + } } + msg := t.I18nBot("tgbot.noResult") + t.SendMsgToTgbot(chatId, msg) + return } else { - output += t.I18nBot("tgbot.messages.inactive") - output += t.I18nBot("tgbot.messages.expire", "Time=="+expiryTime) + for _, traffic := range traffics { + output += t.clientInfoMsg(traffic, true, true, true, true, true, false) + output += "\r\n" + } } - output += t.I18nBot("tgbot.messages.upload", "Upload=="+common.FormatTraffic(traffic.Up)) - output += t.I18nBot("tgbot.messages.download", "Download=="+common.FormatTraffic(traffic.Down)) - output += t.I18nBot("tgbot.messages.total", "UpDown=="+common.FormatTraffic((traffic.Up+traffic.Down)), "Total=="+total) - output += t.I18nBot("tgbot.messages.refreshedOn", "Time=="+time.Now().Format("2006-01-02 15:04:05")) - - t.SendMsgToTgbot(chatId, output) } - t.SendAnswer(chatId, t.I18nBot("tgbot.commands.pleaseChoose"), false) + + output += t.I18nBot("tgbot.messages.refreshedOn", "Time=="+time.Now().Format("2006-01-02 15:04:05")) + t.SendMsgToTgbot(chatId, output) + output = t.I18nBot("tgbot.commands.pleaseChoose") + t.SendAnswer(chatId, output, false) } func (t *Tgbot) searchClientIps(chatId int64, email string, messageID ...int) { @@ -1088,46 +1215,7 @@ func (t *Tgbot) searchClient(chatId int64, email string, messageID ...int) { return } - now := time.Now().Unix() - expiryTime := "" - flag := false - diff := traffic.ExpiryTime/1000 - now - if traffic.ExpiryTime == 0 { - expiryTime = t.I18nBot("tgbot.unlimited") - } else if diff > 172800 || !traffic.Enable { - expiryTime = time.Unix((traffic.ExpiryTime / 1000), 0).Format("2006-01-02 15:04:05") - } else if traffic.ExpiryTime < 0 { - expiryTime = fmt.Sprintf("%d %s", traffic.ExpiryTime/-86400000, t.I18nBot("tgbot.days")) - flag = true - } else { - expiryTime = fmt.Sprintf("%d %s", diff/3600, t.I18nBot("tgbot.hours")) - flag = true - } - - total := "" - if traffic.Total == 0 { - total = t.I18nBot("tgbot.unlimited") - } else { - total = common.FormatTraffic((traffic.Total)) - } - - output := "" - output += t.I18nBot("tgbot.messages.email", "Email=="+traffic.Email) - if traffic.Enable { - output += t.I18nBot("tgbot.messages.active") - if flag { - output += t.I18nBot("tgbot.messages.expireIn", "Time=="+expiryTime) - } else { - output += t.I18nBot("tgbot.messages.expire", "Time=="+expiryTime) - } - } else { - output += t.I18nBot("tgbot.messages.inactive") - output += t.I18nBot("tgbot.messages.expire", "Time=="+expiryTime) - } - output += t.I18nBot("tgbot.messages.upload", "Upload=="+common.FormatTraffic(traffic.Up)) - output += t.I18nBot("tgbot.messages.download", "Download=="+common.FormatTraffic(traffic.Down)) - output += t.I18nBot("tgbot.messages.total", "UpDown=="+common.FormatTraffic((traffic.Up+traffic.Down)), "Total=="+total) - output += t.I18nBot("tgbot.messages.refreshedOn", "Time=="+time.Now().Format("2006-01-02 15:04:05")) + output := t.clientInfoMsg(traffic, true, true, true, true, true, true) inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( @@ -1151,7 +1239,6 @@ func (t *Tgbot) searchClient(chatId int64, email string, messageID ...int) { tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.toggle")).WithCallbackData(t.encodeQuery("toggle_enable "+email)), ), ) - if len(messageID) > 0 { t.editMessageTgBot(chatId, messageID[0], output, inlineKeyboard) } else { @@ -1173,7 +1260,6 @@ func (t *Tgbot) searchInbound(chatId int64, remark string) { return } - now := time.Now().Unix() for _, inbound := range inbouds { info := "" info += t.I18nBot("tgbot.messages.inbound", "Remark=="+inbound.Remark) @@ -1187,111 +1273,17 @@ func (t *Tgbot) searchInbound(chatId int64, remark string) { } t.SendMsgToTgbot(chatId, info) - for _, traffic := range inbound.ClientStats { - expiryTime := "" - flag := false - diff := traffic.ExpiryTime/1000 - now - if traffic.ExpiryTime == 0 { - expiryTime = t.I18nBot("tgbot.unlimited") - } else if diff > 172800 || !traffic.Enable { - expiryTime = time.Unix((traffic.ExpiryTime / 1000), 0).Format("2006-01-02 15:04:05") - } else if traffic.ExpiryTime < 0 { - expiryTime = fmt.Sprintf("%d %s", traffic.ExpiryTime/-86400000, t.I18nBot("tgbot.days")) - flag = true - } else { - expiryTime = fmt.Sprintf("%d %s", diff/3600, t.I18nBot("tgbot.hours")) - flag = true - } - - total := "" - if traffic.Total == 0 { - total = t.I18nBot("tgbot.unlimited") - } else { - total = common.FormatTraffic((traffic.Total)) - } - + if len(inbound.ClientStats) > 0 { output := "" - output += t.I18nBot("tgbot.messages.email", "Email=="+traffic.Email) - if traffic.Enable { - output += t.I18nBot("tgbot.messages.active") - if flag { - output += t.I18nBot("tgbot.messages.expireIn", "Time=="+expiryTime) - } else { - output += t.I18nBot("tgbot.messages.expire", "Time=="+expiryTime) - } - } else { - output += t.I18nBot("tgbot.messages.inactive") - output += t.I18nBot("tgbot.messages.expire", "Time=="+expiryTime) + for _, traffic := range inbound.ClientStats { + output += t.clientInfoMsg(&traffic, true, true, true, true, true, true) } - output += t.I18nBot("tgbot.messages.upload", "Upload=="+common.FormatTraffic(traffic.Up)) - output += t.I18nBot(
|
