158 lines
4.1 KiB
Go
158 lines
4.1 KiB
Go
// Tool to write Exif Date to Snapchat Data Archive.
|
|
// It filters files, takes the date in the name of the file and writes it to EXIF Metadata.
|
|
//
|
|
// Author : Zuma
|
|
// Date : 2025-03
|
|
|
|
package main
|
|
|
|
import (
|
|
"io"
|
|
"errors"
|
|
"os"
|
|
"github.com/tdewolff/argp"
|
|
"path/filepath"
|
|
"io/fs"
|
|
"log"
|
|
"fmt"
|
|
"strings"
|
|
"regexp"
|
|
exif "github.com/barasher/go-exiftool"
|
|
)
|
|
|
|
func listFiles(dir string, ext string) []string {
|
|
var files []string
|
|
|
|
err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
|
|
if !d.IsDir() && filepath.Ext(path) == "." + ext {
|
|
files = append(files, path)
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
return files
|
|
}
|
|
|
|
// https://github.com/barasher/go-exiftool/blob/master/exiftool_sample_test.go
|
|
func copyFile(src, dest string) (err error) {
|
|
s, err := os.Open(src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer s.Close()
|
|
|
|
d, err := os.Create(dest)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer d.Close()
|
|
|
|
_, err = io.Copy(d, s)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func copyFileAndSetMetadata(file string, outputFolder string, exif *exif.Exiftool) {
|
|
newDirectory := filepath.Join(outputFolder, filepath.Base(filepath.Dir(file)))
|
|
|
|
if _, err := os.Stat(newDirectory); errors.Is(err, os.ErrNotExist) {
|
|
if err := os.Mkdir(newDirectory, 0755); err != nil {
|
|
log.Fatalf("Cannot create directory : %s", newDirectory)
|
|
}
|
|
}
|
|
|
|
date := filepath.Base(file)[:10]
|
|
date_fields := strings.Split(date,"-")
|
|
exif_date := fmt.Sprintf("%s:%s:%s 00:00:00\n", date_fields[0], date_fields[1], date_fields[2])
|
|
|
|
exportFile := filepath.Join(newDirectory, filepath.Base(file))
|
|
copyFile(file, exportFile)
|
|
|
|
exifData := exif.ExtractMetadata(exportFile)
|
|
exifData[0].SetString("DateTime", exif_date)
|
|
exifData[0].SetString("DateTimeOriginal", exif_date)
|
|
exifData[0].SetString("DateTimeDigitized", exif_date)
|
|
exif.WriteMetadata(exifData)
|
|
}
|
|
|
|
func set_files_metadata(files []string, outputFolder string) {
|
|
r, _ := regexp.Compile("[0-9]{4}-[0-9]{2}-[0-9]{2}")
|
|
|
|
et, err := exif.NewExiftool()
|
|
if err != nil {
|
|
fmt.Printf("Error when intializing: %v\n", err)
|
|
return
|
|
}
|
|
defer et.Close()
|
|
|
|
for _, file := range files {
|
|
datename := filepath.Base(file)[:10]
|
|
if(r.MatchString(datename)) {
|
|
fileInfos := et.ExtractMetadata(file)
|
|
MIMEType, err := fileInfos[0].GetString("MIMEType")
|
|
if err != nil {
|
|
fmt.Printf("%s\nError when reading MIMEType : %v\n", file, err)
|
|
continue
|
|
}
|
|
|
|
if MIMEType == "video/mp4" {
|
|
HandlerType, err := fileInfos[0].GetString("HandlerType")
|
|
if err != nil {
|
|
fmt.Printf("%s\nError when reading HandlerType : %v\n", file, err)
|
|
continue
|
|
}
|
|
|
|
if HandlerType == "Audio Track" {
|
|
continue
|
|
}
|
|
|
|
copyFileAndSetMetadata(file, outputFolder, et)
|
|
} else if MIMEType == "image/jpeg" {
|
|
filename := filepath.Base(file)
|
|
// Skip thumbnails
|
|
if len(filename) == 116 || len(filename) == 66 {
|
|
continue
|
|
}
|
|
|
|
copyFileAndSetMetadata(file, outputFolder, et)
|
|
} else {
|
|
fmt.Printf("Unknown MIMEType : %v\n", MIMEType)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
var inputFolder string
|
|
var outputFolder string
|
|
|
|
cmd := argp.New("write_metadata, un outil pour mettre la date dans les données EXIF d'une photo")
|
|
cmd.AddArg(&inputFolder, "inputFolder", "Dossier à scanner")
|
|
cmd.AddArg(&outputFolder, "outputFolder", "Dossier ou exporter les fichiers édités")
|
|
cmd.Parse()
|
|
|
|
if(inputFolder == "") {
|
|
log.Fatal("ERROR : You must specify a folder to scan")
|
|
}
|
|
|
|
if(outputFolder == "") {
|
|
log.Fatal("ERROR : You must specify a folder to export output")
|
|
}
|
|
|
|
jpeg_files := listFiles(inputFolder, "jpeg")
|
|
jpg_files := listFiles(inputFolder, "jpg")
|
|
mp4_files := listFiles(inputFolder, "mp4")
|
|
var all_files []string
|
|
all_files = append(all_files, jpeg_files[:]...)
|
|
all_files = append(all_files, jpg_files[:]...)
|
|
all_files = append(all_files, mp4_files[:]...)
|
|
fmt.Println(fmt.Sprintf("%d files found.",len(all_files)))
|
|
|
|
set_files_metadata(all_files, outputFolder)
|
|
|
|
}
|