update: refactor newV2board parser's structure

This commit is contained in:
Senis John 2022-12-27 12:00:34 +08:00
parent d44fa11eee
commit a8742426b3
No known key found for this signature in database
GPG Key ID: 845E9E4727C3E1A4
2 changed files with 111 additions and 55 deletions

View File

@ -1,8 +1,47 @@
package newV2board package newV2board
type serverConfig struct {
ServerPort int `json:"server_port"`
BaseConfig struct {
PushInterval int `json:"push_interval"`
PullInterval int `json:"pull_interval"`
} `json:"base_config"`
Routes []route `json:"routes"`
// shadowsocks
Cipher string `json:"cipher"`
Obfs string `json:"obfs"`
ObfsSettings struct {
Path string `json:"path"`
Host string `json:"host"`
} `json:"obfs_settings"`
ServerKey string `json:"server_key"`
// v2ray
Network string `json:"network"`
NetworkSettings struct {
Path string `json:"path"`
Headers struct {
Host string `json:"Host"`
} `json:"headers"`
ServiceName string `json:"serviceName"`
} `json:"networkSettings"`
Tls int `json:"tls"`
// trojan
Host string `json:"host"`
ServerName *string `json:"server_name"`
}
type route struct { type route struct {
Id int `json:"id"` Id int `json:"id"`
Match []string `json:"match"` Match []string `json:"match"`
Action string `json:"action"` Action string `json:"action"`
ActionValue *string `json:"action_value"` ActionValue string `json:"action_value"`
}
type user struct {
Id int `json:"id"`
Uuid string `json:"uuid"`
SpeedLimit int `json:"speed_limit"`
} }

View File

@ -126,7 +126,7 @@ func (c *APIClient) assembleURL(path string) string {
return c.APIHost + path return c.APIHost + path
} }
func (c *APIClient) parseResponse(res *resty.Response, path string, err error) (*simplejson.Json, error) { func (c *APIClient) parseServerConfig(res *resty.Response, path string, err error) (*serverConfig, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("request %s failed: %s", c.assembleURL(path), err) return nil, fmt.Errorf("request %s failed: %s", c.assembleURL(path), err)
} }
@ -135,11 +135,37 @@ func (c *APIClient) parseResponse(res *resty.Response, path string, err error) (
body := res.Body() body := res.Body()
return nil, fmt.Errorf("request %s failed: %s, %s", c.assembleURL(path), string(body), err) return nil, fmt.Errorf("request %s failed: %s, %s", c.assembleURL(path), string(body), err)
} }
rtn, err := simplejson.NewJson(res.Body())
if err != nil { s := new(serverConfig)
if err := json.Unmarshal(res.Body(), s); err != nil {
return nil, fmt.Errorf("ret %s invalid", res.String()) return nil, fmt.Errorf("ret %s invalid", res.String())
} }
return rtn, nil
if s.ServerPort == 0 {
return nil, errors.New("server port must > 0")
}
return s, nil
}
func (c *APIClient) parseUsers(res *resty.Response, path string, err error) ([]*user, error) {
if err != nil {
return nil, fmt.Errorf("request %s failed: %s", c.assembleURL(path), err)
}
if res.StatusCode() > 399 {
body := res.Body()
return nil, fmt.Errorf("request %s failed: %s, %s", c.assembleURL(path), string(body), err)
}
var u []*user
if data, err := simplejson.NewJson(res.Body()); err != nil {
return nil, fmt.Errorf("ret %s invalid", res.String())
} else {
b, _ := data.Get("users").MarshalJSON()
json.Unmarshal(b, &u)
}
return u, nil
} }
// GetNodeInfo will pull NodeInfo Config from panel // GetNodeInfo will pull NodeInfo Config from panel
@ -150,27 +176,26 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
ForceContentType("application/json"). ForceContentType("application/json").
Get(path) Get(path)
response, err := c.parseResponse(res, path, err) server, err := c.parseServerConfig(res, path, err)
if err != nil { if err != nil {
return nil, err return nil, err
} }
c.resp.Store(response) c.resp.Store(server)
switch c.NodeType { switch c.NodeType {
case "V2ray": case "V2ray":
nodeInfo, err = c.parseV2rayNodeResponse(response) nodeInfo, err = c.parseV2rayNodeResponse(server)
case "Trojan": case "Trojan":
nodeInfo, err = c.parseTrojanNodeResponse(response) nodeInfo, err = c.parseTrojanNodeResponse(server)
case "Shadowsocks": case "Shadowsocks":
nodeInfo, err = c.parseSSNodeResponse(response) nodeInfo, err = c.parseSSNodeResponse(server)
default: default:
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType) return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
} }
if err != nil { if err != nil {
res, _ := response.MarshalJSON() return nil, fmt.Errorf("Parse node info failed: %s, \nError: %s", res.String(), err)
return nil, fmt.Errorf("Parse node info failed: %s, \nError: %s", string(res), err)
} }
return nodeInfo, nil return nodeInfo, nil
@ -201,25 +226,23 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
c.eTag = res.Header().Get("Etag") c.eTag = res.Header().Get("Etag")
} }
response, err := c.parseResponse(res, path, err) users, err := c.parseUsers(res, path, err)
if err != nil { if err != nil {
return nil, err return nil, err
} }
numOfUsers := len(response.Get("users").MustArray()) userList := make([]api.UserInfo, len(users))
userList := make([]api.UserInfo, numOfUsers) for i := 0; i < len(users); i++ {
for i := 0; i < numOfUsers; i++ {
user := response.Get("users").GetIndex(i)
u := api.UserInfo{ u := api.UserInfo{
UID: user.Get("id").MustInt(), UID: users[i].Id,
UUID: user.Get("uuid").MustString(), UUID: users[i].Uuid,
} }
// Support 1.7.1 speed limit // Support 1.7.1 speed limit
if c.SpeedLimit > 0 { if c.SpeedLimit > 0 {
u.SpeedLimit = uint64(c.SpeedLimit * 1000000 / 8) u.SpeedLimit = uint64(c.SpeedLimit * 1000000 / 8)
} else { } else {
u.SpeedLimit = user.Get("speed_limit").MustUint64() * 1000000 / 8 u.SpeedLimit = uint64(users[i].SpeedLimit * 1000000 / 8)
} }
u.DeviceLimit = c.DeviceLimit // todo waiting v2board send configuration u.DeviceLimit = c.DeviceLimit // todo waiting v2board send configuration
@ -247,7 +270,7 @@ func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) error {
SetBody(data). SetBody(data).
ForceContentType("application/json"). ForceContentType("application/json").
Post(path) Post(path)
_, err = c.parseResponse(res, path, err) _, err = c.parseServerConfig(res, path, err)
if err != nil { if err != nil {
return err return err
} }
@ -257,9 +280,7 @@ func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) error {
// GetNodeRule implements the API interface // GetNodeRule implements the API interface
func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) { func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) {
var routes []route routes := c.resp.Load().(*serverConfig).Routes
b, _ := c.resp.Load().(*simplejson.Json).Get("routes").MarshalJSON()
json.Unmarshal(b, &routes)
ruleList := c.LocalRuleList ruleList := c.LocalRuleList
@ -291,7 +312,7 @@ func (c *APIClient) ReportIllegal(detectResultList *[]api.DetectResult) error {
} }
// parseTrojanNodeResponse parse the response for the given nodeInfo format // parseTrojanNodeResponse parse the response for the given nodeInfo format
func (c *APIClient) parseTrojanNodeResponse(nodeInfoResponse *simplejson.Json) (*api.NodeInfo, error) { func (c *APIClient) parseTrojanNodeResponse(s *serverConfig) (*api.NodeInfo, error) {
var TLSType = "tls" var TLSType = "tls"
if c.EnableXTLS { if c.EnableXTLS {
TLSType = "xtls" TLSType = "xtls"
@ -301,24 +322,24 @@ func (c *APIClient) parseTrojanNodeResponse(nodeInfoResponse *simplejson.Json) (
nodeInfo := &api.NodeInfo{ nodeInfo := &api.NodeInfo{
NodeType: c.NodeType, NodeType: c.NodeType,
NodeID: c.NodeID, NodeID: c.NodeID,
Port: uint32(nodeInfoResponse.Get("server_port").MustUint64()), Port: uint32(s.ServerPort),
TransportProtocol: "tcp", TransportProtocol: "tcp",
EnableTLS: true, EnableTLS: true,
TLSType: TLSType, TLSType: TLSType,
Host: nodeInfoResponse.Get("host").MustString(), Host: s.Host,
ServiceName: nodeInfoResponse.Get("server_name").MustString(), ServiceName: *s.ServerName,
NameServerConfig: parseDNSConfig(nodeInfoResponse), NameServerConfig: parseDNSConfig(s),
} }
return nodeInfo, nil return nodeInfo, nil
} }
// parseSSNodeResponse parse the response for the given nodeInfo format // parseSSNodeResponse parse the response for the given nodeInfo format
func (c *APIClient) parseSSNodeResponse(nodeInfoResponse *simplejson.Json) (*api.NodeInfo, error) { func (c *APIClient) parseSSNodeResponse(s *serverConfig) (*api.NodeInfo, error) {
var header json.RawMessage var header json.RawMessage
if nodeInfoResponse.Get("obfs").MustString() == "http" { if s.Obfs == "http" {
path := "/" path := "/"
if p := nodeInfoResponse.Get("obfs_settings").Get("path").MustString(); p != "" { if p := s.ObfsSettings.Path; p != "" {
path = p path = p
} }
header, _ = json.Marshal(map[string]any{ header, _ = json.Marshal(map[string]any{
@ -331,17 +352,17 @@ func (c *APIClient) parseSSNodeResponse(nodeInfoResponse *simplejson.Json) (*api
return &api.NodeInfo{ return &api.NodeInfo{
NodeType: c.NodeType, NodeType: c.NodeType,
NodeID: c.NodeID, NodeID: c.NodeID,
Port: uint32(nodeInfoResponse.Get("server_port").MustUint64()), Port: uint32(s.ServerPort),
TransportProtocol: "tcp", TransportProtocol: "tcp",
CypherMethod: nodeInfoResponse.Get("cipher").MustString(), CypherMethod: s.Cipher,
ServerKey: nodeInfoResponse.Get("server_key").MustString(), // shadowsocks2022 share key ServerKey: s.ServerKey, // shadowsocks2022 share key
NameServerConfig: parseDNSConfig(nodeInfoResponse), NameServerConfig: parseDNSConfig(s),
Header: header, Header: header,
}, nil }, nil
} }
// parseV2rayNodeResponse parse the response for the given nodeInfo format // parseV2rayNodeResponse parse the response for the given nodeInfo format
func (c *APIClient) parseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*api.NodeInfo, error) { func (c *APIClient) parseV2rayNodeResponse(s *serverConfig) (*api.NodeInfo, error) {
var ( var (
TLSType = "tls" TLSType = "tls"
path, host, serviceName string path, host, serviceName string
@ -354,19 +375,17 @@ func (c *APIClient) parseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*
TLSType = "xtls" TLSType = "xtls"
} }
transportProtocol := nodeInfoResponse.Get("network").MustString() switch s.Network {
switch transportProtocol {
case "ws": case "ws":
path = nodeInfoResponse.Get("networkSettings").Get("path").MustString() path = s.NetworkSettings.Path
host = nodeInfoResponse.Get("networkSettings").Get("headers").Get("Host").MustString() host = s.NetworkSettings.Headers.Host
case "grpc": case "grpc":
if data, ok := nodeInfoResponse.Get("networkSettings").CheckGet("serviceName"); ok { if s.NetworkSettings.ServiceName != "" {
serviceName = data.MustString() serviceName = s.NetworkSettings.ServiceName
} }
case "tcp": case "tcp":
if data, ok := nodeInfoResponse.Get("networkSettings").CheckGet("headers"); ok { if &s.NetworkSettings.Headers != nil {
if httpHeader, err := data.MarshalJSON(); err != nil { if httpHeader, err := json.Marshal(s.NetworkSettings.Headers); err != nil {
return nil, err return nil, err
} else { } else {
header = httpHeader header = httpHeader
@ -374,7 +393,7 @@ func (c *APIClient) parseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*
} }
} }
if nodeInfoResponse.Get("tls").MustInt() == 1 { if s.Tls == 1 {
enableTLS = true enableTLS = true
} }
@ -382,9 +401,9 @@ func (c *APIClient) parseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*
return &api.NodeInfo{ return &api.NodeInfo{
NodeType: c.NodeType, NodeType: c.NodeType,
NodeID: c.NodeID, NodeID: c.NodeID,
Port: uint32(nodeInfoResponse.Get("server_port").MustUint64()), Port: uint32(s.ServerPort),
AlterID: alterID, AlterID: alterID,
TransportProtocol: transportProtocol, TransportProtocol: s.Network,
EnableTLS: enableTLS, EnableTLS: enableTLS,
TLSType: TLSType, TLSType: TLSType,
Path: path, Path: path,
@ -392,19 +411,17 @@ func (c *APIClient) parseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*
EnableVless: c.EnableVless, EnableVless: c.EnableVless,
ServiceName: serviceName, ServiceName: serviceName,
Header: header, Header: header,
NameServerConfig: parseDNSConfig(nodeInfoResponse), NameServerConfig: parseDNSConfig(s),
}, nil }, nil
} }
func parseDNSConfig(nodeInfoResponse *simplejson.Json) (nameServerList []*conf.NameServerConfig) { func parseDNSConfig(s *serverConfig) (nameServerList []*conf.NameServerConfig) {
var routes []route routes := s.Routes
b, _ := nodeInfoResponse.Get("routes").MarshalJSON()
json.Unmarshal(b, &routes)
for i := range routes { for i := range routes {
if routes[i].Action == "dns" { if routes[i].Action == "dns" {
nameServerList = append(nameServerList, &conf.NameServerConfig{ nameServerList = append(nameServerList, &conf.NameServerConfig{
Address: &conf.Address{Address: net.ParseAddress(*routes[i].ActionValue)}, Address: &conf.Address{Address: net.ParseAddress(routes[i].ActionValue)},
Domains: routes[i].Match, Domains: routes[i].Match,
}) })
} }