mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-12-24 13:27:56 +08:00
添加 -cvqxtvs 和 -eqxrs 命令,
分别意思是 convert QX to verysimple 和 extract QX remote servers 将圈叉的配置文件转换为verysimple格式,这样就可以更快地使用自己的vs客户端
This commit is contained in:
@@ -26,6 +26,9 @@ var (
|
||||
cmdPrintVer bool
|
||||
cmdGenerateUUid bool
|
||||
|
||||
cmdConvertQxToVs string
|
||||
cmdExtractQX_remoteServer string
|
||||
|
||||
download bool
|
||||
|
||||
defaultApiServerConf machine.ApiServerConf
|
||||
@@ -34,10 +37,13 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.BoolVar(&download, "d", false, " automatically download required mmdb file")
|
||||
|
||||
flag.BoolVar(&cmdPrintSupportedProtocols, "sp", false, "print supported protocols")
|
||||
flag.BoolVar(&cmdPrintVer, "v", false, "print the version string then exit")
|
||||
flag.BoolVar(&download, "d", false, " automatically download required mmdb file")
|
||||
flag.BoolVar(&cmdGenerateUUid, "gu", false, " automatically generate a uuid for you")
|
||||
flag.StringVar(&cmdConvertQxToVs, "cvqxtvs", "", "if given, convert qx server config string to vs toml config")
|
||||
flag.StringVar(&cmdExtractQX_remoteServer, "eqxrs", "", "if given, automatically extract remote servers from quantumultX config for you")
|
||||
|
||||
//apiServer stuff
|
||||
|
||||
@@ -67,6 +73,18 @@ func runExitCommands() (atLeastOneCalled bool) {
|
||||
|
||||
generateAndPrintUUID()
|
||||
}
|
||||
|
||||
if cmdConvertQxToVs != "" {
|
||||
atLeastOneCalled = true
|
||||
|
||||
convertQxToVs()
|
||||
}
|
||||
|
||||
if cmdExtractQX_remoteServer != "" {
|
||||
atLeastOneCalled = true
|
||||
|
||||
extractQxRemoteServers()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
63
cmd/verysimple/cmd_convert.go
Normal file
63
cmd/verysimple/cmd_convert.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/e1732a364fed/v2ray_simple/configAdapter"
|
||||
"github.com/e1732a364fed/v2ray_simple/proxy"
|
||||
"github.com/e1732a364fed/v2ray_simple/utils"
|
||||
)
|
||||
|
||||
func convertQxToVs() {
|
||||
dc := configAdapter.FromQX(cmdConvertQxToVs)
|
||||
fmt.Println(utils.GetPurgedTomlStr(proxy.StandardConf{
|
||||
Dial: []*proxy.DialConf{&dc},
|
||||
}))
|
||||
|
||||
}
|
||||
|
||||
func extractQxRemoteServers() {
|
||||
var bs []byte
|
||||
var readE error
|
||||
if strings.HasPrefix(cmdExtractQX_remoteServer, "http") {
|
||||
|
||||
fmt.Printf("downloading %s\n", cmdExtractQX_remoteServer)
|
||||
|
||||
resp, err := http.DefaultClient.Get(cmdExtractQX_remoteServer)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Download failed %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
counter := &utils.DownloadPrintCounter{}
|
||||
|
||||
bs, readE = io.ReadAll(io.TeeReader(resp.Body, counter))
|
||||
fmt.Printf("\n")
|
||||
} else {
|
||||
if utils.FileExist(cmdExtractQX_remoteServer) {
|
||||
path := utils.GetFilePath(cmdExtractQX_remoteServer)
|
||||
f, e := os.Open(path)
|
||||
if e != nil {
|
||||
fmt.Printf("Download failed %s\n", e.Error())
|
||||
return
|
||||
}
|
||||
bs, readE = io.ReadAll(f)
|
||||
} else {
|
||||
fmt.Printf("file not exist %s\n", cmdExtractQX_remoteServer)
|
||||
return
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if readE != nil {
|
||||
fmt.Printf("read failed %s\n", readE.Error())
|
||||
return
|
||||
}
|
||||
configAdapter.ExtractQxRemoteServers(string(bs))
|
||||
}
|
||||
@@ -1,8 +1,13 @@
|
||||
package configAdapter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -177,21 +182,64 @@ func ToQX(dc *proxy.DialConf) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
/* clash使用yaml作为配置格式。本函数中不导出整个yaml配置文件,而只导出
|
||||
func FromQX(str string) (dc proxy.DialConf) {
|
||||
//qx 的配置应该是基本的逗号分隔值形式
|
||||
str = utils.StandardizeSpaces(str)
|
||||
strs := strings.Split(str, ",")
|
||||
|
||||
for i, p := range strs {
|
||||
ss := strings.Split(p, "=")
|
||||
n := ss[0]
|
||||
v := ss[1]
|
||||
n = strings.TrimSpace(n)
|
||||
v = strings.TrimSpace(v)
|
||||
|
||||
if i == 0 {
|
||||
dc.Protocol = n
|
||||
hostport := v
|
||||
host, port, err := net.SplitHostPort(hostport)
|
||||
if err != nil {
|
||||
fmt.Printf("FromQX: net.SplitHostPort err, %s\n", err.Error())
|
||||
} else {
|
||||
dc.Host = host
|
||||
np, _ := strconv.Atoi(port)
|
||||
dc.Port = np
|
||||
}
|
||||
} else {
|
||||
switch n {
|
||||
case "method":
|
||||
dc.EncryptAlgo = v
|
||||
case "password":
|
||||
dc.Uuid = v
|
||||
case "tag":
|
||||
dc.Tag = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if dc.Protocol == "shadowsocks" {
|
||||
if dc.Uuid != "" && dc.EncryptAlgo != "" {
|
||||
dc.Uuid = "method:" + dc.EncryptAlgo + "\n" + "pass:" + dc.Uuid
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
clash使用yaml作为配置格式。本函数中不导出整个yaml配置文件,而只导出
|
||||
|
||||
对应的proxies项下的子项,比如
|
||||
|
||||
|
||||
- name: "ss1"
|
||||
type: ss
|
||||
server: server
|
||||
port: 443
|
||||
cipher: chacha20-ietf-poly1305
|
||||
password: "password"
|
||||
- name: "ss1"
|
||||
type: ss
|
||||
server: server
|
||||
port: 443
|
||||
cipher: chacha20-ietf-poly1305
|
||||
password: "password"
|
||||
|
||||
See https://github.com/Dreamacro/clash/wiki/Configuration
|
||||
|
||||
clash的配置对于不同的协议来说,格式也有不同,clash基本上尊重了每一个协议的约定, 但也不完全一致
|
||||
|
||||
*/
|
||||
func ToClash(dc *proxy.DialConf) string {
|
||||
//这里我们不使用外部yaml包,可以减少依赖.
|
||||
@@ -391,7 +439,7 @@ type V2rayNConfig struct {
|
||||
Sni string `json:"sni"`
|
||||
}
|
||||
|
||||
//See https://github.com/2dust/v2rayN/wiki/%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E6%A0%BC%E5%BC%8F%E8%AF%B4%E6%98%8E(ver-2)
|
||||
// See https://github.com/2dust/v2rayN/wiki/%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E6%A0%BC%E5%BC%8F%E8%AF%B4%E6%98%8E(ver-2)
|
||||
func ToV2rayN(dc *proxy.DialConf) string {
|
||||
if dc.Protocol != "vmess" {
|
||||
return "ToV2rayN doesn't support any protocol other than vmess, you give " + dc.Protocol
|
||||
@@ -430,3 +478,47 @@ func ToV2rayN(dc *proxy.DialConf) string {
|
||||
return "vmess://" + base64.URLEncoding.EncodeToString(bs)
|
||||
|
||||
}
|
||||
|
||||
func ExtractQxRemoteServers(configContentStr string) {
|
||||
lines := strings.Split(configContentStr, "\n")
|
||||
for i, l := range lines {
|
||||
|
||||
if strings.Contains(l, "[server_remote]") {
|
||||
fmt.Printf("got [server_remote] field\n")
|
||||
|
||||
l = lines[i+1]
|
||||
strs := strings.SplitN(l, ",", 2)
|
||||
l = strs[0]
|
||||
|
||||
fmt.Printf("downloading %s\n", l)
|
||||
|
||||
resp, err := http.DefaultClient.Get(l)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Download failed %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
fmt.Printf("Download got bad status: %s\n", resp.Status)
|
||||
return
|
||||
}
|
||||
fmt.Printf("download ok, reading...\n")
|
||||
|
||||
buf := utils.GetBuf()
|
||||
|
||||
counter := &utils.DownloadPrintCounter{}
|
||||
|
||||
fmt.Printf("\nread ok\n")
|
||||
|
||||
io.Copy(buf, io.TeeReader(resp.Body, counter))
|
||||
ls := bytes.Split(buf.Bytes(), []byte("\n"))
|
||||
for _, v := range ls {
|
||||
fmt.Println(string(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ func GetGatewayDeviceName() (string, error) {
|
||||
|
||||
// helper func, call GetGatewayDeviceName and utils.GetDarwinNetAdapterNameByInterfaceName.
|
||||
//
|
||||
// hardwarePort 和 interface的名称不同,hardwareport是 Wi-Fi, 而interface.Name 是 eth0
|
||||
// hardwarePort 和 interface的名称不同,hardwareport是 Wi-Fi, 而interface.Name 是 en0
|
||||
func GetDefaultHardwarePort() (string, error) {
|
||||
n, e := GetGatewayDeviceName()
|
||||
if e != nil {
|
||||
|
||||
@@ -86,18 +86,18 @@ func SimpleDownloadFile(fname, downloadLink string) (ok bool) {
|
||||
}
|
||||
|
||||
// https://golangcode.com/download-a-file-with-progress/
|
||||
type downloadPrintCounter struct {
|
||||
type DownloadPrintCounter struct {
|
||||
Total uint64
|
||||
}
|
||||
|
||||
func (wc *downloadPrintCounter) Write(p []byte) (int, error) {
|
||||
func (wc *DownloadPrintCounter) Write(p []byte) (int, error) {
|
||||
n := len(p)
|
||||
wc.Total += uint64(n)
|
||||
wc.PrintProgress()
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (wc downloadPrintCounter) PrintProgress() {
|
||||
func (wc DownloadPrintCounter) PrintProgress() {
|
||||
fmt.Printf("\r%s", strings.Repeat(" ", 35))
|
||||
|
||||
fmt.Printf("\rDownloading... %s complete", humanize.Bytes(wc.Total))
|
||||
@@ -121,7 +121,7 @@ func DownloadAndUnzip(fname, downloadLink, dst string) (ok bool) {
|
||||
return
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
counter := &downloadPrintCounter{}
|
||||
counter := &DownloadPrintCounter{}
|
||||
io.Copy(buf, io.TeeReader(resp.Body, counter))
|
||||
|
||||
out := bytes.NewReader(buf.Bytes())
|
||||
|
||||
Reference in New Issue
Block a user