erster docker release
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
"""Plik file upload plugin."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import threading
|
||||
from typing import Optional, Callable
|
||||
|
||||
|
||||
def _parse_ttl_seconds(ttl: str) -> Optional[int]:
|
||||
if not ttl:
|
||||
return None
|
||||
m = re.match(r"^(\d+)d$", ttl)
|
||||
if m:
|
||||
return int(m.group(1)) * 86400
|
||||
m = re.match(r"^(\d+)h$", ttl)
|
||||
if m:
|
||||
return int(m.group(1)) * 3600
|
||||
m = re.match(r"^(\d+)$", ttl)
|
||||
if m:
|
||||
return int(m.group(1))
|
||||
return None
|
||||
|
||||
|
||||
def upload_file(
|
||||
file_path: str,
|
||||
plik_url: str,
|
||||
api_key: str = "",
|
||||
ttl: str = "30d",
|
||||
) -> Optional[dict]:
|
||||
"""Upload a file to Plik. Returns dict with 'browser_url' and 'download_url', or None on failure."""
|
||||
if not plik_url or not os.path.isfile(file_path):
|
||||
return None
|
||||
if os.path.getsize(file_path) == 0:
|
||||
return None
|
||||
|
||||
plik_base = plik_url.rstrip("/")
|
||||
filename = os.path.basename(file_path)
|
||||
|
||||
cmd = ["curl", "-sS", "--max-time", "7200"]
|
||||
if api_key:
|
||||
cmd += ["-H", f"X-PlikToken: {api_key}"]
|
||||
|
||||
cmd += ["-F", f"file=@{file_path};filename={filename}"]
|
||||
|
||||
ttl_secs = _parse_ttl_seconds(ttl)
|
||||
if ttl_secs is not None:
|
||||
cmd += ["-F", f"ttl={ttl_secs}"]
|
||||
|
||||
cmd.append(plik_base)
|
||||
|
||||
try:
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=7200, stdin=subprocess.DEVNULL)
|
||||
if result.returncode != 0:
|
||||
return None
|
||||
|
||||
try:
|
||||
data = json.loads(result.stdout)
|
||||
upload_id = data.get("id", "")
|
||||
if not upload_id:
|
||||
return None
|
||||
|
||||
browser_url = f"{plik_base}/#/?id={upload_id}"
|
||||
|
||||
download_url = None
|
||||
files = data.get("files", [])
|
||||
if files:
|
||||
file_id = files[0].get("id", "")
|
||||
file_name = files[0].get("fileName", filename)
|
||||
if file_id:
|
||||
download_url = f"{plik_base}/file/{upload_id}/{file_id}/{file_name}"
|
||||
|
||||
return {"browser_url": browser_url, "download_url": download_url}
|
||||
except (json.JSONDecodeError, KeyError):
|
||||
urls = re.findall(r'https?://\S+', result.stdout)
|
||||
if urls:
|
||||
download_url = urls[-1]
|
||||
prefix = f"{plik_base}/file/"
|
||||
if download_url.startswith(prefix):
|
||||
rest = download_url[len(prefix):]
|
||||
uid = rest.split("/")[0]
|
||||
if uid:
|
||||
return {"browser_url": f"{plik_base}/#/?id={uid}", "download_url": download_url}
|
||||
return {"browser_url": download_url, "download_url": download_url}
|
||||
return None
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
class PlikUploader:
|
||||
def __init__(self, config, log_fn: Callable, notify_fn: Callable = None):
|
||||
self.config = config
|
||||
self._log = log_fn
|
||||
self._notify = notify_fn
|
||||
|
||||
def upload_recording(self, output_dir: str, output_file: str, job_name: str,
|
||||
segment_mode: bool, delete_after: bool, ntfy_enabled: bool):
|
||||
plik_url = self.config.get("plik", "url", default="")
|
||||
if not plik_url:
|
||||
self._log("WARN", f"Plik-Upload übersprungen: Keine URL konfiguriert [{job_name}]", job_name)
|
||||
return
|
||||
|
||||
api_key = self.config.get("plik", "api_key", default="")
|
||||
ttl = self.config.get("plik", "ttl", default="30d")
|
||||
|
||||
def _do_upload():
|
||||
try:
|
||||
if segment_mode:
|
||||
self._upload_segments(output_dir, job_name, plik_url, api_key, ttl, delete_after, ntfy_enabled)
|
||||
else:
|
||||
self._upload_single(output_file, job_name, plik_url, api_key, ttl, delete_after, ntfy_enabled)
|
||||
except Exception as e:
|
||||
self._log("ERROR", f"Plik-Upload Fehler: {e} [{job_name}]", job_name)
|
||||
|
||||
threading.Thread(target=_do_upload, daemon=True).start()
|
||||
|
||||
def _upload_single(self, file_path, job_name, plik_url, api_key, ttl, delete_after, ntfy_enabled):
|
||||
if not os.path.isfile(file_path) or os.path.getsize(file_path) == 0:
|
||||
self._log("WARN", f"Plik-Upload übersprungen: Datei fehlt oder leer [{job_name}]", job_name)
|
||||
return
|
||||
|
||||
self._log("INFO", f"Plik-Upload: {os.path.basename(file_path)} [{job_name}]", job_name)
|
||||
result = upload_file(file_path, plik_url, api_key, ttl)
|
||||
|
||||
if result:
|
||||
self._log("INFO", f"Plik-Upload abgeschlossen: {result['browser_url']} [{job_name}]", job_name)
|
||||
if result.get("download_url"):
|
||||
self._log("INFO", f"Plik-Download: {result['download_url']} [{job_name}]", job_name)
|
||||
if self._notify:
|
||||
self._notify("upload", "Plik-Upload", f"{job_name}: {result['browser_url']}", ntfy_enabled)
|
||||
if delete_after:
|
||||
os.remove(file_path)
|
||||
self._log("INFO", f"Lokale Datei gelöscht: {file_path} [{job_name}]", job_name)
|
||||
else:
|
||||
self._log("ERROR", f"Plik-Upload fehlgeschlagen [{job_name}]", job_name)
|
||||
|
||||
def _upload_segments(self, output_dir, job_name, plik_url, api_key, ttl, delete_after, ntfy_enabled):
|
||||
if not os.path.isdir(output_dir):
|
||||
return
|
||||
|
||||
files = sorted(f for f in os.listdir(output_dir) if not f.startswith(".") and os.path.isfile(os.path.join(output_dir, f)))
|
||||
if not files:
|
||||
return
|
||||
|
||||
uploaded = 0
|
||||
last_browser_url = None
|
||||
for fname in files:
|
||||
fpath = os.path.join(output_dir, fname)
|
||||
if os.path.getsize(fpath) == 0:
|
||||
continue
|
||||
self._log("INFO", f"Plik Segment-Upload: {fname} [{job_name}]", job_name)
|
||||
result = upload_file(fpath, plik_url, api_key, ttl)
|
||||
if result:
|
||||
last_browser_url = result["browser_url"]
|
||||
self._log("INFO", f"Plik Segment hochgeladen: {last_browser_url} [{job_name}]", job_name)
|
||||
uploaded += 1
|
||||
if delete_after:
|
||||
os.remove(fpath)
|
||||
self._log("INFO", f"Segment gelöscht: {fname} [{job_name}]", job_name)
|
||||
else:
|
||||
self._log("ERROR", f"Plik Segment-Upload fehlgeschlagen: {fname} [{job_name}]", job_name)
|
||||
|
||||
if uploaded > 0 and self._notify:
|
||||
msg = f"{job_name}: {uploaded} Segment(e) hochgeladen"
|
||||
if last_browser_url:
|
||||
msg += f"\n{last_browser_url}"
|
||||
self._notify("upload", "Plik-Upload", msg, ntfy_enabled)
|
||||
Reference in New Issue
Block a user