diff options
| author | Alireza Ahmadi <alireza7@gmail.com> | 2023-12-04 21:20:16 +0300 |
|---|---|---|
| committer | Alireza Ahmadi <alireza7@gmail.com> | 2023-12-04 21:20:16 +0300 |
| commit | a8b7063647c055988f3768a35af59ca391928b9b (patch) | |
| tree | f6038c94629ec22f6c4c7ce507ef96fc16e56518 /web/service | |
| parent | 729d8549e2b536a10c402a88e0d4cfde9e4baf3f (diff) | |
auto renew feature #1286
Diffstat (limited to 'web/service')
| -rw-r--r-- | web/service/inbound.go | 148 |
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 { |
