package cmd import ( "agent-wdd/log" "agent-wdd/utils" "context" "fmt" "net" "net/http" "net/url" "time" "github.com/spf13/cobra" "golang.org/x/net/proxy" ) // 示例:添加download子命令 func addDownloadSubcommands(cmd *cobra.Command) { proxyCmd := &cobra.Command{ Use: "proxy [proxyUrl] [url] [dest]", Short: "使用代理下载 socks5://[username]:[password]@ip:port http://[username]:[password]@ip:port", Args: cobra.ExactArgs(3), Run: func(cmd *cobra.Command, args []string) { proxyURL := args[0] fileURL := args[1] destPath := args[2] log.Info("Downloading using proxy: %s -> from %s to %s\n", proxyURL, fileURL, destPath) // 创建带代理的HTTP客户端 client, err := createProxyClient(proxyURL) if err != nil { log.Error("创建代理客户端失败: %v", err) } // 执行下载 downloadOk, resultLog := utils.DownloadFileWithClient(client, fileURL, destPath) if !downloadOk { log.Error("下载失败: %v", resultLog) } else { log.Info("文件下载完成") } }, } cmd.Run = func(cmd *cobra.Command, args []string) { if len(args) == 0 { log.Error("请输入下载地址") return } else if len(args) == 1 { timeString := utils.CurrentTimeString() args = append(args, "./"+timeString+".txt") } log.Info("Downloading without proxy: %s -> %s\n", args[0], args[1]) downloadOk, resultLog := utils.DownloadFile(args[0], args[1]) if !downloadOk { log.Error("下载失败: %s", resultLog) } else { log.Info("下载成功: %s", args[1]) } } cmd.AddCommand(proxyCmd) } // 创建带代理的HTTP客户端 func createProxyClient(proxyURL string) (*http.Client, error) { parsedURL, err := url.Parse(proxyURL) if err != nil { return nil, fmt.Errorf("无效的代理URL: %w", err) } switch parsedURL.Scheme { case "socks5": return createSocks5Client(parsedURL) case "http", "https": return createHTTPClient(parsedURL), nil default: return nil, fmt.Errorf("不支持的代理协议: %s", parsedURL.Scheme) } } // 创建SOCKS5代理客户端 func createSocks5Client(proxyURL *url.URL) (*http.Client, error) { var auth *proxy.Auth if proxyURL.User != nil { password, _ := proxyURL.User.Password() auth = &proxy.Auth{ User: proxyURL.User.Username(), Password: password, } } dialer, err := proxy.SOCKS5("tcp", proxyURL.Host, auth, proxy.Direct) if err != nil { return nil, fmt.Errorf("创建SOCKS5拨号器失败: %w", err) } return &http.Client{ Transport: &http.Transport{ DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { return dialer.Dial(network, addr) }, }, Timeout: 10 * time.Second, }, nil } // 创建HTTP代理客户端 func createHTTPClient(proxyURL *url.URL) *http.Client { return &http.Client{ Transport: &http.Transport{ Proxy: http.ProxyURL(proxyURL), }, Timeout: 30 * time.Minute, } }