From abc590ae715d13aac60398c99aaa34ab43b06c42 Mon Sep 17 00:00:00 2001 From: Masoud Hidden <130294836+masoud-hidden@users.noreply.github.com> Date: Mon, 20 Nov 2023 17:47:59 +0330 Subject: [PATCH] [bot] Some new features for telegram bot (#1241) * [bot] Some new features for telegram bot +Ability to set traffic limit for client. +Custom input for reset expire days. +Custom input for reset IP limit. +Added refresh time to the client ip log message. * [bot] fix translations --- web/service/inbound.go | 61 +++++++ web/service/tgbot.go | 233 +++++++++++++++++++++++++ web/translation/translate.en_US.toml | 5 + web/translation/translate.es_ES.toml | 5 + web/translation/translate.fa_IR.toml | 5 + web/translation/translate.ru_RU.toml | 5 + web/translation/translate.vi_VN.toml | 5 + web/translation/translate.zh_Hans.toml | 5 + 8 files changed, 324 insertions(+) diff --git a/web/service/inbound.go b/web/service/inbound.go index a9ac8d0e..1646b5ed 100644 --- a/web/service/inbound.go +++ b/web/service/inbound.go @@ -1231,6 +1231,67 @@ func (s *InboundService) ResetClientExpiryTimeByEmail(clientEmail string, expiry return nil } +func (s *InboundService) ResetClientTrafficLimitByEmail(clientEmail string, totalGB int) error { + if totalGB < 0 { + return common.NewError("totalGB must be >= 0") + } + _, inbound, err := s.GetClientInboundByEmail(clientEmail) + if err != nil { + return err + } + if inbound == nil { + return common.NewError("Inbound Not Found For Email:", clientEmail) + } + + oldClients, err := s.GetClients(inbound) + if err != nil { + return err + } + + clientId := "" + + for _, oldClient := range oldClients { + if oldClient.Email == clientEmail { + if inbound.Protocol == "trojan" { + clientId = oldClient.Password + } else { + clientId = oldClient.ID + } + break + } + } + + if len(clientId) == 0 { + return common.NewError("Client Not Found For Email:", clientEmail) + } + + var settings map[string]interface{} + err = json.Unmarshal([]byte(inbound.Settings), &settings) + if err != nil { + return err + } + clients := settings["clients"].([]interface{}) + var newClients []interface{} + for client_index := range clients { + c := clients[client_index].(map[string]interface{}) + if c["email"] == clientEmail { + c["totalGB"] = totalGB * 1024 * 1024 * 1024 + newClients = append(newClients, interface{}(c)) + } + } + settings["clients"] = newClients + modifiedSettings, err := json.MarshalIndent(settings, "", " ") + if err != nil { + return err + } + inbound.Settings = string(modifiedSettings) + _, err = s.UpdateInboundClient(inbound, clientId) + if err != nil { + return err + } + return nil +} + func (s *InboundService) ResetClientTrafficByEmail(clientEmail string) error { db := database.GetDB() diff --git a/web/service/tgbot.go b/web/service/tgbot.go index 69cfd724..b54ceb1c 100644 --- a/web/service/tgbot.go +++ b/web/service/tgbot.go @@ -293,6 +293,113 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool } else { t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) } + case "limit_traffic": + 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.unlimited")).WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 0")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" 0")), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton("1 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 1")), + tu.InlineKeyboardButton("5 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 5")), + tu.InlineKeyboardButton("10 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 10")), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton("20 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 20")), + tu.InlineKeyboardButton("30 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 30")), + tu.InlineKeyboardButton("40 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 40")), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton("50 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 60")), + tu.InlineKeyboardButton("60 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 60")), + tu.InlineKeyboardButton("80 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 80")), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton("100 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 100")), + tu.InlineKeyboardButton("150 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 150")), + tu.InlineKeyboardButton("200 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 200")), + ), + ) + t.editMessageCallbackTgBot(chatId, callbackQuery.Message.MessageID, inlineKeyboard) + case "limit_traffic_c": + if len(dataArray) == 3 { + limitTraffic, err := strconv.Atoi(dataArray[2]) + if err == nil { + err := t.inboundService.ResetClientTrafficLimitByEmail(email, limitTraffic) + if err == nil { + t.xrayService.SetToNeedRestart() + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.setTrafficLimitSuccess", "Email=="+email)) + t.searchClient(chatId, email, callbackQuery.Message.MessageID) + return + } + } + } + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) + t.searchClient(chatId, email, callbackQuery.Message.MessageID) + case "limit_traffic_in": + if len(dataArray) >= 3 { + oldInputNumber, err := strconv.Atoi(dataArray[2]) + inputNumber := oldInputNumber + if err == nil { + if len(dataArray) == 4 { + num, err := strconv.Atoi(dataArray[3]) + if err == nil { + if num == -2 { + inputNumber = 0 + } else if num == -1 { + if inputNumber > 0 { + inputNumber = (inputNumber / 10) ^ 0 + } + } else { + inputNumber = (inputNumber * 10) + num + } + } + if inputNumber == oldInputNumber { + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) + return + } + if inputNumber >= 999999 { + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) + return + } + } + 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.confirmNumber", "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")), + tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 2")), + tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 3")), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 4")), + tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 5")), + tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 6")), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 7")), + tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 8")), + tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 9")), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" -2")), + tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 0")), + tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" -1")), + ), + ) + t.editMessageCallbackTgBot(chatId, callbackQuery.Message.MessageID, inlineKeyboard) + return + } + } + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) + t.searchClient(chatId, email, callbackQuery.Message.MessageID) case "reset_exp": inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( @@ -300,6 +407,7 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool ), tu.InlineKeyboardRow( tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 0")), + 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")), @@ -338,6 +446,67 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool } t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) t.searchClient(chatId, email, callbackQuery.Message.MessageID) + case "reset_exp_in": + if len(dataArray) >= 3 { + oldInputNumber, err := strconv.Atoi(dataArray[2]) + inputNumber := oldInputNumber + if err == nil { + if len(dataArray) == 4 { + num, err := strconv.Atoi(dataArray[3]) + if err == nil { + if num == -2 { + inputNumber = 0 + } else if num == -1 { + if inputNumber > 0 { + inputNumber = (inputNumber / 10) ^ 0 + } + } else { + inputNumber = (inputNumber * 10) + num + } + } + if inputNumber == oldInputNumber { + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) + return + } + if inputNumber >= 999999 { + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) + return + } + } + 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.confirmNumber", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" "+strconv.Itoa(inputNumber))), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 1")), + tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 2")), + tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 3")), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 4")), + tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 5")), + tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 6")), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 7")), + tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 8")), + tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 9")), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" -2")), + tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 0")), + tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" -1")), + ), + ) + t.editMessageCallbackTgBot(chatId, callbackQuery.Message.MessageID, inlineKeyboard) + return + } + } + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) + t.searchClient(chatId, email, callbackQuery.Message.MessageID) case "ip_limit": inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( @@ -345,6 +514,7 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool ), tu.InlineKeyboardRow( tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 0")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("ip_limit_in "+email+" 0")), ), tu.InlineKeyboardRow( tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 1")), @@ -381,6 +551,67 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool } t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) t.searchClient(chatId, email, callbackQuery.Message.MessageID) + case "ip_limit_in": + if len(dataArray) >= 3 { + oldInputNumber, err := strconv.Atoi(dataArray[2]) + inputNumber := oldInputNumber + if err == nil { + if len(dataArray) == 4 { + num, err := strconv.Atoi(dataArray[3]) + if err == nil { + if num == -2 { + inputNumber = 0 + } else if num == -1 { + if inputNumber > 0 { + inputNumber = (inputNumber / 10) ^ 0 + } + } else { + inputNumber = (inputNumber * 10) + num + } + } + if inputNumber == oldInputNumber { + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) + return + } + if inputNumber >= 999999 { + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) + return + } + } + 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.confirmNumber", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("ip_limit_c "+email+" "+strconv.Itoa(inputNumber))), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 1")), + tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 2")), + tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 3")), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 4")), + tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 5")), + tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 6")), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 7")), + tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 8")), + tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 9")), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" -2")), + tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 0")), + tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" -1")), + ), + ) + t.editMessageCallbackTgBot(chatId, callbackQuery.Message.MessageID, inlineKeyboard) + return + } + } + t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) + t.searchClient(chatId, email, callbackQuery.Message.MessageID) case "clear_ips": inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( @@ -772,6 +1003,7 @@ func (t *Tgbot) searchClientIps(chatId int64, email string, messageID ...int) { output := "" output += t.I18nBot("tgbot.messages.email", "Email=="+email) output += t.I18nBot("tgbot.messages.ips", "IPs=="+ips) + output += t.I18nBot("tgbot.messages.refreshedOn", "Time=="+time.Now().Format("2006-01-02 15:04:05")) inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( @@ -902,6 +1134,7 @@ func (t *Tgbot) searchClient(chatId int64, email string, messageID ...int) { ), tu.InlineKeyboardRow( tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.resetTraffic")).WithCallbackData(t.encodeQuery("reset_traffic "+email)), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.limitTraffic")).WithCallbackData(t.encodeQuery("limit_traffic "+email)), ), tu.InlineKeyboardRow( tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.resetExpire")).WithCallbackData(t.encodeQuery("reset_exp "+email)), diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml index 28562485..88ae4067 100644 --- a/web/translation/translate.en_US.toml +++ b/web/translation/translate.en_US.toml @@ -474,8 +474,12 @@ "ipLimit" = "🔢 IP Limit" "setTGUser" = "👤 Set Telegram User" "toggle" = "🔘 Enable / Disable" +"custom" = "🔢 Custom" +"confirmNumber" = "✅ Confirm : {{ .Num }}" +"limitTraffic" = "🚧 Traffic Limit" [tgbot.answers] +"successfulOperation" = "✅ Successful!" "errorOperation" = "❗ Error in Operation." "getInboundsFailed" = "❌ Failed to get inbounds" "canceled" = "❌ {{ .Email }} : Operation canceled." @@ -483,6 +487,7 @@ "IpRefreshSuccess" = "✅ {{ .Email }} : IPs refreshed successfully." "TGIdRefreshSuccess" = "✅ {{ .Email }} : Client's Telegram User refreshed successfully." "resetTrafficSuccess" = "✅ {{ .Email }} : Traffic reset successfully." +"setTrafficLimitSuccess" = "✅ {{ .Email }} : Traffic limit saved successfully." "expireResetSuccess" = "✅ {{ .Email }} : Expire days reset successfully." "resetIpSuccess" = "✅ {{ .Email }} : IP limit {{ .Count }} saved successfully." "clearIpSuccess" = "✅ {{ .Email }} : IPs cleared successfully." diff --git a/web/translation/translate.es_ES.toml b/web/translation/translate.es_ES.toml index 06e53d55..31cd2aff 100644 --- a/web/translation/translate.es_ES.toml +++ b/web/translation/translate.es_ES.toml @@ -474,8 +474,12 @@ "ipLimit" = "🔢 Límite de IP" "setTGUser" = "👤 Establecer Usuario de Telegram" "toggle" = "🔘 Habilitar / Deshabilitar" +"custom" = "🔢 Costumbre" +"confirmNumber" = "✅ Confirmar : {{ .Num }}" +"limitTraffic" = "🚧 Límite de tráfico" [tgbot.answers] +"successfulOperation" = "✅ ¡Exitosa!" "errorOperation" = "❗ Error en la Operación." "getInboundsFailed" = "❌ Error al obtener las entradas" "canceled" = "❌ {{ .Email }} : Operación cancelada." @@ -483,6 +487,7 @@ "IpRefreshSuccess" = "✅ {{ .Email }} : IPs actualizadas exitosamente." "TGIdRefreshSuccess" = "✅ {{ .Email }} : Usuario de Telegram del cliente actualizado exitosamente." "resetTrafficSuccess" = "✅ {{ .Email }} : Tráfico reiniciado exitosamente." +"setTrafficLimitSuccess" = "✅ {{ .Email }} : Límite de Tráfico guardado exitosamente." "expireResetSuccess" = "✅ {{ .Email }} : Días de vencimiento reiniciados exitosamente." "resetIpSuccess" = "✅ {{ .Email }} : Límite de IP {{ .Count }} guardado exitosamente." "clearIpSuccess" = "✅ {{ .Email }} : IPs limpiadas exitosamente." diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml index 29c994f9..c95d135e 100644 --- a/web/translation/translate.fa_IR.toml +++ b/web/translation/translate.fa_IR.toml @@ -474,8 +474,12 @@ "ipLimit" = "🔢 محدودیت IP" "setTGUser" = "👤 تنظیم کاربر تلگرام" "toggle" = "🔘 فعال / غیرفعال" +"custom" = "🔢 سفارشی" +"confirmNumber" = "✅ تایید : {{ .Num }}" +"limitTraffic" = "🚧 محدودیت ترافیک" [tgbot.answers] +"successfulOperation" = "✅ انجام شد!" "errorOperation" = "❗ خطا در عملیات." "getInboundsFailed" = "❌ دریافت ورودی‌ها با خطا مواجه شد." "canceled" = "❌ {{ .Email }} : عملیات لغو شد." @@ -483,6 +487,7 @@ "IpRefreshSuccess" = "✅ {{ .Email }} : آدرس‌ها با موفقیت تازه‌سازی شدند." "TGIdRefreshSuccess" = "✅ {{ .Email }} : کاربر تلگرام کلاینت با موفقیت تازه‌سازی شد." "resetTrafficSuccess" = "✅ {{ .Email }} : ترافیک با موفقیت تنظیم مجدد شد." +"setTrafficLimitSuccess" = "✅ {{ .Email }} : محدودیت ترافیک با موفقیت ذخیره شد." "expireResetSuccess" = "✅ {{ .Email }} : تاریخ انقضا با موفقیت تنظیم مجدد شد." "resetIpSuccess" = "✅ {{ .Email }} : محدودیت آدرس IP {{ .Count }} با موفقیت ذخیره شد." "clearIpSuccess" = "✅ {{ .Email }} : آدرس‌ها با موفقیت پاک‌سازی شدند." diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml index e0e9c565..5cb89a17 100644 --- a/web/translation/translate.ru_RU.toml +++ b/web/translation/translate.ru_RU.toml @@ -474,8 +474,12 @@ "ipLimit" = "🔢 Лимит IP" "setTGUser" = "👤 Установить пользователя Telegram" "toggle" = "🔘 Вкл./Выкл." +"custom" = "🔢 Обычай" +"confirmNumber" = "✅ Подтвердить : {{ .Num }}" +"limitTraffic" = "🚧 Лимит трафика" [tgbot.answers] +"successfulOperation" = "✅ Успешный!" "errorOperation" = "❗ Ошибка в операции." "getInboundsFailed" = "❌ Не удалось получить входящие потоки." "canceled" = "❌ {{ .Email }}: Операция отменена." @@ -483,6 +487,7 @@ "IpRefreshSuccess" = "✅ {{ .Email }}: IP-адреса успешно обновлены." "TGIdRefreshSuccess" = "✅ {{ .Email }}: Пользователь Telegram клиента успешно обновлен." "resetTrafficSuccess" = "✅ {{ .Email }}: Трафик успешно сброшен." +"setTrafficLimitSuccess" = "✅ {{ .Email }}: Лимит Трафик успешно сохранен." "expireResetSuccess" = "✅ {{ .Email }}: Дни истечения успешно сброшены." "resetIpSuccess" = "✅ {{ .Email }}: Лимит IP ({{ .Count }}) успешно сохранен." "clearIpSuccess" = "✅ {{ .Email }}: IP-адреса успешно очищены." diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml index 09a2f7d7..c71e0053 100644 --- a/web/translation/translate.vi_VN.toml +++ b/web/translation/translate.vi_VN.toml @@ -474,8 +474,12 @@ "ipLimit" = "🔢 Giới Hạn IP" "setTGUser" = "👤 Đặt Người Dùng Telegram" "toggle" = "🔘 Bật / Tắt" +"custom" = "🔢 Phong tục" +"confirmNumber" = "✅ Xác nhận : {{ .Num }}" +"limitTraffic" = "🚧 Giới hạn giao thông" [tgbot.answers] +"successfulOperation" = "✅ Thành công!" "errorOperation" = "❗ Lỗi Trong Quá Trình Thực Hiện." "getInboundsFailed" = "❌ Không Thể Lấy Được Inbounds" "canceled" = "❌ {{ .Email }} : Thao Tác Đã Bị Hủy." @@ -483,6 +487,7 @@ "IpRefreshSuccess" = "✅ {{ .Email }} : Cập Nhật Thành Công Cho IPs." "TGIdRefreshSuccess" = "✅ {{ .Email }} : Cập Nhật Thành Công Cho Người Dùng Telegram." "resetTrafficSuccess" = "✅ {{ .Email }} : Đặt Lại Lưu Lượng Thành Công." +"setTrafficLimitSuccess" = "✅ {{ .Email }} : Đã lưu thành công giới hạn lưu lượng." "expireResetSuccess" = "✅ {{ .Email }} : Đặt Lại Ngày Hết Hạn Thành Công." "resetIpSuccess" = "✅ {{ .Email }} : Giới Hạn IP {{ .Count }} Đã Được Lưu Thành Công." "clearIpSuccess" = "✅ {{ .Email }} : IPs Đã Được Xóa Thành Công." diff --git a/web/translation/translate.zh_Hans.toml b/web/translation/translate.zh_Hans.toml index fb091405..1483b556 100644 --- a/web/translation/translate.zh_Hans.toml +++ b/web/translation/translate.zh_Hans.toml @@ -474,8 +474,12 @@ "ipLimit" = "🔢 IP 限制" "setTGUser" = "👤 设置 Telegram 用户" "toggle" = "🔘 启用/禁用" +"custom" = "🔢 风俗" +"confirmNumber" = "✅ 确认 : {{ .Num }}" +"limitTraffic" = "🚧 交通限制" [tgbot.answers] +"successfulOperation" = "✅ 成功的!" "errorOperation" = "❗ 操作错误。" "getInboundsFailed" = "❌ 获取入站信息失败。" "canceled" = "❌ {{ .Email }}:操作已取消。" @@ -483,6 +487,7 @@ "IpRefreshSuccess" = "✅ {{ .Email }}:IP 刷新成功。" "TGIdRefreshSuccess" = "✅ {{ .Email }}:客户端的 Telegram 用户刷新成功。" "resetTrafficSuccess" = "✅ {{ .Email }}:流量已重置成功。" +"setTrafficLimitSuccess" = "✅ {{ .Email }} : 流量限制保存成功。" "expireResetSuccess" = "✅ {{ .Email }}:过期天数已重置成功。" "resetIpSuccess" = "✅ {{ .Email }}:成功保存 IP 限制数量为 {{ .Count }}。" "clearIpSuccess" = "✅ {{ .Email }}:IP 已成功清除。"