Home Download Docs Code Community
     1	/*
     2	Copyright 2014 The Perkeep Authors
     3	
     4	Licensed under the Apache License, Version 2.0 (the "License");
     5	you may not use this file except in compliance with the License.
     6	You may obtain a copy of the License at
     7	
     8	     http://www.apache.org/licenses/LICENSE-2.0
     9	
    10	Unless required by applicable law or agreed to in writing, software
    11	distributed under the License is distributed on an "AS IS" BASIS,
    12	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13	See the License for the specific language governing permissions and
    14	limitations under the License.
    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 // Arbitrary number of sets.
    50			perPage    = 3 // number of photos per page (both when getting sets and when getting photos).
    51			fakeUserId = "fakeUserId"
    52		)
    53		// Photoset N has N photos, so we've got 15 ( = 5 + 4 + 3 + 2 + 1) photos in total.
    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		// TODO(mpl): this scheme does not take into account that we could have the same photo
    69		// in different albums. These two photos will end up with a different photoId.
    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				// Photoset N has N photos.
    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		// Initial photo sets list
    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		// All the photoset calls. One call for each page of each photoset.
    98		// Each page as perPage photos, or maybe less if end of the photoset.
    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		// All the photo page calls (to get the photos info).
   135		// Each page has perPage photos, until end of photos.
   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		// Actual photo(s) URL.
   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	}
Website layout inspired by memcached.
Content by the authors.