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:
authorAlireza Ahmadi <alireza7@gmail.com>2023-12-04 21:20:16 +0300
committerAlireza Ahmadi <alireza7@gmail.com>2023-12-04 21:20:16 +0300
commita8b7063647c055988f3768a35af59ca391928b9b (patch)
treef6038c94629ec22f6c4c7ce507ef96fc16e56518 /web/service
parent729d8549e2b536a10c402a88e0d4cfde9e4baf3f (diff)
auto renew feature #1286
Diffstat (limited to 'web/service')
-rw-r--r--web/service/inbound.go148
1 files changed, 125 insertions, 23 deletions
diff --git a/web/service/inbound.go b/web/service/inbound.go
index 5972d9a5..4ce93f31 100644
--- a/web/service/inbound.go
+++ b/web/service/inbound.go
@@ -263,7 +263,18 @@ func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound,
tag := oldInbound.Tag
- err = s.updateClientTraffics(oldInbound, inbound)
+ db := database.GetDB()
+ tx := db.Begin()
+
+ defer func() {
+ if err != nil {
+ tx.Rollback()
+ } else {
+ tx.Commit()
+ }
+ }()
+
+ err = s.updateClientTraffics(tx, oldInbound, inbound)
if err != nil {
return inbound, false, err
}
@@ -304,11 +315,10 @@ func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound,
}
s.xrayApi.Close()
- db := database.GetDB()
- return inbound, needRestart, db.Save(oldInbound).Error
+ return inbound, needRestart, tx.Save(oldInbound).Error
}
-func (s *InboundService) updateClientTraffics(oldInbound *model.Inbound, newInbound *model.Inbound) error {
+func (s *InboundService) updateClientTraffics(tx *gorm.DB, oldInbound *model.Inbound, newInbound *model.Inbound) error {
oldClients, err := s.GetClients(oldInbound)
if err != nil {
return err
@@ -318,17 +328,6 @@ func (s *InboundService) updateClientTraffics(oldInbound *model.Inbound, newInbo
return err
}
- db := database.GetDB()
- tx := db.Begin()
-
- defer func() {
- if err != nil {
- tx.Rollback()
- } else {
- tx.Commit()
- }
- }()
-
var emailExists bool
for _, oldClient := range oldClients {
@@ -601,7 +600,7 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin
if len(clients[0].Email) > 0 {
if len(oldEmail) > 0 {
- err = s.UpdateClientStat(oldEmail, &clients[0])
+ err = s.UpdateClientStat(tx, oldEmail, &clients[0])
if err != nil {
return false, err
}
@@ -676,6 +675,13 @@ func (s *InboundService) AddTraffic(inboundTraffics []*xray.Traffic, clientTraff
return err, false
}
+ needRestart0, count, err := s.autoRenewClients(tx)
+ if err != nil {
+ logger.Warning("Error in renew clients:", err)
+ } else if count > 0 {
+ logger.Debugf("%v clients renewed", count)
+ }
+
needRestart1, count, err := s.disableInvalidClients(tx)
if err != nil {
logger.Warning("Error in disabling invalid clients:", err)
@@ -689,7 +695,7 @@ func (s *InboundService) AddTraffic(inboundTraffics []*xray.Traffic, clientTraff
} else if count > 0 {
logger.Debugf("%v inbounds disabled", count)
}
- return nil, (needRestart1 || needRestart2)
+ return nil, (needRestart0 || needRestart1 || needRestart2)
}
func (s *InboundService) addInboundTraffic(tx *gorm.DB, traffics []*xray.Traffic) error {
@@ -823,6 +829,102 @@ func (s *InboundService) adjustTraffics(tx *gorm.DB, dbClientTraffics []*xray.Cl
return dbClientTraffics, nil
}
+func (s *InboundService) autoRenewClients(tx *gorm.DB) (bool, int64, error) {
+ // check for time expired
+ var traffics []*xray.ClientTraffic
+ now := time.Now().Unix() * 1000
+ var err, err1 error
+
+ err = tx.Model(xray.ClientTraffic{}).Where("reset > 0 and expiry_time > 0 and expiry_time <= ?", now).Find(&traffics).Error
+ if err != nil {
+ return false, 0, err
+ }
+ // return if there is no client to renew
+ if len(traffics) == 0 {
+ return false, 0, nil
+ }
+
+ var inbound_ids []int
+ var inbounds []*model.Inbound
+ needRestart := false
+ var clientsToAdd []struct {
+ protocol string
+ tag string
+ client map[string]interface{}
+ }
+
+ for _, traffic := range traffics {
+ inbound_ids = append(inbound_ids, traffic.InboundId)
+ }
+ err = tx.Model(model.Inbound{}).Where("id IN ?", inbound_ids).Find(&inbounds).Error
+ if err != nil {
+ return false, 0, err
+ }
+ for inbound_index := range inbounds {
+ settings := map[string]interface{}{}
+ json.Unmarshal([]byte(inbounds[inbound_index].Settings), &settings)
+ clients := settings["clients"].([]interface{})
+ for client_index := range clients {
+ c := clients[client_index].(map[string]interface{})
+ for traffic_index, traffic := range traffics {
+ if traffic.Email == c["email"].(string) {
+ newExpiryTime := traffic.ExpiryTime
+ for newExpiryTime < now {
+ newExpiryTime += (int64(traffic.Reset) * 86400000)
+ }
+ c["expiryTime"] = newExpiryTime
+ traffics[traffic_index].ExpiryTime = newExpiryTime
+ traffics[traffic_index].Down = 0
+ traffics[traffic_index].Up = 0
+ if !traffic.Enable {
+ traffics[traffic_index].Enable = true
+ clientsToAdd = append(clientsToAdd,
+ struct {
+ protocol string
+ tag string
+ client map[string]interface{}
+ }{
+ protocol: string(inbounds[inbound_index].Protocol),
+ tag: inbounds[inbound_index].Tag,
+ client: c,
+ })
+ }
+ clients[client_index] = interface{}(c)
+ break
+ }
+ }
+ }
+ settings["clients"] = clients
+ newSettings, err := json.MarshalIndent(settings, "", " ")
+ if err != nil {
+ return false, 0, err
+ }
+ inbounds[inbound_index].Settings = string(newSettings)
+ }
+ err = tx.Save(inbounds).Error
+ if err != nil {
+ return false, 0, err
+ }
+ err = tx.Save(traffics).Error
+ if err != nil {
+ return false, 0, err
+ }
+ if p != nil {
+ err1 = s.xrayApi.Init(p.GetAPIPort())
+ if err1 != nil {
+ return true, int64(len(traffics)), nil
+ }
+ for _, clientToAdd := range clientsToAdd {
+ err1 = s.xrayApi.AddUser(clientToAdd.protocol, clientToAdd.tag, clientToAdd.client)
+ if err1 != nil {
+ needRestart = true
+ }
+ }
+ s.xrayApi.Close()
+ }
+ return needRestart, int64(len(traffics)), nil
+}
+
func (s *InboundService) disableInvalidInbounds(tx *gorm.DB) (bool, int64, error) {
now := time.Now().Unix() * 1000
needRestart := false
@@ -916,6 +1018,7 @@ func (s *InboundService) AddClientStat(tx *gorm.DB, inboundId int, client *model
clientTraffic.Enable = true
clientTraffic.Up = 0
clientTraffic.Down = 0
+ clientTraffic.Reset = client.Reset
result := tx.Create(&clientTraffic)
err := result.Error
if err != nil {
@@ -924,16 +1027,15 @@ func (s *InboundService) AddClientStat(tx *gorm.DB, inboundId int, client *model
return nil
}
-func (s *InboundService) UpdateClientStat(email string, client *model.Client) error {
- db := database.GetDB()
-
- result := db.Model(xray.ClientTraffic{}).
+func (s *InboundService) UpdateClientStat(tx *gorm.DB, email string, client *model.Client) error {
+ result := tx.Model(xray.ClientTraffic{}).
Where("email = ?", email).
Updates(map[string]interface{}{
"enable": true,
"email": client.Email,
"total": client.TotalGB,
- "expiry_time": client.ExpiryTime})
+ "expiry_time": client.ExpiryTime,
+ "reset": client.Reset})
err := result.Error
if err != nil {
return err
@@ -1429,7 +1531,7 @@ func (s *InboundService) DelDepletedClients(id int) (err error) {
}
}()
- whereText := "inbound_id "
+ whereText := "reset = 0 and inbound_id "
if id < 0 {
whereText += "> ?"
} else {