feat: add clip-vault clipboard history daemon with webhook fanout

This commit is contained in:
dualfroz committed 2026-07-29 15:26:23 +02:00
commit 013c550047
8 files changed
+549

No files matched your search

+61
View File
@@ -0,0 +1,61 @@
import json
import re
import threading
import time
import urllib.request
from clip_vault.config import logPath
def logLine(line):
with open(logPath, "a") as logFile:
logFile.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} {line}\n")
def matchingWebhooks(content, config):
matches = []
for webhook in config.get("webhooks", []):
if not webhook.get("enabled"):
continue
pattern = webhook.get("matchPattern", ".*")
try:
if re.search(pattern, content):
matches.append(webhook)
except re.error as regexError:
logLine(f"invalid matchPattern in webhook '{webhook.get('name')}': {regexError}")
return matches
def sendWebhook(webhook, content, sourceWindow):
body = {"content": content, "timestamp": time.time()}
if webhook.get("includeSourceWindow", True):
body["sourceWindow"] = sourceWindow
data = json.dumps(body).encode("utf-8")
headers = {"Content-Type": "application/json"}
headers.update(webhook.get("headers", {}))
request = urllib.request.Request(webhook["url"], data=data, headers=headers, method=webhook.get("method", "POST"))
try:
with urllib.request.urlopen(request, timeout=webhook.get("timeoutSeconds", 4)) as response:
logLine(f"webhook '{webhook.get('name')}' -> {response.status}")
return True
except Exception as sendError:
logLine(f"webhook '{webhook.get('name')}' failed: {sendError}")
return False
def dispatchAsync(content, sourceWindow, config, onDone=None):
matches = matchingWebhooks(content, config)
if not matches:
if onDone:
onDone([])
return
def worker():
sentNames = []
for webhook in matches:
if sendWebhook(webhook, content, sourceWindow):
sentNames.append(webhook.get("name", webhook["url"]))
if onDone:
onDone(sentNames)
threading.Thread(target=worker, daemon=True).start()