From 105137ab21b763c30ed1d0e3821fa1e5d0ae1757 Mon Sep 17 00:00:00 2001 From: zuma Date: Thu, 27 Mar 2025 15:19:32 +0100 Subject: [PATCH] First commit --- go.mod | 14 ++++ go.sum | 29 +++++++++ write_metadata.go | 158 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 201 insertions(+) create mode 100644 go.mod create mode 100644 go.sum create mode 100644 write_metadata.go diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..2f3594c --- /dev/null +++ b/go.mod @@ -0,0 +1,14 @@ +module shenanigans.cc/write_metadata + +go 1.24.1 + +require ( + github.com/barasher/go-exiftool v1.10.0 + github.com/tdewolff/argp v0.0.0-20250320085902-4439d1422dc0 +) + +require ( + github.com/jmoiron/sqlx v1.4.0 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ef44c48 --- /dev/null +++ b/go.sum @@ -0,0 +1,29 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/barasher/go-exiftool v1.10.0 h1:f5JY5jc42M7tzR6tbL9508S2IXdIcG9QyieEXNMpIhs= +github.com/barasher/go-exiftool v1.10.0/go.mod h1:F9s/a3uHSM8YniVfwF+sbQUtP8Gmh9nyzigNF+8vsWo= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= +github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/tdewolff/argp v0.0.0-20250320085902-4439d1422dc0 h1:YufZL9rQwxKq9R90ktNSh7jaJTxOp/wFMbyJC3JDhXY= +github.com/tdewolff/argp v0.0.0-20250320085902-4439d1422dc0/go.mod h1:EsA2iZLlkV7V/hd67zmi7ebo1HgvokR6QYGOw1ooO/M= +github.com/tdewolff/test v1.0.11 h1:FdLbwQVHxqG16SlkGveC0JVyrJN62COWTRyUFzfbtBE= +github.com/tdewolff/test v1.0.11/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/write_metadata.go b/write_metadata.go new file mode 100644 index 0000000..40d1e1b --- /dev/null +++ b/write_metadata.go @@ -0,0 +1,158 @@ +// 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) + +}