2022-07-28 11:00:05 -04:00
|
|
|
package conf
|
2022-06-01 13:35:41 -04:00
|
|
|
|
2023-08-20 03:13:52 -04:00
|
|
|
import (
|
2023-09-12 13:21:20 -04:00
|
|
|
"fmt"
|
2023-09-22 07:26:21 -04:00
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"strings"
|
2023-11-17 17:05:28 -05:00
|
|
|
|
|
|
|
"github.com/InazumaV/V2bX/common/json5"
|
|
|
|
"github.com/goccy/go-json"
|
2023-08-20 03:13:52 -04:00
|
|
|
)
|
|
|
|
|
2023-05-16 21:46:52 -04:00
|
|
|
type NodeConfig struct {
|
2023-08-20 03:13:52 -04:00
|
|
|
ApiConfig ApiConfig `json:"-"`
|
|
|
|
Options Options `json:"-"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type rawNodeConfig struct {
|
2023-09-12 13:21:20 -04:00
|
|
|
Include string `json:"Include"`
|
|
|
|
ApiRaw json.RawMessage `json:"ApiConfig"`
|
|
|
|
OptRaw json.RawMessage `json:"Options"`
|
2023-05-16 21:46:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
type ApiConfig struct {
|
2023-08-20 03:13:52 -04:00
|
|
|
APIHost string `json:"ApiHost"`
|
|
|
|
NodeID int `json:"NodeID"`
|
|
|
|
Key string `json:"ApiKey"`
|
|
|
|
NodeType string `json:"NodeType"`
|
|
|
|
Timeout int `json:"Timeout"`
|
|
|
|
RuleListPath string `json:"RuleListPath"`
|
|
|
|
}
|
|
|
|
|
2023-08-25 22:57:54 -04:00
|
|
|
func (n *NodeConfig) UnmarshalJSON(data []byte) (err error) {
|
2023-09-12 13:21:20 -04:00
|
|
|
rn := rawNodeConfig{}
|
|
|
|
err = json.Unmarshal(data, &rn)
|
2023-08-20 03:13:52 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-09-12 13:21:20 -04:00
|
|
|
if len(rn.Include) != 0 {
|
2023-09-22 07:26:21 -04:00
|
|
|
file, _ := strings.CutPrefix(rn.Include, ":")
|
|
|
|
switch file {
|
|
|
|
case "http", "https":
|
|
|
|
rsp, err := http.Get(file)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer rsp.Body.Close()
|
|
|
|
data, err = io.ReadAll(json5.NewTrimNodeReader(rsp.Body))
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("open include file error: %s", err)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
f, err := os.Open(rn.Include)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("open include file error: %s", err)
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
data, err = io.ReadAll(json5.NewTrimNodeReader(f))
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("open include file error: %s", err)
|
|
|
|
}
|
2023-09-12 13:21:20 -04:00
|
|
|
}
|
|
|
|
err = json.Unmarshal(data, &rn)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("unmarshal include file error: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-02 14:59:54 -04:00
|
|
|
n.ApiConfig = ApiConfig{
|
|
|
|
APIHost: "http://127.0.0.1",
|
|
|
|
Timeout: 30,
|
|
|
|
}
|
2023-09-12 13:21:20 -04:00
|
|
|
if len(rn.ApiRaw) > 0 {
|
|
|
|
err = json.Unmarshal(rn.ApiRaw, &n.ApiConfig)
|
2023-08-20 03:13:52 -04:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
} else {
|
2023-08-25 22:57:54 -04:00
|
|
|
err = json.Unmarshal(data, &n.ApiConfig)
|
2023-08-20 03:13:52 -04:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2023-09-02 14:59:54 -04:00
|
|
|
|
|
|
|
n.Options = Options{
|
|
|
|
ListenIP: "0.0.0.0",
|
|
|
|
SendIP: "0.0.0.0",
|
|
|
|
CertConfig: NewCertConfig(),
|
|
|
|
}
|
2023-09-12 13:21:20 -04:00
|
|
|
if len(rn.OptRaw) > 0 {
|
|
|
|
err = json.Unmarshal(rn.OptRaw, &n.Options)
|
2023-08-20 03:13:52 -04:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
} else {
|
2023-08-25 22:57:54 -04:00
|
|
|
err = json.Unmarshal(data, &n.Options)
|
2023-08-20 03:13:52 -04:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2023-08-25 22:57:54 -04:00
|
|
|
}
|
2023-09-02 05:30:28 -04:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
type Options struct {
|
2024-02-26 08:00:55 -05:00
|
|
|
Name string `json:"Name"`
|
|
|
|
Core string `json:"Core"`
|
|
|
|
CoreName string `json:"CoreName"`
|
|
|
|
ListenIP string `json:"ListenIP"`
|
|
|
|
SendIP string `json:"SendIP"`
|
|
|
|
DeviceOnlineMinTraffic int64 `json:"DeviceOnlineMinTraffic"`
|
|
|
|
LimitConfig LimitConfig `json:"LimitConfig"`
|
|
|
|
RawOptions json.RawMessage `json:"RawOptions"`
|
|
|
|
XrayOptions *XrayOptions `json:"XrayOptions"`
|
|
|
|
SingOptions *SingOptions `json:"SingOptions"`
|
|
|
|
Hysteria2ConfigPath string `json:"Hysteria2ConfigPath"`
|
|
|
|
CertConfig *CertConfig `json:"CertConfig"`
|
2023-09-02 05:30:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (o *Options) UnmarshalJSON(data []byte) error {
|
|
|
|
type opt Options
|
|
|
|
err := json.Unmarshal(data, (*opt)(o))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
switch o.Core {
|
2023-08-25 22:57:54 -04:00
|
|
|
case "xray":
|
2023-09-02 05:30:28 -04:00
|
|
|
o.XrayOptions = NewXrayOptions()
|
|
|
|
return json.Unmarshal(data, o.XrayOptions)
|
2023-08-25 22:57:54 -04:00
|
|
|
case "sing":
|
2023-09-02 05:30:28 -04:00
|
|
|
o.SingOptions = NewSingOptions()
|
|
|
|
return json.Unmarshal(data, o.SingOptions)
|
2024-02-05 20:59:37 -05:00
|
|
|
case "hysteria2":
|
2024-02-26 08:00:55 -05:00
|
|
|
o.RawOptions = data
|
|
|
|
return nil
|
2023-09-02 05:30:28 -04:00
|
|
|
default:
|
2023-09-02 05:45:32 -04:00
|
|
|
o.Core = ""
|
2023-09-02 05:30:28 -04:00
|
|
|
o.RawOptions = data
|
2023-08-20 03:13:52 -04:00
|
|
|
}
|
2023-09-02 05:30:28 -04:00
|
|
|
return nil
|
2023-05-16 21:46:52 -04:00
|
|
|
}
|