فهرست منبع

[feature] delete depleted clients

Co-Authored-By: Alireza Ahmadi <[email protected]>
MHSanaei 1 سال پیش
والد
کامیت
379451135d

+ 21 - 6
web/controller/inbound.go

@@ -39,6 +39,7 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) {
 	g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic)
 	g.POST("/resetAllTraffics", a.resetAllTraffics)
 	g.POST("/resetAllClientTraffics/:id", a.resetAllClientTraffics)
+	g.POST("/delDepletedClients/:id", a.delDepletedClients)
 
 }
 
@@ -170,7 +171,7 @@ func (a *InboundController) addInboundClient(c *gin.Context) {
 
 	err = a.inboundService.AddInboundClient(data)
 	if err != nil {
-		jsonMsg(c, "something worng!", err)
+		jsonMsg(c, "Something went wrong!", err)
 		return
 	}
 	jsonMsg(c, "Client(s) added", nil)
@@ -189,7 +190,7 @@ func (a *InboundController) delInboundClient(c *gin.Context) {
 
 	err = a.inboundService.DelInboundClient(id, clientId)
 	if err != nil {
-		jsonMsg(c, "something worng!", err)
+		jsonMsg(c, "Something went wrong!", err)
 		return
 	}
 	jsonMsg(c, "Client deleted", nil)
@@ -210,7 +211,7 @@ func (a *InboundController) updateInboundClient(c *gin.Context) {
 
 	err = a.inboundService.UpdateInboundClient(inbound, clientId)
 	if err != nil {
-		jsonMsg(c, "something worng!", err)
+		jsonMsg(c, "Something went wrong!", err)
 		return
 	}
 	jsonMsg(c, "Client updated", nil)
@@ -229,7 +230,7 @@ func (a *InboundController) resetClientTraffic(c *gin.Context) {
 
 	err = a.inboundService.ResetClientTraffic(id, email)
 	if err != nil {
-		jsonMsg(c, "something worng!", err)
+		jsonMsg(c, "Something went wrong!", err)
 		return
 	}
 	jsonMsg(c, "traffic reseted", nil)
@@ -241,7 +242,7 @@ func (a *InboundController) resetClientTraffic(c *gin.Context) {
 func (a *InboundController) resetAllTraffics(c *gin.Context) {
 	err := a.inboundService.ResetAllTraffics()
 	if err != nil {
-		jsonMsg(c, "something worng!", err)
+		jsonMsg(c, "Something went wrong!", err)
 		return
 	}
 	jsonMsg(c, "All traffics reseted", nil)
@@ -256,8 +257,22 @@ func (a *InboundController) resetAllClientTraffics(c *gin.Context) {
 
 	err = a.inboundService.ResetAllClientTraffics(id)
 	if err != nil {
-		jsonMsg(c, "something worng!", err)
+		jsonMsg(c, "Something went wrong!", err)
 		return
 	}
 	jsonMsg(c, "All traffics of client reseted", nil)
 }
+
+func (a *InboundController) delDepletedClients(c *gin.Context) {
+	id, err := strconv.Atoi(c.Param("id"))
+	if err != nil {
+		jsonMsg(c, I18n(c, "pages.inbounds.revise"), err)
+		return
+	}
+	err = a.inboundService.DelDepletedClients(id)
+	if err != nil {
+		jsonMsg(c, "Something went wrong!", err)
+		return
+	}
+	jsonMsg(c, "All delpeted clients are deleted", nil)
+}

+ 23 - 1
web/html/xui/inbounds.html

@@ -82,6 +82,10 @@
                                         <a-icon type="file-done"></a-icon>
                                         {{ i18n "pages.inbounds.resetAllClientTraffics" }}
                                     </a-menu-item>
+                                    <a-menu-item key="delDepletedClients">
+                                        <a-icon type="rest"></a-icon>
+                                        {{ i18n "pages.inbounds.delDepletedClients" }}
+                                    </a-menu-item>
                                 </a-menu>
                             </a-dropdown>
                         </div>
@@ -122,6 +126,10 @@
                                                 <a-icon type="export"></a-icon>
                                                 {{ i18n "pages.inbounds.export"}}
                                             </a-menu-item>
+                                            <a-menu-item key="delDepletedClients">
+                                                <a-icon type="rest"></a-icon>
+                                                {{ i18n "pages.inbounds.delDepletedClients" }}
+                                            </a-menu-item>
                                         </template>
                                         <template v-else>
                                             <a-menu-item key="showInfo">
@@ -416,7 +424,8 @@
                     case "resetClients":
                         this.resetAllClientTraffics(-1);
                         break;
-                    case "":
+                    case "delDepletedClients":
+                        this.delDepletedClients(-1)
                         break;
                 }
             },
@@ -452,6 +461,9 @@
                     case "delete":
                         this.delInbound(dbInbound.id);
                         break;
+                    case "delDepletedClients":
+                        this.delDepletedClients(dbInbound.id)
+                        break;
                 }
             },
 			openCloneInbound(dbInbound) {
@@ -730,6 +742,16 @@
                     onOk: () => this.submit('/xui/inbound/resetAllClientTraffics/' + dbInboundId),
                 })
             },
+            delDepletedClients(dbInboundId) {
+                this.$confirm({
+                    title: '{{ i18n "pages.inbounds.delDepletedClientsTitle"}}',
+                    content: '{{ i18n "pages.inbounds.delDepletedClientsContent"}}',
+                    class: siderDrawer.isDarkTheme ? darkClass : '',
+                    okText: '{{ i18n "reset"}}',
+                    cancelText: '{{ i18n "cancel"}}',
+                    onOk: () => this.submit('/xui/inbound/delDepletedClients/' + dbInboundId),
+                })
+            },
             isExpiry(dbInbound, index) {
                 return dbInbound.toInbound().isExpiry(index)
             },

+ 79 - 0
web/service/inbound.go

@@ -3,6 +3,7 @@ package service
 import (
 	"encoding/json"
 	"fmt"
+	"strings"
 	"time"
 	"x-ui/database"
 	"x-ui/database/model"
@@ -715,6 +716,84 @@ func (s *InboundService) ResetAllTraffics() error {
 	return nil
 }
 
+func (s *InboundService) DelDepletedClients(id int) (err error) {
+	db := database.GetDB()
+	tx := db.Begin()
+	defer func() {
+		if err == nil {
+			tx.Commit()
+		} else {
+			tx.Rollback()
+		}
+	}()
+
+	whereText := "inbound_id "
+	if id < 0 {
+		whereText += "> ?"
+	} else {
+		whereText += "= ?"
+	}
+
+	depletedClients := []xray.ClientTraffic{}
+	err = db.Model(xray.ClientTraffic{}).Where(whereText+" and enable = ?", id, false).Select("inbound_id, GROUP_CONCAT(email) as email").Group("inbound_id").Find(&depletedClients).Error
+	if err != nil {
+		return err
+	}
+
+	for _, depletedClient := range depletedClients {
+		emails := strings.Split(depletedClient.Email, ",")
+		oldInbound, err := s.GetInbound(depletedClient.InboundId)
+		if err != nil {
+			return err
+		}
+		var oldSettings map[string]interface{}
+		err = json.Unmarshal([]byte(oldInbound.Settings), &oldSettings)
+		if err != nil {
+			return err
+		}
+
+		oldClients := oldSettings["clients"].([]interface{})
+		var newClients []interface{}
+		for _, client := range oldClients {
+			deplete := false
+			c := client.(map[string]interface{})
+			for _, email := range emails {
+				if email == c["email"].(string) {
+					deplete = true
+					break
+				}
+			}
+			if !deplete {
+				newClients = append(newClients, client)
+			}
+		}
+		if len(newClients) > 0 {
+			oldSettings["clients"] = newClients
+
+			newSettings, err := json.MarshalIndent(oldSettings, "", "  ")
+			if err != nil {
+				return err
+			}
+
+			oldInbound.Settings = string(newSettings)
+			err = tx.Save(oldInbound).Error
+			if err != nil {
+				return err
+			}
+		} else {
+			// Delete inbound if no client remains
+			s.DelInbound(depletedClient.InboundId)
+		}
+	}
+
+	err = tx.Where(whereText+" and enable = ?", id, false).Delete(xray.ClientTraffic{}).Error
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
 func (s *InboundService) GetClientTrafficTgBot(tguname string) ([]*xray.ClientTraffic, error) {
 	db := database.GetDB()
 	var inbounds []*model.Inbound

+ 3 - 0
web/translation/translate.en_US.toml

@@ -150,6 +150,9 @@
 "resetAllClientTraffics" = "Reset All Clients Traffic"
 "resetAllClientTrafficTitle" = "Reset all clients traffic"
 "resetAllClientTrafficContent" = "Are you sure to reset all traffics of all clients ?"
+"delDepletedClients" = "Delete depleted clients"
+"delDepletedClientsTitle" = "Delete depleted clients"
+"delDepletedClientsContent" = "Are you sure to delete all depleted clients ?"
 "Email" = "Email"
 "EmailDesc" = "Please provide a unique email address"
 "IPLimitlog" = "IP Log"

+ 3 - 0
web/translation/translate.fa_IR.toml

@@ -146,6 +146,9 @@
 "resetAllClientTraffics" = "ریست ترافیک کاربران"
 "resetAllClientTrafficTitle" = "ریست ترافیک کل کاربران"
 "resetAllClientTrafficContent" = "آیا مطمئن هستید که میخواهید تمام ترافیک کاربران را ریست کنید؟"
+"delDepletedClients" = "حذف کاربران منقضی"
+"delDepletedClientsTitle" = "حذف کاربران منقضی"
+"delDepletedClientsContent" = "آیا مطمئن هستید مه میخواهید تمامی کاربران منقضی شده را حذف کنید؟"
 "IPLimit" = "محدودیت ای پی"
 "IPLimitDesc" = "غیرفعال کردن ورودی در صورت بیش از تعداد وارد شده (0 برای غیرفعال کردن محدودیت ای پی )"
 "Email" = "ایمیل"

+ 3 - 0
web/translation/translate.zh_Hans.toml

@@ -146,6 +146,9 @@
 "resetAllClientTraffics" = "重置所有客户端流量"
 "resetAllClientTrafficTitle" = "重置所有客户端流量"
 "resetAllClientTrafficContent" = "你确定要重置所有客户端的所有流量吗?"
+"delDepletedClients" = "删除耗尽的客户端"
+"delDepletedClientsTitle" = "删除耗尽的客户"
+"delDepletedClientsContent" = "你确定要删除所有耗尽的客户端吗?"
 "IPLimit" = "IP限制"
 "IPLimitDesc" = "如果超过输入的计数则禁用入站(0 表示禁用限制 ip)"
 "Email" = "电子邮件"