1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
16
17 package flickr
18
19 import (
20 "encoding/json"
21 "fmt"
22 "log"
23 "net/http"
24 "net/url"
25 "os"
26 "path/filepath"
27 "time"
28
29 "perkeep.org/internal/httputil"
30 "perkeep.org/internal/osutil"
31 "perkeep.org/pkg/blob"
32 "perkeep.org/pkg/importer"
33 )
34
35 var _ importer.TestDataMaker = imp{}
36
37 func (im imp) SetTestAccount(acctNode *importer.Object) error {
38 return acctNode.SetAttrs(
39 importer.AcctAttrAccessToken, "fakeAccessToken",
40 importer.AcctAttrAccessTokenSecret, "fakeAccessSecret",
41 importer.AcctAttrUserID, "fakeUserId",
42 importer.AcctAttrName, "fakeName",
43 importer.AcctAttrUserName, "fakeScreenName",
44 )
45 }
46
47 func (im imp) MakeTestData() http.RoundTripper {
48 const (
49 nPhotosets = 5
50 perPage = 3
51 fakeUserId = "fakeUserId"
52 )
53
54 var nPhotos int
55 for i := 1; i <= nPhotosets; i++ {
56 nPhotos += i
57 }
58 nPhotosPages := nPhotos / perPage
59 if nPhotos%perPage != 0 {
60 nPhotosPages++
61 }
62
63 okHeader := `HTTP/1.1 200 OK
64 Content-Type: application/json; charset=UTF-8
65
66 `
67
68
69
70 buildPhotoIds := func(nsets, perPage int) []string {
71 var ids []string
72 for i := 1; i <= nsets; i++ {
73 photosetId := blob.RefFromString(fmt.Sprintf("Photoset %d", i)).DigestPrefix(10)
74 page := 1
75
76 indexOnPage := 1
77 for j := 1; j <= i; j++ {
78 photoId := blob.RefFromString(fmt.Sprintf("Photo %d on page %d of photoset %s", indexOnPage, page, photosetId)).DigestPrefix(10)
79 ids = append(ids, photoId)
80 indexOnPage++
81 if indexOnPage > perPage {
82 page++
83 indexOnPage = 1
84 }
85 }
86 }
87 return ids
88 }
89 photoIds := buildPhotoIds(nPhotosets, perPage)
90
91 responses := make(map[string]func() *http.Response)
92
93 photosetsURL := fmt.Sprintf("%s?format=json&method=%s&nojsoncallback=1&user_id=%s", apiURL, photosetsAPIPath, fakeUserId)
94 response := fmt.Sprintf("%s%s", okHeader, fakePhotosetsList(nPhotosets))
95 responses[photosetsURL] = httputil.StaticResponder(response)
96
97
98
99 {
100 pageStart := 0
101 albumEnd, pageEnd, albumNum, pages, page := 1, 1, 1, 1, 1
102 photosetId := blob.RefFromString(fmt.Sprintf("Photoset %d", albumNum)).DigestPrefix(10)
103 photosURL := fmt.Sprintf("%s?extras=original_format&format=json&method=%s&nojsoncallback=1&page=%d&photoset_id=%s&user_id=%s",
104 apiURL, photosetAPIPath, page, photosetId, fakeUserId)
105 response := fmt.Sprintf("%s%s", okHeader, fakePhotoset(photosetId, page, pages, photoIds[pageStart:pageEnd]))
106 responses[photosURL] = httputil.StaticResponder(response)
107 for k := range photoIds {
108 if k < pageEnd {
109 continue
110 }
111 page++
112 pageStart = k
113 pageEnd = k + perPage
114 if page > pages {
115 albumNum++
116 page = 1
117 pages = albumNum / perPage
118 if albumNum%perPage != 0 {
119 pages++
120 }
121 albumEnd = pageStart + albumNum
122 photosetId = blob.RefFromString(fmt.Sprintf("Photoset %d", albumNum)).DigestPrefix(10)
123 }
124 if pageEnd > albumEnd {
125 pageEnd = albumEnd
126 }
127 photosURL := fmt.Sprintf("%s?extras=original_format&format=json&method=%s&nojsoncallback=1&page=%d&photoset_id=%s&user_id=%s",
128 apiURL, photosetAPIPath, page, photosetId, fakeUserId)
129 response := fmt.Sprintf("%s%s", okHeader, fakePhotoset(photosetId, page, pages, photoIds[pageStart:pageEnd]))
130 responses[photosURL] = httputil.StaticResponder(response)
131 }
132 }
133
134
135
136 for i := 1; i <= nPhotosPages; i++ {
137 photosURL := fmt.Sprintf("%s?extras=", apiURL) +
138 url.QueryEscape("description,date_upload,date_taken,original_format,last_update,geo,tags,machine_tags,views,media,url_o") +
139 fmt.Sprintf("&format=json&method=%s&nojsoncallback=1&page=%d&user_id=%s", photosAPIPath, i, fakeUserId)
140 response := fmt.Sprintf("%s%s", okHeader, fakePhotosPage(i, nPhotosPages, perPage, photoIds))
141 responses[photosURL] = httputil.StaticResponder(response)
142 }
143
144
145 pudgyPic := fakePicture()
146 for _, v := range photoIds {
147 photoURL := fmt.Sprintf("https://farm3.staticflickr.com/2897/14198397111_%s_o.jpg?user_id=%s", v, fakeUserId)
148 responses[photoURL] = httputil.FileResponder(pudgyPic)
149 }
150
151 return httputil.NewFakeTransport(responses)
152 }
153
154 func fakePhotosetsList(sets int) string {
155 var photosets []*photosetInfo
156 for i := 1; i <= sets; i++ {
157 title := fmt.Sprintf("Photoset %d", i)
158 photosetId := blob.RefFromString(title).DigestPrefix(10)
159 primaryPhotoId := blob.RefFromString(fmt.Sprintf("Photo 1 on page 1 of photoset %s", photosetId)).DigestPrefix(10)
160 item := &photosetInfo{
161 Id: photosetId,
162 PrimaryPhotoId: primaryPhotoId,
163 Title: contentString{Content: title},
164 Description: contentString{Content: "fakePhotosetDescription"},
165 }
166 photosets = append(photosets, item)
167 }
168
169 setslist := struct {
170 Photosets photosetList
171 }{
172 Photosets: photosetList{
173 Photoset: photosets,
174 },
175 }
176
177 list, err := json.MarshalIndent(&setslist, "", " ")
178 if err != nil {
179 log.Fatalf("%v", err)
180 }
181 return string(list)
182 }
183
184 func fakePhotoset(photosetId string, page, pages int, photoIds []string) string {
185 var photos []struct {
186 Id string
187 OriginalFormat string
188 }
189 for _, v := range photoIds {
190 item := struct {
191 Id string
192 OriginalFormat string
193 }{
194 Id: v,
195 OriginalFormat: "jpg",
196 }
197 photos = append(photos, item)
198 }
199
200 photoslist := struct {
201 Photoset photosetItems
202 }{
203 Photoset: photosetItems{
204 Id: photosetId,
205 Page: jsonInt(page),
206 Pages: jsonInt(pages),
207 Photo: photos,
208 },
209 }
210
211 list, err := json.MarshalIndent(&photoslist, "", " ")
212 if err != nil {
213 log.Fatalf("%v", err)
214 }
215 return string(list)
216
217 }
218
219 func fakePhotosPage(page, pages, perPage int, photoIds []string) string {
220 var photos []*photosSearchItem
221 currentPage := 1
222 indexOnPage := 1
223 day := time.Hour * 24
224 year := day * 365
225 const dateCreatedFormat = "2006-01-02 15:04:05"
226
227 for k, v := range photoIds {
228 if indexOnPage > perPage {
229 currentPage++
230 indexOnPage = 1
231 }
232 if currentPage < page {
233 indexOnPage++
234 continue
235 }
236 created := time.Now().Add(-time.Duration(k) * year)
237 published := created.Add(day)
238 updated := published.Add(day)
239 item := &photosSearchItem{
240 Id: v,
241 Title: fmt.Sprintf("Photo %d", k+1),
242 Description: contentString{Content: "fakePhotoDescription"},
243 DateUpload: fmt.Sprintf("%d", published.Unix()),
244 DateTaken: created.Format(dateCreatedFormat),
245 LastUpdate: fmt.Sprintf("%d", updated.Unix()),
246 URL: fmt.Sprintf("https://farm3.staticflickr.com/2897/14198397111_%s_o.jpg", v),
247 OriginalFormat: "jpg",
248 }
249 photos = append(photos, item)
250 if len(photos) >= perPage {
251 break
252 }
253 indexOnPage++
254 }
255
256 photosPage := &photosSearch{
257 Photos: struct {
258 Page jsonInt
259 Pages jsonInt
260 Perpage jsonInt
261 Total jsonInt
262 Photo []*photosSearchItem
263 }{
264 Page: jsonInt(page),
265 Pages: jsonInt(pages),
266 Perpage: jsonInt(perPage),
267 Photo: photos,
268 },
269 }
270
271 list, err := json.MarshalIndent(photosPage, "", " ")
272 if err != nil {
273 log.Fatalf("%v", err)
274 }
275 return string(list)
276
277 }
278
279 func fakePicture() string {
280 camliDir, err := osutil.GoPackagePath("perkeep.org")
281 if err == os.ErrNotExist {
282 log.Fatal("Directory \"perkeep.org\" not found under GOPATH/src; are you not running with devcam?")
283 }
284 if err != nil {
285 log.Fatalf("Error searching for \"perkeep.org\" under GOPATH: %v", err)
286 }
287 return filepath.Join(camliDir, filepath.FromSlash("clients/web/embed/glitch/npc_piggy__x1_walk_png_1354829432.png"))
288 }