arrange/image.go

93 lines
1.9 KiB
Go

package arrange
import (
"errors"
"fmt"
"io"
"os"
"path/filepath"
"time"
"github.com/rwcarlsen/goexif/exif"
)
type Media struct {
Path string
}
func (m Media) Move(root string) error {
return errors.New("NYI")
}
type Image struct {
Path string
Hash string
Year string
Month string
Time string
}
func (im Image) Move(root string) error {
f, err := os.Open(im.Path)
if err != nil {
return fmt.Errorf("problem opening jpg file: %v", err)
}
defer f.Close()
content := filepath.Join(root, "content", im.Hash[:2], im.Hash[2:]+".jpg")
if _, err := os.Stat(content); !os.IsNotExist(err) {
return Dup{content}
}
out, err := os.Create(content)
if err != nil {
return fmt.Errorf("could not create output file: %v", err)
}
defer out.Close()
if _, err := io.Copy(out, f); err != nil {
return fmt.Errorf("trouble copying file: %v", err)
}
if err := os.MkdirAll(filepath.Join(root, "date", im.Year, im.Month), 0755); err != nil {
return fmt.Errorf("problem creating date directory: %v", err)
}
date := filepath.Join(root, "date", im.Year, im.Month, im.Time)
name := date + ".jpg"
for i := 0; i < 10000; i++ {
if _, err := os.Stat(name); os.IsNotExist(err) {
break
}
name = fmt.Sprintf("%s_%04d.jpg", date, i)
}
// TODO: or maybe symlinking? (issue #2)
// rel := filepath.Join("..", "..", "..", "content", j.hash[:2], j.hash[2:]+".jpg")
// return os.Symlink(rel, name)
return os.Link(content, name)
}
func parseExif(f io.Reader) (time.Time, error) {
ti := time.Time{}
x, err := exif.Decode(f)
if err != nil {
if exif.IsCriticalError(err) {
return ti, err
}
}
tm, err := x.DateTime()
if err != nil {
return ti, fmt.Errorf("no datetime in an ostensibly valid exif %v", err)
}
return tm, nil
}
func mtime(path string) (time.Time, error) {
ti := time.Time{}
s, err := os.Stat(path)
if err != nil {
return ti, fmt.Errorf("failure to collect times from stat: %v", err)
}
return s.ModTime(), nil
}