Skip to content

Commit 11c3173

Browse files
committed
basic cli setup
1 parent 304fd59 commit 11c3173

File tree

1 file changed

+206
-0
lines changed

1 file changed

+206
-0
lines changed

main.go

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"log"
7+
"net/http"
8+
"os"
9+
"path"
10+
"strconv"
11+
"sync"
12+
"time"
13+
14+
"github.com/muesli/termenv"
15+
"github.com/pkg/errors"
16+
"github.com/royalbhati/go-tdm/metadata"
17+
"github.com/royalbhati/go-tdm/progress"
18+
)
19+
20+
type Download struct {
21+
URL string
22+
TargetPath string
23+
TotalSections int
24+
DirPath string
25+
}
26+
27+
func main() {
28+
p := termenv.ColorProfile()
29+
30+
startTime := time.Now()
31+
var bar progress.Bar
32+
bar.NewOption(0, 10)
33+
34+
var url string
35+
fmt.Printf("%s\n", termenv.String(" 🖊️ Paste the url here").Bold().Foreground(p.Color("#FDD835")))
36+
fmt.Scanf("%s\n", &url)
37+
38+
if url == "" {
39+
log.Fatal("URL can't be empty")
40+
}
41+
42+
path, err := os.Getwd()
43+
if err != nil {
44+
log.Println(err)
45+
}
46+
47+
d := Download{
48+
URL: url,
49+
TargetPath: "",
50+
TotalSections: 10,
51+
DirPath: path,
52+
}
53+
54+
if err := d.Do(p, &bar); err != nil {
55+
fmt.Printf("\n%s\n", termenv.String("An error occured while downloading the file").Foreground(p.Color("0")).Background(p.Color("#E88388")))
56+
// fmt.Printf("\n%s", err)
57+
log.Fatal(err)
58+
}
59+
60+
fmt.Printf("\n\n ✅ Download completed in %v seconds\n", time.Now().Sub(startTime).Seconds())
61+
}
62+
63+
func (d Download) Do(p termenv.Profile, bar *progress.Bar) error {
64+
65+
fmt.Printf("\n%s\n", termenv.String(" 🔍 CHECKING URL ").Bold().Foreground(p.Color("#FDD835")))
66+
67+
r, err := d.getNewRequest("HEAD")
68+
if err != nil {
69+
return err
70+
}
71+
72+
resp, err := http.DefaultClient.Do(r)
73+
74+
if err != nil {
75+
return err
76+
}
77+
78+
if resp.StatusCode > 299 {
79+
return errors.New(fmt.Sprintf("Can't process, response is %v", resp.StatusCode))
80+
}
81+
82+
fmt.Printf("\n%s\n", termenv.String(" 👍 URL OK ").Bold().Foreground(p.Color("#8BC34A")))
83+
size, err := strconv.Atoi(resp.Header.Get("Content-Length"))
84+
85+
a := metadata.GetFileName(resp)
86+
d.TargetPath = a
87+
88+
if err != nil {
89+
return err
90+
}
91+
var yesOrNo string
92+
fmt.Printf("\n%s %f %s\n", termenv.String(" 🗂 SIZE IS ").Bold().Foreground(p.Color("#FFB300")), (float64(size)*float64(0.001))/1000, "MB")
93+
fmt.Printf("\n%s\n", termenv.String(" 🚀 PROCEED DOWNLOADING (y/n)").Bold().Foreground(p.Color("#FFB300")))
94+
fmt.Scanf("%s", &yesOrNo)
95+
96+
if yesOrNo == "n" {
97+
fmt.Printf("%s\n", termenv.String("EXITING").Bold().Foreground(p.Color("#FF7043")))
98+
os.Exit(2)
99+
return nil
100+
}
101+
102+
var sections = make([][2]int, d.TotalSections)
103+
104+
eachSize := size / d.TotalSections
105+
106+
for i := range sections {
107+
if i == 0 {
108+
sections[i][0] = 0
109+
} else {
110+
sections[i][0] = sections[i-1][1] + 1
111+
}
112+
113+
if i < d.TotalSections-1 {
114+
sections[i][1] = sections[i][0] + eachSize
115+
} else {
116+
sections[i][1] = size - 1
117+
}
118+
}
119+
120+
var wg sync.WaitGroup
121+
sum2 := 0
122+
123+
for i, s := range sections {
124+
wg.Add(1)
125+
126+
go func(i int, s [2]int, bar *progress.Bar) {
127+
defer wg.Done()
128+
err = d.downloadSection(i, s, &sum2, p, bar)
129+
if err != nil {
130+
panic(err)
131+
}
132+
}(i, s, bar)
133+
134+
}
135+
wg.Wait()
136+
return d.mergeFiles(sections)
137+
}
138+
func (d Download) downloadSection(i int, c [2]int, sum *int, p termenv.Profile, bar *progress.Bar) error {
139+
r, err := d.getNewRequest("GET")
140+
if err != nil {
141+
return err
142+
}
143+
r.Header.Set("Range", fmt.Sprintf("bytes=%v-%v", c[0], c[1]))
144+
resp, err := http.DefaultClient.Do(r)
145+
if err != nil {
146+
return err
147+
}
148+
if resp.StatusCode > 299 {
149+
return errors.New(fmt.Sprintf("Can't process, response is %v", resp.StatusCode))
150+
}
151+
152+
b, err := ioutil.ReadAll(resp.Body)
153+
if err != nil {
154+
return err
155+
}
156+
err = ioutil.WriteFile(path.Join(d.DirPath, fmt.Sprintf("section-%v.tmp", i)), b, os.ModePerm)
157+
if err != nil {
158+
return err
159+
}
160+
fmt.Printf("section-%v.tmp", i)
161+
*sum = *sum + 1
162+
bar.Play(int64(*sum))
163+
164+
return nil
165+
}
166+
167+
// Get a new http request
168+
func (d Download) getNewRequest(method string) (*http.Request, error) {
169+
r, err := http.NewRequest(
170+
method,
171+
d.URL,
172+
nil,
173+
)
174+
if err != nil {
175+
return nil, err
176+
}
177+
r.Header.Set("User-Agent", "TDM")
178+
return r, nil
179+
}
180+
181+
func (d Download) mergeFiles(sections [][2]int) error {
182+
f, err := os.OpenFile(path.Join(d.DirPath, d.TargetPath), os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.ModePerm)
183+
if err != nil {
184+
return err
185+
}
186+
defer f.Close()
187+
for i := range sections {
188+
tmpFileName := fmt.Sprintf("section-%v.tmp", i)
189+
b, err := ioutil.ReadFile(path.Join(d.DirPath, tmpFileName))
190+
if err != nil {
191+
return err
192+
}
193+
_, err = f.Write(b)
194+
if err != nil {
195+
return err
196+
}
197+
err = os.Remove(tmpFileName)
198+
if err != nil {
199+
return err
200+
}
201+
202+
}
203+
204+
return nil
205+
206+
}

0 commit comments

Comments
 (0)