forked from riptl/fma-scraper
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
120 lines (100 loc) · 2.39 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package main
import (
"context"
"fmt"
"github.com/cenkalti/backoff"
"github.com/sirupsen/logrus"
"os"
"os/signal"
"sync"
"sync/atomic"
"time"
)
var startTime = time.Now()
var totalBytes int64
var numDownloaded int64
var downloadGroup sync.WaitGroup
var helperGroup sync.WaitGroup
var exitRequested int32
type Track struct {
Artist string `json:"artist"`
Title string `json:"title"`
Album string `json:"album"`
Genres []string `json:"genre"`
Download string `json:"download"`
}
func main() {
if err := parseArgs(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
logrus.Info("Starting Free Music Archive Scraper")
logrus.Info(" https://github.com/terorie/fma-scraper/")
jobs := make(chan Track, 2 * *pageSize)
results := make(chan Track, 2 * *pageSize)
c, cancel := context.WithCancel(context.Background())
go listenCtrlC(cancel)
go stats()
// Start logger
helperGroup.Add(1)
go logger(results)
// Start downloaderss
downloadGroup.Add(int(*concurrency))
for i := 0; i < int(*concurrency); i++ {
go downloader(jobs, results)
}
// Start meta grabber
page := *minPage
for {
if atomic.LoadInt32(&exitRequested) != 0 {
break
}
err := backoff.Retry(func() error {
err := list(c, jobs, *genre, int(page))
if err != nil {
logrus.WithError(err).
Errorf("Failed visiting page %d", page)
}
return err
}, backoff.NewExponentialBackOff())
if err != nil {
logrus.Fatal(err)
}
page++
}
// Shutdown
close(jobs)
downloadGroup.Wait()
close(results)
helperGroup.Wait()
total := atomic.LoadInt64(&totalBytes)
dur := time.Since(startTime).Seconds()
logrus.WithFields(logrus.Fields{
"total_bytes": total,
"dur": dur,
"avg_rate": float64(total) / dur,
}).Info("Stats")
}
func listenCtrlC(cancel context.CancelFunc) {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
atomic.StoreInt32(&exitRequested, 1)
cancel()
fmt.Fprintln(os.Stderr, "\nWaiting for downloads to finish...")
fmt.Fprintln(os.Stderr, "Press ^C again to exit instantly.")
<-c
fmt.Fprintln(os.Stderr, "\nKilled!")
os.Exit(255)
}
func stats() {
for range time.NewTicker(time.Second).C {
total := atomic.LoadInt64(&totalBytes)
dur := time.Since(startTime).Seconds()
logrus.WithFields(logrus.Fields{
"tracks": numDownloaded,
"total_bytes": totalBytes,
"avg_rate": fmt.Sprintf("%.0f", float64(total) / dur),
}).Info("Stats")
}
}