Skip to content
This repository has been archived by the owner on Sep 10, 2023. It is now read-only.

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
MrYakobo committed Apr 5, 2023
0 parents commit 0bc6aab
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .env-example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copy this file to .env and edit the path below

# The unzipped takeout directory
TAKEOUT_DIR="/home/user/Downloads/Takeout"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.env
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "google-photos-exif"]
path = google-photos-exif
url = https://github.com/mattwilson1024/google-photos-exif.git
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM docker.io/python:3.11.2-bullseye

RUN apt-get update && apt-get install -y nodejs npm ffmpeg exiftool
RUN npm i -g yarn

COPY ./google-photos-exif /app

WORKDIR /app
RUN yarn install
12 changes: 12 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: "3.8"

services:
metadata:
container_name: fix_metadata
build: .
entrypoint: ["/app/fix_metadata.py", "/mnt"]
volumes:
- ${TAKEOUT_DIR}:/mnt
- ./fix_metadata.py:/app/fix_metadata.py
env_file:
- .env
122 changes: 122 additions & 0 deletions fix_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#!/usr/bin/env python3

import subprocess
from glob import glob
import argparse
import os
from pathlib import Path
import shutil
import sys


def sh(args):
p = subprocess.run(args)
p.check_returncode()

def p(s):
print(s, file=sys.stderr)


def run_mattwilson1024_google_photos_exif(albumdir, outdir, errdir, check_errdir=True):
os.makedirs(albumdir, exist_ok=True)
os.makedirs(outdir, exist_ok=True)
os.makedirs(errdir, exist_ok=True)

sh(
[
"yarn", "start",
"--inputDir", albumdir,
"--outputDir", outdir,
"--errorDir", errdir,
]
)

if not check_errdir:
return

errdir_not_empty = len(glob(f"{errdir}/*")) > 0
if errdir_not_empty:
sh(
[
"exiftool", "-all=", "-tagsfromfile", "@",
"-all:all", "-unsafe", "-icc_profile", errdir,
]
)
# rerun analysis
run_mattwilson1024_google_photos_exif(
albumdir, outdir, errdir, check_errdir=False
)

def process_albums(rootdir):
globstr = f"{rootdir}/Albums/*/"
albums = glob(globstr)
if len(albums) == 0:
p(f"WARN: No albums found at {globstr}")

for albumdir in albums:
p(f"Processing album {albumdir}...")
album_name = Path(albumdir).stem
outdir = f"{rootdir}/AlbumsProcessed/{album_name}"
errdir = f"{rootdir}/AlbumsError/{album_name}"
run_mattwilson1024_google_photos_exif(albumdir, outdir, errdir)

def process_photos(rootdir):
# also run the exif fix for the Photos
p(f"Processing photos...")
albumdir = f"{rootdir}/Photos"
outdir = f"{rootdir}/PhotosProcessed"
errdir = f"{rootdir}/PhotosError"

run_mattwilson1024_google_photos_exif(albumdir, outdir, errdir)

def _restructure_if_needed(globstr, target_dir):
if os.path.exists(target_dir) and len(glob(f"{target_dir}/*")) > 0:
p(f"{target_dir} exists and is non-empty, assuming no further restructuring is needed")
return

os.makedirs(target_dir, exist_ok=True)

albums = glob(globstr)
if len(albums) == 0:
p(f"Warning: {globstr} didn't match anything")

for album in albums:
shutil.move(album, target_dir)

p(f"Restructured {len(albums)} folders")


def restructure_folders_if_needed(rootdir):
# before
# $rootdir/My Album 1
# $rootdir/My Album 2
# $rootdir/Photos from 2008

# after
# $rootdir/Albums/My Album 1
# $rootdir/Albums/My Album 2
# $rootdir/Photos/Photos from 2008

# move the "Photos from $YEAR" directories to Photos/
_restructure_if_needed(f"{rootdir}/Photos from */", f"{rootdir}/Photos")

# move the other directories to Albums/
_restructure_if_needed(f"{rootdir}/*/", f"{rootdir}/Albums")


def main(rootdir):
# at least in my takeout, the Takeout folder contains a subfolder
# Takeout/Google Foto
# rootdir refers to that subfolder

rootdir = glob(f"{rootdir}/*/")[0]
restructure_folders_if_needed(rootdir)

process_albums(rootdir)
process_photos(rootdir)

if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('rootdir', help="Path to the Takeout/ folder")
args = parser.parse_args()
main(args.rootdir)
1 change: 1 addition & 0 deletions google-photos-exif
Submodule google-photos-exif added at e272b5
15 changes: 15 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# ugly wrapper around mattwilson1024/google-photos-exif

## How do I run it?

```bash
git clone --recurse-submodules https://github.com/MrYakobo/exif-wrapper.git
cd exif-wrapper

echo "TAKEOUT_DIR=/home/user/Downloads/Takeout" > .env
docker-compose up
```

## Why

Because I found making manual steps daunting, and I already hacked this script together. Might as well share it

0 comments on commit 0bc6aab

Please sign in to comment.