mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-02-27 20:53:01 +00:00
191 lines
4.9 KiB
Go
191 lines
4.9 KiB
Go
package service
|
|
|
|
import (
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"github.com/mhsanaei/3x-ui/v2/database/model"
|
|
"github.com/mhsanaei/3x-ui/v2/util/common"
|
|
)
|
|
|
|
func (s *InboundService) resolveInboundAndClient(clientEmail string) (*model.Inbound, string, bool, error) {
|
|
_, inbound, err := s.GetClientInboundByEmail(clientEmail)
|
|
if err != nil {
|
|
return nil, "", false, err
|
|
}
|
|
if inbound == nil {
|
|
return nil, "", false, common.NewError("Inbound Not Found For Email:", clientEmail)
|
|
}
|
|
|
|
clients, err := s.GetClients(inbound)
|
|
if err != nil {
|
|
return nil, "", false, err
|
|
}
|
|
|
|
clientID := ""
|
|
clientEnabled := false
|
|
for _, oldClient := range clients {
|
|
if oldClient.Email != clientEmail {
|
|
continue
|
|
}
|
|
switch inbound.Protocol {
|
|
case "trojan":
|
|
clientID = oldClient.Password
|
|
case "shadowsocks":
|
|
clientID = oldClient.Email
|
|
default:
|
|
clientID = oldClient.ID
|
|
}
|
|
clientEnabled = oldClient.Enable
|
|
break
|
|
}
|
|
|
|
if clientID == "" {
|
|
return nil, "", false, common.NewError("Client Not Found For Email:", clientEmail)
|
|
}
|
|
|
|
return inbound, clientID, clientEnabled, nil
|
|
}
|
|
|
|
func (s *InboundService) applySingleClientUpdate(inbound *model.Inbound, clientEmail string, mutate func(client map[string]any)) error {
|
|
var settings map[string]any
|
|
if err := json.Unmarshal([]byte(inbound.Settings), &settings); err != nil {
|
|
return err
|
|
}
|
|
clients, ok := settings["clients"].([]any)
|
|
if !ok {
|
|
return common.NewError("invalid clients format in inbound settings")
|
|
}
|
|
|
|
newClients := make([]any, 0, 1)
|
|
for idx := range clients {
|
|
c, ok := clients[idx].(map[string]any)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if c["email"] != clientEmail {
|
|
continue
|
|
}
|
|
mutate(c)
|
|
c["updated_at"] = time.Now().Unix() * 1000
|
|
newClients = append(newClients, c)
|
|
break
|
|
}
|
|
|
|
if len(newClients) == 0 {
|
|
return common.NewError("Client Not Found For Email:", clientEmail)
|
|
}
|
|
|
|
settings["clients"] = newClients
|
|
modifiedSettings, err := json.MarshalIndent(settings, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
inbound.Settings = string(modifiedSettings)
|
|
return nil
|
|
}
|
|
|
|
func (s *InboundService) SetClientTelegramUserID(trafficId int, tgId int64) (bool, error) {
|
|
traffic, inbound, err := s.GetClientInboundByTrafficID(trafficId)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if inbound == nil {
|
|
return false, common.NewError("Inbound Not Found For Traffic ID:", trafficId)
|
|
}
|
|
clientEmail := traffic.Email
|
|
|
|
_, clientID, _, err := s.resolveInboundAndClient(clientEmail)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if err := s.applySingleClientUpdate(inbound, clientEmail, func(client map[string]any) {
|
|
client["tgId"] = tgId
|
|
}); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
needRestart, err := s.UpdateInboundClient(inbound, clientID)
|
|
return needRestart, err
|
|
}
|
|
|
|
func (s *InboundService) checkIsEnabledByEmail(clientEmail string) (bool, error) {
|
|
_, _, enabled, err := s.resolveInboundAndClient(clientEmail)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return enabled, nil
|
|
}
|
|
|
|
func (s *InboundService) ToggleClientEnableByEmail(clientEmail string) (bool, bool, error) {
|
|
inbound, clientID, oldEnabled, err := s.resolveInboundAndClient(clientEmail)
|
|
if err != nil {
|
|
return false, false, err
|
|
}
|
|
|
|
if err := s.applySingleClientUpdate(inbound, clientEmail, func(client map[string]any) {
|
|
client["enable"] = !oldEnabled
|
|
}); err != nil {
|
|
return false, false, err
|
|
}
|
|
|
|
needRestart, err := s.UpdateInboundClient(inbound, clientID)
|
|
if err != nil {
|
|
return false, needRestart, err
|
|
}
|
|
|
|
return !oldEnabled, needRestart, nil
|
|
}
|
|
|
|
func (s *InboundService) ResetClientIpLimitByEmail(clientEmail string, count int) (bool, error) {
|
|
inbound, clientID, _, err := s.resolveInboundAndClient(clientEmail)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if err := s.applySingleClientUpdate(inbound, clientEmail, func(client map[string]any) {
|
|
client["limitIp"] = count
|
|
}); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
needRestart, err := s.UpdateInboundClient(inbound, clientID)
|
|
return needRestart, err
|
|
}
|
|
|
|
func (s *InboundService) ResetClientExpiryTimeByEmail(clientEmail string, expiryTime int64) (bool, error) {
|
|
inbound, clientID, _, err := s.resolveInboundAndClient(clientEmail)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if err := s.applySingleClientUpdate(inbound, clientEmail, func(client map[string]any) {
|
|
client["expiryTime"] = expiryTime
|
|
}); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
needRestart, err := s.UpdateInboundClient(inbound, clientID)
|
|
return needRestart, err
|
|
}
|
|
|
|
func (s *InboundService) ResetClientTrafficLimitByEmail(clientEmail string, totalGB int) (bool, error) {
|
|
if totalGB < 0 {
|
|
return false, common.NewError("totalGB must be >= 0")
|
|
}
|
|
|
|
inbound, clientID, _, err := s.resolveInboundAndClient(clientEmail)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if err := s.applySingleClientUpdate(inbound, clientEmail, func(client map[string]any) {
|
|
client["totalGB"] = totalGB * 1024 * 1024 * 1024
|
|
}); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
needRestart, err := s.UpdateInboundClient(inbound, clientID)
|
|
return needRestart, err
|
|
}
|