From ac9408c37f023b0fbe357735f1cb0915430ed596 Mon Sep 17 00:00:00 2001 From: Hamidreza Ghavami <70919649+hamid-gh98@users.noreply.github.com> Date: Sat, 20 May 2023 18:44:18 +0430 Subject: update sub remark for shadowsocks --- web/service/sub.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'web/service') diff --git a/web/service/sub.go b/web/service/sub.go index f39fdb1e..b9ea49bd 100644 --- a/web/service/sub.go +++ b/web/service/sub.go @@ -603,7 +603,8 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st } } encPart := fmt.Sprintf("%s:%s:%s", method, inboundPassword, clients[clientIndex].Password) - return fmt.Sprintf("ss://%s@%s:%d#%s", base64.StdEncoding.EncodeToString([]byte(encPart)), address, inbound.Port, clients[clientIndex].Email) + remark := fmt.Sprintf("%s-%s", inbound.Remark, clients[clientIndex].Email) + return fmt.Sprintf("ss://%s@%s:%d#%s", base64.StdEncoding.EncodeToString([]byte(encPart)), address, inbound.Port, remark) } func searchKey(data interface{}, key string) (interface{}, bool) { -- cgit v1.2.3 From 4831c2f1b2c73c1e40f23a61e728530b7cf4afe9 Mon Sep 17 00:00:00 2001 From: Hamidreza Ghavami <70919649+hamid-gh98@users.noreply.github.com> Date: Sat, 20 May 2023 19:15:20 +0430 Subject: Add tgLang option --- web/service/setting.go | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'web/service') diff --git a/web/service/setting.go b/web/service/setting.go index d3072252..fec324af 100644 --- a/web/service/setting.go +++ b/web/service/setting.go @@ -39,6 +39,7 @@ var defaultValueMap = map[string]string{ "tgRunTime": "@daily", "tgBotBackup": "false", "tgCpu": "0", + "tgLang": "en-US", "secretEnable": "false", } @@ -256,6 +257,10 @@ func (s *SettingService) GetTgCpu() (int, error) { return s.getInt("tgCpu") } +func (s *SettingService) GetTgLang() (string, error) { + return s.getString("tgLang") +} + func (s *SettingService) GetPort() (int, error) { return s.getInt("webPort") } -- cgit v1.2.3 From 678962d4ca3045bd869930efef0a196a0f8a29ba Mon Sep 17 00:00:00 2001 From: Hamidreza Ghavami <70919649+hamid-gh98@users.noreply.github.com> Date: Sat, 20 May 2023 19:39:01 +0430 Subject: some fix and prune for tgbot --- web/service/tgbot.go | 104 +++++++++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 44 deletions(-) (limited to 'web/service') diff --git a/web/service/tgbot.go b/web/service/tgbot.go index 0b301e29..72f8ae1a 100644 --- a/web/service/tgbot.go +++ b/web/service/tgbot.go @@ -81,7 +81,7 @@ func (t *Tgbot) Start() error { return nil } -func (t *Tgbot) IsRunnging() bool { +func (t *Tgbot) IsRunning() bool { return isRunning } @@ -102,19 +102,19 @@ func (t *Tgbot) OnReceive() { botHandler, _ = th.NewBotHandler(bot, updates) - botHandler.HandleMessage(func(bot *telego.Bot, message telego.Message) { + botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { t.SendMsgToTgbot(message.Chat.ID, "Custom Keyboard Closed!", tu.ReplyKeyboardRemove()) }, th.TextEqual("โŒ Close Keyboard")) - botHandler.HandleMessage(func(bot *telego.Bot, message telego.Message) { + botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { t.answerCommand(&message, message.Chat.ID, checkAdmin(message.From.ID)) }, th.AnyCommand()) - botHandler.HandleCallbackQuery(func(bot *telego.Bot, query telego.CallbackQuery) { + botHandler.HandleCallbackQuery(func(_ *telego.Bot, query telego.CallbackQuery) { t.asnwerCallback(&query, checkAdmin(query.From.ID)) }, th.AnyCallbackQueryWithMessage()) - botHandler.HandleMessage(func(bot *telego.Bot, message telego.Message) { + botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { if message.UserShared != nil { if checkAdmin(message.From.ID) { err := t.inboundService.SetClientTelegramUserID(message.UserShared.RequestID, strconv.FormatInt(message.UserShared.UserID, 10)) @@ -424,32 +424,32 @@ func (t *Tgbot) SendAnswer(chatId int64, msg string, isAdmin bool) { tu.InlineKeyboardButton("Commands").WithCallbackData("client_commands"), ), ) - params := telego.SendMessageParams{ - ChatID: tu.ID(chatId), - Text: msg, - ParseMode: "HTML", - } + var ReplyMarkup telego.ReplyMarkup if isAdmin { - params.ReplyMarkup = numericKeyboard + ReplyMarkup = numericKeyboard } else { - params.ReplyMarkup = numericKeyboardClient - } - _, err := bot.SendMessage(¶ms) - if err != nil { - logger.Warning("Error sending telegram message :", err) + ReplyMarkup = numericKeyboardClient } + t.SendMsgToTgbot(chatId, msg, ReplyMarkup) } func (t *Tgbot) SendMsgToTgbot(chatId int64, msg string, replyMarkup ...telego.ReplyMarkup) { if !isRunning { return } + if msg == "" { + logger.Info("[tgbot] message is empty!") + return + } + var allMessages []string limit := 2000 + // paging message if it is big if len(msg) > limit { messages := strings.Split(msg, "\r\n \r\n") lastIndex := -1 + for _, message := range messages { if (len(allMessages) == 0) || (len(allMessages[lastIndex])+len(message) > limit) { allMessages = append(allMessages, message) @@ -510,12 +510,12 @@ func (t *Tgbot) SendBackUP(c *gin.Context) { func (t *Tgbot) getServerUsage() string { var info string //get hostname - name, err := os.Hostname() + hostname, err := os.Hostname() if err != nil { logger.Error("get hostname error:", err) - name = "" + hostname = "" } - info = fmt.Sprintf("๐Ÿ’ป Hostname: %s\r\n", name) + info = fmt.Sprintf("๐Ÿ’ป Hostname: %s\r\n", hostname) info += fmt.Sprintf("๐Ÿš€X-UI Version: %s\r\n", config.GetVersion()) //get ip address var ip string @@ -557,25 +557,32 @@ func (t *Tgbot) getServerUsage() string { } func (t *Tgbot) UserLoginNotify(username string, ip string, time string, status LoginStatus) { + if !t.IsRunning() { + return + } + if username == "" || ip == "" || time == "" { - logger.Warning("UserLoginNotify failed,invalid info") + logger.Warning("UserLoginNotify failed, invalid info!") return } - var msg string + // Get hostname - name, err := os.Hostname() + hostname, err := os.Hostname() if err != nil { logger.Warning("get hostname error:", err) return } + + msg := "" if status == LoginSuccess { - msg = fmt.Sprintf("โœ… Successfully logged-in to the panel\r\nHostname:%s\r\n", name) + msg = fmt.Sprintf("โœ… Successfully logged-in to the panel\r\nHostname:%s\r\n", hostname) } else if status == LoginFail { - msg = fmt.Sprintf("โ— Login to the panel was unsuccessful\r\nHostname:%s\r\n", name) + msg = fmt.Sprintf("โ— Login to the panel was unsuccessful\r\nHostname:%s\r\n", hostname) } msg += fmt.Sprintf("โฐ Time:%s\r\n", time) msg += fmt.Sprintf("๐Ÿ†” Username:%s\r\n", username) msg += fmt.Sprintf("๐ŸŒ IP:%s\r\n", ip) + t.SendMsgToTgbotAdmins(msg) } @@ -686,11 +693,12 @@ func (t *Tgbot) clientTelegramUserInfo(chatId int64, email string, messageID ... t.SendMsgToTgbot(chatId, msg) return } - tdId := "None" + tgId := "None" if len(client.TgID) > 0 { - tdId = client.TgID + tgId = client.TgID } - output := fmt.Sprintf("๐Ÿ“ง Email: %s\r\n๐Ÿ‘ค Telegram User: %s\r\n", email, tdId) + + output := fmt.Sprintf("๐Ÿ“ง Email: %s\r\n๐Ÿ‘ค Telegram User: %s\r\n", email, tgId) inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( tu.InlineKeyboardButton("๐Ÿ”„ Refresh").WithCallbackData("tgid_refresh "+email), @@ -699,6 +707,7 @@ func (t *Tgbot) clientTelegramUserInfo(chatId int64, email string, messageID ... tu.InlineKeyboardButton("โŒ Remove Telegram User").WithCallbackData("tgid_remove "+email), ), ) + if len(messageID) > 0 { t.editMessageTgBot(chatId, messageID[0], output, inlineKeyboard) } else { @@ -732,6 +741,7 @@ func (t *Tgbot) searchClient(chatId int64, email string, messageID ...int) { t.SendMsgToTgbot(chatId, msg) return } + expiryTime := "" if traffic.ExpiryTime == 0 { expiryTime = "โ™พUnlimited" @@ -740,15 +750,18 @@ func (t *Tgbot) searchClient(chatId int64, email string, messageID ...int) { } else { expiryTime = time.Unix((traffic.ExpiryTime / 1000), 0).Format("2006-01-02 15:04:05") } + total := "" if traffic.Total == 0 { total = "โ™พUnlimited" } else { total = common.FormatTraffic((traffic.Total)) } + output := fmt.Sprintf("๐Ÿ’ก Active: %t\r\n๐Ÿ“ง Email: %s\r\n๐Ÿ”ผ Uploadโ†‘: %s\r\n๐Ÿ”ฝ Downloadโ†“: %s\r\n๐Ÿ”„ Total: %s / %s\r\n๐Ÿ“… Expire in: %s\r\n", traffic.Enable, traffic.Email, common.FormatTraffic(traffic.Up), common.FormatTraffic(traffic.Down), common.FormatTraffic((traffic.Up + traffic.Down)), total, expiryTime) + inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( tu.InlineKeyboardButton("๐Ÿ”„ Refresh").WithCallbackData("client_refresh "+email), @@ -770,6 +783,7 @@ func (t *Tgbot) searchClient(chatId int64, email string, messageID ...int) { tu.InlineKeyboardButton("๐Ÿ”˜ Enable / Disable").WithCallbackData("toggle_enable "+email), ), ) + if len(messageID) > 0 { t.editMessageTgBot(chatId, messageID[0], output, inlineKeyboard) } else { @@ -785,6 +799,12 @@ func (t *Tgbot) searchInbound(chatId int64, remark string) { t.SendMsgToTgbot(chatId, msg) return } + if len(inbouds) == 0 { + msg := "โŒ No inbounds found!" + t.SendMsgToTgbot(chatId, msg) + return + } + for _, inbound := range inbouds { info := "" info += fmt.Sprintf("๐Ÿ“Inbound:%s\r\nPort:%d\r\n", inbound.Remark, inbound.Port) @@ -795,6 +815,7 @@ func (t *Tgbot) searchInbound(chatId int64, remark string) { info += fmt.Sprintf("Expire date:%s\r\n \r\n", time.Unix((inbound.ExpiryTime/1000), 0).Format("2006-01-02 15:04:05")) } t.SendMsgToTgbot(chatId, info) + for _, traffic := range inbound.ClientStats { expiryTime := "" if traffic.ExpiryTime == 0 { @@ -804,6 +825,7 @@ func (t *Tgbot) searchInbound(chatId int64, remark string) { } else { expiryTime = time.Unix((traffic.ExpiryTime / 1000), 0).Format("2006-01-02 15:04:05") } + total := "" if traffic.Total == 0 { total = "โ™พUnlimited" @@ -831,6 +853,7 @@ func (t *Tgbot) searchForClient(chatId int64, query string) { t.SendMsgToTgbot(chatId, msg) return } + expiryTime := "" if traffic.ExpiryTime == 0 { expiryTime = "โ™พUnlimited" @@ -839,12 +862,14 @@ func (t *Tgbot) searchForClient(chatId int64, query string) { } else { expiryTime = time.Unix((traffic.ExpiryTime / 1000), 0).Format("2006-01-02 15:04:05") } + total := "" if traffic.Total == 0 { total = "โ™พUnlimited" } else { total = common.FormatTraffic((traffic.Total)) } + output := fmt.Sprintf("๐Ÿ’ก Active: %t\r\n๐Ÿ“ง Email: %s\r\n๐Ÿ”ผ Uploadโ†‘: %s\r\n๐Ÿ”ฝ Downloadโ†“: %s\r\n๐Ÿ”„ Total: %s / %s\r\n๐Ÿ“… Expire in: %s\r\n", traffic.Enable, traffic.Email, common.FormatTraffic(traffic.Up), common.FormatTraffic(traffic.Down), common.FormatTraffic((traffic.Up + traffic.Down)), total, expiryTime) @@ -859,6 +884,7 @@ func (t *Tgbot) getExhausted() string { var exhaustedClients []xray.ClientTraffic var disabledInbounds []model.Inbound var disabledClients []xray.ClientTraffic + output := "" TrafficThreshold, err := t.settingService.GetTrafficDiff() if err == nil && TrafficThreshold > 0 { @@ -872,6 +898,7 @@ func (t *Tgbot) getExhausted() string { if err != nil { logger.Warning("Unable to load Inbounds", err) } + for _, inbound := range inbounds { if inbound.Enable { if (inbound.ExpiryTime > 0 && (inbound.ExpiryTime-now < exDiff)) || @@ -894,6 +921,7 @@ func (t *Tgbot) getExhausted() string { disabledInbounds = append(disabledInbounds, *inbound) } } + output += fmt.Sprintf("Exhausted Inbounds count:\r\n๐Ÿ›‘ Disabled: %d\r\n๐Ÿ”œ Deplete soon: %d\r\n \r\n", len(disabledInbounds), len(exhaustedInbounds)) if len(exhaustedInbounds) > 0 { output += "Exhausted Inbounds:\r\n" @@ -906,6 +934,7 @@ func (t *Tgbot) getExhausted() string { } } } + output += fmt.Sprintf("Exhausted Clients count:\r\n๐Ÿ›‘ Exhausted: %d\r\n๐Ÿ”œ Deplete soon: %d\r\n \r\n", len(disabledClients), len(exhaustedClients)) if len(exhaustedClients) > 0 { output += "Exhausted Clients:\r\n" @@ -934,6 +963,10 @@ func (t *Tgbot) getExhausted() string { } func (t *Tgbot) sendBackup(chatId int64) { + if !t.IsRunning() { + return + } + sendingTime := time.Now().Format("2006-01-02 15:04:05") t.SendMsgToTgbot(chatId, "Backup time: "+sendingTime) file, err := os.Open(config.GetDBPath()) @@ -997,20 +1030,3 @@ func (t *Tgbot) editMessageTgBot(chatId int64, messageID int, text string, inlin logger.Warning(err) } } - -func fromChat(u *telego.Update) *telego.Chat { - switch { - case u.Message != nil: - return &u.Message.Chat - case u.EditedMessage != nil: - return &u.EditedMessage.Chat - case u.ChannelPost != nil: - return &u.ChannelPost.Chat - case u.EditedChannelPost != nil: - return &u.EditedChannelPost.Chat - case u.CallbackQuery != nil: - return &u.CallbackQuery.Message.Chat - default: - return nil - } -} -- cgit v1.2.3 From 4dfe527f203cbae9b90e77e876fcfd90803bcb26 Mon Sep 17 00:00:00 2001 From: Hamidreza Ghavami <70919649+hamid-gh98@users.noreply.github.com> Date: Sat, 20 May 2023 20:08:01 +0430 Subject: init i18n in tgbot --- web/service/tgbot.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'web/service') diff --git a/web/service/tgbot.go b/web/service/tgbot.go index 72f8ae1a..3dcb6df0 100644 --- a/web/service/tgbot.go +++ b/web/service/tgbot.go @@ -1,6 +1,7 @@ package service import ( + "embed" "fmt" "net" "os" @@ -11,6 +12,7 @@ import ( "x-ui/database/model" "x-ui/logger" "x-ui/util/common" + "x-ui/web/locale" "x-ui/xray" "github.com/gin-gonic/gin" @@ -43,7 +45,16 @@ func (t *Tgbot) NewTgbot() *Tgbot { return new(Tgbot) } -func (t *Tgbot) Start() error { +func (t *Tgbot) BotI18n(name string, params ...string) string { + return locale.I18n(locale.Bot, name, params...) +} + +func (t *Tgbot) Start(i18nFS embed.FS) error { + err := locale.InitLocalizer(i18nFS, &t.settingService) + if err != nil { + return err + } + tgBottoken, err := t.settingService.GetTgBotToken() if err != nil || tgBottoken == "" { logger.Warning("Get TgBotToken failed:", err) -- cgit v1.2.3 From 8c5648eb09b0d6d1479f102156e8a548ed478caa Mon Sep 17 00:00:00 2001 From: Hamidreza Ghavami <70919649+hamid-gh98@users.noreply.github.com> Date: Sat, 20 May 2023 20:29:28 +0430 Subject: FIX callback query and BUTTON_DATA_INVALID error with hashStorage --- web/service/tgbot.go | 106 ++++++++++++++++++++++++++++----------------------- 1 file changed, 59 insertions(+), 47 deletions(-) (limited to 'web/service') diff --git a/web/service/tgbot.go b/web/service/tgbot.go index 3dcb6df0..8777cbbd 100644 --- a/web/service/tgbot.go +++ b/web/service/tgbot.go @@ -12,6 +12,7 @@ import ( "x-ui/database/model" "x-ui/logger" "x-ui/util/common" + "x-ui/web/global" "x-ui/web/locale" "x-ui/xray" @@ -39,6 +40,7 @@ type Tgbot struct { serverService ServerService xrayService XrayService lastStatus *Status + hashStorage *global.HashStorage } func (t *Tgbot) NewTgbot() *Tgbot { @@ -49,12 +51,19 @@ func (t *Tgbot) BotI18n(name string, params ...string) string { return locale.I18n(locale.Bot, name, params...) } +func (t *Tgbot) GetHashStorage() *global.HashStorage { + return t.hashStorage +} + func (t *Tgbot) Start(i18nFS embed.FS) error { err := locale.InitLocalizer(i18nFS, &t.settingService) if err != nil { return err } + // init hash storage + t.hashStorage = global.NewHashStorage(5*time.Minute, false) + tgBottoken, err := t.settingService.GetTgBotToken() if err != nil || tgBottoken == "" { logger.Warning("Get TgBotToken failed:", err) @@ -190,7 +199,10 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool chatId := callbackQuery.Message.Chat.ID if isAdmin { - dataArray := strings.Split(callbackQuery.Data, " ") + // get query from hash storage (if the query was <= 64 chars hash storage dont save the hash and return data itself) + decodedQuery := t.hashStorage.GetValue(callbackQuery.Data) + dataArray := strings.Split(decodedQuery, " ") + if len(dataArray) >= 2 && len(dataArray[1]) > 0 { email := dataArray[1] switch dataArray[0] { @@ -215,10 +227,10 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool case "reset_traffic": inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โŒ Cancel Reset").WithCallbackData("client_cancel "+email), + tu.InlineKeyboardButton("โŒ Cancel Reset").WithCallbackData(t.hashStorage.AddHash("client_cancel "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โœ… Confirm Reset Traffic?").WithCallbackData("reset_traffic_c "+email), + tu.InlineKeyboardButton("โœ… Confirm Reset Traffic?").WithCallbackData(t.hashStorage.AddHash("reset_traffic_c "+email)), ), ) t.editMessageCallbackTgBot(chatId, callbackQuery.Message.MessageID, inlineKeyboard) @@ -234,26 +246,26 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool case "reset_exp": var inlineKeyboard = tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โŒ Cancel Reset").WithCallbackData("client_cancel "+email), + tu.InlineKeyboardButton("โŒ Cancel Reset").WithCallbackData(t.hashStorage.AddHash("client_cancel "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โ™พ Unlimited").WithCallbackData("reset_exp_c "+email+" 0"), + tu.InlineKeyboardButton("โ™พ Unlimited").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 0")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("1 Month").WithCallbackData("reset_exp_c "+email+" 30"), - tu.InlineKeyboardButton("2 Months").WithCallbackData("reset_exp_c "+email+" 60"), + tu.InlineKeyboardButton("1 Month").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 30")), + tu.InlineKeyboardButton("2 Months").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 60")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("3 Months").WithCallbackData("reset_exp_c "+email+" 90"), - tu.InlineKeyboardButton("6 Months").WithCallbackData("reset_exp_c "+email+" 180"), + tu.InlineKeyboardButton("3 Months").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 90")), + tu.InlineKeyboardButton("6 Months").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 180")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("9 Months").WithCallbackData("reset_exp_c "+email+" 270"), - tu.InlineKeyboardButton("12 Months").WithCallbackData("reset_exp_c "+email+" 360"), + tu.InlineKeyboardButton("9 Months").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 270")), + tu.InlineKeyboardButton("12 Months").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 360")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("10 Days").WithCallbackData("reset_exp_c "+email+" 10"), - tu.InlineKeyboardButton("20 Days").WithCallbackData("reset_exp_c "+email+" 20"), + tu.InlineKeyboardButton("10 Days").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 10")), + tu.InlineKeyboardButton("20 Days").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 20")), ), ) t.editMessageCallbackTgBot(chatId, callbackQuery.Message.MessageID, inlineKeyboard) @@ -279,28 +291,28 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool case "ip_limit": inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โŒ Cancel IP Limit").WithCallbackData("client_cancel "+email), + tu.InlineKeyboardButton("โŒ Cancel IP Limit").WithCallbackData(t.hashStorage.AddHash("client_cancel "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โ™พ Unlimited").WithCallbackData("ip_limit_c "+email+" 0"), + tu.InlineKeyboardButton("โ™พ Unlimited").WithCallbackData(t.hashStorage.AddHash("ip_limit_c "+email+" 0")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("1").WithCallbackData("ip_limit_c "+email+" 1"), - tu.InlineKeyboardButton("2").WithCallbackData("ip_limit_c "+email+" 2"), + tu.InlineKeyboardButton("1").WithCallbackData(t.hashStorage.AddHash("ip_limit_c "+email+" 1")), + tu.InlineKeyboardButton("2").WithCallbackData(t.hashStorage.AddHash("ip_limit_c "+email+" 2")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("3").WithCallbackData("ip_limit_c "+email+" 3"), - tu.InlineKeyboardButton("4").WithCallbackData("ip_limit_c "+email+" 4"), + tu.InlineKeyboardButton("3").WithCallbackData(t.hashStorage.AddHash("ip_limit_c "+email+" 3")), + tu.InlineKeyboardButton("4").WithCallbackData(t.hashStorage.AddHash("ip_limit_c "+email+" 4")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("5").WithCallbackData("ip_limit_c "+email+" 5"), - tu.InlineKeyboardButton("6").WithCallbackData("ip_limit_c "+email+" 6"), - tu.InlineKeyboardButton("7").WithCallbackData("ip_limit_c "+email+" 7"), + tu.InlineKeyboardButton("5").WithCallbackData(t.hashStorage.AddHash("ip_limit_c "+email+" 5")), + tu.InlineKeyboardButton("6").WithCallbackData(t.hashStorage.AddHash("ip_limit_c "+email+" 6")), + tu.InlineKeyboardButton("7").WithCallbackData(t.hashStorage.AddHash("ip_limit_c "+email+" 7")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("8").WithCallbackData("ip_limit_c "+email+" 8"), - tu.InlineKeyboardButton("9").WithCallbackData("ip_limit_c "+email+" 9"), - tu.InlineKeyboardButton("10").WithCallbackData("ip_limit_c "+email+" 10"), + tu.InlineKeyboardButton("8").WithCallbackData(t.hashStorage.AddHash("ip_limit_c "+email+" 8")), + tu.InlineKeyboardButton("9").WithCallbackData(t.hashStorage.AddHash("ip_limit_c "+email+" 9")), + tu.InlineKeyboardButton("10").WithCallbackData(t.hashStorage.AddHash("ip_limit_c "+email+" 10")), ), ) t.editMessageCallbackTgBot(chatId, callbackQuery.Message.MessageID, inlineKeyboard) @@ -322,10 +334,10 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool case "clear_ips": inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โŒ Cancel").WithCallbackData("ips_cancel "+email), + tu.InlineKeyboardButton("โŒ Cancel").WithCallbackData(t.hashStorage.AddHash("ips_cancel "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โœ… Confirm Clear IPs?").WithCallbackData("clear_ips_c "+email), + tu.InlineKeyboardButton("โœ… Confirm Clear IPs?").WithCallbackData(t.hashStorage.AddHash("clear_ips_c "+email)), ), ) t.editMessageCallbackTgBot(chatId, callbackQuery.Message.MessageID, inlineKeyboard) @@ -346,10 +358,10 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool case "tgid_remove": inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โŒ Cancel").WithCallbackData("tgid_cancel "+email), + tu.InlineKeyboardButton("โŒ Cancel").WithCallbackData(t.hashStorage.AddHash("tgid_cancel "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โœ… Confirm Remove Telegram User?").WithCallbackData("tgid_remove_c "+email), + tu.InlineKeyboardButton("โœ… Confirm Remove Telegram User?").WithCallbackData(t.hashStorage.AddHash("tgid_remove_c "+email)), ), ) t.editMessageCallbackTgBot(chatId, callbackQuery.Message.MessageID, inlineKeyboard) @@ -418,21 +430,21 @@ func checkAdmin(tgId int64) bool { func (t *Tgbot) SendAnswer(chatId int64, msg string, isAdmin bool) { numericKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("Server Usage").WithCallbackData("get_usage"), - tu.InlineKeyboardButton("Get DB Backup").WithCallbackData("get_backup"), + tu.InlineKeyboardButton("Server Usage").WithCallbackData(t.hashStorage.AddHash("get_usage")), + tu.InlineKeyboardButton("Get DB Backup").WithCallbackData(t.hashStorage.AddHash("get_backup")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("Get Inbounds").WithCallbackData("inbounds"), - tu.InlineKeyboardButton("Deplete soon").WithCallbackData("deplete_soon"), + tu.InlineKeyboardButton("Get Inbounds").WithCallbackData(t.hashStorage.AddHash("inbounds")), + tu.InlineKeyboardButton("Deplete soon").WithCallbackData(t.hashStorage.AddHash("deplete_soon")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("Commands").WithCallbackData("commands"), + tu.InlineKeyboardButton("Commands").WithCallbackData(t.hashStorage.AddHash("commands")), ), ) numericKeyboardClient := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("Get Usage").WithCallbackData("client_traffic"), - tu.InlineKeyboardButton("Commands").WithCallbackData("client_commands"), + tu.InlineKeyboardButton("Get Usage").WithCallbackData(t.hashStorage.AddHash("client_traffic")), + tu.InlineKeyboardButton("Commands").WithCallbackData(t.hashStorage.AddHash("client_commands")), ), ) var ReplyMarkup telego.ReplyMarkup @@ -678,10 +690,10 @@ func (t *Tgbot) searchClientIps(chatId int64, email string, messageID ...int) { output := fmt.Sprintf("๐Ÿ“ง Email: %s\r\n๐Ÿ”ข IPs: \r\n%s\r\n", email, ips) inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("๐Ÿ”„ Refresh").WithCallbackData("ips_refresh "+email), + tu.InlineKeyboardButton("๐Ÿ”„ Refresh").WithCallbackData(t.hashStorage.AddHash("ips_refresh "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โŒ Clear IPs").WithCallbackData("clear_ips "+email), + tu.InlineKeyboardButton("โŒ Clear IPs").WithCallbackData(t.hashStorage.AddHash("clear_ips "+email)), ), ) if len(messageID) > 0 { @@ -712,10 +724,10 @@ func (t *Tgbot) clientTelegramUserInfo(chatId int64, email string, messageID ... output := fmt.Sprintf("๐Ÿ“ง Email: %s\r\n๐Ÿ‘ค Telegram User: %s\r\n", email, tgId) inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("๐Ÿ”„ Refresh").WithCallbackData("tgid_refresh "+email), + tu.InlineKeyboardButton("๐Ÿ”„ Refresh").WithCallbackData(t.hashStorage.AddHash("tgid_refresh "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โŒ Remove Telegram User").WithCallbackData("tgid_remove "+email), + tu.InlineKeyboardButton("โŒ Remove Telegram User").WithCallbackData(t.hashStorage.AddHash("tgid_remove "+email)), ), ) @@ -775,23 +787,23 @@ func (t *Tgbot) searchClient(chatId int64, email string, messageID ...int) { inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("๐Ÿ”„ Refresh").WithCallbackData("client_refresh "+email), + tu.InlineKeyboardButton("๐Ÿ”„ Refresh").WithCallbackData(t.hashStorage.AddHash("client_refresh "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("๐Ÿ“ˆ Reset Traffic").WithCallbackData("reset_traffic "+email), + tu.InlineKeyboardButton("๐Ÿ“ˆ Reset Traffic").WithCallbackData(t.hashStorage.AddHash("reset_traffic "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("๐Ÿ“… Reset Expire Days").WithCallbackData("reset_exp "+email), + tu.InlineKeyboardButton("๐Ÿ“… Reset Expire Days").WithCallbackData(t.hashStorage.AddHash("reset_exp "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("๐Ÿ”ข IP Log").WithCallbackData("ip_log "+email), - tu.InlineKeyboardButton("๐Ÿ”ข IP Limit").WithCallbackData("ip_limit "+email), + tu.InlineKeyboardButton("๐Ÿ”ข IP Log").WithCallbackData(t.hashStorage.AddHash("ip_log "+email)), + tu.InlineKeyboardButton("๐Ÿ”ข IP Limit").WithCallbackData(t.hashStorage.AddHash("ip_limit "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("๐Ÿ‘ค Set Telegram User").WithCallbackData("tg_user "+email), + tu.InlineKeyboardButton("๐Ÿ‘ค Set Telegram User").WithCallbackData(t.hashStorage.AddHash("tg_user "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("๐Ÿ”˜ Enable / Disable").WithCallbackData("toggle_enable "+email), + tu.InlineKeyboardButton("๐Ÿ”˜ Enable / Disable").WithCallbackData(t.hashStorage.AddHash("toggle_enable "+email)), ), ) -- cgit v1.2.3 From 786a3ac992043e1e1ca398d4b408e34d9ae46973 Mon Sep 17 00:00:00 2001 From: Hamidreza Ghavami <70919649+hamid-gh98@users.noreply.github.com> Date: Sat, 20 May 2023 21:46:42 +0430 Subject: FIX hashStorage --- web/service/tgbot.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'web/service') diff --git a/web/service/tgbot.go b/web/service/tgbot.go index 8777cbbd..fa9ccb1d 100644 --- a/web/service/tgbot.go +++ b/web/service/tgbot.go @@ -61,8 +61,9 @@ func (t *Tgbot) Start(i18nFS embed.FS) error { return err } - // init hash storage - t.hashStorage = global.NewHashStorage(5*time.Minute, false) + // init hash storage => store callback queries + // NOTE: it only save the query if its length is more than 64 chars. + t.hashStorage = global.NewHashStorage(20*time.Minute, false) tgBottoken, err := t.settingService.GetTgBotToken() if err != nil || tgBottoken == "" { @@ -199,8 +200,12 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool chatId := callbackQuery.Message.Chat.ID if isAdmin { - // get query from hash storage (if the query was <= 64 chars hash storage dont save the hash and return data itself) - decodedQuery := t.hashStorage.GetValue(callbackQuery.Data) + // get query from hash storage + decodedQuery, err := t.hashStorage.GetValue(callbackQuery.Data) + if err != nil { + t.SendMsgToTgbot(chatId, "Query not found! Please use the command again!") + return + } dataArray := strings.Split(decodedQuery, " ") if len(dataArray) >= 2 && len(dataArray[1]) > 0 { -- cgit v1.2.3 From 82ead0509359aa364cc188ef7f22e74cd45fe347 Mon Sep 17 00:00:00 2001 From: Hamidreza Ghavami <70919649+hamid-gh98@users.noreply.github.com> Date: Sun, 21 May 2023 03:30:26 +0430 Subject: Update tgbot locale + add I18nBot --- web/service/tgbot.go | 444 +++++++++++++++++++++++++++++---------------------- 1 file changed, 252 insertions(+), 192 deletions(-) (limited to 'web/service') diff --git a/web/service/tgbot.go b/web/service/tgbot.go index fa9ccb1d..ea42793f 100644 --- a/web/service/tgbot.go +++ b/web/service/tgbot.go @@ -16,7 +16,6 @@ import ( "x-ui/web/locale" "x-ui/xray" - "github.com/gin-gonic/gin" "github.com/mymmrac/telego" th "github.com/mymmrac/telego/telegohandler" tu "github.com/mymmrac/telego/telegoutil" @@ -26,6 +25,7 @@ var bot *telego.Bot var botHandler *th.BotHandler var adminIds []int64 var isRunning bool +var hostname string type LoginStatus byte @@ -47,7 +47,7 @@ func (t *Tgbot) NewTgbot() *Tgbot { return new(Tgbot) } -func (t *Tgbot) BotI18n(name string, params ...string) string { +func (t *Tgbot) I18nBot(name string, params ...string) string { return locale.I18n(locale.Bot, name, params...) } @@ -65,6 +65,7 @@ func (t *Tgbot) Start(i18nFS embed.FS) error { // NOTE: it only save the query if its length is more than 64 chars. t.hashStorage = global.NewHashStorage(20*time.Minute, false) + t.SetHostname() tgBottoken, err := t.settingService.GetTgBotToken() if err != nil || tgBottoken == "" { logger.Warning("Get TgBotToken failed:", err) @@ -106,6 +107,16 @@ func (t *Tgbot) IsRunning() bool { return isRunning } +func (t *Tgbot) SetHostname() { + host, err := os.Hostname() + if err != nil { + logger.Error("get hostname error:", err) + hostname = "" + return + } + hostname = host +} + func (t *Tgbot) Stop() { botHandler.Stop() bot.StopLongPolling() @@ -124,8 +135,8 @@ func (t *Tgbot) OnReceive() { botHandler, _ = th.NewBotHandler(bot, updates) botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { - t.SendMsgToTgbot(message.Chat.ID, "Custom Keyboard Closed!", tu.ReplyKeyboardRemove()) - }, th.TextEqual("โŒ Close Keyboard")) + t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.keyboardClosed"), tu.ReplyKeyboardRemove()) + }, th.TextEqual(t.I18nBot("tgbot.buttons.closeKeyboard"))) botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { t.answerCommand(&message, message.Chat.ID, checkAdmin(message.From.ID)) @@ -139,15 +150,15 @@ func (t *Tgbot) OnReceive() { if message.UserShared != nil { if checkAdmin(message.From.ID) { err := t.inboundService.SetClientTelegramUserID(message.UserShared.RequestID, strconv.FormatInt(message.UserShared.UserID, 10)) - var output string + output := "" if err != nil { - output = "โŒ Error in user selection!" + output += t.I18nBot("tgbot.messages.selectUserFailed") } else { - output = "โœ… Telegram User saved." + output += t.I18nBot("tgbot.messages.userSaved") } t.SendMsgToTgbot(message.Chat.ID, output, tu.ReplyKeyboardRemove()) } else { - t.SendMsgToTgbot(message.Chat.ID, "No result!", tu.ReplyKeyboardRemove()) + t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.noResult"), tu.ReplyKeyboardRemove()) } } }, th.AnyMessage()) @@ -163,16 +174,16 @@ func (t *Tgbot) answerCommand(message *telego.Message, chatId int64, isAdmin boo // Extract the command from the Message. switch command { case "help": - msg = "This bot is providing you some specefic data from the server.\n\n Please choose:" + msg += t.I18nBot("tgbot.commands.help") + msg += t.I18nBot("tgbot.commands.pleaseChoose") case "start": - msg = "Hello " + message.From.FirstName + " ๐Ÿ‘‹" + msg += t.I18nBot("tgbot.commands.start", "Firstname=="+message.From.FirstName) if isAdmin { - hostname, _ := os.Hostname() - msg += "\nWelcome to " + hostname + " management bot" + msg += t.I18nBot("tgbot.commands.welcome", "Hostname=="+hostname) } - msg += "\n\nI can do some magics for you, please choose:" + msg += "\n\n" + t.I18nBot("tgbot.commands.pleaseChoose") case "status": - msg = "bot is ok โœ…" + msg += t.I18nBot("tgbot.commands.status") case "usage": if len(commandArgs) > 0 { if isAdmin { @@ -181,16 +192,16 @@ func (t *Tgbot) answerCommand(message *telego.Message, chatId int64, isAdmin boo t.searchForClient(chatId, commandArgs[0]) } } else { - msg = "โ—Please provide a text for search!" + msg += t.I18nBot("tgbot.commands.usage") } case "inbound": if isAdmin && len(commandArgs) > 0 { t.searchInbound(chatId, commandArgs[0]) } else { - msg = "โ— Unknown command" + msg += t.I18nBot("tgbot.commands.unknown") } default: - msg = "โ— Unknown command" + msg += t.I18nBot("tgbot.commands.unknown") } t.SendAnswer(chatId, msg, isAdmin) } @@ -203,7 +214,7 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool // get query from hash storage decodedQuery, err := t.hashStorage.GetValue(callbackQuery.Data) if err != nil { - t.SendMsgToTgbot(chatId, "Query not found! Please use the command again!") + t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.noQuery")) return } dataArray := strings.Split(decodedQuery, " ") @@ -212,30 +223,30 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool email := dataArray[1] switch dataArray[0] { case "client_refresh": - t.sendCallbackAnswerTgBot(callbackQuery.ID, fmt.Sprintf("โœ… %s : Client refreshed successfully.", email)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.clientRefreshSuccess", "Email=="+email)) t.searchClient(chatId, email, callbackQuery.Message.MessageID) case "client_cancel": - t.sendCallbackAnswerTgBot(callbackQuery.ID, fmt.Sprintf("โŒ %s : Operation canceled.", email)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+email)) t.searchClient(chatId, email, callbackQuery.Message.MessageID) case "ips_refresh": - t.sendCallbackAnswerTgBot(callbackQuery.ID, fmt.Sprintf("โœ… %s : IPs refreshed successfully.", email)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.IpRefreshSuccess", "Email=="+email)) t.searchClientIps(chatId, email, callbackQuery.Message.MessageID) case "ips_cancel": - t.sendCallbackAnswerTgBot(callbackQuery.ID, fmt.Sprintf("โŒ %s : Operation canceled.", email)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+email)) t.searchClientIps(chatId, email, callbackQuery.Message.MessageID) case "tgid_refresh": - t.sendCallbackAnswerTgBot(callbackQuery.ID, fmt.Sprintf("โœ… %s : Client's Telegram User refreshed successfully.", email)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.TGIdRefreshSuccess", "Email=="+email)) t.clientTelegramUserInfo(chatId, email, callbackQuery.Message.MessageID) case "tgid_cancel": - t.sendCallbackAnswerTgBot(callbackQuery.ID, fmt.Sprintf("โŒ %s : Operation canceled.", email)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+email)) t.clientTelegramUserInfo(chatId, email, callbackQuery.Message.MessageID) case "reset_traffic": inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โŒ Cancel Reset").WithCallbackData(t.hashStorage.AddHash("client_cancel "+email)), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancelReset")).WithCallbackData(t.hashStorage.AddHash("client_cancel "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โœ… Confirm Reset Traffic?").WithCallbackData(t.hashStorage.AddHash("reset_traffic_c "+email)), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmResetTraffic")).WithCallbackData(t.hashStorage.AddHash("reset_traffic_c "+email)), ), ) t.editMessageCallbackTgBot(chatId, callbackQuery.Message.MessageID, inlineKeyboard) @@ -243,34 +254,34 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool err := t.inboundService.ResetClientTrafficByEmail(email) if err == nil { t.xrayService.SetToNeedRestart() - t.sendCallbackAnswerTgBot(callbackQuery.ID, fmt.Sprintf("โœ… %s : Traffic reset successfully.", email)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.resetTrafficSuccess", "Email=="+email)) t.searchClient(chatId, email, callbackQuery.Message.MessageID) } else { - t.sendCallbackAnswerTgBot(callbackQuery.ID, "โ— Error in Operation.") + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) } case "reset_exp": - var inlineKeyboard = tu.InlineKeyboard( + inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โŒ Cancel Reset").WithCallbackData(t.hashStorage.AddHash("client_cancel "+email)), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancelReset")).WithCallbackData(t.hashStorage.AddHash("client_cancel "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โ™พ Unlimited").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 0")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 0")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("1 Month").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 30")), - tu.InlineKeyboardButton("2 Months").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 60")), + tu.InlineKeyboardButton("1 "+t.I18nBot("tgbot.month")).WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 30")), + tu.InlineKeyboardButton("2 "+t.I18nBot("tgbot.months")).WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 60")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("3 Months").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 90")), - tu.InlineKeyboardButton("6 Months").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 180")), + tu.InlineKeyboardButton("3 "+t.I18nBot("tgbot.months")).WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 90")), + tu.InlineKeyboardButton("6 "+t.I18nBot("tgbot.months")).WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 180")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("9 Months").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 270")), - tu.InlineKeyboardButton("12 Months").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 360")), + tu.InlineKeyboardButton("9 "+t.I18nBot("tgbot.months")).WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 270")), + tu.InlineKeyboardButton("12 "+t.I18nBot("tgbot.months")).WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 360")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("10 Days").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 10")), - tu.InlineKeyboardButton("20 Days").WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 20")), + tu.InlineKeyboardButton("10 "+t.I18nBot("tgbot.days")).WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 10")), + tu.InlineKeyboardButton("20 "+t.I18nBot("tgbot.days")).WithCallbackData(t.hashStorage.AddHash("reset_exp_c "+email+" 20")), ), ) t.editMessageCallbackTgBot(chatId, callbackQuery.Message.MessageID, inlineKeyboard) @@ -285,21 +296,21 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool err := t.inboundService.ResetClientExpiryTimeByEmail(email, date) if err == nil { t.xrayService.SetToNeedRestart() - t.sendCallbackAnswerTgBot(callbackQuery.ID, fmt.Sprintf("โœ… %s : Expire days reset successfully.", email)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.expireResetSuccess", "Email=="+email)) t.searchClient(chatId, email, callbackQuery.Message.MessageID) return } } } - t.sendCallbackAnswerTgBot(callbackQuery.ID, "โ— Error in Operation.") + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) t.searchClient(chatId, email, callbackQuery.Message.MessageID) case "ip_limit": inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โŒ Cancel IP Limit").WithCallbackData(t.hashStorage.AddHash("client_cancel "+email)), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancelIpLimit")).WithCallbackData(t.hashStorage.AddHash("client_cancel "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โ™พ Unlimited").WithCallbackData(t.hashStorage.AddHash("ip_limit_c "+email+" 0")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.hashStorage.AddHash("ip_limit_c "+email+" 0")), ), tu.InlineKeyboardRow( tu.InlineKeyboardButton("1").WithCallbackData(t.hashStorage.AddHash("ip_limit_c "+email+" 1")), @@ -328,73 +339,73 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool err := t.inboundService.ResetClientIpLimitByEmail(email, count) if err == nil { t.xrayService.SetToNeedRestart() - t.sendCallbackAnswerTgBot(callbackQuery.ID, fmt.Sprintf("โœ… %s : IP limit %d saved successfully.", email, count)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.resetIpSuccess", "Email=="+email, "Count=="+strconv.Itoa(count))) t.searchClient(chatId, email, callbackQuery.Message.MessageID) return } } } - t.sendCallbackAnswerTgBot(callbackQuery.ID, "โ— Error in Operation.") + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) t.searchClient(chatId, email, callbackQuery.Message.MessageID) case "clear_ips": inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โŒ Cancel").WithCallbackData(t.hashStorage.AddHash("ips_cancel "+email)), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.hashStorage.AddHash("ips_cancel "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โœ… Confirm Clear IPs?").WithCallbackData(t.hashStorage.AddHash("clear_ips_c "+email)), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmClearIps")).WithCallbackData(t.hashStorage.AddHash("clear_ips_c "+email)), ), ) t.editMessageCallbackTgBot(chatId, callbackQuery.Message.MessageID, inlineKeyboard) case "clear_ips_c": err := t.inboundService.ClearClientIps(email) if err == nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, fmt.Sprintf("โœ… %s : IPs cleared successfully.", email)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.clearIpSuccess", "Email=="+email)) t.searchClientIps(chatId, email, callbackQuery.Message.MessageID) } else { - t.sendCallbackAnswerTgBot(callbackQuery.ID, "โ— Error in Operation.") + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) } case "ip_log": - t.sendCallbackAnswerTgBot(callbackQuery.ID, fmt.Sprintf("โœ… %s : Get IP Log.", email)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.getIpLog", "Email=="+email)) t.searchClientIps(chatId, email) case "tg_user": - t.sendCallbackAnswerTgBot(callbackQuery.ID, fmt.Sprintf("โœ… %s : Get Telegram User Info.", email)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.getUserInfo", "Email=="+email)) t.clientTelegramUserInfo(chatId, email) case "tgid_remove": inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โŒ Cancel").WithCallbackData(t.hashStorage.AddHash("tgid_cancel "+email)), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.hashStorage.AddHash("tgid_cancel "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โœ… Confirm Remove Telegram User?").WithCallbackData(t.hashStorage.AddHash("tgid_remove_c "+email)), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmRemoveTGUser")).WithCallbackData(t.hashStorage.AddHash("tgid_remove_c "+email)), ), ) t.editMessageCallbackTgBot(chatId, callbackQuery.Message.MessageID, inlineKeyboard) case "tgid_remove_c": traffic, err := t.inboundService.GetClientTrafficByEmail(email) if err != nil || traffic == nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, "โ— Error in Operation.") + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) return } err = t.inboundService.SetClientTelegramUserID(traffic.Id, "") if err == nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, fmt.Sprintf("โœ… %s : Telegram User removed successfully.", email)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.removedTGUserSuccess", "Email=="+email)) t.clientTelegramUserInfo(chatId, email, callbackQuery.Message.MessageID) } else { - t.sendCallbackAnswerTgBot(callbackQuery.ID, "โ— Error in Operation.") + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) } case "toggle_enable": enabled, err := t.inboundService.ToggleClientEnableByEmail(email) if err == nil { t.xrayService.SetToNeedRestart() if enabled { - t.sendCallbackAnswerTgBot(callbackQuery.ID, fmt.Sprintf("โœ… %s : Enabled successfully.", email)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.enableSuccess", "Email=="+email)) } else { - t.sendCallbackAnswerTgBot(callbackQuery.ID, fmt.Sprintf("โœ… %s : Disabled successfully.", email)) + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.disableSuccess", "Email=="+email)) } t.searchClient(chatId, email, callbackQuery.Message.MessageID) } else { - t.sendCallbackAnswerTgBot(callbackQuery.ID, "โ— Error in Operation.") + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) } } return @@ -417,9 +428,9 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool case "client_traffic": t.getClientUsage(chatId, callbackQuery.From.Username, strconv.FormatInt(callbackQuery.From.ID, 10)) case "client_commands": - t.SendMsgToTgbot(chatId, "To search for statistics, just use folowing command:\r\n \r\n/usage [UID|Password]\r\n \r\nUse UID for vmess/vless and Password for Trojan.") + t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.helpClientCommands")) case "commands": - t.SendMsgToTgbot(chatId, "Search for a client email:\r\n/usage email\r\n \r\nSearch for inbounds (with client stats):\r\n/inbound [remark]") + t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.helpAdminCommands")) } } @@ -435,23 +446,24 @@ func checkAdmin(tgId int64) bool { func (t *Tgbot) SendAnswer(chatId int64, msg string, isAdmin bool) { numericKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("Server Usage").WithCallbackData(t.hashStorage.AddHash("get_usage")), - tu.InlineKeyboardButton("Get DB Backup").WithCallbackData(t.hashStorage.AddHash("get_backup")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.serverUsage")).WithCallbackData(t.hashStorage.AddHash("get_usage")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.dbBackup")).WithCallbackData(t.hashStorage.AddHash("get_backup")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("Get Inbounds").WithCallbackData(t.hashStorage.AddHash("inbounds")), - tu.InlineKeyboardButton("Deplete soon").WithCallbackData(t.hashStorage.AddHash("deplete_soon")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.getInbounds")).WithCallbackData(t.hashStorage.AddHash("inbounds")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.depleteSoon")).WithCallbackData(t.hashStorage.AddHash("deplete_soon")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("Commands").WithCallbackData(t.hashStorage.AddHash("commands")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.commands")).WithCallbackData(t.hashStorage.AddHash("commands")), ), ) numericKeyboardClient := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("Get Usage").WithCallbackData(t.hashStorage.AddHash("client_traffic")), - tu.InlineKeyboardButton("Commands").WithCallbackData(t.hashStorage.AddHash("client_commands")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.clientUsage")).WithCallbackData(t.hashStorage.AddHash("client_traffic")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.commands")).WithCallbackData(t.hashStorage.AddHash("client_commands")), ), ) + var ReplyMarkup telego.ReplyMarkup if isAdmin { ReplyMarkup = numericKeyboard @@ -515,43 +527,44 @@ func (t *Tgbot) SendMsgToTgbotAdmins(msg string) { func (t *Tgbot) SendReport() { runTime, err := t.settingService.GetTgbotRuntime() if err == nil && len(runTime) > 0 { - t.SendMsgToTgbotAdmins("๐Ÿ•ฐ Scheduled reports: " + runTime + "\r\nDate-Time: " + time.Now().Format("2006-01-02 15:04:05")) + msg := "" + msg += t.I18nBot("tgbot.messages.report", "RunTime=="+runTime) + msg += t.I18nBot("tgbot.messages.datetime", "DateTime=="+time.Now().Format("2006-01-02 15:04:05")) + t.SendMsgToTgbotAdmins(msg) } + info := t.getServerUsage() t.SendMsgToTgbotAdmins(info) + exhausted := t.getExhausted() t.SendMsgToTgbotAdmins(exhausted) + backupEnable, err := t.settingService.GetTgBotBackup() if err == nil && backupEnable { - for _, adminId := range adminIds { - t.sendBackup(int64(adminId)) - } + t.SendBackupToAdmins() } } -func (t *Tgbot) SendBackUP(c *gin.Context) { +func (t *Tgbot) SendBackupToAdmins() { + if !t.IsRunning() { + return + } for _, adminId := range adminIds { t.sendBackup(int64(adminId)) } } func (t *Tgbot) getServerUsage() string { - var info string - //get hostname - hostname, err := os.Hostname() - if err != nil { - logger.Error("get hostname error:", err) - hostname = "" - } - info = fmt.Sprintf("๐Ÿ’ป Hostname: %s\r\n", hostname) - info += fmt.Sprintf("๐Ÿš€X-UI Version: %s\r\n", config.GetVersion()) - //get ip address - var ip string - var ipv6 string + info, ipv4, ipv6 := "", "", "" + info += t.I18nBot("tgbot.messages.hostname", "Hostname=="+hostname) + info += t.I18nBot("tgbot.messages.version", "Version=="+config.GetVersion()) + + // get ip address netInterfaces, err := net.Interfaces() if err != nil { - logger.Error("net.Interfaces failed, err:", err.Error()) - info += "๐ŸŒ IP: Unknown\r\n \r\n" + logger.Error("net.Interfaces failed, err: ", err.Error()) + info += t.I18nBot("tgbot.messages.ip", "IP=="+t.I18nBot("tgbot.unknown")) + info += " \r\n" } else { for i := 0; i < len(netInterfaces); i++ { if (netInterfaces[i].Flags & net.FlagUp) != 0 { @@ -560,7 +573,7 @@ func (t *Tgbot) getServerUsage() string { for _, address := range addrs { if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { if ipnet.IP.To4() != nil { - ip += ipnet.IP.String() + " " + ipv4 += ipnet.IP.String() + " " } else if ipnet.IP.To16() != nil && !ipnet.IP.IsLinkLocalUnicast() { ipv6 += ipnet.IP.String() + " " } @@ -568,19 +581,20 @@ func (t *Tgbot) getServerUsage() string { } } } - info += fmt.Sprintf("๐ŸŒIP: %s\r\n๐ŸŒIPv6: %s\r\n", ip, ipv6) + + info += t.I18nBot("tgbot.messages.ipv4", "IPv4=="+ipv4) + info += t.I18nBot("tgbot.messages.ipv6", "IPv6=="+ipv6) } // get latest status of server t.lastStatus = t.serverService.GetStatus(t.lastStatus) - info += fmt.Sprintf("๐Ÿ”ŒServer Uptime: %d days\r\n", int(t.lastStatus.Uptime/86400)) - info += fmt.Sprintf("๐Ÿ“ˆServer Load: %.1f, %.1f, %.1f\r\n", t.lastStatus.Loads[0], t.lastStatus.Loads[1], t.lastStatus.Loads[2]) - info += fmt.Sprintf("๐Ÿ“‹Server Memory: %s/%s\r\n", common.FormatTraffic(int64(t.lastStatus.Mem.Current)), common.FormatTraffic(int64(t.lastStatus.Mem.Total))) - info += fmt.Sprintf("๐Ÿ”นTcpCount: %d\r\n", t.lastStatus.TcpCount) - info += fmt.Sprintf("๐Ÿ”ธUdpCount: %d\r\n", t.lastStatus.UdpCount) - info += fmt.Sprintf("๐ŸšฆTraffic: %s (โ†‘%s,โ†“%s)\r\n", common.FormatTraffic(int64(t.lastStatus.NetTraffic.Sent+t.lastStatus.NetTraffic.Recv)), common.FormatTraffic(int64(t.lastStatus.NetTraffic.Sent)), common.FormatTraffic(int64(t.lastStatus.NetTraffic.Recv))) - info += fmt.Sprintf("โ„นXray status: %s", t.lastStatus.Xray.State) - + 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.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))) + info += t.I18nBot("tgbot.messages.xrayStatus", "State=="+fmt.Sprint(t.lastStatus.Xray.State)) return info } @@ -594,23 +608,17 @@ func (t *Tgbot) UserLoginNotify(username string, ip string, time string, status return } - // Get hostname - hostname, err := os.Hostname() - if err != nil { - logger.Warning("get hostname error:", err) - return - } - msg := "" if status == LoginSuccess { - msg = fmt.Sprintf("โœ… Successfully logged-in to the panel\r\nHostname:%s\r\n", hostname) + msg += t.I18nBot("tgbot.messages.loginSuccess") } else if status == LoginFail { - msg = fmt.Sprintf("โ— Login to the panel was unsuccessful\r\nHostname:%s\r\n", hostname) + msg += t.I18nBot("tgbot.messages.loginFailed") } - msg += fmt.Sprintf("โฐ Time:%s\r\n", time) - msg += fmt.Sprintf("๐Ÿ†” Username:%s\r\n", username) - msg += fmt.Sprintf("๐ŸŒ IP:%s\r\n", ip) + msg += t.I18nBot("tgbot.messages.hostname", "Hostname=="+hostname) + msg += t.I18nBot("tgbot.messages.username", "Username=="+username) + msg += t.I18nBot("tgbot.messages.ip", "IP=="+ip) + msg += t.I18nBot("tgbot.messages.time", "Time=="+time) t.SendMsgToTgbotAdmins(msg) } @@ -620,17 +628,19 @@ func (t *Tgbot) getInboundUsages() string { inbouds, err := t.inboundService.GetAllInbounds() if err != nil { logger.Warning("GetAllInbounds run failed:", err) - info += "โŒ Failed to get inbounds" + info += t.I18nBot("tgbot.answers.getInboundsFailed") } else { // NOTE:If there no any sessions here,need to notify here // TODO:Sub-node push, automatic conversion format for _, inbound := range inbouds { - info += fmt.Sprintf("๐Ÿ“Inbound:%s\r\nPort:%d\r\n", inbound.Remark, inbound.Port) - info += fmt.Sprintf("Traffic: %s (โ†‘%s,โ†“%s)\r\n", common.FormatTraffic((inbound.Up + inbound.Down)), common.FormatTraffic(inbound.Up), common.FormatTraffic(inbound.Down)) + info += t.I18nBot("tgbot.messages.inbound", "Remark=="+inbound.Remark) + info += t.I18nBot("tgbot.messages.port", "Port=="+strconv.Itoa(inbound.Port)) + info += t.I18nBot("tgbot.messages.traffic", "Total=="+common.FormatTraffic((inbound.Up+inbound.Down)), "Upload=="+common.FormatTraffic(inbound.Up), "Download=="+common.FormatTraffic(inbound.Down)) + if inbound.ExpiryTime == 0 { - info += "Expire date: โ™พ Unlimited\r\n \r\n" + info += t.I18nBot("tgbot.messages.expire", "DateTime=="+t.I18nBot("tgbot.unlimited")) } else { - info += fmt.Sprintf("Expire date:%s\r\n \r\n", time.Unix((inbound.ExpiryTime/1000), 0).Format("2006-01-02 15:04:05")) + info += t.I18nBot("tgbot.messages.expire", "DateTime=="+time.Unix((inbound.ExpiryTime/1000), 0).Format("2006-01-02 15:04:05")) } } } @@ -641,13 +651,14 @@ func (t *Tgbot) getClientUsage(chatId int64, tgUserName string, tgUserID string) traffics, err := t.inboundService.GetClientTrafficTgBot(tgUserID) if err != nil { logger.Warning(err) - msg := "โŒ Something went wrong!" + msg := t.I18nBot("tgbot.wentWrong") t.SendMsgToTgbot(chatId, msg) return } + if len(traffics) == 0 { if len(tgUserName) == 0 { - msg := "Your configuration is not found!\nPlease ask your Admin to use your telegram user id in your configuration(s).\n\nYour user id: " + tgUserID + "" + msg := t.I18nBot("tgbot.answers.askToAddUserId", "TgUserID=="+tgUserID) t.SendMsgToTgbot(chatId, msg) return } @@ -655,52 +666,65 @@ func (t *Tgbot) getClientUsage(chatId int64, tgUserName string, tgUserID string) } if err != nil { logger.Warning(err) - msg := "โŒ Something went wrong!" + msg := t.I18nBot("tgbot.wentWrong") t.SendMsgToTgbot(chatId, msg) return } if len(traffics) == 0 { - msg := "Your configuration is not found!\nPlease ask your Admin to use your telegram username or user id in your configuration(s).\n\nYour username: @" + tgUserName + "\n\nYour user id: " + tgUserID + "" + msg := t.I18nBot("tgbot.answers.askToAddUserName", "TgUserName=="+tgUserName, "TgUserID=="+tgUserID) t.SendMsgToTgbot(chatId, msg) return } + for _, traffic := range traffics { expiryTime := "" if traffic.ExpiryTime == 0 { - expiryTime = "โ™พUnlimited" + expiryTime = t.I18nBot("tgbot.unlimited") } else if traffic.ExpiryTime < 0 { - expiryTime = fmt.Sprintf("%d days", traffic.ExpiryTime/-86400000) + expiryTime = fmt.Sprintf("%d %s", traffic.ExpiryTime/-86400000, t.I18nBot("tgbot.days")) } else { expiryTime = time.Unix((traffic.ExpiryTime / 1000), 0).Format("2006-01-02 15:04:05") } + total := "" if traffic.Total == 0 { - total = "โ™พUnlimited" + total = t.I18nBot("tgbot.unlimited") } else { total = common.FormatTraffic((traffic.Total)) } - output := fmt.Sprintf("๐Ÿ’ก Active: %t\r\n๐Ÿ“ง Email: %s\r\n๐Ÿ”ผ Uploadโ†‘: %s\r\n๐Ÿ”ฝ Downloadโ†“: %s\r\n๐Ÿ”„ Total: %s / %s\r\n๐Ÿ“… Expire in: %s\r\n", - traffic.Enable, traffic.Email, common.FormatTraffic(traffic.Up), common.FormatTraffic(traffic.Down), common.FormatTraffic((traffic.Up + traffic.Down)), - total, expiryTime) + + output := "" + output += t.I18nBot("tgbot.messages.active", "Enable=="+strconv.FormatBool(traffic.Enable)) + output += t.I18nBot("tgbot.messages.email", "Email=="+traffic.Email) + 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.expireIn", "Time=="+expiryTime) + t.SendMsgToTgbot(chatId, output) } - t.SendAnswer(chatId, "Please choose:", false) + t.SendAnswer(chatId, t.I18nBot("tgbot.commands.pleaseChoose"), false) } func (t *Tgbot) searchClientIps(chatId int64, email string, messageID ...int) { ips, err := t.inboundService.GetInboundClientIps(email) if err != nil || len(ips) == 0 { - ips = "No IP Record" + ips = t.I18nBot("tgbot.noIpRecord") } - output := fmt.Sprintf("๐Ÿ“ง Email: %s\r\n๐Ÿ”ข IPs: \r\n%s\r\n", email, ips) + + output := "" + output += t.I18nBot("tgbot.messages.email", "Email=="+email) + output += t.I18nBot("tgbot.messages.ips", "IPs=="+ips) + inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("๐Ÿ”„ Refresh").WithCallbackData(t.hashStorage.AddHash("ips_refresh "+email)), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.refresh")).WithCallbackData(t.hashStorage.AddHash("ips_refresh "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โŒ Clear IPs").WithCallbackData(t.hashStorage.AddHash("clear_ips "+email)), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.clearIPs")).WithCallbackData(t.hashStorage.AddHash("clear_ips "+email)), ), ) + if len(messageID) > 0 { t.editMessageTgBot(chatId, messageID[0], output, inlineKeyboard) } else { @@ -712,12 +736,12 @@ func (t *Tgbot) clientTelegramUserInfo(chatId int64, email string, messageID ... traffic, client, err := t.inboundService.GetClientByEmail(email) if err != nil { logger.Warning(err) - msg := "โŒ Something went wrong!" + msg := t.I18nBot("tgbot.wentWrong") t.SendMsgToTgbot(chatId, msg) return } if client == nil { - msg := "No result!" + msg := t.I18nBot("tgbot.noResult") t.SendMsgToTgbot(chatId, msg) return } @@ -726,13 +750,16 @@ func (t *Tgbot) clientTelegramUserInfo(chatId int64, email string, messageID ... tgId = client.TgID } - output := fmt.Sprintf("๐Ÿ“ง Email: %s\r\n๐Ÿ‘ค Telegram User: %s\r\n", email, tgId) + output := "" + output += t.I18nBot("tgbot.messages.email", "Email=="+email) + output += t.I18nBot("tgbot.messages.TGUser", "TelegramID=="+tgId) + inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton("๐Ÿ”„ Refresh").WithCallbackData(t.hashStorage.AddHash("tgid_refresh "+email)), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.refresh")).WithCallbackData(t.hashStorage.AddHash("tgid_refresh "+email)), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("โŒ Remove Telegram User").WithCallbackData(t.hashStorage.AddHash("tgid_remove "+email)), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.removeTGUser")).WithCallbackData(t.hashStorage.AddHash("tgid_remove "+email)), ), ) @@ -746,13 +773,13 @@ func (t *Tgbot) clientTelegramUserInfo(chatId int64, email string, messageID ... } keyboard := tu.Keyboard( tu.KeyboardRow( - tu.KeyboardButton("๐Ÿ‘ค Select Telegram User").WithRequestUser(&requestUser), + tu.KeyboardButton(t.I18nBot("tgbot.buttons.selectTGUser")).WithRequestUser(&requestUser), ), tu.KeyboardRow( - tu.KeyboardButton("โŒ Close Keyboard"), + tu.KeyboardButton(t.I18nBot("tgbot.buttons.closeKeyboard")), ), ).WithIsPersistent().WithResizeKeyboard() -