Files
platform/gateway/integrations/karakeep.py
Yusuf Suleman 7cd81181ed Refactor gateway into modular architecture
Split 1878-line server.py into 15 focused modules:
- config.py: all env vars and constants
- database.py: schema, init, seed logic
- sessions.py: session/token CRUD
- proxy.py: proxy_request, SERVICE_MAP, resolve_service
- responses.py: ResponseMixin for handler helpers
- auth.py: login/logout/register handlers
- dashboard.py: dashboard, apps, connections, pinning
- command.py: AI command bar
- integrations/booklore.py: auth, books, cover, import
- integrations/kindle.py: send-to-kindle, file finder
- integrations/karakeep.py: save/delete bookmarks
- integrations/qbittorrent.py: download status
- integrations/image_proxy.py: external image proxy

server.py is now thin routing only (~344 lines).
All routes, methods, status codes, and responses preserved exactly.
Added PYTHONUNBUFFERED=1 to Dockerfile for live logging.
2026-03-29 00:14:46 -05:00

77 lines
2.4 KiB
Python

"""
Platform Gateway — Karakeep integration (bookmarking).
"""
import json
from config import KARAKEEP_URL, KARAKEEP_API_KEY
from proxy import proxy_request
def handle_karakeep_save(handler, body):
"""Save a URL to Karakeep as a bookmark."""
if not KARAKEEP_API_KEY:
handler._send_json({"error": "Karakeep not configured"}, 502)
return
try:
data = json.loads(body)
except Exception as e:
handler._send_json({"error": "Invalid JSON"}, 400)
return
url = data.get("url", "")
if not url:
handler._send_json({"error": "Missing url"}, 400)
return
payload = json.dumps({"type": "link", "url": url}).encode()
headers = {
"Authorization": f"Bearer {KARAKEEP_API_KEY}",
"Content-Type": "application/json",
}
try:
status, _, resp = proxy_request(
f"{KARAKEEP_URL}/api/v1/bookmarks", "POST",
headers, payload, timeout=15
)
if status in (200, 201):
result = json.loads(resp)
handler._send_json({"ok": True, "id": result.get("id", "")})
else:
print(f"[Karakeep] Save failed ({status}): {resp[:200]}")
handler._send_json({"error": "Failed to save", "status": status}, status)
except Exception as e:
print(f"[Karakeep] Error: {e}")
handler._send_json({"error": str(e)}, 500)
def handle_karakeep_delete(handler, body):
"""Delete a bookmark from Karakeep."""
if not KARAKEEP_API_KEY:
handler._send_json({"error": "Karakeep not configured"}, 502)
return
try:
data = json.loads(body)
except Exception as e:
handler._send_json({"error": "Invalid JSON"}, 400)
return
bookmark_id = data.get("id", "")
if not bookmark_id:
handler._send_json({"error": "Missing id"}, 400)
return
headers = {
"Authorization": f"Bearer {KARAKEEP_API_KEY}",
}
try:
status, _, resp = proxy_request(
f"{KARAKEEP_URL}/api/v1/bookmarks/{bookmark_id}", "DELETE",
headers, timeout=10
)
if status in (200, 204):
handler._send_json({"ok": True})
else:
handler._send_json({"error": "Delete failed", "status": status}, status)
except Exception as e:
print(f"[Karakeep] Delete error: {e}")
handler._send_json({"error": str(e)}, 500)