-
Notifications
You must be signed in to change notification settings - Fork 3
/
main.go
152 lines (129 loc) · 3.8 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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package main
import (
"flag"
"fmt"
"log"
"os"
"os/user"
"path"
"sync"
"time"
)
// Settings
var (
RemoteFolderName = flag.String("putio-folder", "Putio Desktop", "putio folder name under your root")
AccessToken = flag.String("oauth-token", "", "Oauth Token")
LocalFolderPath = flag.String("local-path", "~/Putio Desktop", "local folder to fetch")
CheckInterval = flag.Int("check-minutes", 5, "check interval of remote files in put.io")
)
// Globals
var (
RemoteFolderId int
TotalDownloaded int64
TotalToDownload int64
TotalFilesSize int64
)
// Download functions
func WalkAndDownload(parentId int, folderPath string, runWg *sync.WaitGroup, reportCh chan Report) {
defer runWg.Done()
log.Println("Walking in:", folderPath)
// Creating if the folder is absent
if _, err := os.Stat(folderPath); err != nil {
err := os.Mkdir(folderPath, 0755)
if err != nil {
// Will try again at the next run
log.Println(err)
return
}
}
files, err := FilesListRequest(parentId)
if err != nil {
log.Println(err)
return
}
for _, file := range files {
path := path.Join(folderPath, file.Name)
if file.ContentType == "application/x-directory" {
runWg.Add(1)
go WalkAndDownload(file.Id, path, runWg, reportCh)
} else {
reportCh <- Report{FilesSize: file.Size}
if _, err := os.Stat(path); err != nil {
runWg.Add(1)
go DownloadFile(file, path, runWg, reportCh)
}
}
}
}
func StartWalkAndDownloadClearReports(RemoteFolderId int, reportCh chan Report) {
TotalFilesSize = 0
TotalDownloaded = 0
TotalToDownload = 0
var runWg sync.WaitGroup
runWg.Add(1)
go WalkAndDownload(RemoteFolderId, *LocalFolderPath, &runWg, reportCh)
runWg.Wait()
}
type Report struct {
Downloaded int64
ToDownload int64
FilesSize int64
}
func HumanReadableSpeed(bytePerSec float64) string {
if bytePerSec > 1024*1024 {
return fmt.Sprintf("%5.2f MB/s", bytePerSec/(1024*1024))
} else if bytePerSec > 1024 {
return fmt.Sprintf("%5.1f KB/s", bytePerSec/1024)
} else {
return fmt.Sprintf("%5.0f B/s ", bytePerSec)
}
}
func Reporter(reportCh chan Report) {
lastRecordedTime := time.Now()
lastRecordedTotalDownloaded := int64(0)
minReportTime := 1 * time.Second
log.Println("Reporter started")
for report := range reportCh {
TotalDownloaded += report.Downloaded
TotalToDownload += report.ToDownload
TotalFilesSize += report.FilesSize
currentTime := time.Now()
lastReportTimeDifference := currentTime.Sub(lastRecordedTime)
if lastReportTimeDifference > minReportTime {
remainingDownload := TotalToDownload - TotalDownloaded
syncPercentage := 100 - (float32(remainingDownload) / float32(TotalFilesSize) * 100)
completePercentage := float32(TotalDownloaded) / float32(TotalToDownload) * 100
speed := (float64(TotalDownloaded) - float64(lastRecordedTotalDownloaded)) / lastReportTimeDifference.Seconds()
fmt.Printf("[ Downloads %% %2.0f - %s ] [ Sync: %% %5.2f ]\r", completePercentage, HumanReadableSpeed(speed), syncPercentage)
lastRecordedTime = currentTime
lastRecordedTotalDownloaded = TotalDownloaded
}
}
}
func StartReporter() chan Report {
reportCh := make(chan Report)
go Reporter(reportCh)
return reportCh
}
func main() {
log.Println("Starting...")
flag.Parse()
RemoteFolderId, err := GetRemoteFolderId()
if err != nil {
log.Fatal(err)
}
// If local folder path is left at default value, find os users home directory
// and name "Putio Folder" as the local folder path under it
if *LocalFolderPath == "~/Putio Desktop" {
user, _ := user.Current()
defaultPath := path.Join(user.HomeDir, "Putio Desktop")
LocalFolderPath = &defaultPath
}
reportCh := StartReporter()
for {
log.Println("Started syncing...")
StartWalkAndDownloadClearReports(RemoteFolderId, reportCh)
time.Sleep(time.Duration(*CheckInterval) * time.Minute)
}
log.Println("Exiting...")
}