From 827f057989c9ba0880f2f4af48f0046630f786e4 Mon Sep 17 00:00:00 2001 From: Kameron Kenny <1267885+kkenny@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:02:59 -0400 Subject: [PATCH] add logic for EXIF timestamp not being consistent --- import_media.py | 79 ++++++++++++++++++++++++++++++++-------------- import_media_ui.py | 0 2 files changed, 55 insertions(+), 24 deletions(-) mode change 100644 => 100755 import_media.py create mode 100644 import_media_ui.py diff --git a/import_media.py b/import_media.py old mode 100644 new mode 100755 index b02c8ba..2f68435 --- a/import_media.py +++ b/import_media.py @@ -1,21 +1,21 @@ #!/usr/bin/env python -''' -Import photos from SD card into folder with todays date + nickname -Use: importphotos (--jpg|--raw|--both) +""" +Import photos from SD card into folder with today's date + nickname +Use: import_media.py (--jpg|--raw|--both) Add script to path - TODO: -8. Optinally allow specification of a backup location on another disk +8. Optionally allow specification of a backup location on another disk or NAS to ship a 3rd copy to 10. Every config option has an arg override 11. Optionally rename file if EVENT name was passed in -- STRETCH -- 12. Make a graphical interface -''' +""" import os +import sys from pprint import pprint import argparse import shutil @@ -47,6 +47,8 @@ parser.add_argument("-b", "--backup-destination", help = "Create a backup of e specified location") parser.add_argument("-D", "--delete-source-files", help = "Delete files from SD after validating \ checksum of copied files") +parser.add_argument("-v", "--verify", help = "[True|False] Verify the checksum of \ + the copied file") parser.add_argument("-c", "--config", help = "Load the specified config file instead \ of the default " + CONFIG_FILE) parser.add_argument("-g", "--generate-config", help = "Generate config file based on options \ @@ -62,7 +64,7 @@ if args.source: config['folders']['source']['base'] = args.source if args.destination: config['folders']['destination']['base'] = args.source -#if args.create-oringinals: +#if args.create-originals: # pass #if args.backup-destination: # pass @@ -80,10 +82,13 @@ def dump_yaml(dictionary, file): def md5_hash(file): """ calculates and returns md5 hash """ - #print("calculating md5 for ", f) - md5 = hashlib.md5(open(file, 'rb').read()).hexdigest() - #with open(file, 'r') as f: - # md5 = hashlib.md5(f).hexdigest() + if config['verify_checksum']: + #print("calculating md5 for ", f) + md5 = hashlib.md5(open(file, 'rb').read()).hexdigest() + #with open(file, 'r') as f: + # md5 = hashlib.md5(f).hexdigest() + else: + md5 = 'no_verify' return md5 def cmp_files(file_1,file_2): @@ -93,19 +98,45 @@ def cmp_files(file_1,file_2): def get_capture_date(path, f_type): """ get capture date from meta """ if f_type == 'image': - with open(path, 'rb') as file: + with open(path, "rb") as file: tags = exifread.process_file(file) + if 'EXIF DateTimeOriginal' in tags: - stamp = datetime.strptime(str(tags['EXIF DateTimeOriginal']), '%Y:%m:%d %H:%M:%S') + try: + stamp = datetime.strptime( + str(tags['EXIF DateTimeOriginal']), + '%Y:%m:%d %H:%M:%S') + except ValueError as ve_dte: + print(f"\nError: {ve_dte}") + print("\nTrying digitized") + try: + stamp = datetime.strptime( + str(tags['EXIF DateTimeDigitized']), + '%Y:%m:%d %H:%M:%S') + except ValueError as ve_dtd: + print(f"\nError: {ve_dtd}") + print("\nTrying Image DateTime") + try: + stamp = datetime.strptime( + str(tags['Image DateTime']), + '%Y:%m:%d %H:%M:%S') + except ValueError as ve_idt: + print(f"\nError: {ve_idt}") + print(f"\nGiving up... Please inspect {path} and try again\n") + sys.exit() elif 'Image DateTime' in tags: - stamp = datetime.strptime(str(tags['Image DateTime']), '%Y:%m:%d %H:%M:%S') + stamp = datetime.strptime( + str(tags['Image DateTime']), '%Y:%m:%d %H:%M:%S') else: - stamp = datetime.strptime(str('1900:01:01 00:00:00'), '%Y:%m:%d %H:%M:%S') + stamp = datetime.strptime( + str('1900:01:01 00:00:00'), '%Y:%m:%d %H:%M:%S') elif f_type == 'video': - stamp = datetime.strptime(ffmpeg.probe(path)['format']['tags']['creation_time'], + stamp = datetime.strptime( + ffmpeg.probe(path)['format']['tags']['creation_time'], '%Y-%m-%dT%H:%M:%S.%f%z') elif f_type == 'audio': - stamp = datetime.strptime(ffmpeg.probe(path)['format']['tags']['date'], '%Y-%m-%d') + stamp = datetime.strptime( + ffmpeg.probe(path)['format']['tags']['date'], '%Y-%m-%d') else: stamp = datetime.fromtimestamp(os.path.getctime(path)) @@ -233,7 +264,7 @@ def process_file(path, f_type, f_name, ext): files[i]['folders']['destination'] = files[i]['folders']['destination'] + '/AUDIO' else: - print('WARN: ', files[i]['type'], \ + print('WARN: ', files[i]['type'], ' is not a known type and you never should have landed here.') def find_files(directory): @@ -243,11 +274,11 @@ def find_files(directory): for ext in config['file_types'][f_type]: for file in tqdm(filename, desc = 'Finding ' + ext + ' Files', ncols = 100): if file.lower().endswith(ext): - print(file) + # print(file) process_file(folder, f_type, file, ext) def validate_config_dir_access(): - """ Validate we can op in the defined directories """ + """ Validate we can operate in the defined directories """ check = path_access_write(config['folders']['destination']['base']) if check is False: writable = False @@ -300,19 +331,19 @@ def validate_checksums(): for checksum in files[file]['md5_checksums']: c[i] = files[file]['md5_checksums'][checksum] if i > 0: - P = i - 1 - if c[i] == c[P]: + p = i - 1 + if c[i] == c[p]: files[file]['source_cleanable'] = True else: files[file]['source_cleanable'] = False print(f'FATAL: Checksum validation failed for: \ - {files[file]["name"]} \n{c[i]}\n is not equal to \n{c[P]}\n') + {files[file]["name"]} \n{c[i]}\n is not equal to \n{c[p]}\n') print('\n File Meta:\n') pprint(files[file]) i = i + 1 def cleanup_sd(): - """ If we should cleanup the SD, nuke the copied files. """ + """ If we should clean up the SD, nuke the copied files. """ if config['cleanup_sd'] is True: for file in tqdm(files, desc = "Cleaning Up SD:", ncols = 100): if files[file]['source_cleanable'] is True: diff --git a/import_media_ui.py b/import_media_ui.py new file mode 100644 index 0000000..e69de29