🍯 Glaze

package main

import (
	"encoding/csv"
	"flag"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/perlw/pict/internal/app/pictadd"
	"github.com/perlw/pict/internal/pkg/store"
)

func collectDataFromCsv(csvFilename string) []pictadd.FileWithMetadata {
	filesWithMetadata := make([]pictadd.FileWithMetadata, 0, 10)

	csvFile, err := os.Open(csvFilename)
	if err != nil {
		flag.PrintDefaults()
		fmt.Println("could not find/read csv file")
		os.Exit(1)
	}
	defer csvFile.Close()
	csvReader := csv.NewReader(csvFile)
	for {
		record, err := csvReader.Read()
		if err == io.EOF {
			break
		}

		var fileData pictadd.FileWithMetadata
		if len(record) > 0 {
			fileData.Filename = record[0]
		}
		if len(record) > 1 {
			fileData.Tags = strings.Split(record[1], ",")
		}
		if len(record) > 2 {
			fileData.Title = record[2]
		}
		if len(record) > 3 {
			fileData.Timestamp = parseTimestampFromFilename(fileData.Filename, record[3])
		}

		filesWithMetadata = append(filesWithMetadata, fileData)
	}

	return filesWithMetadata
}

func parseTimestampFromFilename(filename, format string) int64 {
	var result int64

	var start, end int
	start = strings.Index(format, "[[")
	end = strings.Index(format, "]]")

	timeFormat := format[start+2 : end]
	if start > -1 && end > -1 && end > start {
		timeFormat = strings.Replace(timeFormat, "YYYY", "2006", -1)
		timeFormat = strings.Replace(timeFormat, "MM", "01", -1)
		timeFormat = strings.Replace(timeFormat, "DD", "02", -1)
		timeFormat = strings.Replace(timeFormat, "hh", "15", -1)
		timeFormat = strings.Replace(timeFormat, "mm", "04", -1)
		timeFormat = strings.Replace(timeFormat, "ss", "05", -1)
	}

	if format != "" {
		if dt, err := time.Parse(
			timeFormat, filepath.Base(filename)[start:end-2],
		); err != nil {
			fmt.Printf("invalid timestamp: %s\n", err.Error())
			result = time.Now().Unix()
		} else {
			result = dt.Unix()
		}
	} else {
		result = time.Now().Unix()
	}

	return result
}

func main() {
	var tagsArg, storageDir string
	var goAhead, fixThumbnails, fixPreviews bool
	var timestampArg int64
	var filenameFormat, title string
	var csvFilename string
	var imageFilename string
	flag.StringVar(
		&storageDir, "storage-dir", "./", "where to find database files etc",
	)
	flag.BoolVar(&fixThumbnails, "fix-thumbnails", false, "fixes thumbnails")
	flag.BoolVar(&fixPreviews, "fix-previews", false, "fixes previews")
	flag.StringVar(&tagsArg, "tags", "", "tags to add/create")
	flag.StringVar(&title, "title", "", "the title to attach to the image")
	flag.Int64Var(×tampArg, "timestamp", 0, "timestamp, defaults to now")
	flag.StringVar(&filenameFormat, "format", "", "the format of the filename")
	flag.StringVar(&csvFilename, "csv", "", "read files from csv (format: filename,\"tag_a,tag_b\",title,filenameformat)")
	flag.StringVar(&imageFilename, "file", "", "name of a single file")
	flag.BoolVar(&goAhead, "yes", false, "tells it to go ahead, used for scripts")
	flag.Parse()

	var filesWithMetadata []pictadd.FileWithMetadata
	if csvFilename != "" && imageFilename != "" {
		flag.PrintDefaults()
		fmt.Println("can't specify both -csv and -file")
		os.Exit(1)
	} else if csvFilename != "" {
		filesWithMetadata = collectDataFromCsv(csvFilename)
	} else if imageFilename != "" {
		tags := strings.Split(tagsArg, ",")

		var timestamp int64
		if filenameFormat != "" {
			timestamp = parseTimestampFromFilename(imageFilename, filenameFormat)
		} else {
			if timestampArg <= 0 {
				timestamp = time.Now().Unix()
			} else {
				timestamp = time.Unix(timestampArg, 0).Unix()
			}
		}

		filesWithMetadata = []pictadd.FileWithMetadata{
			{
				Filename:  imageFilename,
				Tags:      tags,
				Title:     title,
				Timestamp: timestamp,
			},
		}
	} else {
		flag.PrintDefaults()
		fmt.Println("must specify either -csv or -file")
		os.Exit(1)
	}

	store, err := store.NewSQLiteProvider(
		filepath.Join(storageDir, "metadata.db"),
	)
	if err != nil {
		fmt.Printf("%s\n", err.Error())
		os.Exit(2)
	}
	defer store.Close()

	opts := []pictadd.Option{
		pictadd.WithStoreProvider(store),
		pictadd.WithImageStorageDir(storageDir),
	}
	if goAhead {
		opts = append(opts, pictadd.WithGoAhead())
	}
	app, err := pictadd.New(
		opts...,
	)
	if err != nil {
		fmt.Printf("%s\n", err.Error())
		os.Exit(3)
	}

	if fixThumbnails {
		if err := app.FixThumbnails(filesWithMetadata); err != nil {
			fmt.Printf("%s\n", err.Error())
			os.Exit(4)
		}
	}
	if fixPreviews {
		if err := app.FixPreviews(filesWithMetadata); err != nil {
			fmt.Printf("%s\n", err.Error())
			os.Exit(4)
		}
	}
	if !fixThumbnails && !fixPreviews {
		if err := app.Import(filesWithMetadata); err != nil {
			fmt.Printf("%s\n", err.Error())
			os.Exit(4)
		}
	}
}