Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor pluto package to make it usable as a library and to simplify main.go #4

Merged
merged 3 commits into from Oct 31, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
200 changes: 0 additions & 200 deletions cli.go

This file was deleted.

173 changes: 173 additions & 0 deletions main.go
@@ -0,0 +1,173 @@
package main

import (
"bufio"
"context"
"fmt"
"io"
"log"
"net/url"
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"

"github.com/ishanjain28/pluto/pluto"

humanize "github.com/dustin/go-humanize"
flag "github.com/jessevdk/go-flags"
)

var Version string
var Build string

var options struct {
Verbose bool `long:"verbose" description:"Enable Verbose Mode"`
Connections uint `short:"n" long:"connections" default:"1" description:"Number of concurrent connections"`
Name string `long:"name" description:"Path or Name of save file"`
LoadFromFile string `short:"f" long:"load-from-file" description:"Load URLs from a file"`
Headers []string `short:"H" long:"Headers" description:"Headers to send with each request. Useful if a server requires some information in headers"`
Version bool `short:"v" long:"version" description:"Print Pluto Version and exit"`
urls []string
}

func parseArgs() error {
args, err := flag.ParseArgs(&options, os.Args)
if err != nil {
return fmt.Errorf("error parsing args: %v", err)
}

args = args[1:]

options.urls = []string{}

if options.LoadFromFile != "" {
f, err := os.OpenFile(options.LoadFromFile, os.O_RDONLY, 0x444)
if err != nil {
return fmt.Errorf("error in opening file %s: %v", options.LoadFromFile, err)
}
defer f.Close()
reader := bufio.NewReader(f)

for {
str, err := reader.ReadString('\n')
if err != nil {
if err == io.EOF {
break
}
return fmt.Errorf("error in reading file: %v", err)
}
u := str[:len(str)-1]
if u != "" {
options.urls = append(options.urls, u)
}
}

fmt.Printf("queued %d urls\n", len(options.urls))
} else {
for _, v := range args {
if v != "" && v != "\n" {
options.urls = append(options.urls, v)
}
}

}
if len(options.urls) == 0 {
return fmt.Errorf("nothing to do. Please pass some url to fetch")
}

if options.Connections == 0 {
return fmt.Errorf("connections should be > 0")
}
if len(options.urls) > 1 && options.Name != "" {
return fmt.Errorf("it is not possible to specify 'name' with more than one url")
}
return nil
}
func main() {

sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
ctx, cancel := context.WithCancel(context.Background())

go func() {
<-sig
fmt.Printf("Interrupt Detected, Shutting Down.")
cancel()
}()

err := parseArgs()
if err != nil {
log.Fatalf("error parsing args: %v", err)
}

if options.Version {
fmt.Println("Pluto - A Fast Multipart File Downloader")
fmt.Printf("Version: %s\n", Version)
fmt.Printf("Build: %s\n", Build)
return
}

for _, v := range options.urls {
up, err := url.Parse(v)
if err != nil {
log.Printf("Invalid URL: %v", err)
continue
}
p, err := pluto.New(up, options.Headers, options.Connections, options.Verbose)
if err != nil {
log.Fatalf("error creating pluto instance for url %s: %v\n", v, err)
}

go func() {
if p.StatsChan == nil {
return
}

for {
select {
case <-p.Finished:
break
case v := <-p.StatsChan:
os.Stdout.WriteString(fmt.Sprintf("%.2f%% - %s/%s - %s/s \r", float64(v.Downloaded)/float64(v.Size)*100, humanize.IBytes(v.Downloaded), humanize.IBytes(v.Size), humanize.IBytes(v.Speed)))
os.Stdout.Sync()
}

}

}()

var fileName string
if options.Name != "" {
fileName = options.Name
} else if p.MetaData.Name == "" {
fileName = strings.Split(filepath.Base(up.String()), "?")[0]
}
fileName = strings.Replace(fileName, "/", "\\/", -1)
writer, err := os.Create(fileName)
if err != nil {
log.Fatalf("unable to create file %s: %v\n", fileName, err)
}
defer writer.Close()

if !p.MetaData.MultipartSupported && options.Connections > 1 {
fmt.Printf("Downloading %s(%s) with 1 connection(Multipart downloads not supported)\n", fileName, humanize.Bytes(p.MetaData.Size))
}

result, err := p.Download(ctx, writer)
if err != nil {
log.Printf("error downloading url %s: %v", v, err)
} else {
s := humanize.IBytes(result.Size)
htime := result.TimeTaken.String()

as := humanize.IBytes(uint64(result.AvgSpeed))

fmt.Printf("Downloaded %s in %s. Avg. Speed - %s/s\n", s, htime, as)
fmt.Printf("File saved in %s\n", result.FileName)

}

}
}
Binary file added pluto/fixtures/testfile
Binary file not shown.