mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-04-22 23:45:50 +00:00
parent
8d512d55e5
commit
53fb4fe8f9
1 changed files with 79 additions and 11 deletions
90
xray/api.go
90
xray/api.go
|
|
@ -37,6 +37,34 @@ type XrayAPI struct {
|
||||||
isConnected bool
|
isConnected bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getRequiredUserString(user map[string]any, key string) (string, error) {
|
||||||
|
value, ok := user[key]
|
||||||
|
if !ok || value == nil {
|
||||||
|
return "", fmt.Errorf("missing required user field %q", key)
|
||||||
|
}
|
||||||
|
|
||||||
|
strValue, ok := value.(string)
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("invalid type for user field %q: %T", key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strValue, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getOptionalUserString(user map[string]any, key string) (string, error) {
|
||||||
|
value, ok := user[key]
|
||||||
|
if !ok || value == nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
strValue, ok := value.(string)
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("invalid type for user field %q: %T", key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strValue, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Init connects to the Xray API server and initializes handler and stats service clients.
|
// Init connects to the Xray API server and initializes handler and stats service clients.
|
||||||
func (x *XrayAPI) Init(apiPort int) error {
|
func (x *XrayAPI) Init(apiPort int) error {
|
||||||
if apiPort <= 0 || apiPort > math.MaxUint16 {
|
if apiPort <= 0 || apiPort > math.MaxUint16 {
|
||||||
|
|
@ -104,16 +132,36 @@ func (x *XrayAPI) DelInbound(tag string) error {
|
||||||
|
|
||||||
// AddUser adds a user to an inbound in the Xray core using the specified protocol and user data.
|
// AddUser adds a user to an inbound in the Xray core using the specified protocol and user data.
|
||||||
func (x *XrayAPI) AddUser(Protocol string, inboundTag string, user map[string]any) error {
|
func (x *XrayAPI) AddUser(Protocol string, inboundTag string, user map[string]any) error {
|
||||||
|
userEmail, err := getRequiredUserString(user, "email")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
var account *serial.TypedMessage
|
var account *serial.TypedMessage
|
||||||
switch Protocol {
|
switch Protocol {
|
||||||
case "vmess":
|
case "vmess":
|
||||||
|
userID, err := getRequiredUserString(user, "id")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
account = serial.ToTypedMessage(&vmess.Account{
|
account = serial.ToTypedMessage(&vmess.Account{
|
||||||
Id: user["id"].(string),
|
Id: userID,
|
||||||
})
|
})
|
||||||
case "vless":
|
case "vless":
|
||||||
|
userID, err := getRequiredUserString(user, "id")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
userFlow, err := getOptionalUserString(user, "flow")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
vlessAccount := &vless.Account{
|
vlessAccount := &vless.Account{
|
||||||
Id: user["id"].(string),
|
Id: userID,
|
||||||
Flow: user["flow"].(string),
|
Flow: userFlow,
|
||||||
}
|
}
|
||||||
// Add testseed if provided
|
// Add testseed if provided
|
||||||
if testseedVal, ok := user["testseed"]; ok {
|
if testseedVal, ok := user["testseed"]; ok {
|
||||||
|
|
@ -139,12 +187,27 @@ func (x *XrayAPI) AddUser(Protocol string, inboundTag string, user map[string]an
|
||||||
}
|
}
|
||||||
account = serial.ToTypedMessage(vlessAccount)
|
account = serial.ToTypedMessage(vlessAccount)
|
||||||
case "trojan":
|
case "trojan":
|
||||||
|
password, err := getRequiredUserString(user, "password")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
account = serial.ToTypedMessage(&trojan.Account{
|
account = serial.ToTypedMessage(&trojan.Account{
|
||||||
Password: user["password"].(string),
|
Password: password,
|
||||||
})
|
})
|
||||||
case "shadowsocks":
|
case "shadowsocks":
|
||||||
|
cipher, err := getOptionalUserString(user, "cipher")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
password, err := getRequiredUserString(user, "password")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
var ssCipherType shadowsocks.CipherType
|
var ssCipherType shadowsocks.CipherType
|
||||||
switch user["cipher"].(string) {
|
switch cipher {
|
||||||
case "aes-128-gcm":
|
case "aes-128-gcm":
|
||||||
ssCipherType = shadowsocks.CipherType_AES_128_GCM
|
ssCipherType = shadowsocks.CipherType_AES_128_GCM
|
||||||
case "aes-256-gcm":
|
case "aes-256-gcm":
|
||||||
|
|
@ -159,18 +222,23 @@ func (x *XrayAPI) AddUser(Protocol string, inboundTag string, user map[string]an
|
||||||
|
|
||||||
if ssCipherType != shadowsocks.CipherType_NONE {
|
if ssCipherType != shadowsocks.CipherType_NONE {
|
||||||
account = serial.ToTypedMessage(&shadowsocks.Account{
|
account = serial.ToTypedMessage(&shadowsocks.Account{
|
||||||
Password: user["password"].(string),
|
Password: password,
|
||||||
CipherType: ssCipherType,
|
CipherType: ssCipherType,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
account = serial.ToTypedMessage(&shadowsocks_2022.ServerConfig{
|
account = serial.ToTypedMessage(&shadowsocks_2022.ServerConfig{
|
||||||
Key: user["password"].(string),
|
Key: password,
|
||||||
Email: user["email"].(string),
|
Email: userEmail,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
case "hysteria":
|
case "hysteria":
|
||||||
|
auth, err := getRequiredUserString(user, "auth")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
account = serial.ToTypedMessage(&hysteriaAccount.Account{
|
account = serial.ToTypedMessage(&hysteriaAccount.Account{
|
||||||
Auth: user["auth"].(string),
|
Auth: auth,
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -178,11 +246,11 @@ func (x *XrayAPI) AddUser(Protocol string, inboundTag string, user map[string]an
|
||||||
|
|
||||||
client := *x.HandlerServiceClient
|
client := *x.HandlerServiceClient
|
||||||
|
|
||||||
_, err := client.AlterInbound(context.Background(), &command.AlterInboundRequest{
|
_, err = client.AlterInbound(context.Background(), &command.AlterInboundRequest{
|
||||||
Tag: inboundTag,
|
Tag: inboundTag,
|
||||||
Operation: serial.ToTypedMessage(&command.AddUserOperation{
|
Operation: serial.ToTypedMessage(&command.AddUserOperation{
|
||||||
User: &protocol.User{
|
User: &protocol.User{
|
||||||
Email: user["email"].(string),
|
Email: userEmail,
|
||||||
Account: account,
|
Account: account,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue