mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-04-19 21:42:24 +00:00
[feature] delete depleted clients
Co-Authored-By: Alireza Ahmadi <alireza7@gmail.com>
This commit is contained in:
parent
bc06dbab21
commit
379451135d
6 changed files with 132 additions and 7 deletions
|
@ -39,6 +39,7 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) {
|
||||||
g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic)
|
g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic)
|
||||||
g.POST("/resetAllTraffics", a.resetAllTraffics)
|
g.POST("/resetAllTraffics", a.resetAllTraffics)
|
||||||
g.POST("/resetAllClientTraffics/:id", a.resetAllClientTraffics)
|
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)
|
err = a.inboundService.AddInboundClient(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "something worng!", err)
|
jsonMsg(c, "Something went wrong!", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonMsg(c, "Client(s) added", nil)
|
jsonMsg(c, "Client(s) added", nil)
|
||||||
|
@ -189,7 +190,7 @@ func (a *InboundController) delInboundClient(c *gin.Context) {
|
||||||
|
|
||||||
err = a.inboundService.DelInboundClient(id, clientId)
|
err = a.inboundService.DelInboundClient(id, clientId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "something worng!", err)
|
jsonMsg(c, "Something went wrong!", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonMsg(c, "Client deleted", nil)
|
jsonMsg(c, "Client deleted", nil)
|
||||||
|
@ -210,7 +211,7 @@ func (a *InboundController) updateInboundClient(c *gin.Context) {
|
||||||
|
|
||||||
err = a.inboundService.UpdateInboundClient(inbound, clientId)
|
err = a.inboundService.UpdateInboundClient(inbound, clientId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "something worng!", err)
|
jsonMsg(c, "Something went wrong!", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonMsg(c, "Client updated", nil)
|
jsonMsg(c, "Client updated", nil)
|
||||||
|
@ -229,7 +230,7 @@ func (a *InboundController) resetClientTraffic(c *gin.Context) {
|
||||||
|
|
||||||
err = a.inboundService.ResetClientTraffic(id, email)
|
err = a.inboundService.ResetClientTraffic(id, email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "something worng!", err)
|
jsonMsg(c, "Something went wrong!", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonMsg(c, "traffic reseted", nil)
|
jsonMsg(c, "traffic reseted", nil)
|
||||||
|
@ -241,7 +242,7 @@ func (a *InboundController) resetClientTraffic(c *gin.Context) {
|
||||||
func (a *InboundController) resetAllTraffics(c *gin.Context) {
|
func (a *InboundController) resetAllTraffics(c *gin.Context) {
|
||||||
err := a.inboundService.ResetAllTraffics()
|
err := a.inboundService.ResetAllTraffics()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "something worng!", err)
|
jsonMsg(c, "Something went wrong!", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonMsg(c, "All traffics reseted", nil)
|
jsonMsg(c, "All traffics reseted", nil)
|
||||||
|
@ -256,8 +257,22 @@ func (a *InboundController) resetAllClientTraffics(c *gin.Context) {
|
||||||
|
|
||||||
err = a.inboundService.ResetAllClientTraffics(id)
|
err = a.inboundService.ResetAllClientTraffics(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "something worng!", err)
|
jsonMsg(c, "Something went wrong!", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonMsg(c, "All traffics of client reseted", nil)
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -82,6 +82,10 @@
|
||||||
<a-icon type="file-done"></a-icon>
|
<a-icon type="file-done"></a-icon>
|
||||||
{{ i18n "pages.inbounds.resetAllClientTraffics" }}
|
{{ i18n "pages.inbounds.resetAllClientTraffics" }}
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
|
<a-menu-item key="delDepletedClients">
|
||||||
|
<a-icon type="rest"></a-icon>
|
||||||
|
{{ i18n "pages.inbounds.delDepletedClients" }}
|
||||||
|
</a-menu-item>
|
||||||
</a-menu>
|
</a-menu>
|
||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
@ -122,6 +126,10 @@
|
||||||
<a-icon type="export"></a-icon>
|
<a-icon type="export"></a-icon>
|
||||||
{{ i18n "pages.inbounds.export"}}
|
{{ i18n "pages.inbounds.export"}}
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
|
<a-menu-item key="delDepletedClients">
|
||||||
|
<a-icon type="rest"></a-icon>
|
||||||
|
{{ i18n "pages.inbounds.delDepletedClients" }}
|
||||||
|
</a-menu-item>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a-menu-item key="showInfo">
|
<a-menu-item key="showInfo">
|
||||||
|
@ -416,7 +424,8 @@
|
||||||
case "resetClients":
|
case "resetClients":
|
||||||
this.resetAllClientTraffics(-1);
|
this.resetAllClientTraffics(-1);
|
||||||
break;
|
break;
|
||||||
case "":
|
case "delDepletedClients":
|
||||||
|
this.delDepletedClients(-1)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -452,6 +461,9 @@
|
||||||
case "delete":
|
case "delete":
|
||||||
this.delInbound(dbInbound.id);
|
this.delInbound(dbInbound.id);
|
||||||
break;
|
break;
|
||||||
|
case "delDepletedClients":
|
||||||
|
this.delDepletedClients(dbInbound.id)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openCloneInbound(dbInbound) {
|
openCloneInbound(dbInbound) {
|
||||||
|
@ -730,6 +742,16 @@
|
||||||
onOk: () => this.submit('/xui/inbound/resetAllClientTraffics/' + dbInboundId),
|
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) {
|
isExpiry(dbInbound, index) {
|
||||||
return dbInbound.toInbound().isExpiry(index)
|
return dbInbound.toInbound().isExpiry(index)
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,6 +3,7 @@ package service
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"x-ui/database"
|
"x-ui/database"
|
||||||
"x-ui/database/model"
|
"x-ui/database/model"
|
||||||
|
@ -715,6 +716,84 @@ func (s *InboundService) ResetAllTraffics() error {
|
||||||
return nil
|
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) {
|
func (s *InboundService) GetClientTrafficTgBot(tguname string) ([]*xray.ClientTraffic, error) {
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
var inbounds []*model.Inbound
|
var inbounds []*model.Inbound
|
||||||
|
|
|
@ -150,6 +150,9 @@
|
||||||
"resetAllClientTraffics" = "Reset All Clients Traffic"
|
"resetAllClientTraffics" = "Reset All Clients Traffic"
|
||||||
"resetAllClientTrafficTitle" = "Reset all clients traffic"
|
"resetAllClientTrafficTitle" = "Reset all clients traffic"
|
||||||
"resetAllClientTrafficContent" = "Are you sure to reset all traffics of all clients ?"
|
"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"
|
"Email" = "Email"
|
||||||
"EmailDesc" = "Please provide a unique email address"
|
"EmailDesc" = "Please provide a unique email address"
|
||||||
"IPLimitlog" = "IP Log"
|
"IPLimitlog" = "IP Log"
|
||||||
|
|
|
@ -146,6 +146,9 @@
|
||||||
"resetAllClientTraffics" = "ریست ترافیک کاربران"
|
"resetAllClientTraffics" = "ریست ترافیک کاربران"
|
||||||
"resetAllClientTrafficTitle" = "ریست ترافیک کل کاربران"
|
"resetAllClientTrafficTitle" = "ریست ترافیک کل کاربران"
|
||||||
"resetAllClientTrafficContent" = "آیا مطمئن هستید که میخواهید تمام ترافیک کاربران را ریست کنید؟"
|
"resetAllClientTrafficContent" = "آیا مطمئن هستید که میخواهید تمام ترافیک کاربران را ریست کنید؟"
|
||||||
|
"delDepletedClients" = "حذف کاربران منقضی"
|
||||||
|
"delDepletedClientsTitle" = "حذف کاربران منقضی"
|
||||||
|
"delDepletedClientsContent" = "آیا مطمئن هستید مه میخواهید تمامی کاربران منقضی شده را حذف کنید؟"
|
||||||
"IPLimit" = "محدودیت ای پی"
|
"IPLimit" = "محدودیت ای پی"
|
||||||
"IPLimitDesc" = "غیرفعال کردن ورودی در صورت بیش از تعداد وارد شده (0 برای غیرفعال کردن محدودیت ای پی )"
|
"IPLimitDesc" = "غیرفعال کردن ورودی در صورت بیش از تعداد وارد شده (0 برای غیرفعال کردن محدودیت ای پی )"
|
||||||
"Email" = "ایمیل"
|
"Email" = "ایمیل"
|
||||||
|
|
|
@ -146,6 +146,9 @@
|
||||||
"resetAllClientTraffics" = "重置所有客户端流量"
|
"resetAllClientTraffics" = "重置所有客户端流量"
|
||||||
"resetAllClientTrafficTitle" = "重置所有客户端流量"
|
"resetAllClientTrafficTitle" = "重置所有客户端流量"
|
||||||
"resetAllClientTrafficContent" = "你确定要重置所有客户端的所有流量吗?"
|
"resetAllClientTrafficContent" = "你确定要重置所有客户端的所有流量吗?"
|
||||||
|
"delDepletedClients" = "删除耗尽的客户端"
|
||||||
|
"delDepletedClientsTitle" = "删除耗尽的客户"
|
||||||
|
"delDepletedClientsContent" = "你确定要删除所有耗尽的客户端吗?"
|
||||||
"IPLimit" = "IP限制"
|
"IPLimit" = "IP限制"
|
||||||
"IPLimitDesc" = "如果超过输入的计数则禁用入站(0 表示禁用限制 ip)"
|
"IPLimitDesc" = "如果超过输入的计数则禁用入站(0 表示禁用限制 ip)"
|
||||||
"Email" = "电子邮件"
|
"Email" = "电子邮件"
|
||||||
|
|
Loading…
Reference in a new issue