dump carddav

This commit is contained in:
2026-08-05 06:10:36 +02:00
parent cf3563124f
commit 447528b5ff
3 changed files with 21 additions and 4 deletions
+18 -2
View File
@@ -15,8 +15,9 @@ antwortet der Server mit 403 valid-sync-token, dann fällt der Client automatisc
auf einen vollständigen Re-Sync zurück. auf einen vollständigen Re-Sync zurück.
""" """
import logging import logging
import os
from urllib.parse import urljoin, urlparse
from xml.etree import ElementTree as ET from xml.etree import ElementTree as ET
from urllib.parse import urljoin
import requests import requests
@@ -35,10 +36,11 @@ class SyncTokenInvalid(Exception):
class CardDAVClient: class CardDAVClient:
def __init__(self, base_url: str, username: str, password: str, timeout: int = 30): def __init__(self, base_url: str, username: str, password: str, timeout: int = 30, account_name: str = ""):
self.base_url = base_url self.base_url = base_url
self.auth = (username, password) self.auth = (username, password)
self.timeout = timeout self.timeout = timeout
self.account_name = account_name
self.session = requests.Session() self.session = requests.Session()
def _request(self, method: str, url: str, body: str, depth: str = "0"): def _request(self, method: str, url: str, body: str, depth: str = "0"):
@@ -49,6 +51,7 @@ class CardDAVClient:
if resp.status_code == 403 and "valid-sync-token" in resp.text: if resp.status_code == 403 and "valid-sync-token" in resp.text:
raise SyncTokenInvalid("sync-token vom Server abgelehnt") raise SyncTokenInvalid("sync-token vom Server abgelehnt")
resp.raise_for_status() resp.raise_for_status()
self._dump_debug(method, url, resp)
return ET.fromstring(resp.content) return ET.fromstring(resp.content)
def discover_principal(self) -> str: def discover_principal(self) -> str:
@@ -148,3 +151,16 @@ class CardDAVClient:
if href.startswith("http"): if href.startswith("http"):
return href return href
return urljoin(self.base_url, href) return urljoin(self.base_url, href)
def _dump_debug(self, method: str, url: str, resp: requests.Response):
dump_dir = f"/app/debug/carddav/{self.account_name}" if self.account_name else "/app/debug/carddav"
try:
os.makedirs(dump_dir, exist_ok=True)
path = urlparse(url).path.rstrip("/").replace("/", "_") or "root"
filename = f"{method}_{path}.xml"
filepath = os.path.join(dump_dir, filename)
with open(filepath, "w", encoding="utf-8") as f:
f.write(resp.text)
logger.debug("CardDAV-Debug-Dump: %s", filepath)
except Exception:
logger.warning("Debug-Dump fehlgeschlagen", exc_info=True)
+2 -1
View File
@@ -1,7 +1,8 @@
# Copyright (c) 2026 Stefan Koelle (https://stefankoelle.de) # Copyright (c) 2026 Stefan Koelle (https://stefankoelle.de)
# Licensed under the MIT License. See LICENSE file in project root for details. # Licensed under the MIT License. See LICENSE file in project root for details.
import os
import json import json
import os
from dotenv import load_dotenv from dotenv import load_dotenv
load_dotenv() load_dotenv()
+1 -1
View File
@@ -19,7 +19,7 @@ logger = logging.getLogger("sync")
def sync_account(conn, account, href_to_uid_cache: dict): def sync_account(conn, account, href_to_uid_cache: dict):
client = CardDAVClient(ICLOUD_BASE_URL, account.apple_email, account.apple_app_password) client = CardDAVClient(ICLOUD_BASE_URL, account.apple_email, account.apple_app_password, account_name=account.name)
collection_url = client.discover_collection() collection_url = client.discover_collection()
stored_token = db.get_sync_token(conn, account.name) stored_token = db.get_sync_token(conn, account.name)