From 12befa0ac33f49019627091ffd4b500efd050c33 Mon Sep 17 00:00:00 2001 From: Balakrishnan Balasubramanian Date: Tue, 6 Aug 2024 23:14:06 -0400 Subject: [PATCH] Implement LoadPhotos and DownloadPhoto --- main.go | 123 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 105 insertions(+), 18 deletions(-) diff --git a/main.go b/main.go index c976c11..9ef1420 100644 --- a/main.go +++ b/main.go @@ -26,11 +26,12 @@ import ( var ( imagesDir string collageDir string + photosDir string devMode bool collageNameGen *nameGen imagesDirFs fs.FS listenAddr string - photoPrismURL string + photoPrismURL *url.URL photoPrismToken string //go:embed web @@ -38,19 +39,32 @@ var ( ) func main() { + var ppURL string + flag.StringVar(&imagesDir, "images-dir", "images", "Sets the images dir") flag.StringVar(&collageDir, "collages-dir", "collages", "Sets the collages dir") + flag.StringVar(&photosDir, "photos-dir", "photos", "Cache directory for downloaded photos") flag.BoolVar(&devMode, "dev", false, "Serve local assets during development") flag.StringVar(&listenAddr, "addr", "127.0.0.1:8767", "Web listen address, see https://pkg.go.dev/go.balki.me/anyhttp#readme-address-syntax") - flag.StringVar(&photoPrismURL, "pp-url", "", "Base url for photoprism") + flag.StringVar(&ppURL, "pp-url", "", "Base url for photoprism") flag.StringVar(&photoPrismToken, "pp-token", "", "API token for photoprism") flag.Parse() + photoPrismURL = func() *url.URL { + photoPrismURL, err := url.Parse(ppURL) + if err != nil { + panic(err) + } + return photoPrismURL + }() + copy := *photoPrismURL + fmt.Println(copy) collageNameGen = NewNameGen() imagesDirFs = os.DirFS(imagesDir) imagesURLPath := "images" collagesPath := "collages" + photosPath := "photos" addFileServer := func(path, dir string) { httpFileServer := http.FileServer(http.Dir(dir)) @@ -59,6 +73,7 @@ func main() { addFileServer(imagesURLPath, imagesDir) addFileServer(collagesPath, collageDir) + addFileServer(photosPath, photosDir) if devMode { httpFileServer := http.FileServer(http.Dir("web")) @@ -170,41 +185,113 @@ type Album struct { } func GetAlbums() ([]Album, error) { - u, err := url.Parse(photoPrismURL) - if err != nil { - return nil, err - } + albumURL := func() string { + u := *photoPrismURL + u.Path = "/api/v1/albums" + v := url.Values{} + v.Add("count", "20") + v.Add("type", "album") + u.RawQuery = v.Encode() + return u.String() + }() - u.Path = "/api/v1/albums" - v := url.Values{} - v.Add("count", "10") - v.Add("type", "album") - u.RawQuery = v.Encode() - - req, err := http.NewRequest("GET", u.String(), nil) + req, err := http.NewRequest("GET", albumURL, nil) if err != nil { return nil, err } req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", photoPrismToken)) - req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } - albums := []Album{} - respBytes, err := io.ReadAll(resp.Body) if err != nil { return nil, err } + albums := []Album{} err = json.Unmarshal(respBytes, &albums) if err != nil { return nil, err } - // List albums - // yq -oc '[.[] | pick(["UID", "Title"])]' albums.json | pandoc -fcsv -tplain return albums, nil } + +type Photo struct { + Hash string `json:"Hash"` + FileUID string `json:"FileUID"` +} + +func LoadPhotos(albumID string) ([]Photo, error) { + loadPhotosURL := func() string { + u := *photoPrismURL + u.Path = "/api/v1/photos" + v := url.Values{} + v.Add("count", "50") + v.Add("s", albumID) + v.Add("merged", "true") + v.Add("video", "false") + u.RawQuery = v.Encode() + return u.String() + + }() + + req, err := http.NewRequest("GET", loadPhotosURL, nil) + if err != nil { + return nil, err + } + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", photoPrismToken)) + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + respBytes, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + photos := []Photo{} + err = json.Unmarshal(respBytes, &photos) + if err != nil { + return nil, err + } + + return photos, nil +} + +func DownloadPhoto(photo *Photo) (string, error) { + photoPath := path.Join(photosDir, fmt.Sprintf("%s.jpg", photo.FileUID)) + _, err := os.Stat(photoPath) + if err == nil { + return photoPath, nil + } else if !os.IsNotExist(err) { + return "", err + } + out, err := os.Create(photoPath) + if err != nil { + return "", fmt.Errorf("failed to create collage output file, err: %w", err) + } + defer out.Close() + downloadPhotoURL := func() string { + u := *photoPrismURL + u.Path = fmt.Sprintf("/api/v1/dl/%s", photo.Hash) + return u.String() + }() + req, err := http.NewRequest("GET", downloadPhotoURL, nil) + if err != nil { + return "", err + } + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", photoPrismToken)) + resp, err := http.DefaultClient.Do(req) + if err != nil { + return "", err + } + + _, err = io.Copy(out, resp.Body) + if err != nil { + return "", err + } + + return photoPath, nil +}