-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
134 lines (111 loc) · 2.72 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
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"github.com/codegangsta/cli"
)
func main() {
app := cli.NewApp()
app.Name = "igtagsnarf"
app.Usage = "download assets from instagram that match a tag"
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "client",
Value: "",
Usage: "instagram client ID",
},
cli.StringFlag{
Name: "tag",
Value: "",
Usage: "tag to search by",
},
}
app.Action = func(c *cli.Context) {
tag, clientID := c.String("tag"), c.String("client")
snarf(tag, clientID, "")
}
app.Run(os.Args)
}
// download a list of items that match a tag
func snarf(tag, clientID, url string) error {
if url == "" {
url = fmt.Sprintf("https://api.instagram.com/v1/tags/%s/media/recent?count=500&client_id=%s", tag, clientID)
}
fmt.Println("GET ", url)
resp, err := http.Get(url)
if err != nil {
fmt.Println("error fetching list from instagram: ", err)
return err
}
body, err := ioutil.ReadAll(resp.Body)
defer resp.Body.Close()
if err != nil {
fmt.Println("error reading the response from instagram:", err)
return err
}
s := struct {
Assets []Asset `json:"data"`
Pagination map[string]string `json:"pagination"`
}{}
if err := json.Unmarshal(body, &s); err != nil {
fmt.Println("error unmarshaling response json:", err)
fmt.Printf("%s", string(body))
return err
}
// prep the output directory
path := fmt.Sprintf("./files/%s/", tag)
if err := os.MkdirAll(path, 0755); err != nil {
fmt.Println("error: could not create output directory:", err)
return err
}
work := make(chan Asset, len(s.Assets))
done := make(chan error, 5)
// launch five downloaders
for i := 0; i < 5; i++ {
go download(work, done, path)
}
// send items to workers
for _, a := range s.Assets {
work <- a
}
close(work)
for i := 0; i < 5; i++ {
err := <-done
if err != nil {
// handle
}
}
// do it all over again if there's more!
if s.Pagination["next_url"] != "" {
snarf(tag, clientID, s.Pagination["next_url"])
}
return nil
}
// trigger a download of an asset
func download(assets <-chan Asset, done chan<- error, out string) error {
for a := range assets {
path := fmt.Sprintf("%s/%s-%s.jpg", out, a.User.Username, a.ID)
imgUrl := a.Images["standard_resolution"].URL
fmt.Println("downloading", imgUrl)
resp, err := http.Get(imgUrl)
if err != nil {
fmt.Println("error: fetch img failed:", err)
return err
}
body, err := ioutil.ReadAll(resp.Body)
defer resp.Body.Close()
if err != nil {
fmt.Println("error: read response failed:", err)
return err
}
if err := ioutil.WriteFile(path, body, 0644); err != nil {
fmt.Println("error: could not write file:", err)
return err
}
}
done <- nil
return nil
}