44 "bytes"
55 "context"
66 "fmt"
7- "github.com/linuxsuren/http-downloader/pkg/exec "
7+ "io "
88 "net/http"
99 "net/url"
1010 sysos "os"
@@ -13,6 +13,11 @@ import (
1313 "strings"
1414 "sync"
1515
16+ "github.com/AlecAivazis/survey/v2"
17+ "github.com/linuxsuren/http-downloader/pkg/exec"
18+ "golang.org/x/net/html"
19+ "golang.org/x/net/html/charset"
20+
1621 "github.com/linuxsuren/http-downloader/pkg"
1722 "github.com/linuxsuren/http-downloader/pkg/installer"
1823 "github.com/linuxsuren/http-downloader/pkg/net"
@@ -62,6 +67,7 @@ func newGetCmd(ctx context.Context) (cmd *cobra.Command) {
6267 "Print the category list" )
6368 flags .IntVarP (& opt .PrintVersionCount , "print-version-count" , "" , 20 ,
6469 "The number of the version list" )
70+ flags .BoolVarP (& opt .Magnet , "magnet" , "" , false , "Fetch magnet list from a website" )
6571
6672 _ = cmd .RegisterFlagCompletionFunc ("proxy-github" , ArrayCompletion ("gh.api.99988866.xyz" ,
6773 "ghproxy.com" , "mirror.ghproxy.com" ))
@@ -74,6 +80,7 @@ func newDownloadOption(ctx context.Context) *downloadOption {
7480 RoundTripper : getRoundTripper (ctx ),
7581 fetcher : & installer.DefaultFetcher {},
7682 wait : & sync.WaitGroup {},
83+ execer : exec.DefaultExecer {},
7784 }
7885}
7986
@@ -91,6 +98,7 @@ type downloadOption struct {
9198 MaxAttempts int
9299 AcceptPreRelease bool
93100 RoundTripper http.RoundTripper
101+ Magnet bool
94102
95103 ContinueAt int64
96104
@@ -111,6 +119,7 @@ type downloadOption struct {
111119 org string
112120 repo string
113121 fetcher installer.Fetcher
122+ execer exec.Execer
114123 ExpectVersion string // should be like >v1.1.0
115124}
116125
@@ -170,7 +179,7 @@ func (o *downloadOption) preRunE(cmd *cobra.Command, args []string) (err error)
170179
171180 targetURL := args [0 ]
172181 o .Package = & installer.HDConfig {}
173- if strings .HasPrefix (targetURL , "magnet:?" ) {
182+ if o . Magnet || strings .HasPrefix (targetURL , "magnet:?" ) {
174183 // download via external tool
175184 o .URL = targetURL
176185 return
@@ -208,6 +217,21 @@ func (o *downloadOption) preRunE(cmd *cobra.Command, args []string) (err error)
208217 return
209218}
210219
220+ func findAnchor (n * html.Node ) (items []string ) {
221+ if n .Type == html .ElementNode && n .Data == "a" {
222+ for _ , a := range n .Attr {
223+ if a .Key == "href" && strings .Contains (a .Val , "magnet" ) {
224+ items = append (items , strings .TrimSpace (n .FirstChild .Data ))
225+ break
226+ }
227+ }
228+ }
229+ for c := n .FirstChild ; c != nil ; c = c .NextSibling {
230+ items = append (items , findAnchor (c )... )
231+ }
232+ return
233+ }
234+
211235func (o * downloadOption ) runE (cmd * cobra.Command , args []string ) (err error ) {
212236 defer func () {
213237 if o .cancel != nil {
@@ -247,8 +271,8 @@ func (o *downloadOption) runE(cmd *cobra.Command, args []string) (err error) {
247271 return
248272 }
249273
250- if strings .HasPrefix (o .URL , "magnet:?" ) {
251- err = downloadMagnetFile (o .ProxyGitHub , o .URL )
274+ if o . Magnet || strings .HasPrefix (o .URL , "magnet:?" ) {
275+ err = downloadMagnetFile (o .ProxyGitHub , o .URL , o . execer )
252276 return
253277 }
254278
@@ -273,9 +297,8 @@ func (o *downloadOption) runE(cmd *cobra.Command, args []string) (err error) {
273297 return
274298}
275299
276- func downloadMagnetFile (proxyGitHub , target string ) (err error ) {
300+ func downloadMagnetFile (proxyGitHub , target string , execer exec. Execer ) (err error ) {
277301 targetCmd := "gotorrent"
278- execer := exec.DefaultExecer {}
279302 is := installer.Installer {
280303 Provider : "github" ,
281304 Execer : execer ,
@@ -287,6 +310,43 @@ func downloadMagnetFile(proxyGitHub, target string) (err error) {
287310 return
288311 }
289312
313+ if strings .HasPrefix (target , "http" ) {
314+ var resp * http.Response
315+ if resp , err = http .Get (target ); err == nil && resp .StatusCode == http .StatusOK {
316+ var data []byte
317+ data , err = io .ReadAll (resp .Body )
318+ if err != nil {
319+ return
320+ }
321+
322+ var reader io.Reader
323+ if reader , err = charset .NewReader (strings .NewReader (string (data )), "UTF-8" ); err != nil {
324+ return
325+ }
326+
327+ var docutf8 * html.Node
328+ if docutf8 , err = html .Parse (reader ); err != nil {
329+ return
330+ }
331+ items := findAnchor (docutf8 )
332+
333+ if len (items ) > 1 {
334+ selector := & survey.Select {
335+ Message : "Select item" ,
336+ Options : items ,
337+ }
338+ err = survey .AskOne (selector , & target )
339+ } else if len (items ) > 0 {
340+ target = items [0 ]
341+ }
342+ }
343+ }
344+
345+ fmt .Println (target )
346+ if target == "" || err != nil {
347+ return
348+ }
349+
290350 var targetBinary string
291351 if targetBinary , err = execer .LookPath (targetCmd ); err == nil {
292352 sysCallArgs := []string {targetCmd }
0 commit comments