|
|
|
|
@ -1,31 +1,23 @@
|
|
|
|
|
from watchdog.events import FileSystemEventHandler
|
|
|
|
|
from watchdog.observers import Observer
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
import shutil
|
|
|
|
|
import time
|
|
|
|
|
import os
|
|
|
|
|
from funcs import get_media_dimensions
|
|
|
|
|
|
|
|
|
|
# Base directories
|
|
|
|
|
media_dir = Path("media")
|
|
|
|
|
stories_dir = media_dir / "stories"
|
|
|
|
|
posts_dir = media_dir / "posts"
|
|
|
|
|
media_dir = "media"
|
|
|
|
|
stories_dir = os.path.join(media_dir, "stories")
|
|
|
|
|
posts_dir = os.path.join(media_dir, "posts")
|
|
|
|
|
|
|
|
|
|
# Ensure output dirs exist
|
|
|
|
|
stories_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
posts_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
os.makedirs(stories_dir, exist_ok=True)
|
|
|
|
|
os.makedirs(posts_dir, exist_ok=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def wait_for_complete(file_path, timeout=10):
|
|
|
|
|
"""
|
|
|
|
|
Wait until a file is fully written (size stops changing).
|
|
|
|
|
Returns True if stable within timeout, else False.
|
|
|
|
|
"""
|
|
|
|
|
file_path = Path(file_path)
|
|
|
|
|
prev_size = -1
|
|
|
|
|
for _ in range(timeout * 2): # check every 0.5 sec
|
|
|
|
|
try:
|
|
|
|
|
size = file_path.stat().st_size
|
|
|
|
|
size = os.path.getsize(file_path)
|
|
|
|
|
except FileNotFoundError:
|
|
|
|
|
return False
|
|
|
|
|
if size == prev_size:
|
|
|
|
|
@ -36,9 +28,6 @@ def wait_for_complete(file_path, timeout=10):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_story(width, height, tolerance=0.02):
|
|
|
|
|
"""
|
|
|
|
|
Check if dimensions are close to 9:16 (0.5625) ratio.
|
|
|
|
|
"""
|
|
|
|
|
if width == 0 or height == 0:
|
|
|
|
|
return False
|
|
|
|
|
ratio = min(width, height) / max(width, height)
|
|
|
|
|
@ -46,10 +35,7 @@ def is_story(width, height, tolerance=0.02):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def determine_post_type(filepath):
|
|
|
|
|
"""
|
|
|
|
|
Determines if a file is 'posts' or 'stories' based on aspect ratio.
|
|
|
|
|
"""
|
|
|
|
|
lower = str(filepath).lower()
|
|
|
|
|
lower = filepath.lower()
|
|
|
|
|
if "posts" in lower:
|
|
|
|
|
return "posts"
|
|
|
|
|
try:
|
|
|
|
|
@ -62,14 +48,12 @@ def determine_post_type(filepath):
|
|
|
|
|
|
|
|
|
|
class DownloadHandler(FileSystemEventHandler):
|
|
|
|
|
def process_file(self, file_path):
|
|
|
|
|
file_path = Path(file_path)
|
|
|
|
|
file = file_path.name
|
|
|
|
|
file = os.path.basename(file_path)
|
|
|
|
|
|
|
|
|
|
# Skip temp/incomplete files
|
|
|
|
|
if "crdownload" in file or file.count("~") != 3:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if not file_path.exists():
|
|
|
|
|
if not os.path.exists(file_path):
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if not wait_for_complete(file_path):
|
|
|
|
|
@ -85,14 +69,14 @@ class DownloadHandler(FileSystemEventHandler):
|
|
|
|
|
print(f"Could not determine post type for {file}. Skipping...")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
output_path = dest_dir / file
|
|
|
|
|
output_path = os.path.join(dest_dir, file)
|
|
|
|
|
|
|
|
|
|
if output_path.exists():
|
|
|
|
|
if os.path.exists(output_path):
|
|
|
|
|
print(f"File already exists {output_path}. Removing...")
|
|
|
|
|
file_path.unlink(missing_ok=True)
|
|
|
|
|
os.remove(file_path)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
shutil.move(str(file_path), str(output_path))
|
|
|
|
|
shutil.move(file_path, output_path)
|
|
|
|
|
print(f"Moved {file_path} → {output_path}")
|
|
|
|
|
|
|
|
|
|
def on_created(self, event):
|
|
|
|
|
@ -105,14 +89,14 @@ class DownloadHandler(FileSystemEventHandler):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
download_path = Path.home() / "Downloads"
|
|
|
|
|
download_path = os.path.join(os.path.expanduser("~"), "Downloads")
|
|
|
|
|
event_handler = DownloadHandler()
|
|
|
|
|
observer = Observer()
|
|
|
|
|
observer.schedule(event_handler, str(download_path), recursive=False)
|
|
|
|
|
observer.schedule(event_handler, download_path, recursive=False)
|
|
|
|
|
observer.start()
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
observer.join() # idle until interrupted
|
|
|
|
|
observer.join()
|
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
|
observer.stop()
|
|
|
|
|
observer.join()
|
|
|
|
|
observer.join()
|