Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMasoud Hidden <130294836+masoud-hidden@users.noreply.github.com>2023-11-20 17:17:59 +0300
committerGitHub <noreply@github.com>2023-11-20 17:17:59 +0300
commitabc590ae715d13aac60398c99aaa34ab43b06c42 (patch)
tree6aa182fa869b579cd67e9a1caa5fd055b027305f /web/service
parentad6d07326a6b23fd0e54446a24bf537de4dba4e1 (diff)
[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
Diffstat (limited to 'web/service')
-rw-r--r--web/service/inbound.go61
-rw-r--r--web/service/tgbot.go233
2 files changed, 294 insertions, 0 deletions
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)),