Skip to content

Commit f051a0b

Browse files
author
V2RaySSR综合网
committed
优化错误处理和用户体验
- 添加域名格式验证,支持空格分隔的批量检测 - 改进错误提示,移除图标,使用简洁的错误信息 - CSV错误时统一提示使用RealiTLScanner工具 - 删除程序运行时的清屏操作 - 优化命令参数错误提示,提供具体示例
1 parent 5a9ef20 commit f051a0b

File tree

5 files changed

+158
-17
lines changed

5 files changed

+158
-17
lines changed

internal/cmd/batch.go

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package cmd
22

33
import (
44
"fmt"
5+
"net"
6+
"regexp"
57
"strings"
68

79
"RealityChecker/internal/ui"
@@ -10,9 +12,20 @@ import (
1012
// executeBatch 执行批量检测
1113
func (r *RootCmd) executeBatch(domainsStr string) {
1214
// 解析域名列表
13-
domains := parseDomains(domainsStr)
15+
domains, invalidDomains := parseDomains(domainsStr)
16+
17+
// 显示无效域名警告
18+
if len(invalidDomains) > 0 {
19+
fmt.Printf("警告:发现 %d 个无效域名,已跳过:\n", len(invalidDomains))
20+
for _, domain := range invalidDomains {
21+
fmt.Printf(" - %s\n", domain)
22+
}
23+
fmt.Println()
24+
}
25+
1426
if len(domains) == 0 {
15-
fmt.Println("没有有效的域名")
27+
fmt.Println("错误:没有有效的域名可以检测")
28+
fmt.Println("提示:请检查域名格式,例如:apple.com, google.com")
1629
return
1730
}
1831

@@ -28,14 +41,63 @@ func (r *RootCmd) executeBatch(domainsStr string) {
2841
// 详细结果已在batch manager中打印,无需重复
2942
}
3043

31-
// parseDomains 解析域名列表
32-
func parseDomains(domainsStr string) []string {
33-
var domains []string
34-
for _, domain := range strings.Split(domainsStr, ",") {
44+
// parseDomains 解析域名列表,返回有效域名和无效域名
45+
func parseDomains(domainsStr string) ([]string, []string) {
46+
var validDomains []string
47+
var invalidDomains []string
48+
49+
// 支持空格分隔的域名列表
50+
fields := strings.Fields(domainsStr)
51+
for _, domain := range fields {
3552
domain = strings.TrimSpace(domain)
36-
if domain != "" {
37-
domains = append(domains, domain)
53+
if domain == "" {
54+
continue
55+
}
56+
57+
if isValidDomain(domain) {
58+
validDomains = append(validDomains, domain)
59+
} else {
60+
invalidDomains = append(invalidDomains, domain)
3861
}
3962
}
40-
return domains
63+
return validDomains, invalidDomains
64+
}
65+
66+
// isValidDomain 验证域名格式是否有效
67+
func isValidDomain(domain string) bool {
68+
// 基本长度检查
69+
if len(domain) == 0 || len(domain) > 253 {
70+
return false
71+
}
72+
73+
// 检查是否包含非法字符
74+
if strings.ContainsAny(domain, " \t\n\r") {
75+
return false
76+
}
77+
78+
// 检查是否以点开头或结尾
79+
if strings.HasPrefix(domain, ".") || strings.HasSuffix(domain, ".") {
80+
return false
81+
}
82+
83+
// 检查是否包含连续的点
84+
if strings.Contains(domain, "..") {
85+
return false
86+
}
87+
88+
// 使用正则表达式验证域名格式
89+
domainRegex := regexp.MustCompile(`^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$`)
90+
if !domainRegex.MatchString(domain) {
91+
return false
92+
}
93+
94+
// 尝试解析域名(不进行实际DNS查询)
95+
_, err := net.LookupHost(domain)
96+
if err != nil {
97+
// 即使DNS解析失败,只要格式正确就认为是有效的
98+
// 因为可能是网络问题或域名确实不存在
99+
return true
100+
}
101+
102+
return true
41103
}

internal/cmd/check.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ package cmd
22

33
import (
44
"fmt"
5+
"net"
6+
"regexp"
7+
"strings"
58

69
"RealityChecker/internal/config"
710
"RealityChecker/internal/report"
@@ -10,6 +13,19 @@ import (
1013

1114
// executeCheck 执行单域名检测
1215
func (r *RootCmd) executeCheck(domain string) {
16+
// 验证域名格式
17+
domain = strings.TrimSpace(domain)
18+
if !isValidDomain(domain) {
19+
fmt.Printf("错误:域名格式无效 '%s'\n", domain)
20+
fmt.Println("提示:请检查域名格式,例如:apple.com, google.com")
21+
fmt.Println("域名要求:")
22+
fmt.Println(" - 只能包含字母、数字、连字符和点")
23+
fmt.Println(" - 不能以点开头或结尾")
24+
fmt.Println(" - 不能包含连续的点")
25+
fmt.Println(" - 长度不超过253个字符")
26+
return
27+
}
28+
1329
ui.PrintBanner()
1430
ui.PrintTimestampedMessage("开始检测域名: %s", domain)
1531

@@ -24,3 +40,42 @@ func (r *RootCmd) executeCheck(domain string) {
2440
formatter := report.NewFormatter(cfg)
2541
fmt.Printf("\n%s", formatter.FormatSingleResult(result))
2642
}
43+
44+
// isValidDomain 验证域名格式是否有效(与batch.go中的函数相同)
45+
func isValidDomain(domain string) bool {
46+
// 基本长度检查
47+
if len(domain) == 0 || len(domain) > 253 {
48+
return false
49+
}
50+
51+
// 检查是否包含非法字符
52+
if strings.ContainsAny(domain, " \t\n\r") {
53+
return false
54+
}
55+
56+
// 检查是否以点开头或结尾
57+
if strings.HasPrefix(domain, ".") || strings.HasSuffix(domain, ".") {
58+
return false
59+
}
60+
61+
// 检查是否包含连续的点
62+
if strings.Contains(domain, "..") {
63+
return false
64+
}
65+
66+
// 使用正则表达式验证域名格式
67+
domainRegex := regexp.MustCompile(`^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$`)
68+
if !domainRegex.MatchString(domain) {
69+
return false
70+
}
71+
72+
// 尝试解析域名(不进行实际DNS查询)
73+
_, err := net.LookupHost(domain)
74+
if err != nil {
75+
// 即使DNS解析失败,只要格式正确就认为是有效的
76+
// 因为可能是网络问题或域名确实不存在
77+
return true
78+
}
79+
80+
return true
81+
}

internal/cmd/csv.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,19 @@ import (
1111

1212
// executeCSV 从CSV文件批量检测域名
1313
func (r *RootCmd) executeCSV(csvFile string) {
14+
// 检查文件是否存在
15+
if _, err := os.Stat(csvFile); os.IsNotExist(err) {
16+
fmt.Printf("错误:CSV文件不存在 '%s'\n", csvFile)
17+
fmt.Println("请使用 RealiTLScanner 工具扫描,得到 CSV 文件")
18+
fmt.Println("命令:./RealiTLScanner -addr <VPS IP> -port 443 -thread 50 -timeout 5 -out file.csv")
19+
fmt.Println("(提示:RealiTLScanner 不要在VPS上面运行)")
20+
return
21+
}
22+
1423
// 读取CSV文件
1524
file, err := os.Open(csvFile)
1625
if err != nil {
17-
fmt.Printf("无法打开CSV文件: %v\n", err)
26+
fmt.Printf("错误:无法打开CSV文件 '%s': %v\n", csvFile, err)
1827
return
1928
}
2029
defer file.Close()
@@ -23,19 +32,25 @@ func (r *RootCmd) executeCSV(csvFile string) {
2332
reader := csv.NewReader(file)
2433
records, err := reader.ReadAll()
2534
if err != nil {
26-
fmt.Printf("解析CSV文件失败: %v\n", err)
35+
fmt.Printf("错误:解析CSV文件失败: %v\n", err)
36+
fmt.Println("请使用 RealiTLScanner 工具扫描,得到 CSV 文件")
37+
fmt.Println("命令:./RealiTLScanner -addr <VPS IP> -port 443 -thread 50 -timeout 5 -out file.csv")
2738
return
2839
}
2940

3041
if len(records) < 2 {
31-
fmt.Println("CSV文件格式错误或为空")
42+
fmt.Println("错误:CSV文件格式错误或为空")
43+
fmt.Println("请使用 RealiTLScanner 工具扫描,得到 CSV 文件")
44+
fmt.Println("命令:./RealiTLScanner -addr <VPS IP> -port 443 -thread 50 -timeout 5 -out file.csv")
3245
return
3346
}
3447

3548
// 提取域名(从CERT_DOMAIN列)
3649
domains := extractDomainsFromCSV(records)
3750
if len(domains) == 0 {
38-
fmt.Println("未找到有效的域名")
51+
fmt.Println("错误:未找到有效的域名")
52+
fmt.Println("请使用 RealiTLScanner 工具扫描,得到 CSV 文件")
53+
fmt.Println("命令:./RealiTLScanner -addr <VPS IP> -port 443 -thread 50 -timeout 5 -out file.csv")
3954
return
4055
}
4156

internal/cmd/root.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,25 +72,36 @@ func (r *RootCmd) Execute() {
7272
switch os.Args[1] {
7373
case "check":
7474
if len(os.Args) < 3 {
75+
fmt.Println("错误:缺少域名参数")
7576
fmt.Println("用法: reality-checker check <domain>")
77+
fmt.Println("示例: reality-checker check apple.com")
7678
os.Exit(1)
7779
}
7880
r.executeCheck(os.Args[2])
7981
case "batch":
8082
if len(os.Args) < 3 {
81-
fmt.Println("用法: reality-checker batch <domain1,domain2,...>")
83+
fmt.Println("错误:缺少域名参数")
84+
fmt.Println("用法: reality-checker batch <domain1> <domain2> <domain3> ...")
85+
fmt.Println("示例: reality-checker batch apple.com google.com microsoft.com")
8286
os.Exit(1)
8387
}
84-
r.executeBatch(os.Args[2])
88+
// 将所有参数(除了命令名)合并为空格分隔的字符串
89+
domainsStr := strings.Join(os.Args[2:], " ")
90+
r.executeBatch(domainsStr)
8591
case "csv":
8692
if len(os.Args) < 3 {
93+
fmt.Println("错误:缺少CSV文件参数")
8794
fmt.Println("用法: reality-checker csv <csv_file>")
95+
fmt.Println("示例: reality-checker csv domains.csv")
8896
os.Exit(1)
8997
}
9098
r.executeCSV(os.Args[2])
9199
case "version", "-v", "--version":
92100
r.showVersion()
93101
default:
102+
fmt.Printf("错误:未知命令 '%s'\n", os.Args[1])
103+
fmt.Println("可用命令: check, batch, csv, version")
104+
fmt.Println()
94105
ui.PrintUsage()
95106
os.Exit(1)
96107
}

internal/ui/banner.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ import (
77

88
// PrintBanner 打印程序横幅
99
func PrintBanner() {
10-
// 清屏
11-
fmt.Print("\033[2J\033[H")
1210

1311
// 获取版本信息
1412
versionInfo := getVersionInfo()

0 commit comments

Comments
 (0)