-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathparse.go
More file actions
182 lines (148 loc) · 3.96 KB
/
parse.go
File metadata and controls
182 lines (148 loc) · 3.96 KB
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package main
import (
"encoding/json"
"net/url"
"path"
"strconv"
"sync"
// "github.com/davecgh/go-spew/spew"
)
var (
derpiURL = url.URL{
Scheme: "https",
Host: "derpibooru.org",
}
derpiquery = make(url.Values)
)
//RawImage contains data we got from API that needs to be modified before further usage
type RawImage struct {
Imgid int `json:"id"`
URL string `json:"image"`
Score int `json:"score"`
OriginalFormat string `json:"original_format"`
Faves int `json:"faves"`
}
//Image contains data needed to filter fetch and save image
type Image struct {
Imgid int
URL *url.URL
Filename string
Score int
Faves int
}
//Search returns to us array of searched images...
type Search struct {
Images []RawImage `json:"search"`
}
//Push gets unmarchalled JSON info, massages it and plugs it into channel so it
//would be processed in other places
func trim(dat RawImage) Image {
fn := strconv.Itoa(dat.Imgid) + "." + dat.OriginalFormat
tu, _ := url.Parse(dat.URL)
tu.Scheme = derpiURL.Scheme
tu.Path = path.Dir(tu.Path) + "/" + fn
return Image{
Imgid: dat.Imgid,
Filename: fn,
URL: tu,
Score: dat.Score,
Faves: dat.Faves,
}
}
//ParseImg gets image IDs, fetches information about those images from Derpibooru and pushes them into the channel.
func ParseImg(imgchan chan<- Image, ids []int, key string) {
for _, imgid := range ids {
if isInterrupted() {
break
}
derpiURL.Path = strconv.Itoa(imgid) + ".json"
derpiURL.RawQuery = ""
lInfo("Getting image info at:", derpiURL.String())
if key != "" {
derpiquery.Add("key", key)
}
derpiURL.RawQuery = derpiquery.Encode()
body, err := getJSON(derpiURL.String())
if err != nil {
lErr(err)
break
}
var dat RawImage
if err := json.Unmarshal(body, &dat); //transforming json into native map
err != nil {
lErr(err)
continue
}
imgchan <- trim(dat)
}
close(imgchan) //closing channel, we are done here
}
//DlImg reads image data from channel and downloads specified images to disc
func downloadImages(imgchan <-chan Image, opts *Config) {
lInfo("Worker started; reading channel") //nice notification that we are not forgotten
var n int
var size int64
var l sync.Mutex
var wg sync.WaitGroup
for k := 0; k < 4; k++ {
wg.Add(1)
go func() {
for imgdata := range imgchan {
lInfo("Saving as", imgdata.Filename)
tsize, ok := imgdata.saveImage(opts)
l.Lock()
size += tsize
if ok {
n++
}
l.Unlock()
}
wg.Done()
}()
}
wg.Wait()
lInfof("Downloaded %d images, for a total of %s", n, fmtbytes(float64(size)))
}
//ParseTag gets image tags, fetches information about all images it could from Derpibooru and pushes them into the channel.
func ParseTag(imgchan chan<- Image, opts *TagOpts, key string) {
//Unlike main, I don't see how I could separate bits out to decrease complexity
derpiURL.Path = "search.json"
derpiquery.Add("sbq", opts.Tag)
derpiURL.RawQuery = derpiquery.Encode()
lInfo("Searching as", derpiURL.String())
if key != "" {
derpiquery.Add("key", key)
}
for page := opts.StartPage; opts.StopPage == 0 || page <= opts.StopPage; page++ {
if isInterrupted() {
break
}
lInfo("Searching page", page)
derpiquery.Set("page", strconv.Itoa(page))
derpiURL.RawQuery = derpiquery.Encode()
body, err := getJSON(derpiURL.String())
if err != nil {
lErr("Error while getting json from page ", page)
lErr(err)
break
}
var dats Search
err = json.Unmarshal(body, &dats)
if err != nil {
lErr("Error while parsing search page", page)
lErr(err)
if serr, ok := err.(*json.SyntaxError); ok { //In case crap was still given, we are looking at it.
lErr("Occurred at offset: ", serr.Offset)
}
break
}
if len(dats.Images) == 0 {
lInfo("Pages are all over") //Does not mean that process is over.
break
} //exit due to finishing all pages
for _, dat := range dats.Images {
imgchan <- trim(dat)
}
}
close(imgchan)
}