[feature] using xray API for inbound
Co-Authored-By: Alireza Ahmadi <alireza7@gmail.com>
This commit is contained in:
+14
-12
@@ -3,7 +3,6 @@ package controller
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"x-ui/database/model"
|
||||
"x-ui/logger"
|
||||
"x-ui/web/global"
|
||||
@@ -99,11 +98,12 @@ func (a *InboundController) addInbound(c *gin.Context) {
|
||||
}
|
||||
user := session.GetLoginUser(c)
|
||||
inbound.UserId = user.Id
|
||||
inbound.Enable = true
|
||||
inbound.Tag = fmt.Sprintf("inbound-%v", inbound.Port)
|
||||
inbound, err = a.inboundService.AddInbound(inbound)
|
||||
|
||||
needRestart := false
|
||||
inbound, needRestart, err = a.inboundService.AddInbound(inbound)
|
||||
jsonMsgObj(c, I18nWeb(c, "pages.inbounds.create"), inbound, err)
|
||||
if err == nil {
|
||||
if err == nil && needRestart {
|
||||
a.xrayService.SetToNeedRestart()
|
||||
}
|
||||
}
|
||||
@@ -114,9 +114,10 @@ func (a *InboundController) delInbound(c *gin.Context) {
|
||||
jsonMsg(c, I18nWeb(c, "delete"), err)
|
||||
return
|
||||
}
|
||||
err = a.inboundService.DelInbound(id)
|
||||
needRestart := true
|
||||
needRestart, err = a.inboundService.DelInbound(id)
|
||||
jsonMsgObj(c, I18nWeb(c, "delete"), id, err)
|
||||
if err == nil {
|
||||
if err == nil && needRestart {
|
||||
a.xrayService.SetToNeedRestart()
|
||||
}
|
||||
}
|
||||
@@ -135,9 +136,10 @@ func (a *InboundController) updateInbound(c *gin.Context) {
|
||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.update"), err)
|
||||
return
|
||||
}
|
||||
inbound, err = a.inboundService.UpdateInbound(inbound)
|
||||
needRestart := true
|
||||
inbound, needRestart, err = a.inboundService.UpdateInbound(inbound)
|
||||
jsonMsgObj(c, I18nWeb(c, "pages.inbounds.update"), inbound, err)
|
||||
if err == nil {
|
||||
if err == nil && needRestart {
|
||||
a.xrayService.SetToNeedRestart()
|
||||
}
|
||||
}
|
||||
@@ -173,7 +175,7 @@ func (a *InboundController) addInboundClient(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
needRestart := false
|
||||
needRestart := true
|
||||
|
||||
needRestart, err = a.inboundService.AddInboundClient(data)
|
||||
if err != nil {
|
||||
@@ -194,7 +196,7 @@ func (a *InboundController) delInboundClient(c *gin.Context) {
|
||||
}
|
||||
clientId := c.Param("clientId")
|
||||
|
||||
needRestart := false
|
||||
needRestart := true
|
||||
|
||||
needRestart, err = a.inboundService.DelInboundClient(id, clientId)
|
||||
if err != nil {
|
||||
@@ -217,7 +219,7 @@ func (a *InboundController) updateInboundClient(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
needRestart := false
|
||||
needRestart := true
|
||||
|
||||
needRestart, err = a.inboundService.UpdateInboundClient(inbound, clientId)
|
||||
if err != nil {
|
||||
@@ -238,7 +240,7 @@ func (a *InboundController) resetClientTraffic(c *gin.Context) {
|
||||
}
|
||||
email := c.Param("email")
|
||||
|
||||
needRestart := false
|
||||
needRestart := true
|
||||
|
||||
needRestart, err = a.inboundService.ResetClientTraffic(id, email)
|
||||
if err != nil {
|
||||
|
||||
@@ -25,11 +25,13 @@ func (j *CheckInboundJob) Run() {
|
||||
}
|
||||
}
|
||||
|
||||
count, err = j.inboundService.DisableInvalidInbounds()
|
||||
needRestart, count, err = j.inboundService.DisableInvalidInbounds()
|
||||
if err != nil {
|
||||
logger.Warning("Error in disabling invalid inbounds:", err)
|
||||
} else if count > 0 {
|
||||
logger.Debugf("%v inbounds disabled", count)
|
||||
j.xrayService.SetToNeedRestart()
|
||||
if needRestart {
|
||||
j.xrayService.SetToNeedRestart()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+130
-37
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"x-ui/database"
|
||||
"x-ui/database/model"
|
||||
"x-ui/logger"
|
||||
@@ -75,6 +74,7 @@ func (s *InboundService) getAllEmails() ([]string, error) {
|
||||
FROM inbounds,
|
||||
JSON_EACH(JSON_EXTRACT(inbounds.settings, '$.clients')) AS client
|
||||
`).Scan(&emails).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -134,26 +134,26 @@ func (s *InboundService) checkEmailExistForInbound(inbound *model.Inbound) (stri
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (s *InboundService) AddInbound(inbound *model.Inbound) (*model.Inbound, error) {
|
||||
func (s *InboundService) AddInbound(inbound *model.Inbound) (*model.Inbound, bool, error) {
|
||||
exist, err := s.checkPortExist(inbound.Port, 0)
|
||||
if err != nil {
|
||||
return inbound, err
|
||||
return inbound, false, err
|
||||
}
|
||||
if exist {
|
||||
return inbound, common.NewError("Port already exists:", inbound.Port)
|
||||
return inbound, false, common.NewError("Port already exists:", inbound.Port)
|
||||
}
|
||||
|
||||
existEmail, err := s.checkEmailExistForInbound(inbound)
|
||||
if err != nil {
|
||||
return inbound, err
|
||||
return inbound, false, err
|
||||
}
|
||||
if existEmail != "" {
|
||||
return inbound, common.NewError("Duplicate email:", existEmail)
|
||||
return inbound, false, common.NewError("Duplicate email:", existEmail)
|
||||
}
|
||||
|
||||
clients, err := s.GetClients(inbound)
|
||||
if err != nil {
|
||||
return inbound, err
|
||||
return inbound, false, err
|
||||
}
|
||||
|
||||
db := database.GetDB()
|
||||
@@ -172,7 +172,26 @@ func (s *InboundService) AddInbound(inbound *model.Inbound) (*model.Inbound, err
|
||||
s.AddClientStat(tx, inbound.Id, &client)
|
||||
}
|
||||
}
|
||||
return inbound, err
|
||||
|
||||
needRestart := false
|
||||
if inbound.Enable {
|
||||
s.xrayApi.Init(p.GetAPIPort())
|
||||
inboundJson, err1 := json.MarshalIndent(inbound.GenXrayInboundConfig(), "", " ")
|
||||
if err1 != nil {
|
||||
logger.Debug("Unable to marshal inbound config:", err1)
|
||||
}
|
||||
|
||||
err1 = s.xrayApi.AddInbound(inboundJson)
|
||||
if err1 == nil {
|
||||
logger.Debug("New inbound added by api:", inbound.Tag)
|
||||
} else {
|
||||
logger.Debug("Unable to add inbound by api:", err1)
|
||||
needRestart = true
|
||||
}
|
||||
s.xrayApi.Close()
|
||||
}
|
||||
|
||||
return inbound, needRestart, err
|
||||
}
|
||||
|
||||
func (s *InboundService) AddInbounds(inbounds []*model.Inbound) error {
|
||||
@@ -207,27 +226,47 @@ func (s *InboundService) AddInbounds(inbounds []*model.Inbound) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *InboundService) DelInbound(id int) error {
|
||||
func (s *InboundService) DelInbound(id int) (bool, error) {
|
||||
db := database.GetDB()
|
||||
|
||||
var tag string
|
||||
needRestart := false
|
||||
result := db.Model(model.Inbound{}).Select("tag").Where("id = ? and enable = ?", id, true).First(&tag)
|
||||
if result.Error == nil {
|
||||
s.xrayApi.Init(p.GetAPIPort())
|
||||
err1 := s.xrayApi.DelInbound(tag)
|
||||
if err1 == nil {
|
||||
logger.Debug("Inbound deleted by api:", tag)
|
||||
} else {
|
||||
logger.Debug("Unable to delete inbound by api:", err1)
|
||||
needRestart = true
|
||||
}
|
||||
s.xrayApi.Close()
|
||||
} else {
|
||||
logger.Debug("No enabled inbound founded to removing by api", tag)
|
||||
}
|
||||
|
||||
// Delete client traffics of inbounds
|
||||
err := db.Where("inbound_id = ?", id).Delete(xray.ClientTraffic{}).Error
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
inbound, err := s.GetInbound(id)
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
clients, err := s.GetClients(inbound)
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
for _, client := range clients {
|
||||
err := s.DelClientIPs(db, client.Email)
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return db.Delete(model.Inbound{}, id).Error
|
||||
|
||||
return needRestart, db.Delete(model.Inbound{}, id).Error
|
||||
}
|
||||
|
||||
func (s *InboundService) GetInbound(id int) (*model.Inbound, error) {
|
||||
@@ -240,23 +279,25 @@ func (s *InboundService) GetInbound(id int) (*model.Inbound, error) {
|
||||
return inbound, nil
|
||||
}
|
||||
|
||||
func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound, error) {
|
||||
func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound, bool, error) {
|
||||
exist, err := s.checkPortExist(inbound.Port, inbound.Id)
|
||||
if err != nil {
|
||||
return inbound, err
|
||||
return inbound, false, err
|
||||
}
|
||||
if exist {
|
||||
return inbound, common.NewError("Port already exists:", inbound.Port)
|
||||
return inbound, false, common.NewError("Port already exists:", inbound.Port)
|
||||
}
|
||||
|
||||
oldInbound, err := s.GetInbound(inbound.Id)
|
||||
if err != nil {
|
||||
return inbound, err
|
||||
return inbound, false, err
|
||||
}
|
||||
|
||||
tag := oldInbound.Tag
|
||||
|
||||
err = s.updateClientTraffics(oldInbound, inbound)
|
||||
if err != nil {
|
||||
return inbound, err
|
||||
return inbound, false, err
|
||||
}
|
||||
|
||||
oldInbound.Up = inbound.Up
|
||||
@@ -273,8 +314,34 @@ func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound,
|
||||
oldInbound.Sniffing = inbound.Sniffing
|
||||
oldInbound.Tag = fmt.Sprintf("inbound-%v", inbound.Port)
|
||||
|
||||
needRestart := false
|
||||
s.xrayApi.Init(p.GetAPIPort())
|
||||
err1 := s.xrayApi.DelInbound(tag)
|
||||
if err1 != nil {
|
||||
logger.Debug("Unable to delete old inbound by api:", err1)
|
||||
needRestart = true
|
||||
} else {
|
||||
logger.Debug("Old inbound deleted by api:", tag)
|
||||
|
||||
if inbound.Enable {
|
||||
inboundJson, err2 := json.MarshalIndent(oldInbound.GenXrayInboundConfig(), "", " ")
|
||||
if err2 != nil {
|
||||
logger.Debug("Unable to marshal updated inbound config:", err2)
|
||||
}
|
||||
|
||||
err2 = s.xrayApi.AddInbound(inboundJson)
|
||||
if err1 == nil {
|
||||
logger.Debug("Updated inbound added by api:", oldInbound.Tag)
|
||||
} else {
|
||||
logger.Debug("Unable to update inbound by api:", err2)
|
||||
needRestart = true
|
||||
}
|
||||
}
|
||||
}
|
||||
s.xrayApi.Close()
|
||||
|
||||
db := database.GetDB()
|
||||
return inbound, db.Save(oldInbound).Error
|
||||
return inbound, needRestart, db.Save(oldInbound).Error
|
||||
}
|
||||
|
||||
func (s *InboundService) updateClientTraffics(oldInbound *model.Inbound, newInbound *model.Inbound) error {
|
||||
@@ -393,16 +460,18 @@ func (s *InboundService) AddInboundClient(data *model.Inbound) (bool, error) {
|
||||
for _, client := range clients {
|
||||
if len(client.Email) > 0 {
|
||||
s.AddClientStat(tx, data.Id, &client)
|
||||
err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]interface{}{
|
||||
"email": client.Email,
|
||||
"id": client.ID,
|
||||
"flow": client.Flow,
|
||||
"password": client.Password,
|
||||
})
|
||||
if err1 == nil {
|
||||
logger.Debug("Client added by api:", client.Email)
|
||||
} else {
|
||||
needRestart = true
|
||||
if client.Enable {
|
||||
err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]interface{}{
|
||||
"email": client.Email,
|
||||
"id": client.ID,
|
||||
"flow": client.Flow,
|
||||
"password": client.Password,
|
||||
})
|
||||
if err1 == nil {
|
||||
logger.Debug("Client added by api:", client.Email)
|
||||
} else {
|
||||
needRestart = true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
needRestart = true
|
||||
@@ -466,7 +535,7 @@ func (s *InboundService) DelInboundClient(inboundId int, clientId string) (bool,
|
||||
logger.Error("Error in delete client IPs")
|
||||
return false, err
|
||||
}
|
||||
needRestart := true
|
||||
needRestart := false
|
||||
s.xrayApi.Init(p.GetAPIPort())
|
||||
if len(email) > 0 {
|
||||
err = s.xrayApi.RemoveUser(oldInbound.Tag, email)
|
||||
@@ -580,7 +649,7 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
needRestart := true
|
||||
needRestart := false
|
||||
s.xrayApi.Init(p.GetAPIPort())
|
||||
if len(oldEmail) > 0 {
|
||||
s.xrayApi.RemoveUser(oldInbound.Tag, oldEmail)
|
||||
@@ -729,15 +798,38 @@ func (s *InboundService) adjustTraffics(tx *gorm.DB, dbClientTraffics []*xray.Cl
|
||||
return dbClientTraffics, nil
|
||||
}
|
||||
|
||||
func (s *InboundService) DisableInvalidInbounds() (int64, error) {
|
||||
func (s *InboundService) DisableInvalidInbounds() (bool, int64, error) {
|
||||
db := database.GetDB()
|
||||
now := time.Now().Unix() * 1000
|
||||
needRestart := false
|
||||
|
||||
if p != nil {
|
||||
var tags []string
|
||||
err := db.Table("inbounds").
|
||||
Select("inbounds.tag").
|
||||
Where("((total > 0 and up + down >= total) or (expiry_time > 0 and expiry_time <= ?)) and enable = ?", now, true).
|
||||
Scan(&tags).Error
|
||||
if err != nil {
|
||||
return false, 0, err
|
||||
}
|
||||
s.xrayApi.Init(p.GetAPIPort())
|
||||
for _, tag := range tags {
|
||||
err = s.xrayApi.DelInbound(tag)
|
||||
if err == nil {
|
||||
logger.Debug("Inbound disabled by api:", tag)
|
||||
} else {
|
||||
needRestart = true
|
||||
}
|
||||
}
|
||||
s.xrayApi.Close()
|
||||
}
|
||||
|
||||
result := db.Model(model.Inbound{}).
|
||||
Where("((total > 0 and up + down >= total) or (expiry_time > 0 and expiry_time <= ?)) and enable = ?", now, true).
|
||||
Update("enable", false)
|
||||
err := result.Error
|
||||
count := result.RowsAffected
|
||||
return count, err
|
||||
return needRestart, count, err
|
||||
}
|
||||
|
||||
func (s *InboundService) DisableInvalidClients() (bool, int64, error) {
|
||||
@@ -763,7 +855,7 @@ func (s *InboundService) DisableInvalidClients() (bool, int64, error) {
|
||||
for _, result := range results {
|
||||
err = s.xrayApi.RemoveUser(result.Tag, result.Email)
|
||||
if err == nil {
|
||||
logger.Debug("Client deleted by api:", result.Email)
|
||||
logger.Debug("Client disabled by api:", result.Email)
|
||||
} else {
|
||||
needRestart = true
|
||||
}
|
||||
@@ -816,8 +908,7 @@ func (s *InboundService) UpdateClientStat(email string, client *model.Client) er
|
||||
"enable": true,
|
||||
"email": client.Email,
|
||||
"total": client.TotalGB,
|
||||
"expiry_time": client.ExpiryTime,
|
||||
})
|
||||
"expiry_time": client.ExpiryTime})
|
||||
err := result.Error
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -1208,6 +1299,7 @@ func (s *InboundService) ResetAllClientTraffics(id int) error {
|
||||
Updates(map[string]interface{}{"enable": true, "up": 0, "down": 0})
|
||||
|
||||
err := result.Error
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1222,6 +1314,7 @@ func (s *InboundService) ResetAllTraffics() error {
|
||||
Updates(map[string]interface{}{"up": 0, "down": 0})
|
||||
|
||||
err := result.Error
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -403,25 +403,20 @@ func (s *ServerService) GetLogs(count string, logLevel string) ([]string, error)
|
||||
}
|
||||
|
||||
func (s *ServerService) GetConfigJson() (interface{}, error) {
|
||||
// Open the file for reading
|
||||
file, err := os.Open(xray.GetConfigPath())
|
||||
config, err := s.xrayService.GetXrayConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Read the file contents
|
||||
fileContents, err := io.ReadAll(file)
|
||||
contents, err := json.MarshalIndent(config, "", " ")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var jsonData interface{}
|
||||
err = json.Unmarshal(fileContents, &jsonData)
|
||||
err = json.Unmarshal(contents, &jsonData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return jsonData, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user