From ceee1e4277953b68aeded8af01cf2eddfee2fbd5 Mon Sep 17 00:00:00 2001 From: somebodywashere <68244480+somebodywashere@users.noreply.github.com> Date: Mon, 1 Jan 2024 18:07:56 +0300 Subject: 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 --- web/service/inbound.go | 42 ++- web/service/tgbot.go | 698 ++++++++++++++++++++++++++++--------------------- web/service/xray.go | 2 +- 3 files changed, 447 insertions(+), 295 deletions(-) (limited to 'web/service') 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("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) } } } -func (t *Tgbot) searchForClient(chatId int64, query string) { - traffic, err := t.inboundService.SearchClientTraffic(query) - 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 - } - - 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")) - - t.SendMsgToTgbot(chatId, output) -} - -func (t *Tgbot) getExhausted() string { +func (t *Tgbot) getExhausted(chatId int64) { trDiff := int64(0) exDiff := int64(0) now := time.Now().Unix() * 1000 @@ -1341,10 +1333,9 @@ func (t *Tgbot) getExhausted() string { output += t.I18nBot("tgbot.messages.exhaustedCount", "Type=="+t.I18nBot("tgbot.inbounds")) output += t.I18nBot("tgbot.messages.disabled", "Disabled=="+strconv.Itoa(len(disabledInbounds))) output += t.I18nBot("tgbot.messages.depleteSoon", "Deplete=="+strconv.Itoa(len(exhaustedInbounds))) - output += "\r\n \r\n" if len(exhaustedInbounds) > 0 { - output += t.I18nBot("tgbot.messages.exhaustedMsg", "Type=="+t.I18nBot("tgbot.inbounds")) + output += t.I18nBot("tgbot.messages.depleteSoon", "Deplete=="+t.I18nBot("tgbot.inbounds")) for _, inbound := range exhaustedInbounds { output += t.I18nBot("tgbot.messages.inbound", "Remark=="+inbound.Remark) @@ -1355,63 +1346,148 @@ func (t *Tgbot) getExhausted() string { } else { output += t.I18nBot("tgbot.messages.expire", "Time=="+time.Unix((inbound.ExpiryTime/1000), 0).Format("2006-01-02 15:04:05")) } - output += "\r\n \r\n" + output += "\r\n" } } // Clients + exhaustedCC := len(exhaustedClients) output += t.I18nBot("tgbot.messages.exhaustedCount", "Type=="+t.I18nBot("tgbot.clients")) output += t.I18nBot("tgbot.messages.disabled", "Disabled=="+strconv.Itoa(len(disabledClients))) - output += t.I18nBot("tgbot.messages.depleteSoon", "Deplete=="+strconv.Itoa(len(exhaustedClients))) - output += "\r\n \r\n" - - if len(exhaustedClients) > 0 { - output += t.I18nBot("tgbot.messages.exhaustedMsg", "Type=="+t.I18nBot("tgbot.clients")) + output += t.I18nBot("tgbot.messages.depleteSoon", "Deplete=="+strconv.Itoa(exhaustedCC)) + + if exhaustedCC > 0 { + output += t.I18nBot("tgbot.messages.depleteSoon", "Deplete=="+t.I18nBot("tgbot.clients")) + var buttons []telego.InlineKeyboardButton for _, traffic := range exhaustedClients { - expiryTime := "" - flag := false - diff := (traffic.ExpiryTime - now) / 1000 - 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 - } + output += t.clientInfoMsg(&traffic, true, false, false, true, true, false) + output += "\r\n" + buttons = append(buttons, tu.InlineKeyboardButton(traffic.Email).WithCallbackData(t.encodeQuery("client_get_usage "+traffic.Email))) + } + cols := 0 + if exhaustedCC < 11 { + cols = 1 + } else { + cols = 2 + } + output += t.I18nBot("tgbot.messages.refreshedOn", "Time=="+time.Now().Format("2006-01-02 15:04:05")) + keyboard := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols, buttons...)) + t.SendMsgToTgbot(chatId, output, keyboard) + } else { + output += t.I18nBot("tgbot.messages.refreshedOn", "Time=="+time.Now().Format("2006-01-02 15:04:05")) + t.SendMsgToTgbot(chatId, output) + } +} - total := "" - if traffic.Total == 0 { - total = t.I18nBot("tgbot.unlimited") - } else { - total = common.FormatTraffic((traffic.Total)) - } +func (t *Tgbot) notifyExhausted() { + trDiff := int64(0) + exDiff := int64(0) + now := time.Now().Unix() * 1000 - 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) + TrafficThreshold, err := t.settingService.GetTrafficDiff() + if err == nil && TrafficThreshold > 0 { + trDiff = int64(TrafficThreshold) * 1073741824 + } + ExpireThreshold, err := t.settingService.GetExpireDiff() + if err == nil && ExpireThreshold > 0 { + exDiff = int64(ExpireThreshold) * 86400000 + } + inbounds, err := t.inboundService.GetAllInbounds() + if err != nil { + logger.Warning("Unable to load Inbounds", err) + } + + var chatIDsDone []string + for _, inbound := range inbounds { + if inbound.Enable { + if len(inbound.ClientStats) > 0 { + clients, err := t.inboundService.GetClients(inbound) + if err == nil { + for _, client := range clients { + if client.TgID != "" { + chatID, err := strconv.ParseInt(client.TgID, 10, 64) + if err != nil { + logger.Warning("TgID is not a number: ", client.TgID) + continue + } + if !slices.Contains(chatIDsDone, client.TgID) && !checkAdmin(chatID) { + var disabledClients []xray.ClientTraffic + var exhaustedClients []xray.ClientTraffic + traffics, err := t.inboundService.GetClientTrafficTgBot(client.TgID) + if err == nil { + output := t.I18nBot("tgbot.messages.exhaustedCount", "Type=="+t.I18nBot("tgbot.clients")) + for _, traffic := range traffics { + if traffic.Enable { + if (traffic.ExpiryTime > 0 && (traffic.ExpiryTime-now < exDiff)) || + (traffic.Total > 0 && (traffic.Total-(traffic.Up+traffic.Down) < trDiff)) { + exhaustedClients = append(exhaustedClients, *traffic) + } + } else { + disabledClients = append(disabledClients, *traffic) + } + } + if len(exhaustedClients) > 0 { + output += t.I18nBot("tgbot.messages.disabled", "Disabled=="+strconv.Itoa(len(disabledClients))) + if len(disabledClients) > 0 { + output += t.I18nBot("tgbot.clients") + ":\r\n" + for _, traffic := range disabledClients { + output += " " + traffic.Email + } + output += "\r\n" + } + output += "\r\n" + output += t.I18nBot("tgbot.messages.depleteSoon", "Deplete=="+strconv.Itoa(len(exhaustedClients))) + for _, traffic := range exhaustedClients { + output += t.clientInfoMsg(&traffic, true, false, false, true, true, false) + output += "\r\n" + } + t.SendMsgToTgbot(chatID, output) + } + chatIDsDone = append(chatIDsDone, client.TgID) + } + } + } + } } - } 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 += "\r\n \r\n" } } +} - return output +func (t *Tgbot) onlineClients(chatId int64, messageID ...int) { + if !p.IsRunning() { + return + } + + onlines := p.GetOnlineClients() + onlinesCount := len(onlines) + output := t.I18nBot("tgbot.messages.onlinesCount", "Count=="+fmt.Sprint(onlinesCount)) + keyboard := tu.InlineKeyboard(tu.InlineKeyboardRow( + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.refresh")).WithCallbackData(t.encodeQuery("onlines_refresh")))) + + + if onlinesCount > 0 { + var buttons []telego.InlineKeyboardButton + for _, online := range onlines { + buttons = append(buttons, tu.InlineKeyboardButton(online).WithCallbackData(t.encodeQuery("client_get_usage "+online))) + } + cols := 0 + if onlinesCount < 21 { + cols = 2 + } else if onlinesCount < 61 { + cols = 3 + } else { + cols = 4 + } + keyboard.InlineKeyboard = append(keyboard.InlineKeyboard, tu.InlineKeyboardCols(cols, buttons...)...) + } + + if len(messageID) > 0 { + t.editMessageTgBot(chatId, messageID[0], output, keyboard) + } else { + t.SendMsgToTgbot(chatId, output, keyboard) + } } func (t *Tgbot) sendBackup(chatId int64) { @@ -1421,33 +1497,73 @@ func (t *Tgbot) sendBackup(chatId int64) { // Update by manually trigger a checkpoint operation err := database.Checkpoint() if err != nil { - logger.Warning("Error in trigger a checkpoint operation: ", err) + logger.Error("Error in trigger a checkpoint operation: ", err) } file, err := os.Open(config.GetDBPath()) - if err != nil { - logger.Warning("Error in opening db file for backup: ", err) - } - document := tu.Document( - tu.ID(chatId), - tu.File(file), - ) - _, err = bot.SendDocument(document) - if err != nil { - logger.Warning("Error in uploading backup: ", err) + if err == nil { + document := tu.Document( + tu.ID(chatId), + tu.File(file), + ) + _, err = bot.SendDocument(document) + if err != nil { + logger.Error("Error in uploading backup: ", err) + } + } else { + logger.Error("Error in opening db file for backup: ", err) + } file, err = os.Open(xray.GetConfigPath()) - if err != nil { - logger.Warning("Error in opening config.json file for backup: ", err) + if err == nil { + document := tu.Document( + tu.ID(chatId), + tu.File(file), + ) + _, err = bot.SendDocument(document) + if err != nil { + logger.Error("Error in uploading config.json: ", err) + } + } else { + logger.Error("Error in opening config.json file for backup: ", err) } - document = tu.Document( - tu.ID(chatId), - tu.File(file), - ) - _, err = bot.SendDocument(document) - if err != nil { - logger.Warning("Error in uploading config.json: ", err) + + t.sendBanLogs(chatId, false) +} + +func (t *Tgbot) sendBanLogs(chatId int64, dt bool) { + if dt { + output := t.I18nBot("tgbot.messages.datetime", "DateTime=="+time.Now().Format("2006-01-02 15:04:05")) + t.SendMsgToTgbot(chatId, output) + } + + file, err := os.Open(xray.GetIPLimitBannedPrevLogPath()) + if err == nil { + document := tu.Document( + tu.ID(chatId), + tu.File(file), + ) + _, err = bot.SendDocument(document) + if err != nil { + logger.Error("Error in uploading backup: ", err) + } + } else { + logger.Error("Error in opening db file for backup: ", err) + } + + file, err = os.Open(xray.GetIPLimitBannedLogPath()) + if err == nil { + document := tu.Document( + tu.ID(chatId), + tu.File(file), + ) + _, err = bot.SendDocument(document) + if err != nil { + logger.Error("Error in uploading config.json: ", err) + } + } else { + logger.Error("Error in opening config.json file for backup: ", err) } } diff --git a/web/service/xray.go b/web/service/xray.go index 7233cec5..82d1cc3f 100644 --- a/web/service/xray.go +++ b/web/service/xray.go @@ -185,7 +185,7 @@ func (s *XrayService) RestartXray(isForce bool) error { return err } - if p != nil && p.IsRunning() { + if s.IsXrayRunning() { if !isForce && p.GetConfig().Equals(xrayConfig) { logger.Debug("It does not need to restart xray") return nil -- cgit v1.2.3