package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"path"
|
|
"regexp"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gocolly/colly"
|
|
"github.com/machinebox/progress"
|
|
)
|
|
|
|
func list() {
|
|
c := colly.NewCollector(
|
|
colly.AllowedDomains("downloads.raspberrypi.org"),
|
|
colly.UserAgent("github.com/klingtnet/raspi-toolbox"),
|
|
colly.Async(true),
|
|
)
|
|
c.Limit(&colly.LimitRule{Parallelism: 4})
|
|
urls := []string{}
|
|
|
|
imgMatcher := regexp.MustCompile(".*raspbian-stretch-lite.*\\.zip$")
|
|
|
|
c.OnHTML("a[href]", func(e *colly.HTMLElement) {
|
|
link := e.Attr("href")
|
|
if strings.HasPrefix(link, "raspbian_lite") {
|
|
c.Visit(e.Request.AbsoluteURL(link))
|
|
return
|
|
}
|
|
if imgMatcher.Match([]byte(link)) {
|
|
urls = append(urls, e.Request.AbsoluteURL(link))
|
|
}
|
|
})
|
|
|
|
c.Visit("https://downloads.raspberrypi.org/raspbian_lite/images/")
|
|
c.Wait()
|
|
|
|
sort.Strings(urls)
|
|
for _, u := range urls {
|
|
fmt.Println(u)
|
|
}
|
|
}
|
|
|
|
func download(u string) error {
|
|
filename := path.Base(u)
|
|
fmt.Printf("writing into %q\n", filename)
|
|
f, err := os.Create(filename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close()
|
|
resp, err := http.Get(u)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode != http.StatusOK {
|
|
return fmt.Errorf("expected HTTP 200 OK but was %d", resp.StatusCode)
|
|
}
|
|
size, err := strconv.Atoi(resp.Header.Get("Content-Length"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
pr := progress.NewReader(resp.Body)
|
|
go func() {
|
|
progressChan := progress.NewTicker(context.Background(), pr, int64(size), 3*time.Second)
|
|
for p := range progressChan {
|
|
fmt.Printf("\r%.2f%%", p.Percent())
|
|
}
|
|
}()
|
|
|
|
_, err = io.Copy(f, pr)
|
|
fmt.Println("\r100.0%")
|
|
return err
|
|
}
|
|
|
|
func usage() {
|
|
fmt.Printf(`%s [list|usage|help|<url>]
|
|
|
|
usage|help:
|
|
Prints this message
|
|
list:
|
|
Prints all available images
|
|
<url>:
|
|
Downloads the image under <url>
|
|
`, os.Args[0])
|
|
}
|
|
|
|
func main() {
|
|
if len(os.Args) <= 1 {
|
|
usage()
|
|
os.Exit(1)
|
|
}
|
|
arg := os.Args[1]
|
|
switch arg {
|
|
case "usage":
|
|
fallthrough
|
|
case "help":
|
|
usage()
|
|
return
|
|
case "list":
|
|
list()
|
|
default:
|
|
if err := download(os.Args[1]); err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
}
|
|
}
|