Files
V2bX/core/xray/user.go
2025-08-07 15:46:12 +09:00

122 lines
3.2 KiB
Go

package xray
import (
"context"
"fmt"
"github.com/InazumaV/V2bX/api/panel"
"github.com/InazumaV/V2bX/common/counter"
"github.com/InazumaV/V2bX/common/format"
vCore "github.com/InazumaV/V2bX/core"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/proxy"
)
func (c *Xray) GetUserManager(tag string) (proxy.UserManager, error) {
handler, err := c.ihm.GetHandler(context.Background(), tag)
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
}
func (c *Xray) DelUsers(users []panel.UserInfo, tag string, _ *panel.NodeInfo) error {
userManager, err := c.GetUserManager(tag)
if err != nil {
return fmt.Errorf("get user manager error: %s", err)
}
var user string
c.users.mapLock.Lock()
defer c.users.mapLock.Unlock()
for i := range users {
user = format.UserTag(tag, users[i].Uuid)
err = userManager.RemoveUser(context.Background(), user)
if err != nil {
return err
}
delete(c.users.uidMap, user)
c.dispatcher.Counter.Delete(user)
c.dispatcher.Wm.RemoveWritersForUser(user)
}
return nil
}
func (x *Xray) GetUserTrafficSlice(tag string, reset bool) ([]panel.UserTraffic, error) {
trafficSlice := make([]panel.UserTraffic, 0)
x.users.mapLock.RLock()
defer x.users.mapLock.RUnlock()
if v, ok := x.dispatcher.Counter.Load(tag); ok {
c := v.(*counter.TrafficCounter)
c.Counters.Range(func(key, value interface{}) bool {
email := key.(string)
traffic := value.(*counter.TrafficStorage)
up := traffic.UpCounter.Load()
down := traffic.DownCounter.Load()
if up+down > x.nodeReportMinTrafficBytes[tag] {
if reset {
traffic.UpCounter.Store(0)
traffic.DownCounter.Store(0)
}
trafficSlice = append(trafficSlice, panel.UserTraffic{
UID: x.users.uidMap[email],
Upload: up,
Download: down,
})
}
return true
})
if len(trafficSlice) == 0 {
return nil, nil
}
return trafficSlice, nil
}
return nil, nil
}
func (c *Xray) AddUsers(p *vCore.AddUsersParams) (added int, err error) {
c.users.mapLock.Lock()
defer c.users.mapLock.Unlock()
for i := range p.Users {
c.users.uidMap[format.UserTag(p.Tag, p.Users[i].Uuid)] = p.Users[i].Id
}
var users []*protocol.User
switch p.NodeInfo.Type {
case "vmess":
users = buildVmessUsers(p.Tag, p.Users)
case "vless":
users = buildVlessUsers(p.Tag, p.Users, p.VAllss.Flow)
case "trojan":
users = buildTrojanUsers(p.Tag, p.Users)
case "shadowsocks":
users = buildSSUsers(p.Tag,
p.Users,
p.Shadowsocks.Cipher,
p.Shadowsocks.ServerKey)
default:
return 0, fmt.Errorf("unsupported node type: %s", p.NodeInfo.Type)
}
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
}