2022-08-12 06:02:06 -04:00
|
|
|
package core
|
2022-07-28 11:00:05 -04:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
2023-05-22 09:01:31 -04:00
|
|
|
"github.com/Yuzuki616/V2bX/api/panel"
|
|
|
|
"github.com/Yuzuki616/V2bX/common/builder"
|
|
|
|
"github.com/Yuzuki616/V2bX/conf"
|
2022-07-28 11:00:05 -04:00
|
|
|
"github.com/xtls/xray-core/common/protocol"
|
|
|
|
"github.com/xtls/xray-core/proxy"
|
2023-05-22 09:01:31 -04:00
|
|
|
"github.com/xtls/xray-core/proxy/shadowsocks"
|
|
|
|
"strings"
|
2022-07-28 11:00:05 -04:00
|
|
|
)
|
|
|
|
|
2023-05-22 09:01:31 -04:00
|
|
|
func (c *Core) GetUserManager(tag string) (proxy.UserManager, error) {
|
|
|
|
handler, err := c.ihm.GetHandler(context.Background(), tag)
|
2022-07-28 11:00:05 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("no such inbound tag: %s", err)
|
|
|
|
}
|
|
|
|
inboundInstance, ok := handler.(proxy.GetInbound)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("handler %s is not implement proxy.GetInbound", tag)
|
|
|
|
}
|
|
|
|
userManager, ok := inboundInstance.GetInbound().(proxy.UserManager)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("handler %s is not implement proxy.UserManager", tag)
|
|
|
|
}
|
|
|
|
return userManager, nil
|
|
|
|
}
|
|
|
|
|
2023-05-22 09:01:31 -04:00
|
|
|
func (c *Core) RemoveUsers(users []string, tag string) error {
|
|
|
|
userManager, err := c.GetUserManager(tag)
|
2022-07-28 11:00:05 -04:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("get user manager error: %s", err)
|
|
|
|
}
|
|
|
|
for _, email := range users {
|
|
|
|
err = userManager.RemoveUser(context.Background(), email)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-05-22 09:01:31 -04:00
|
|
|
func (c *Core) GetUserTraffic(email string, reset bool) (up int64, down int64) {
|
2022-07-28 11:00:05 -04:00
|
|
|
upName := "user>>>" + email + ">>>traffic>>>uplink"
|
|
|
|
downName := "user>>>" + email + ">>>traffic>>>downlink"
|
2023-05-22 09:01:31 -04:00
|
|
|
upCounter := c.shm.GetCounter(upName)
|
|
|
|
downCounter := c.shm.GetCounter(downName)
|
2022-09-07 05:26:12 -04:00
|
|
|
if reset {
|
|
|
|
if upCounter != nil {
|
|
|
|
up = upCounter.Set(0)
|
|
|
|
}
|
|
|
|
if downCounter != nil {
|
|
|
|
down = downCounter.Set(0)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if upCounter != nil {
|
|
|
|
up = upCounter.Value()
|
|
|
|
}
|
|
|
|
if downCounter != nil {
|
|
|
|
down = downCounter.Value()
|
|
|
|
}
|
2022-07-28 11:00:05 -04:00
|
|
|
}
|
|
|
|
return up, down
|
|
|
|
}
|
2023-05-22 09:01:31 -04:00
|
|
|
|
|
|
|
type AddUsersParams struct {
|
|
|
|
Tag string
|
|
|
|
Config *conf.ControllerConfig
|
|
|
|
UserInfo []panel.UserInfo
|
|
|
|
NodeInfo *panel.NodeInfo
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) AddUsers(p *AddUsersParams) (added int, err error) {
|
|
|
|
users := make([]*protocol.User, 0, len(p.UserInfo))
|
|
|
|
switch p.NodeInfo.NodeType {
|
|
|
|
case "v2ray":
|
|
|
|
if p.Config.EnableVless {
|
|
|
|
users = builder.BuildVlessUsers(p.Tag, p.UserInfo, p.Config.EnableXtls)
|
|
|
|
} else {
|
|
|
|
users = builder.BuildVmessUsers(p.Tag, p.UserInfo)
|
|
|
|
}
|
|
|
|
case "trojan":
|
|
|
|
users = builder.BuildTrojanUsers(p.Tag, p.UserInfo)
|
|
|
|
case "shadowsocks":
|
|
|
|
users = builder.BuildSSUsers(p.Tag,
|
|
|
|
p.UserInfo,
|
|
|
|
getCipherFromString(p.NodeInfo.Cipher),
|
|
|
|
p.NodeInfo.ServerKey)
|
|
|
|
default:
|
|
|
|
return 0, fmt.Errorf("unsupported node type: %s", p.NodeInfo.NodeType)
|
|
|
|
}
|
|
|
|
man, err := c.GetUserManager(p.Tag)
|
|
|
|
if err != nil {
|
|
|
|
return 0, fmt.Errorf("get user manager error: %s", err)
|
|
|
|
}
|
|
|
|
for _, u := range users {
|
|
|
|
mUser, err := u.ToMemoryUser()
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
err = man.AddUser(context.Background(), mUser)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return len(users), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func getCipherFromString(c string) shadowsocks.CipherType {
|
|
|
|
switch strings.ToLower(c) {
|
|
|
|
case "aes-128-gcm", "aead_aes_128_gcm":
|
|
|
|
return shadowsocks.CipherType_AES_128_GCM
|
|
|
|
case "aes-256-gcm", "aead_aes_256_gcm":
|
|
|
|
return shadowsocks.CipherType_AES_256_GCM
|
|
|
|
case "chacha20-poly1305", "aead_chacha20_poly1305", "chacha20-ietf-poly1305":
|
|
|
|
return shadowsocks.CipherType_CHACHA20_POLY1305
|
|
|
|
case "none", "plain":
|
|
|
|
return shadowsocks.CipherType_NONE
|
|
|
|
default:
|
|
|
|
return shadowsocks.CipherType_UNKNOWN
|
|
|
|
}
|
|
|
|
}
|