Skip to content

Commit

Permalink
feat: 可以输出排序后的节点的详细配置 (#14)
Browse files Browse the repository at this point in the history
* fix: 修复了无法使用本地文件进行指定的情况

* feat: 一些已知问题的修复

* feat: 可以输出节点的详细配置
  • Loading branch information
sxueck authored Aug 18, 2023
1 parent eed27d7 commit 27027b3
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 27 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
dist/
*.exe

.idea/*
.idea/*
result.yaml
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ Usage of clash-speedtest:
download concurrent size (default 4)
-f string
filter proxies by name, use regexp (default ".*")
-output string
output result to csv file
-output yaml / csv
output result to csv / yaml file
-size int
download size for testing proxies (default 104857600)
-sort string
Expand Down Expand Up @@ -61,6 +61,8 @@ TW-IEPL-01 109.34KB/s 73.00ms
USA-GIA 14.42KB/s 688.00ms
```

> 当您指定了 `--output yaml` 的时候,会自动将排序后的节点以完整配置输出,方便您编辑自己的节点文件
## 如何使用自定义服务器进行测速

```shell
Expand Down
82 changes: 58 additions & 24 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,26 @@ var (
downloadSizeConfig = flag.Int("size", 1024*1024*100, "download size for testing proxies")
timeoutConfig = flag.Duration("timeout", time.Second*5, "timeout for testing proxies")
sortField = flag.String("sort", "b", "sort field for testing proxies, b for bandwidth, t for TTFB")
output = flag.String("output", "", "output result to csv file")
output = flag.String("output", "", "output result to csv/yaml file")
concurrent = flag.Int("concurrent", 4, "download concurrent size")
)

type CProxy struct {
C.Proxy
SecretConfig any
}

type Result struct {
Name string
Bandwidth float64
TTFB time.Duration
}

var (
red = "\033[31m"
green = "\033[32m"
)

type RawConfig struct {
Providers map[string]map[string]any `yaml:"proxy-providers"`
Proxies []map[string]any `yaml:"proxies"`
Expand Down Expand Up @@ -74,7 +90,7 @@ func main() {
log.Fatalln("Please specify the configuration file")
}

var allProxies = make(map[string]C.Proxy)
var allProxies = make(map[string]CProxy)
arURL := strings.Split(*configPathConfig, ",")
for _, v := range arURL {
var u any
Expand Down Expand Up @@ -155,12 +171,18 @@ func main() {
}
}

if *output != "" {
writeToCSV(*output, results)
if strings.EqualFold(*output, "yaml") {
if err := writeNodeConfigurationToYAML("result.yaml", results, allProxies); err != nil {
log.Fatalln("Failed to write yaml: %s", err)
}
} else if strings.EqualFold(*output, "csv") {
if err := writeToCSV("result.csv", results); err != nil {
log.Fatalln("Failed to write csv: %s", err)
}
}
}

func filterProxies(filter string, proxies map[string]C.Proxy) []string {
func filterProxies(filter string, proxies map[string]CProxy) []string {
filterRegexp := regexp.MustCompile(filter)
filteredProxies := make([]string, 0, len(proxies))
for name := range proxies {
Expand All @@ -172,14 +194,14 @@ func filterProxies(filter string, proxies map[string]C.Proxy) []string {
return filteredProxies
}

func loadProxies(buf []byte) (map[string]C.Proxy, error) {
func loadProxies(buf []byte) (map[string]CProxy, error) {
rawCfg := &RawConfig{
Proxies: []map[string]any{},
}
if err := yaml.Unmarshal(buf, rawCfg); err != nil {
return nil, err
}
proxies := make(map[string]C.Proxy)
proxies := make(map[string]CProxy)
proxiesConfig := rawCfg.Proxies
providersConfig := rawCfg.Providers

Expand All @@ -192,7 +214,7 @@ func loadProxies(buf []byte) (map[string]C.Proxy, error) {
if _, exist := proxies[proxy.Name()]; exist {
return nil, fmt.Errorf("proxy %s is the duplicate name", proxy.Name())
}
proxies[proxy.Name()] = proxy
proxies[proxy.Name()] = CProxy{Proxy: proxy, SecretConfig: config}
}
for name, config := range providersConfig {
if name == provider.ReservedName {
Expand All @@ -206,31 +228,20 @@ func loadProxies(buf []byte) (map[string]C.Proxy, error) {
return nil, fmt.Errorf("initial proxy provider %s error: %w", pd.Name(), err)
}
for _, proxy := range pd.Proxies() {
proxies[fmt.Sprintf("[%s] %s", name, proxy.Name())] = proxy
proxies[fmt.Sprintf("[%s] %s", name, proxy.Name())] = CProxy{Proxy: proxy}
}
}
return proxies, nil
}

type Result struct {
Name string
Bandwidth float64
TTFB time.Duration
}

var (
red = "\033[31m"
green = "\033[32m"
)

func (r *Result) Printf(format string) {
color := ""
if r.Bandwidth < 1024*1024 {
color = red
} else if r.Bandwidth > 1024*1024*10 {
color = green
}
fmt.Printf(format, color, formatName(r.Name), formatBandwidth(r.Bandwidth), formatMillseconds(r.TTFB))
fmt.Printf(format, color, formatName(r.Name), formatBandwidth(r.Bandwidth), formatMilliseconds(r.TTFB))
}

func TestProxyConcurrent(name string, proxy C.Proxy, downloadSize int, timeout time.Duration, concurrentCount int) *Result {
Expand Down Expand Up @@ -290,7 +301,7 @@ func TestProxy(name string, proxy C.Proxy, downloadSize int, timeout time.Durati
return &Result{name, -1, -1}, 0
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
if resp.StatusCode-http.StatusOK > 100 {
return &Result{name, -1, -1}, 0
}
ttfb := time.Since(start)
Expand Down Expand Up @@ -339,13 +350,36 @@ func formatBandwidth(v float64) string {
return fmt.Sprintf("%.02fTB/s", v)
}

func formatMillseconds(v time.Duration) string {
func formatMilliseconds(v time.Duration) string {
if v <= 0 {
return "N/A"
}
return fmt.Sprintf("%.02fms", float64(v.Milliseconds()))
}

func writeNodeConfigurationToYAML(filePath string, results []Result, proxies map[string]CProxy) error {
fp, err := os.Create(filePath)
if err != nil {
return err
}
defer fp.Close()

var sortedProxies []any
for _, result := range results {
if v, ok := proxies[result.Name]; ok {
sortedProxies = append(sortedProxies, v.SecretConfig)
}
}

bytes, err := yaml.Marshal(sortedProxies)
if err != nil {
return err
}

_, err = fp.Write(bytes)
return err
}

func writeToCSV(filePath string, results []Result) error {
csvFile, err := os.Create(filePath)
if err != nil {
Expand All @@ -367,7 +401,7 @@ func writeToCSV(filePath string, results []Result) error {
fmt.Sprintf("%.2f", result.Bandwidth/1024/1024),
strconv.FormatInt(result.TTFB.Milliseconds(), 10),
}
err := csvWriter.Write(line)
err = csvWriter.Write(line)
if err != nil {
return err
}
Expand Down

0 comments on commit 27027b3

Please sign in to comment.