Files
HomeDash-Backend/utility/network_utils/node_utils.go
2023-10-03 15:57:52 +08:00

130 lines
3.3 KiB
Go

package network_utils
import (
"context"
"crypto/tls"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/gclient"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
"home-network-watcher/manifest"
"net/http"
"time"
)
type uNodeUtils struct{}
var NodeUtils = &uNodeUtils{}
// GetNodeInfo
//
// @dc: 获取节点信息
// @author: laixin @date:2023/4/2 20:08:50
func (u *uNodeUtils) GetNodeInfo() (err error) {
var (
connectedNode string
lastChangeTime string
nodeInfo = g.Map{
"nodeName": "",
"lastChangeTime": "",
"updateTime": "",
}
)
// 获取token
token, err := u.GetToken()
if err != nil {
return err
}
wsUrl := "ws://" + manifest.XrayBaseUrl + "/api/message?Authorization=" + token
// websocket获取节点列表
client := gclient.NewWebSocket()
client.HandshakeTimeout = time.Second // 设置超时时间
client.Proxy = http.ProxyFromEnvironment // 设置代理
client.TLSClientConfig = &tls.Config{} // 设置 tls 配置
conn, _, err := client.Dial(wsUrl, nil)
if err != nil {
return err
}
_, data, err := conn.ReadMessage()
if err != nil {
return err
}
// 打印消息类型和消息内容
nodeList := gjson.New(string(data)).Get("body.outboundStatus").Array()
for _, v := range nodeList {
if !gjson.New(gconv.String(v)).Get("alive").Bool() {
continue
}
// 根据"delay"获得延迟最小的节点
if connectedNode == "" {
connectedNode = gconv.String(v)
} else {
if gjson.New(connectedNode).Get("delay").Int() > gjson.New(gconv.String(v)).Get("delay").Int() {
connectedNode = gconv.String(v)
}
}
}
// 比对缓存中的节点信息
cacheNodeInfo, _ := gcache.Get(context.Background(), manifest.ProxyNodeCacheKey)
if cacheNodeInfo != nil {
if gjson.New(cacheNodeInfo.String()).Get("nodeName").String() == gjson.New(connectedNode).Get("outbound_tag").String() {
lastChangeTime = gjson.New(cacheNodeInfo).Get("lastChangeTime").String()
} else {
lastChangeTime = gtime.Now().String()
}
} else {
lastChangeTime = gtime.Now().String()
}
// 获取节点信息
nodeInfo["nodeName"] = gjson.New(connectedNode).Get("outbound_tag").String()
nodeInfo["lastChangeTime"] = lastChangeTime
nodeInfo["updateTime"] = gtime.Now().String()
// 关闭连接
_ = conn.Close()
// 存入缓存
err = gcache.Set(context.Background(), manifest.ProxyNodeCacheKey, nodeInfo, 0)
if err != nil {
return err
}
return nil
}
// GetToken
//
// @dc: 获取v2raya面板token
// @author: laixin @date:2023/4/2 20:13:24
func (u *uNodeUtils) GetToken() (token string, err error) {
var (
url = "http://" + manifest.XrayBaseUrl + "/api/login"
)
// 登陆获取token
response, err := g.Client().Post(context.Background(), url, manifest.XrayLoginDataMap)
defer func(response *gclient.Response) {
err := response.Close()
if err != nil {
glog.Warning(context.Background(), err)
}
}(response)
if err != nil {
return "", err
}
resData := gjson.New(response.ReadAllString())
if resData.Get("code").String() != "SUCCESS" {
err = gerror.New("登陆失败")
return
}
token = resData.Get("data.token").String()
if token == "" {
err = gerror.New("token获取失败")
return
}
return
}