pgollangi/fastget

View on GitHub
commands/root.go

Summary

Maintainability
A
0 mins
Test Coverage
package commands

import (
    "fmt"
    "os"
    "path/filepath"
    "strings"
    "time"

    "github.com/MakeNowJust/heredoc"
    "github.com/pgollangi/fastget"
    "github.com/spf13/cobra"

    "github.com/vbauerster/mpb/v5"
    "github.com/vbauerster/mpb/v5/decor"

    "github.com/inhies/go-bytesize"
)

// Version is the version for netselect
var Version string

// Build holds the date bin was released
var Build string

// RootCmd is the main root/parent command
var RootCmd = &cobra.Command{
    Use:           "fastget $fileURL",
    Short:         "A fastget CLI Tool",
    Long:          `fastget is an open source CLI tool to ultrafast download files over HTTP(s).`,
    SilenceErrors: true,
    SilenceUsage:  true,
    Example: heredoc.Doc(`
        $ fastget https://file.example.com // Basic Usage
        $ fastget http://speedtest.tele2.net/10MB.zip -H "Authorization: Basic ASYFASUF" // Custom Header
        $ fastget http://speedtest.tele2.net/10MB.zip -w 6 // Increased no. of workers
        $ fastget -v
        `),
    RunE: runCommand,
}

type barStatus struct {
    iT  time.Time
    bar *mpb.Bar
}

func runCommand(cmd *cobra.Command, args []string) error {
    if ok, _ := cmd.Flags().GetBool("version"); ok {
        executeVersionCmd()
        return nil
    } else if len(args) != 1 {
        cmd.Usage()
        return nil
    }

    threads, _ := cmd.Flags().GetInt("workers")

    headers, _ := cmd.Flags().GetStringArray("header")

    url := args[0]

    fg, err := fastget.NewFastGetter(url)

    if err != nil {
        return err
    }
    fg.Workers = threads

    for _, header := range headers {
        split := strings.Split(header, ":")
        fg.Headers[split[0]] = split[1]
        fmt.Println(header)
    }

    fmt.Println("Initializing download..")

    mpbars := make(map[int]*barStatus)

    mp := mpb.New(
        mpb.WithWidth(100),
        mpb.WithRefreshRate(240*time.Millisecond),
    )

    fg.OnBeforeStart = func(filesize int64, chunckLen int64) {
        fmt.Printf("File size : %s\n", bytesize.New(float64(filesize)))
    }

    fg.OnStart = func(worker int, totalSize int64) {
        mpbar := mp.AddBar(totalSize, mpb.BarStyle("[=>-|"),
            mpb.PrependDecorators(
                decor.CountersKiloByte("% 6.2f / % .2f"),
                decor.Percentage(decor.WCSyncSpace),
            ),
            mpb.AppendDecorators(
                decor.EwmaETA(decor.ET_STYLE_GO, 90),
                decor.Name(" ] "),
                decor.EwmaSpeed(decor.UnitKB, "% .2f", 60),
            ))

        mpbars[worker] = &barStatus{
            bar: mpbar,
            iT:  time.Now(),
        }

    }

    fg.OnProgress = func(worker int, download int64) {
        barStatus := mpbars[worker]

        dur := time.Since(barStatus.iT)

        barStatus.bar.SetCurrent(download)
        barStatus.bar.DecoratorEwmaUpdate(dur)
        barStatus.iT = time.Now()
    }

    result, err := fg.Get()
    if err != nil {
        return err
    }

    mp.Wait()

    pwd, err := os.Getwd()

    oFile := filepath.Join(pwd, result.OutputFile.Name())

    fmt.Printf("Download finished in %s. File: %s", result.ElapsedTime.Round(time.Second), oFile)

    return nil
}

// Execute performs fastget command execution
func Execute() error {
    return RootCmd.Execute()
}

func init() {
    RootCmd.Flags().BoolP("version", "v", false, "show fastget version information")
    RootCmd.Flags().BoolP("debug", "d", false, "show debug information")
    RootCmd.Flags().IntP("workers", "w", 3, "use <n> parellel threads")
    RootCmd.Flags().StringP("output", "o", ".", "output file to be written")
    RootCmd.Flags().StringArrayP("header", "H", []string{}, "output file to be written")
}

func executeVersionCmd() {
    fmt.Printf("fast version %s (%s)\n", Version, Build)
    fmt.Println("More info: pgollangi.com/fastget")
}