Initial commit: PDF OCR Hotfolder v0.1.0
Komplettes Rewrite des alten Bash-Tools `pdf-tool` in Python. - ocrmypdf als Library, watchdog für Hotfolder, ThreadPool für Parallelität - Upload-Targets: folder, Nextcloud (WebDAV), SFTP - E-Mail-Notify, optional veraPDF - Interaktiver Installer mit Service-User-Support (lokal + AD via SSSD) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
"""Upload-Ziele: lokaler Ordner, Nextcloud (WebDAV), SFTP. Plus E-Mail-Notify."""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import smtplib
|
||||
import ssl
|
||||
from email.message import EmailMessage
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote
|
||||
|
||||
import paramiko
|
||||
import requests
|
||||
|
||||
from .config import EmailNotify, FolderUpload, NextcloudUpload, SftpUpload
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def upload_folder(pdf: Path, cfg: FolderUpload, default_target: Path) -> bool:
|
||||
if not cfg.enabled:
|
||||
return True
|
||||
target = Path(cfg.target) if cfg.target else default_target
|
||||
target.mkdir(parents=True, exist_ok=True)
|
||||
dest = target / pdf.name
|
||||
try:
|
||||
if pdf.resolve() == dest.resolve():
|
||||
return True
|
||||
dest.write_bytes(pdf.read_bytes())
|
||||
log.info("Folder upload OK: %s", dest)
|
||||
return True
|
||||
except OSError as e:
|
||||
log.error("Folder upload failed: %s", e)
|
||||
return False
|
||||
|
||||
|
||||
def upload_nextcloud(pdf: Path, cfg: NextcloudUpload) -> bool:
|
||||
if not cfg.enabled:
|
||||
return True
|
||||
base = cfg.url.rstrip("/")
|
||||
remote = "/".join(quote(part) for part in cfg.remote_path.strip("/").split("/") if part)
|
||||
url = f"{base}/remote.php/dav/files/{quote(cfg.username)}/{remote}/{quote(pdf.name)}"
|
||||
try:
|
||||
with pdf.open("rb") as f:
|
||||
r = requests.put(url, data=f, auth=(cfg.username, cfg.password),
|
||||
verify=cfg.verify_ssl, timeout=300)
|
||||
if r.status_code in (200, 201, 204):
|
||||
log.info("Nextcloud upload OK: %s", pdf.name)
|
||||
return True
|
||||
log.error("Nextcloud upload HTTP %s: %s", r.status_code, r.text[:200])
|
||||
return False
|
||||
except requests.RequestException as e:
|
||||
log.error("Nextcloud upload failed: %s", e)
|
||||
return False
|
||||
|
||||
|
||||
def upload_sftp(pdf: Path, cfg: SftpUpload) -> bool:
|
||||
if not cfg.enabled:
|
||||
return True
|
||||
try:
|
||||
client = paramiko.SSHClient()
|
||||
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
connect_kwargs: dict = {
|
||||
"hostname": cfg.host, "port": cfg.port, "username": cfg.username,
|
||||
"timeout": 30,
|
||||
}
|
||||
if cfg.key_file:
|
||||
connect_kwargs["key_filename"] = cfg.key_file
|
||||
if cfg.password:
|
||||
connect_kwargs["password"] = cfg.password
|
||||
client.connect(**connect_kwargs)
|
||||
sftp = client.open_sftp()
|
||||
try:
|
||||
remote = f"{cfg.remote_path.rstrip('/')}/{pdf.name}"
|
||||
sftp.put(str(pdf), remote)
|
||||
log.info("SFTP upload OK: %s", remote)
|
||||
return True
|
||||
finally:
|
||||
sftp.close()
|
||||
client.close()
|
||||
except (paramiko.SSHException, OSError) as e:
|
||||
log.error("SFTP upload failed: %s", e)
|
||||
return False
|
||||
|
||||
|
||||
def notify_email(cfg: EmailNotify, subject: str, body: str, success: bool) -> None:
|
||||
if not cfg.enabled or cfg.on == "never":
|
||||
return
|
||||
if cfg.on == "errors" and success:
|
||||
return
|
||||
msg = EmailMessage()
|
||||
msg["Subject"] = subject
|
||||
msg["From"] = cfg.from_addr
|
||||
msg["To"] = ", ".join(cfg.to_addrs)
|
||||
msg.set_content(body)
|
||||
try:
|
||||
with smtplib.SMTP(cfg.smtp_host, cfg.smtp_port, timeout=30) as s:
|
||||
if cfg.use_starttls:
|
||||
s.starttls(context=ssl.create_default_context())
|
||||
if cfg.smtp_user:
|
||||
s.login(cfg.smtp_user, cfg.smtp_password)
|
||||
s.send_message(msg)
|
||||
log.info("E-Mail-Notify gesendet: %s", subject)
|
||||
except (smtplib.SMTPException, OSError) as e:
|
||||
log.error("E-Mail-Notify fehlgeschlagen: %s", e)
|
||||
Reference in New Issue
Block a user