From b2659ba5ce48b223490b8f51db065d93ae8f0cf5 Mon Sep 17 00:00:00 2001 From: Michael Mayer Date: Sun, 17 Jun 2018 20:12:02 +0200 Subject: [PATCH] Implemented export command --- Gopkg.lock | 8 ++++- cmd/photoprism/photoprism.go | 55 +++++++++++++++++++++++++------- export.go | 61 ++++++++++++++++++++++++++++++++++++ mediafile.go | 30 ++++++++++++++++++ 4 files changed, 141 insertions(+), 13 deletions(-) create mode 100644 export.go diff --git a/Gopkg.lock b/Gopkg.lock index d677372e9..941230f72 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,6 +1,12 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. +[[projects]] + branch = "master" + name = "github.com/araddon/dateparse" + packages = ["."] + revision = "6135c1994ea28aa1bb341f5c704885906f584904" + [[projects]] branch = "master" name = "github.com/bamiaux/rez" @@ -109,6 +115,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "af3dcd4c923c605a744d0ffad8c1a20ed0ce15fc3bdedb6d73b32be52dba9d23" + inputs-digest = "1ffc35574da6350baeabae12e2aed7a151f4db332e9e73656bd10b8db55de7d2" solver-name = "gps-cdcl" solver-version = 1 diff --git a/cmd/photoprism/photoprism.go b/cmd/photoprism/photoprism.go index 6a8438763..198d6f96f 100644 --- a/cmd/photoprism/photoprism.go +++ b/cmd/photoprism/photoprism.go @@ -5,6 +5,7 @@ import ( "github.com/photoprism/photoprism" "github.com/urfave/cli" "os" + "github.com/araddon/dateparse" ) func main() { @@ -13,7 +14,7 @@ func main() { app := cli.NewApp() app.Name = "PhotoPrism" app.Usage = "Digital Photo Archive" - app.Version = "0.0.3" + app.Version = "0.1.0" app.Flags = globalCliFlags app.Commands = []cli.Command{ { @@ -24,7 +25,7 @@ func main() { conf.SetValuesFromCliContext(context) - fmt.Printf(" \n") + fmt.Printf("NAME VALUE\n") fmt.Printf("config-file %s\n", conf.ConfigFile) fmt.Printf("darktable-cli %s\n", conf.DarktableCli) fmt.Printf("originals-path %s\n", conf.OriginalsPath) @@ -128,19 +129,21 @@ func main() { Usage: "Export photos as JPEG", Flags: []cli.Flag{ cli.StringFlag{ - Name: "from, f", - Usage: "Start date & time", - Value: "yesterday", + Name: "name, n", + Usage: "Sub-directory name", }, cli.StringFlag{ - Name: "to, t", - Usage: "End date & time", - Value: "today", + Name: "after, a", + Usage: "Start date e.g. 2017/04/15", }, cli.StringFlag{ + Name: "before, b", + Usage: "End date e.g. 2018/05/02", + }, + cli.IntFlag{ Name: "size, s", - Usage: "Max image size in pixels", - Value: "4096", + Usage: "Image size in pixels", + Value: 2560, }, }, Action: func(context *cli.Context) error { @@ -150,9 +153,37 @@ func main() { conf.CreateDirectories() - fmt.Printf("Exporting photos to %s...\n", conf.ExportPath) + before := context.String("before") + after := context.String("after") - fmt.Println("[TODO]") + if before == "" || after == "" { + fmt.Println("You need to provide before and after dates for export, e.g.\n\nphotoprism export --after 2018/04/10 --before '2018/04/15 23:00:00'") + + return nil + } + + afterDate, _ := dateparse.ParseAny(after) + beforeDate, _ := dateparse.ParseAny(before) + afterDateFormatted := afterDate.Format("20060102") + beforeDateFormatted := beforeDate.Format("20060102") + + name := context.String("name") + + if name == "" { + if afterDateFormatted == beforeDateFormatted { + name = beforeDateFormatted + } else { + name = fmt.Sprintf("%s - %s", afterDateFormatted, beforeDateFormatted) + } + } + + exportPath := fmt.Sprintf("%s/%s", conf.ExportPath, name); + size := context.Int("size") + originals := photoprism.FindOriginalsByDate(conf.OriginalsPath, afterDate, beforeDate) + + fmt.Printf("Exporting photos to %s...\n", exportPath) + + photoprism.ExportPhotosFromOriginals(originals, conf.ThumbnailsPath, exportPath, size) fmt.Println("Done.") diff --git a/export.go b/export.go new file mode 100644 index 000000000..9da60429c --- /dev/null +++ b/export.go @@ -0,0 +1,61 @@ +package photoprism + +import ( + "os" + "log" + "fmt" + "path/filepath" + "strings" + "time" +) + +func FindOriginalsByDate(originalsPath string, after time.Time, before time.Time) (result []*MediaFile) { + filepath.Walk(originalsPath, func(filename string, fileInfo os.FileInfo, err error) error { + if err != nil || fileInfo.IsDir() || strings.HasPrefix(filepath.Base(filename), ".") { + return nil + } + + _, basename := filepath.Split(filename) + + if basename <= after.Format("20060102_150405") || basename >= before.Format("20060102_150405") { + return nil + } + + mediaFile := NewMediaFile(filename) + + if !mediaFile.Exists() || !mediaFile.IsJpeg() { + return nil + } + + result = append(result, mediaFile) + + return nil + }) + + return result +} + +func ExportPhotosFromOriginals(originals []*MediaFile, thumbnailsPath string, exportPath string, size int) (err error) { + for _, mediaFile := range originals { + + if !mediaFile.Exists() || !mediaFile.IsJpeg() { + return nil + } + + log.Printf("Exporting %s as %dpx JPEG", mediaFile.GetFilename(), size) + + thumbnail, err := mediaFile.GetThumbnail(thumbnailsPath, size) + + if err != nil { + log.Print(err.Error()) + } + + os.MkdirAll(exportPath, os.ModePerm) + + destinationFilename := fmt.Sprintf("%s/%s_%dpx.jpg", exportPath, mediaFile.GetCanonicalName(), size) + + thumbnail.Copy(destinationFilename) + } + + return nil +} diff --git a/mediafile.go b/mediafile.go index 2cf7ab3a3..d87dfe05d 100644 --- a/mediafile.go +++ b/mediafile.go @@ -11,6 +11,7 @@ import ( "path/filepath" "strings" "time" + "io" ) const ( @@ -254,6 +255,35 @@ func (m *MediaFile) Move(newFilename string) error { return nil } +func (m *MediaFile) Copy(destinationFilename string) error { + file, err := m.openFile() + + if err != nil { + log.Println(err.Error()) + return err + } + + defer file.Close() + + destination, err := os.OpenFile(destinationFilename, os.O_RDWR|os.O_CREATE, 0666) + + if err != nil { + log.Println(err.Error()) + return err + } + + defer destination.Close() + + _, err = io.Copy(destination, file) + + if err != nil { + log.Println(err.Error()) + return err + } + + return nil +} + func (m *MediaFile) GetExtension() string { return strings.ToLower(filepath.Ext(m.filename)) }