a working prototype with so much more to do.

This commit is contained in:
Kameron Kenny 2023-08-07 22:15:26 -04:00
parent 63f2af02c5
commit 63a4124837
1 changed files with 194 additions and 0 deletions

194
import_media.py Normal file
View File

@ -0,0 +1,194 @@
#!/usr/bin/env python3
'''
Import photos from SD card into folder with todays date + nickname
Use: importphotos (--jpg|--raw|--both) <nickname of folder (optional)>
Add script to path
'''
'''
TODO:
1. Import configuration from config file
2. Set raw file extension based on camera specified in configuration
3. Create destination folders based on concatination of configuration,
metadata, and event name passed from ARG
4. Create destination sub-folder based on filetype
5. Copy files to appropriate folder
6. Compare files from source
7. Create 'originals' with copy of files from destination after
checksum for photos only
8. Optinally allow specification of a backup location on another disk
or NAS to ship a 3rd copy to
9. Optionally cleanup SD only after checksum matching
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
import yaml
import argparse
import shutil
import hashlib
from datetime import datetime
import exifread
config_file = 'config.yaml'
# Read configuration from file
try:
with open(config_file, 'r') as f:
config = yaml.load(f, Loader=yaml.FullLoader)
except FileNotFoundError:
print("Configuration file not found: ", config_file)
print("Copy config.yaml.EXAMPLE to ", config_file, " and update accordingly.")
''' Parse Arguments '''
parser = argparse.ArgumentParser()
parser.add_argument("-e", "--event", help = "Event Name")
args = parser.parse_args()
if args.event:
event = args.event
def md5_hash(f):
print("calculating md5 for ", f)
md5 = hashlib.md5(open(f, 'rb').read()).hexdigest()
return md5
def cmp_files(f1,f2):
print('comparing md5 hashes...')
return md5_hash(f1) == md5_hash(f2)
def file_classification(f):
print('Classifying media for: ', f)
for classification in config['file_types']:
for ext in config['file_types'][classification]:
if f.lower().endswith(ext):
c = classification
return classification
def get_capture_date(p, t):
if t == 'image':
with open(p, 'rb') as f:
tags = exifread.process_file(f)
captured = tags['EXIF DateTimeOriginal']
year = str(captured).split(' ')[0].split(':')[0]
month = str(captured).split(' ')[0].split(':')[1]
day = str(captured).split(' ')[0].split(':')[2]
else:
stamp = datetime.fromtimestamp(os.path.getctime(p))
year = stamp.strftime("%Y")
month = stamp.strftime("%m")
day = stamp.strftime("%d")
return year, month, day
def create_folder(f):
try:
os.makedirs(f)
except FileExistsError as exists:
print()
def copy_from_source(p, dest_folder, dest_orig_folder, file):
if os.path.exists(os.path.join(dest_folder, file)):
check_match = cmp_files(p, os.path.join(dest_folder, file))
if check_match == False:
base, extension = os.path.splitext(file)
file_name_hash = base + '_' + md5_hash(os.path.join(dest_folder, file)) + extension
os.rename(os.path.join(dest_folder, file), os.path.join(dest_folder, file_name_hash))
shutil.copy(p, dest_folder)
check_match = cmp_files(p, dest_folder + '/' + file)
if check_match == False:
print(f'CRITICAL: md5 hash does not match for {file}')
print(p, ': ', md5_hash(p))
print(dest_folder + '/' + file, ': ', md5_hash(dest_folder + '/' + file))
exit
if dest_orig_folder != False:
shutil.copy(dest_folder + '/' + file, dest_orig_folder)
check_match = cmp_files(dest_folder + '/' + file, dest_orig_folder + '/' + file)
if check_match == False:
print(f'CRITICAL: md5 hash does not match for {file}')
print(dest_folder + '/' + file, ': ', md5_hash(dest_folder + '/' + file))
print(dest_orig_folder + '/' + file, ': ', md5_hash(dest_orig_folder + '/' + file))
exit
else:
shutil.copy(p, dest_folder)
check_match = cmp_files(p, dest_folder + '/' + file)
if check_match == False:
print(f'CRITICAL: md5 hash does not match for {file}')
print(p, ': ', md5_hash(p))
print(dest_folder + '/' + file, ': ', md5_hash(dest_folder + '/' + file))
exit
if dest_orig_folder != False:
shutil.copy(dest_folder + '/' + file, dest_orig_folder)
check_match = cmp_files(dest_folder + '/' + file, dest_orig_folder + '/' + file)
if check_match == False:
print(f'CRITICAL: md5 hash does not match for {file}')
print(dest_folder + '/' + file, ': ', md5_hash(dest_folder + '/' + file))
print(dest_orig_folder + '/' + file, ': ', md5_hash(dest_orig_folder + '/' + file))
exit
def process_file(p, t, file, ext):
capture_date = get_capture_date(p, t)
y = capture_date[0]
m = capture_date[1]
d = capture_date[2]
if event:
dest_folder = config['folders']['destination']['base'] + '/' + y + '/' + y + '-' + m + '/' + y + '-' + m + '-' + d + '-' + event
else:
dest_folder = config['folders']['destination']['base'] + '/' + y + '/' + y + '-' + m + '/' + y + '-' + m + '-' + d
if t == 'image':
dest_folder = dest_folder + '/photos'
if config['store_originals'] == True:
dest_orig_folder = dest_folder + '/ORIGINALS'
if ext in ('jpg', 'jpeg'):
dest_folder = dest_folder + '/JPG'
if dest_orig_folder:
dest_orig_folder = dest_orig_folder + '/JPG'
else:
dest_folder = dest_folder + '/RAW'
if dest_orig_folder:
dest_orig_folder = dest_orig_folder + '/RAW'
elif t == 'video':
dest_folder = dest_folder + '/VIDEO'
elif t == 'audio':
dest_folder = dest_folder + '/AUDIO'
else:
print(f'WARN: {t} is not a known type and you never should have landed here.')
create_folder(dest_folder)
try:
dest_orig_folder
except NameError:
dest_orig_folder = False
else:
create_folder(dest_orig_folder)
copy_from_source(p, dest_folder, dest_orig_folder, file)
def file_list(directory):
for folder, subfolders, filename in os.walk(directory):
for t in config['file_types']:
for ext in config['file_types'][t]:
for file in filename:
if file.lower().endswith(ext):
p = folder + '/' + file
process_file(p, t, file, ext)
file_list(config['folders']['source']['base'])
print('done.')