The application might be finished. Testing required.

This commit is contained in:
Erik Thuning 2024-06-11 16:32:06 +02:00
parent 8418728815
commit 1b9386cd1a
4 changed files with 133 additions and 0 deletions

1
.gitignore vendored

@ -2,4 +2,5 @@
__pycache__/*
*.pyc
testfiles/*
env/*
config.ini

6
config.ini.example Normal file

@ -0,0 +1,6 @@
[arec-watcher]
watchdir = /some/uploaddir/to/watch
notify_url = https://example.com/notify
[logging]
level = DEBUG

68
watcher/__init__.py Normal file

@ -0,0 +1,68 @@
import logging
from pathlib import Path
import requests
from watchdog.events import PatternMatchingEventHandler
from watchdog.observers.polling import PollingObserver
class Watcher(PatternMatchingEventHandler):
def __init__(self, watchdir: Path, notify_url: str):
super().__init__(ignore_directories=True)
self.watchdir = watchdir
self.notify_url = notify_url
self.watcher = PollingObserver()
self.watcher.schedule(self, self.watchdir, recursive=True)
self.logger = logging.getLogger('arec-watcher.Watcher')
def start(self) -> None:
self.logger.debug('Starting')
self.logger.info("Montoring '%s' for new uploads, notifying to '%s'",
self.watchdir,
self.notify_url)
self._pickup_existing()
return self.watcher.start()
def shutdown(self) -> None:
self.logger.debug('Stopping')
return self.watcher.stop()
def is_datfile(self, path: Path) -> bool:
return path.match('*.dat')
def _pickup_existing(self):
for subdir in self.watchdir.iterdir():
if not subdir.is_dir():
continue
for child in subdir.iterdir():
self._process(child)
def _process(self, path: Path) -> None:
if not self.is_datfile(path):
return
basedir = path.parent
sentinel = basedir / 'arec-watcher-notified'
if sentinel.exists():
continue
self.logger.info('Picked up %s', basedir)
try:
result = requests.post(self.notify_url,
data={'upload_dir': basedir})
result.raise_for_status()
sentinel.touch(exist_ok=False)
except requests.HTTPError as e:
self.logger.error('Failed to notify %s about %s',
self.notify_url,
basedir)
def on_created(self, event):
self._process(Path(event.src_path))
def on_moved(self, event):
self._process(Path(event.dest_path))

58
watcher/__main__.py Normal file

@ -0,0 +1,58 @@
import logging
import signal
import sys
from configparser import ConfigParser
from pathlib import Path
import watcher
conffile = Path('config.ini')
if not conffile.exists():
print(f"{conffile} missing, exiting")
sys.exit(1)
config = ConfigParser(empty_lines_in_values=False)
config.read(conffile)
if 'logging' not in config:
config.add_section('logging')
# Basic logging settings
baselogger = logging.getLogger('arec-watcher')
log_level = config['logging'].get('level', 'ERROR')
baselogger.setLevel(log_level)
fmt = logging.Formatter('%(levelname)s in %(name)s: %(message)s')
if baselogger.getEffectiveLevel() <= logging.DEBUG:
fmt = logging.Formatter(
'%(levelname)s in %(name)s (%(process)d): %(message)s')
stderrlog = logging.StreamHandler()
stderrlog.setLevel(log_level)
stderrlog.setFormatter(fmt)
baselogger.addHandler(stderrlog)
# Mail logging settings
if 'mail_level' in config['logging']:
from_addr = config['logging']['mail_from']
to_addr = config['logging']['mail_to']
subject = config['logging']['mail_subject']
maillog = logging.handlers.SMTPHandler('localhost',
from_addr,
[to_addr],
subject)
maillog.setLevel(config['logging']['mail_level'])
maillog.setFormatter(fmt)
baselogger.addHandler(maillog)
watch = watcher.Watcher(Path(config['arec-watcher']['watchdir']),
config['arec-watcher']['notify_url'])
watch.start()
try:
signal.pause()
except KeyboardInterrupt:
watch.shutdown()