Created
January 25, 2020 19:43
-
-
Save Dynom/dfe491a20b9b6d8f48dd2b1b25c147a0 to your computer and use it in GitHub Desktop.
Flickr data recovery script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/json" | |
"io/ioutil" | |
"log" | |
"os" | |
"path/filepath" | |
"strings" | |
"time" | |
) | |
/* | |
1. Visit https://www.flickr.com/account/ | |
2. Request your data, when the are available, download them to the same directory on a local drive | |
3. Extract all zip files to the same directory (both photo and JSON files) | |
4. Run this script to: | |
- Rename files back to their original name | |
- Set the correct file modified times | |
*/ | |
func main() { | |
var dir = "." | |
var loc = time.UTC | |
var dryRun = false | |
logger := log.New(os.Stdout, "", log.LstdFlags) | |
files, err := ioutil.ReadDir(dir) | |
if err != nil { | |
panic(err) | |
} | |
var jsonFiles = make([]string, 0, 128) | |
var photoFiles = make(map[string]string, 128) | |
for _, file := range files { | |
if file.IsDir() { | |
continue | |
} | |
if strings.HasPrefix(file.Name(), "photo_") && strings.HasSuffix(file.Name(), ".json") { | |
jsonFiles = append(jsonFiles, file.Name()) | |
continue | |
} | |
// If it's a file, matching Flickr's expected structure | |
if id, ok := getIDFromFileName(file.Name()); ok { | |
if _, ok := photoFiles[id]; ok { | |
logger.Printf("Muiltiple ID's are possible! %q", file.Name()) | |
} | |
photoFiles[id] = file.Name() | |
continue | |
} | |
} | |
for _, fileName := range jsonFiles { | |
contents, err := ioutil.ReadFile(filepath.Join(dir, fileName)) | |
if err != nil { | |
panic(err) | |
} | |
var details FlickrDEPhoto | |
if err := json.Unmarshal(contents, &details); err != nil { | |
panic(err) | |
} | |
photoFileName, ok := photoFiles[details.ID] | |
if !ok { | |
logger.Printf("Have a match in file %q, but didn't find a photo with id %q", fileName, details.ID) | |
continue | |
} | |
var ext string | |
if ext = filepath.Ext(photoFileName); ext == "" || ext == "." || ext[0] != '.' { | |
logger.Printf("Missing extension for file %q", photoFileName) | |
continue | |
} | |
logger.Printf("Processing %q", photoFileName) | |
source := filepath.Join(dir, photoFileName) | |
destination := filepath.Join(dir, details.Name+ext) | |
logger.Printf("==> Renaming to: %q", destination) | |
if !dryRun { | |
if err := os.Rename(source, destination); err != nil { | |
logger.Printf("==> Failed to rename %q to %q, %s", source, destination, err) | |
} | |
} | |
originalCTime, err := time.ParseInLocation("2006-01-02 15:04:05", details.DateTaken, loc) | |
logger.Printf("==> Setting time to: %q", originalCTime) | |
if !dryRun { | |
err = os.Chtimes(destination, originalCTime, originalCTime) | |
if err != nil { | |
logger.Printf("==> Failed to set time %q on file %q, %s", originalCTime, destination, err) | |
} | |
} | |
} | |
} | |
func getIDFromFileName(fileName string) (string, bool) { | |
endIndex := strings.LastIndex(fileName, ".") | |
if endIndex <= 0 { | |
return "", false | |
} | |
// images typically have the "_o.jpg" suffix | |
if strings.HasSuffix(fileName[:endIndex], "_o") { | |
endIndex = endIndex - 2 | |
} | |
// The identifier is prefixed with the "_" separator | |
startIndex := strings.LastIndex(fileName[:endIndex], "_") | |
if startIndex < 0 { | |
return "", false | |
} | |
for _, c := range fileName[startIndex+1 : endIndex] { | |
if '0' <= c && c <= '9' { | |
continue | |
} | |
return "", false | |
} | |
return fileName[startIndex+1 : endIndex], true | |
} | |
type FlickrDEPhoto struct { | |
ID string `json:"id"` | |
Name string `json:"name"` | |
Description string `json:"description"` | |
DateTaken string `json:"date_taken"` | |
Rotation int `json:"rotation"` | |
Original string `json:"original"` | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment