package downloader import ( "errors" "fmt" "io" "os" "strings" req "github.com/levigross/grequests" "github.com/schollz/progressbar/v3" ) type Context struct { Filename string Link string } func NewContext(filename, link string) *Context { return &Context{ Filename: filename, Link: link, } } func (c *Context) Download() error { resp, err := req.Head(c.Link, nil) if err != nil { if strings.Contains(err.Error(), "no such host") { return fmt.Errorf("invalid url") } if strings.Contains(err.Error(), "certificate signed by unknown authority") { return fmt.Errorf("certificate from unknown authority") } return err } defer resp.Close() if resp.StatusCode == 404 { return fmt.Errorf("invalid url") } if resp.StatusCode == 401 { return fmt.Errorf("restricted access (credentials required)") } if resp.StatusCode != 200 { return fmt.Errorf(resp.RawResponse.Status) } resp.Close() resp, err = req.Get(c.Link, nil) if err != nil { return err } var filesize int64 if resp.RawResponse.ContentLength > -1 { filesize = resp.RawResponse.ContentLength } destFile, err := os.OpenFile(c.Filename, os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return err } defer destFile.Close() bar := progressbar.DefaultBytes( filesize, "downloading", ) _, err = io.Copy(io.MultiWriter(destFile, bar), resp.RawResponse.Body) if err != nil { return err } return nil } func (c *Context) FileExists() bool { _, err := os.Stat(c.Filename) return !errors.Is(err, os.ErrNotExist) }