mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-05-02 13:18:49 +00:00
feature/9
9 / ClientOnlineIPs api
This commit is contained in:
parent
26abb907a0
commit
42d5dcb17e
6 changed files with 78 additions and 2 deletions
|
@ -12,6 +12,10 @@ import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ClientOnlineIPsResponse struct {
|
||||||
|
Count int `json:"count"`
|
||||||
|
}
|
||||||
|
|
||||||
type InboundController struct {
|
type InboundController struct {
|
||||||
inboundService service.InboundService
|
inboundService service.InboundService
|
||||||
xrayService service.XrayService
|
xrayService service.XrayService
|
||||||
|
@ -30,6 +34,7 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) {
|
||||||
g.POST("/add", a.addInbound)
|
g.POST("/add", a.addInbound)
|
||||||
g.POST("/del/:id", a.delInbound)
|
g.POST("/del/:id", a.delInbound)
|
||||||
g.POST("/update/:id", a.updateInbound)
|
g.POST("/update/:id", a.updateInbound)
|
||||||
|
g.POST("/clientOnlineIps/:email", a.getClientOnlineIPs)
|
||||||
g.POST("/clientIps/:email", a.getClientIps)
|
g.POST("/clientIps/:email", a.getClientIps)
|
||||||
g.POST("/clearClientIps/:email", a.clearClientIps)
|
g.POST("/clearClientIps/:email", a.clearClientIps)
|
||||||
g.POST("/addClient", a.addInboundClient)
|
g.POST("/addClient", a.addInboundClient)
|
||||||
|
@ -146,6 +151,21 @@ func (a *InboundController) updateInbound(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *InboundController) getClientOnlineIPs(c *gin.Context) {
|
||||||
|
email := c.Param("email")
|
||||||
|
|
||||||
|
count, err := a.inboundService.GetClientOnlineIPs(email)
|
||||||
|
res := &ClientOnlineIPsResponse{
|
||||||
|
Count: count,
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
jsonObj(c, res, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonObj(c, res, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *InboundController) getClientIps(c *gin.Context) {
|
func (a *InboundController) getClientIps(c *gin.Context) {
|
||||||
email := c.Param("email")
|
email := c.Param("email")
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,13 @@ func jsonMsgObj(c *gin.Context, msg string, obj interface{}, err error) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m.Success = false
|
m.Success = false
|
||||||
|
if msg != "" {
|
||||||
m.Msg = msg + " " + I18nWeb(c, "fail") + ": " + err.Error()
|
m.Msg = msg + " " + I18nWeb(c, "fail") + ": " + err.Error()
|
||||||
logger.Warning(msg+" "+I18nWeb(c, "fail")+": ", err)
|
logger.Warning(msg+" "+I18nWeb(c, "fail")+": ", err)
|
||||||
|
} else {
|
||||||
|
m.Msg = I18nWeb(c, "fail") + ": " + err.Error()
|
||||||
|
logger.Warning(I18nWeb(c, "fail")+": ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, m)
|
c.JSON(http.StatusOK, m)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1855,6 +1855,18 @@ func (s *InboundService) SearchClientTraffic(query string) (traffic *xray.Client
|
||||||
return traffic, nil
|
return traffic, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *InboundService) GetClientOnlineIPs(email string) (int, error) {
|
||||||
|
s.xrayApi.Init(p.GetAPIPort())
|
||||||
|
defer s.xrayApi.Close()
|
||||||
|
|
||||||
|
count, err := s.xrayApi.GetClientOnlineIPs(email)
|
||||||
|
if err != nil {
|
||||||
|
logger.Debug("Failed to fetch Xray Client Online IPs:", err)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *InboundService) GetInboundClientIps(clientEmail string) (string, error) {
|
func (s *InboundService) GetInboundClientIps(clientEmail string) (string, error) {
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
InboundClientIps := &model.InboundClientIps{}
|
InboundClientIps := &model.InboundClientIps{}
|
||||||
|
|
|
@ -61,6 +61,7 @@ type Status struct {
|
||||||
State ProcessState `json:"state"`
|
State ProcessState `json:"state"`
|
||||||
ErrorMsg string `json:"errorMsg"`
|
ErrorMsg string `json:"errorMsg"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
|
ApiPort string `json:"apiPort"`
|
||||||
} `json:"xray"`
|
} `json:"xray"`
|
||||||
Uptime uint64 `json:"uptime"`
|
Uptime uint64 `json:"uptime"`
|
||||||
Loads []float64 `json:"loads"`
|
Loads []float64 `json:"loads"`
|
||||||
|
@ -239,6 +240,7 @@ func (s *ServerService) GetStatus(lastStatus *Status) *Status {
|
||||||
status.Xray.ErrorMsg = s.xrayService.GetXrayResult()
|
status.Xray.ErrorMsg = s.xrayService.GetXrayResult()
|
||||||
}
|
}
|
||||||
status.Xray.Version = s.xrayService.GetXrayVersion()
|
status.Xray.Version = s.xrayService.GetXrayVersion()
|
||||||
|
status.Xray.ApiPort = s.xrayService.GetXrayApiPort()
|
||||||
var rtm runtime.MemStats
|
var rtm runtime.MemStats
|
||||||
runtime.ReadMemStats(&rtm)
|
runtime.ReadMemStats(&rtm)
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"x-ui/logger"
|
"x-ui/logger"
|
||||||
"x-ui/xray"
|
"x-ui/xray"
|
||||||
|
@ -56,6 +57,13 @@ func (s *XrayService) GetXrayVersion() string {
|
||||||
return p.GetVersion()
|
return p.GetVersion()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *XrayService) GetXrayApiPort() string {
|
||||||
|
if p == nil {
|
||||||
|
return "Unknown"
|
||||||
|
}
|
||||||
|
return strconv.Itoa(p.GetAPIPort())
|
||||||
|
}
|
||||||
|
|
||||||
func RemoveIndex(s []interface{}, index int) []interface{} {
|
func RemoveIndex(s []interface{}, index int) []interface{} {
|
||||||
return append(s[:index], s[index+1:]...)
|
return append(s[:index], s[index+1:]...)
|
||||||
}
|
}
|
||||||
|
|
29
xray/api.go
29
xray/api.go
|
@ -204,6 +204,35 @@ func (x *XrayAPI) GetTraffic(reset bool) ([]*Traffic, []*ClientTraffic, error) {
|
||||||
return mapToSlice(tagTrafficMap), mapToSlice(emailTrafficMap), nil
|
return mapToSlice(tagTrafficMap), mapToSlice(emailTrafficMap), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *XrayAPI) GetClientOnlineIPs(email string) (int, error) {
|
||||||
|
if x.grpcClient == nil {
|
||||||
|
return 0, common.NewError("xray api is not initialized")
|
||||||
|
}
|
||||||
|
|
||||||
|
statName := "user>>>" + email + ">>>online"
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
if x.StatsServiceClient == nil {
|
||||||
|
return 0, common.NewError("xray StatusServiceClient is not initialized")
|
||||||
|
}
|
||||||
|
|
||||||
|
r := &statsService.GetStatsRequest{
|
||||||
|
Name: statName,
|
||||||
|
Reset_: false,
|
||||||
|
}
|
||||||
|
resp, err := (*x.StatsServiceClient).GetStatsOnline(ctx, r)
|
||||||
|
if err != nil {
|
||||||
|
logger.Debug("Failed to query Xray statsonline:", err)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
count := resp.GetStat().Value
|
||||||
|
|
||||||
|
return int(count), nil
|
||||||
|
}
|
||||||
|
|
||||||
func processTraffic(matches []string, value int64, trafficMap map[string]*Traffic) {
|
func processTraffic(matches []string, value int64, trafficMap map[string]*Traffic) {
|
||||||
isInbound := matches[1] == "inbound"
|
isInbound := matches[1] == "inbound"
|
||||||
tag := matches[2]
|
tag := matches[2]
|
||||||
|
|
Loading…
Reference in a new issue