feature/9

9 / ClientOnlineIPs api
This commit is contained in:
serogaq 2024-12-10 16:31:43 +03:00
parent 26abb907a0
commit 42d5dcb17e
No known key found for this signature in database
GPG key ID: 6657A27160536D7E
6 changed files with 78 additions and 2 deletions

View file

@ -12,6 +12,10 @@ import (
"github.com/gin-gonic/gin"
)
type ClientOnlineIPsResponse struct {
Count int `json:"count"`
}
type InboundController struct {
inboundService service.InboundService
xrayService service.XrayService
@ -30,6 +34,7 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) {
g.POST("/add", a.addInbound)
g.POST("/del/:id", a.delInbound)
g.POST("/update/:id", a.updateInbound)
g.POST("/clientOnlineIps/:email", a.getClientOnlineIPs)
g.POST("/clientIps/:email", a.getClientIps)
g.POST("/clearClientIps/:email", a.clearClientIps)
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) {
email := c.Param("email")

View file

@ -46,8 +46,13 @@ func jsonMsgObj(c *gin.Context, msg string, obj interface{}, err error) {
}
} else {
m.Success = false
m.Msg = msg + " " + I18nWeb(c, "fail") + ": " + err.Error()
logger.Warning(msg+" "+I18nWeb(c, "fail")+": ", err)
if msg != "" {
m.Msg = msg + " " + I18nWeb(c, "fail") + ": " + err.Error()
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)
}

View file

@ -1855,6 +1855,18 @@ func (s *InboundService) SearchClientTraffic(query string) (traffic *xray.Client
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) {
db := database.GetDB()
InboundClientIps := &model.InboundClientIps{}

View file

@ -61,6 +61,7 @@ type Status struct {
State ProcessState `json:"state"`
ErrorMsg string `json:"errorMsg"`
Version string `json:"version"`
ApiPort string `json:"apiPort"`
} `json:"xray"`
Uptime uint64 `json:"uptime"`
Loads []float64 `json:"loads"`
@ -239,6 +240,7 @@ func (s *ServerService) GetStatus(lastStatus *Status) *Status {
status.Xray.ErrorMsg = s.xrayService.GetXrayResult()
}
status.Xray.Version = s.xrayService.GetXrayVersion()
status.Xray.ApiPort = s.xrayService.GetXrayApiPort()
var rtm runtime.MemStats
runtime.ReadMemStats(&rtm)

View file

@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"sync"
"strconv"
"x-ui/logger"
"x-ui/xray"
@ -56,6 +57,13 @@ func (s *XrayService) GetXrayVersion() string {
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{} {
return append(s[:index], s[index+1:]...)
}

View file

@ -204,6 +204,35 @@ func (x *XrayAPI) GetTraffic(reset bool) ([]*Traffic, []*ClientTraffic, error) {
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) {
isInbound := matches[1] == "inbound"
tag := matches[2]