feat: bootstrap NAS music deduper
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
from watchdog.observers import Observer
|
||||
|
||||
from .constants import MUSIC_EXTENSIONS, STABILITY_CHECKS, STABILITY_INTERVAL_SECONDS
|
||||
from .db import connect
|
||||
from .scanner import index_file
|
||||
|
||||
|
||||
class Handler(FileSystemEventHandler):
|
||||
def __init__(self, root: Path, db_path: Path):
|
||||
self.root = root
|
||||
self.db_path = db_path
|
||||
|
||||
def _process(self, filename: str) -> None:
|
||||
path = Path(filename)
|
||||
if path.is_symlink() or path.suffix.lower() not in MUSIC_EXTENSIONS:
|
||||
return
|
||||
try:
|
||||
previous = path.stat().st_size
|
||||
stable = 0
|
||||
while stable < STABILITY_CHECKS - 1:
|
||||
time.sleep(STABILITY_INTERVAL_SECONDS)
|
||||
size = path.stat().st_size
|
||||
if size == previous:
|
||||
stable += 1
|
||||
else:
|
||||
previous = size
|
||||
stable = 0
|
||||
with connect(self.db_path) as conn:
|
||||
index_file(conn, path)
|
||||
except (FileNotFoundError, PermissionError):
|
||||
return
|
||||
|
||||
def on_created(self, event):
|
||||
if not event.is_directory:
|
||||
self._process(event.src_path)
|
||||
|
||||
def on_moved(self, event):
|
||||
if not event.is_directory:
|
||||
self._process(event.dest_path)
|
||||
|
||||
|
||||
def watch(root: Path, db_path: Path) -> None:
|
||||
observer = Observer()
|
||||
observer.schedule(Handler(root, db_path), str(root), recursive=True)
|
||||
observer.start()
|
||||
try:
|
||||
while True:
|
||||
time.sleep(1)
|
||||
finally:
|
||||
observer.stop()
|
||||
observer.join()
|
||||
Reference in New Issue
Block a user