diff --git a/dm_logs.py b/dm_logs.py new file mode 100644 index 0000000..b8f8b7a --- /dev/null +++ b/dm_logs.py @@ -0,0 +1,40 @@ +""" +Logging module for the Download Manager + +Written by Jadon Yack +""" + +import logging + +class dm_logger_t: + def dm_logs_init(self): + """Initialize logger.""" + self.dm_logger = logging.getLogger('dm_logger') + self.dm_logger.setLevel(logging.INFO) + + dm_console = logging.StreamHandler() + dm_logfile = logging.FileHandler('dm.log') + + dm_format = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') + dm_console.setFormatter(dm_format) + dm_logfile.setFormatter(dm_format) + + self.dm_logger.addHandler(dm_console) + self.dm_logger.addHandler(dm_logfile) + + self.dm_logger.info('Logger initialized.') + + def dm_log_info(self, string: str): + """Print info log.""" + self.dm_logger.info(string) + + def dm_log_err(self, string: str): + """Print error log.""" + self.dm_logger.error(string) + + def dm_log_debug(self, string: str): + """Print debug log.""" + self.dm_logger.debug(string) + + def __init__(self): + self.dm_logs_init() diff --git a/download_manager.py b/download_manager.py index 6d99fa5..214a09c 100755 --- a/download_manager.py +++ b/download_manager.py @@ -1,28 +1,76 @@ #!/usr/bin/env python3 -# This is a Python script that automates the management of the Downloads folder -# for an organized experience. It will sort images, videos, documents, and ISO -# files on download. -# -# Written by Jadon Yack (jyack) +""" +This is a Python script that automates the management of the Downloads folder +for an organized experience. It will sort images, videos, documents, and ISO +files on download. -from os import scandir, getlogin, rename -from os.path import splitext, exists, join, isfile +Written by Jadon Yack (jyack) +""" + +from os import scandir, getlogin +from os.path import split, splitext, exists, isfile from shutil import move as mv from time import sleep - -import logging +import threading from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler -user = getlogin() -src_dir = f"/home/{user}/Downloads" -img_dst = f"/home/{user}/Pictures/DownloadedImages" -vid_dst = f"/home/{user}/Videos" -doc_dst = f"/home/{user}/Documents" -iso_dst = f"/home/{user}/ISOs" +from dm_logs import dm_logger_t -def makeUniq(file, dst, name): +user = getlogin() +src_dir = f"/home/{user}/Downloads/" +img_dst = f"/home/{user}/Pictures/DownloadedImages/" +vid_dst = f"/home/{user}/Videos/" +doc_dst = f"/home/{user}/Documents/" +iso_dst = f"/home/{user}/ISOs/" + +dm_logger = dm_logger_t() + +file_types = { + 'image': [ + '.jpg', + '.jpeg', + '.png', + '.gif', + '.bmp', + '.tiff', + '.svg', + '.webp', + '.ico', + '.heic', + '.psd' + ], + 'video': [ + '.mp4', + '.mkv', + '.avi', + '.mov', + '.wmv', + '.flv', + '.webm', + '.mpeg', + '.mpg', + '.m4v', + '.3gp' + ], + 'doc': [ + '.pdf', + '.doc', + '.docx', + '.txt', + '.rtf', + '.odt', + '.ppt', + '.pptx', + '.xls', + '.xlsx', + '.csv', + '.epub' + ] +} + +def makeUniq(dst, name): filename, extension = splitext(name) counter = 1 uniq_name = name @@ -31,44 +79,68 @@ def makeUniq(file, dst, name): uniq_name = f"{filename}({counter}){extension}" counter += 1 + dm_logger.dm_log_info(f'Generated unique file name {uniq_name}') return uniq_name -def move(entry, name, dst_dir): - # Generate a unique file name and move the file to the destination +def move(event, name, dst_dir): + # Generate a unique file name and move the file to the destination # directory - uniq_name = makeUniq(entry, dst_dir, name) - # Check that entry is a file before moving it - if (isfile(entry.path)): - mv(entry.path, f"{dst_dir}/{uniq_name}") + uniq_name = makeUniq(dst_dir, name) + # Check that event is a file before moving it + if isfile(event.src_path): + mv(event.src_path, f"{dst_dir}/{uniq_name}") + dm_logger.dm_log_info(f"Moved file {uniq_name} to {dst_dir}") + else: + dm_logger.dm_log_err(f"ERROR: {name} not a file") class FileHandler(FileSystemEventHandler): - def on_modified(self, event): - with scandir(src_dir) as entries: - for entry in entries: - name = entry.name - dst = src_dir - # If entry is an image - if name.endswith('.jpg') or name.endswith('.jpeg') or name.endswith('.png'): + def __init__(self, buffer_time=5): + self.events = [] + self.buffer_time = buffer_time + self.lock = threading.Lock() + self.timer = None + + def on_created(self, event): + with self.lock: + dm_logger.dm_log_debug(f"Found new file {event.src_path}") + self.events.append(event) + if not self.timer: + self.timer = threading.Timer(self.buffer_time, + self.process_event) + self.timer.start() + + def process_event(self): + with self.lock: + dm_logger.dm_log_info(f'Processing {len(self.events)} files...') + for event in self.events: + file_name = split(event.src_path)[1] + file_extension = splitext(file_name)[1] + dst = src_dir + dm_logger.dm_log_debug(f"Sorting {file_name}...") + + # If event is an image + if file_extension in file_types['image']: dst = img_dst - move(entry, name, dst) - # If entry is a video - elif name.endswith('.mp4') or name.endswith('.mov'): + move(event, file_name, dst) + # If event is a video + elif file_extension in file_types['video']: dst = vid_dst - move(entry, name, dst) - # If entry is a document - elif name.endswith('.docx') or name.endswith('.pdf'): + move(event, file_name, dst) + # If event is a document + elif file_extension in file_types['doc']: dst = doc_dst - move(entry, name, dst) - # If entry is an ISO file - elif name.endswith('.iso'): + move(event, file_name, dst) + # If event is an ISO file + elif file_extension == 'iso': dst = iso_dst - move(entry, name, dst) + move(event, file_name, dst) + + self.events = [] + self.timer = None if __name__ == "__main__": - logging.basicConfig(level=logging.INFO, - format='%(asctime)s - %(message)s', - datefmt='%Y-%m-%d %H:%M:%S') + dm_logger.dm_log_info('Starting watchdog module...') path = src_dir event_handler = FileHandler() observer = Observer() @@ -76,7 +148,7 @@ if __name__ == "__main__": observer.start() try: while True: - sleep(10) + sleep(3) except KeyboardInterrupt: observer.stop() observer.join()