mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-12-24 13:27:56 +08:00
修订cmd,gui;添加导出全部配置功能
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user