修订cmd,gui;添加导出全部配置功能

This commit is contained in:
e1732a364fed
2000-01-01 00:00:00 +00:00
parent 354d1db459
commit 968b2d6615
11 changed files with 149 additions and 62 deletions

View File

@@ -66,6 +66,8 @@ func init() {
sc := mainM.GetStandardConfFromCurrentState()
interactively_generate_share(&sc)
},
}, &CliCmd{
"【导出标准配置文件】<-当前全部配置", interactively_exportVsConf,
}, &CliCmd{
"【交互生成配置】,超级强大", func() { generateConfigFileInteractively(mainM) },
}, &CliCmd{
@@ -96,29 +98,6 @@ func runCli_func() {
loadPreferences()
/*
langList := []string{"简体中文", "English"}
utils.PrintStr("Welcome to Interactive Mode, please choose a Language \n")
Select := promptui.Select{
Label: "Select Language",
Items: langList,
}
_, result, err := Select.Run()
if err != nil {
fmt.Printf("Prompt failed %v\n", err)
return
}
fmt.Printf("You choose %q\n", result)
if result != langList[0] {
utils.PrintStr("Sorry, language not supported yet \n")
return
}
*/
searcher := func(input string, index int) bool {
pepper := cliCmdList[index]
name := strings.Replace(strings.ToLower(pepper.Name), " ", "", -1)

View File

@@ -5,6 +5,7 @@ package main
import (
"errors"
"fmt"
"os"
"strconv"
"strings"
@@ -15,6 +16,43 @@ import (
"github.com/manifoldco/promptui"
)
func interactively_exportVsConf() {
vc := mainM.GetVSConfFromCurrentState()
bs, e := utils.GetPurgedTomlBytes(vc)
if e != nil {
utils.PrintStr("转换格式错误\n")
utils.PrintStr(e.Error())
utils.PrintStr("\n")
return
}
utils.PrintStr("请输入生成配置文件的名称(不含.toml后缀)\n")
promptDomain := promptui.Prompt{
Label: "文件名",
}
result, err := promptDomain.Run()
if err != nil {
fmt.Println("Prompt failed ", err, result)
return
}
fmt.Printf("你输入了 %s\n", result)
e = os.WriteFile(result+".toml", bs, 0666)
if e != nil {
utils.PrintStr("写入文件错误\n")
utils.PrintStr(e.Error())
utils.PrintStr("\n")
return
}
utils.PrintStr("导出成功!\n")
}
func interactively_generate_share(conf *proxy.StandardConf) {
all := []*CliCmd{
@@ -188,11 +226,12 @@ func interactively_generateConf(confClient, confServer *proxy.StandardConf) {
"vless",
"vmess",
"trojan",
"shadowsocks",
},
}
i3, result, err := select3.Run()
if err != nil || i3 != 0 {
if err != nil {
fmt.Println("Prompt failed ", err, i3)
return
}
@@ -232,7 +271,7 @@ func interactively_generateConf(confClient, confServer *proxy.StandardConf) {
i4, result, err := select4.Run()
if err != nil {
fmt.Println("Prompt failed ", err, i3)
fmt.Println("Prompt failed ", err, i4)
return
}
@@ -286,8 +325,7 @@ func interactively_generateConf(confClient, confServer *proxy.StandardConf) {
utils.PrintStr("请输入你服务端的域名\n")
promptDomain := promptui.Prompt{
Label: "域名",
Validate: func(s string) error { return nil }, //允许不设域名
Label: "域名",
}
result, err = promptDomain.Run()
@@ -310,7 +348,7 @@ func interactively_generateConf(confClient, confServer *proxy.StandardConf) {
i5, result, err := select5.Run()
if err != nil {
fmt.Println("Prompt failed ", err, i3)
fmt.Println("Prompt failed ", err, i5)
return
}
if i5 == 0 {
@@ -358,7 +396,7 @@ func interactively_generateConf(confClient, confServer *proxy.StandardConf) {
i6, result, err := select6.Run()
if err != nil {
fmt.Println("Prompt failed ", err, i3)
fmt.Println("Prompt failed ", err, i6)
return
}
if i6 == 0 {

View File

@@ -278,6 +278,31 @@ func makeBasicControlsPage() ui.Control {
return
}
vc := mainM.GetVSConfFromCurrentState()
bs, e := utils.GetPurgedTomlBytes(vc)
if e != nil {
if ce := utils.CanLogErr("转换格式错误"); ce != nil {
ce.Write(zap.Error(e))
}
return
}
filename += ".toml"
e = os.WriteFile(filename, bs, 0666)
if e != nil {
if ce := utils.CanLogErr("写入文件错误"); ce != nil {
ce.Write(zap.Error(e))
}
return
}
if ce := utils.CanLogInfo("导出成功"); ce != nil {
ce.Write(zap.String("filename", filename))
}
})
fgrid.Append(button,
1, 1, 1, 1,

View File

@@ -391,5 +391,5 @@ func NoFuture(m *machine.M) bool {
}
func NothingRunning(m *machine.M) bool {
return !m.HasProxyRunning() && !(interactive_mode || gui_mode || m.ApiServerRunning)
return !m.HasProxyRunning() && !(interactive_mode || gui_mode || m.IsApiServerRunning())
}

View File

@@ -4,6 +4,15 @@ default_uuid = "a684455c-b14f-11ea-bf0d-42010aaa0003" # 这个除了作为默
# 每个listen 可以只配置users来配置用户列表然后 这个default_uuid 会作为 每个listen 的uuid 的值。
# 这样作为管理员每个listen自己都能用自己的 账户连上不必再额外对每一个listen 添加一遍 自己的账户。
# [apiServer] # v1.2.5开始, apiServer配置单独在一项中配置
# enable = true # 默认为false
# plain = false # 是否使用明文http, 默认false
# admin_pass = "i_love_verysimple"
# addr = "127.0.0.1:8080"
# key = "/home/vs/key" # 若不用明文http, 可配置tls证书, 若不给出, vs会自动生成随机证书
# cert = "/home/vs/cert"
# prefix = "/myapi"
[[listen]]
tag = "my_vlesss1"
protocol = "vlesss"

View File

@@ -85,7 +85,7 @@ func (asc *ApiServerConf) SetUnDefault(acref *ApiServerConf) {
// 非阻塞,如果运行成功则 apiServerRunning 会被设为 true
func (m *M) TryRunApiServer() {
m.ApiServerRunning = true
m.apiServerRunning = true
go m.runApiServer()
@@ -279,7 +279,7 @@ func (m *M) runApiServer() {
srv.ListenAndServeTLS(m.CertFile, m.KeyFile)
}
m.ApiServerRunning = false
m.apiServerRunning = false
}
type auth struct {

View File

@@ -145,13 +145,13 @@ func (m *M) LoadConfigByTomlBytes(bs []byte) (err error) {
m.AppConf.Setup()
}
if vsConf.ApiServerConf != nil {
m.TomlApiServerConf = *vsConf.ApiServerConf
m.tomlApiServerConf = *vsConf.ApiServerConf
}
return nil
}
// 先检查configFileName是否存在存在就尝试加载文件到 standardConf , 否则尝试通过 listenURL, dialURL 参数 创建urlConf
// 先检查configFileName是否存在存在就尝试加载文件到 standardConf , 否则尝试通过 listenURL, dialURL 参数 创建urlConf. 若使用url, 自动加载进机器; 若为toml, 需要手动调用 SetupListenAndRoute 和 SetupDial
func (m *M) LoadConfig(configFileName, listenURL, dialURL string) (confMode int, err error) {
fpath := utils.GetFilePath(configFileName)
@@ -218,7 +218,7 @@ func (m *M) SetupListenAndRoute() {
m.ParseFallbacksAtSymbol(m.standardConf.Fallbacks)
}
m.RoutingEnv = proxy.LoadEnvFromStandardConf(&m.standardConf, myCountryISO_3166)
m.routingEnv = proxy.LoadEnvFromStandardConf(&m.standardConf, myCountryISO_3166)
}
func (m *M) SetupDial() {

View File

@@ -30,7 +30,7 @@ func (m *M) LoadDialConf(conf []*proxy.DialConf) (ok bool) {
m.allClients = append(m.allClients, outClient)
if tag := outClient.GetTag(); tag != "" {
m.RoutingEnv.SetClient(tag, outClient)
m.routingEnv.SetClient(tag, outClient)
}
}
@@ -69,7 +69,7 @@ func (m *M) LoadListenConf(conf []*proxy.ListenConf, hot bool) (ok bool) {
}
if hot {
lis := v2ray_simple.ListenSer(inServer, m.DefaultOutClient, &m.RoutingEnv, &m.GlobalInfo)
lis := v2ray_simple.ListenSer(inServer, m.DefaultOutClient, &m.routingEnv, &m.GlobalInfo)
if lis != nil {
m.listenCloserList = append(m.listenCloserList, lis)
m.allServers = append(m.allServers, inServer)
@@ -92,7 +92,7 @@ func (m *M) HotDeleteClient(index int) {
}
doomedClient := m.allClients[index]
m.RoutingEnv.DelClient(doomedClient.GetTag())
m.routingEnv.DelClient(doomedClient.GetTag())
doomedClient.Stop()
m.allClients = utils.TrimSlice(m.allClients, index)
}
@@ -123,7 +123,7 @@ func (m *M) loadUrlConf(hot bool) (result int) {
}
if hot {
lis := v2ray_simple.ListenSer(ser, cli, &m.RoutingEnv, &m.GlobalInfo)
lis := v2ray_simple.ListenSer(ser, cli, &m.routingEnv, &m.GlobalInfo)
if lis != nil {
m.listenCloserList = append(m.listenCloserList, lis)
} else {
@@ -168,6 +168,14 @@ func (m *M) loadUrlClient(urlConf proxy.UrlConf) (result int, client proxy.Clien
return
}
func (m *M) GetVSConfFromCurrentState() (vc VSConf) {
vc.StandardConf = m.GetStandardConfFromCurrentState()
vc.ApiServerConf = &m.ApiServerConf
vc.AppConf = &m.AppConf
return
}
func (m *M) GetStandardConfFromCurrentState() (sc proxy.StandardConf) {
for i := range m.allClients {
sc.Dial = append(sc.Dial, m.getDialConfFromCurrentState(i))

View File

@@ -18,44 +18,42 @@ import (
"github.com/e1732a364fed/v2ray_simple/httpLayer"
"github.com/e1732a364fed/v2ray_simple/proxy"
"github.com/e1732a364fed/v2ray_simple/utils"
"go.uber.org/zap"
)
type M struct {
ApiServerConf
TomlApiServerConf ApiServerConf
CmdApiServerConf ApiServerConf
sync.RWMutex
v2ray_simple.GlobalInfo
AppConf
ApiServerConf
tomlApiServerConf ApiServerConf
CmdApiServerConf ApiServerConf
standardConf proxy.StandardConf
urlConf proxy.UrlConf
//appConf *AppConf
v2ray_simple.GlobalInfo
sync.RWMutex
//DefaultUUID string
ApiServerRunning bool
running bool
apiServerRunning bool
DefaultOutClient proxy.Client
RoutingEnv proxy.RoutingEnv
callbacks
routingEnv proxy.RoutingEnv
allServers []proxy.Server
allClients []proxy.Client
listenCloserList []io.Closer
running bool
callbacks
}
func New() *M {
m := new(M)
m.allClients = make([]proxy.Client, 0, 8)
m.allServers = make([]proxy.Server, 0, 8)
m.RoutingEnv.ClientsTagMap = make(map[string]proxy.Client)
m.routingEnv.ClientsTagMap = make(map[string]proxy.Client)
directClient, _ := proxy.ClientFromURL(proxy.DirectURL)
m.DefaultOutClient = directClient
return m
@@ -83,6 +81,10 @@ func (m *M) IsRunning() bool {
return m.running
}
func (m *M) IsApiServerRunning() bool {
return m.apiServerRunning
}
// 运行配置 以及 apiServer
func (m *M) Start() {
if (m.DefaultOutClient != nil) && (len(m.allServers) > 0) {
@@ -91,20 +93,20 @@ func (m *M) Start() {
m.running = true
m.callToggleFallback(1)
for _, inServer := range m.allServers {
lis := v2ray_simple.ListenSer(inServer, m.DefaultOutClient, &m.RoutingEnv, &m.GlobalInfo)
lis := v2ray_simple.ListenSer(inServer, m.DefaultOutClient, &m.routingEnv, &m.GlobalInfo)
if lis != nil {
m.listenCloserList = append(m.listenCloserList, lis)
}
}
if dm := m.RoutingEnv.DnsMachine; dm != nil {
if dm := m.routingEnv.DnsMachine; dm != nil {
dm.StartListen()
}
m.Unlock()
}
if !m.ApiServerRunning && m.EnableApiServer {
if !m.apiServerRunning && m.EnableApiServer {
m.TryRunApiServer()
}
@@ -114,10 +116,11 @@ func (m *M) Start() {
func (m *M) SetupApiConf() {
m.ApiServerConf = NewApiServerConf()
m.ApiServerConf.SetUnDefault(&m.TomlApiServerConf)
m.ApiServerConf.SetUnDefault(&m.tomlApiServerConf)
m.ApiServerConf.SetUnDefault(&m.CmdApiServerConf)
}
// Stop不会停止ApiServer
func (m *M) Stop() {
utils.Info("Stopping...")
@@ -135,7 +138,7 @@ func (m *M) Stop() {
listener.Close()
}
}
if dm := m.RoutingEnv.DnsMachine; dm != nil {
if dm := m.routingEnv.DnsMachine; dm != nil {
dm.Stop()
}
m.Unlock()
@@ -145,7 +148,7 @@ func (m *M) SetDefaultDirectClient() {
m.allClients = append(m.allClients, v2ray_simple.DirectClient)
m.DefaultOutClient = v2ray_simple.DirectClient
m.RoutingEnv.SetClient("direct", v2ray_simple.DirectClient)
m.routingEnv.SetClient("direct", v2ray_simple.DirectClient)
}
// 将fallback配置中的@转化成实际对应的server的地址
@@ -157,7 +160,10 @@ func (m *M) ParseFallbacksAtSymbol(fs []*httpLayer.FallbackConf) {
if deststr, ok := fbConf.Dest.(string); ok && strings.HasPrefix(deststr, "@") {
for _, s := range m.allServers {
if s.GetTag() == deststr[1:] {
//log.Println("got tag fallback dest, will set to ", s.AddrStr())
if ce := utils.CanLogDebug("got @tag fallback dest"); ce != nil {
ce.Write(zap.String("will set to ", s.AddrStr()), zap.String("tag", deststr[1:]))
}
fbConf.Dest = s.AddrStr()
}
}

View File

@@ -1,6 +1,7 @@
package utils
import (
"bytes"
"math/rand"
"os"
"strings"
@@ -67,3 +68,24 @@ func GetPurgedTomlStr(v any) (string, error) {
return sb.String(), nil
}
// mimic GetPurgedTomlStr
func GetPurgedTomlBytes(v any) ([]byte, error) {
buf := GetBuf()
defer PutBuf(buf)
if err := toml.NewEncoder(buf).Encode(v); err != nil {
return nil, err
}
lines := bytes.Split(buf.Bytes(), []byte{'\n'})
var sb bytes.Buffer
for _, l := range lines {
if !bytes.HasSuffix(l, []byte(` = ""`)) && !bytes.HasSuffix(l, []byte(` = false`)) && !bytes.HasSuffix(l, []byte(` = 0`)) {
sb.Write(l)
sb.WriteByte('\n')
}
}
return sb.Bytes(), nil
}