fix: HA Delete – mehrere Body-Formate ausprobieren
HA's Service-Call-Schema akzeptiert je nach Version verschiedene Body-Shapes für entity_id. Wir probieren jetzt der Reihe nach: 1. entity_id als String 2. entity_id als Liste 3. target-Wrapper Wenn alle fehlschlagen, klare Anweisung zum HA-Developer-Tools-Test.
This commit is contained in:
@@ -211,37 +211,44 @@ def _ha_update_event(url: str, token: str, entity_id: str, uid: str, data: dict)
|
|||||||
|
|
||||||
|
|
||||||
def _ha_delete_event(url: str, token: str, entity_id: str, uid: str):
|
def _ha_delete_event(url: str, token: str, entity_id: str, uid: str):
|
||||||
"""Delete an event via HA service call API (calendar.delete_event)."""
|
"""Delete an event via HA service call API (calendar.delete_event).
|
||||||
|
|
||||||
|
Tries multiple body formats since HA's service-call schema accepts
|
||||||
|
different shapes depending on version.
|
||||||
|
"""
|
||||||
base = url.rstrip("/")
|
base = url.rstrip("/")
|
||||||
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
|
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
|
||||||
body = {"entity_id": entity_id, "uid": uid}
|
service_url = f"{base}/api/services/calendar/delete_event"
|
||||||
logger.info("HA delete_event body: %s", body)
|
|
||||||
resp = http_requests.post(
|
|
||||||
f"{base}/api/services/calendar/delete_event",
|
|
||||||
headers=headers, json=body, timeout=15, verify=False,
|
|
||||||
)
|
|
||||||
if resp.ok:
|
|
||||||
return resp
|
|
||||||
|
|
||||||
# Try REST API DELETE as fallback (works for some integrations)
|
# Format 1: entity_id flat in body (most common)
|
||||||
from urllib.parse import quote
|
bodies = [
|
||||||
encoded_uid = quote(uid, safe="")
|
{"entity_id": entity_id, "uid": uid},
|
||||||
rest_resp = http_requests.delete(
|
# Format 2: entity_id as list
|
||||||
f"{base}/api/calendars/{entity_id}/{encoded_uid}",
|
{"entity_id": [entity_id], "uid": uid},
|
||||||
headers={"Authorization": f"Bearer {token}"},
|
# Format 3: target wrapper
|
||||||
timeout=15, verify=False,
|
{"target": {"entity_id": entity_id}, "uid": uid},
|
||||||
)
|
]
|
||||||
if rest_resp.ok:
|
|
||||||
return rest_resp
|
|
||||||
|
|
||||||
# Both failed – build a helpful error message
|
last_resp = None
|
||||||
|
for i, body in enumerate(bodies):
|
||||||
|
logger.info("HA delete_event try %d body: %s", i + 1, body)
|
||||||
|
resp = http_requests.post(
|
||||||
|
service_url, headers=headers, json=body, timeout=15, verify=False,
|
||||||
|
)
|
||||||
|
if resp.ok:
|
||||||
|
return resp
|
||||||
|
last_resp = resp
|
||||||
|
logger.warning("HA delete_event format %d failed (%s): %s",
|
||||||
|
i + 1, resp.status_code, resp.text[:200])
|
||||||
|
|
||||||
|
# All failed – build a helpful error message
|
||||||
try:
|
try:
|
||||||
detail = resp.json().get("message", resp.text[:500])
|
detail = last_resp.json().get("message", last_resp.text[:500])
|
||||||
except Exception:
|
except Exception:
|
||||||
detail = resp.text[:500] if resp.text else f"HTTP {resp.status_code}"
|
detail = last_resp.text[:500] if last_resp.text else f"HTTP {last_resp.status_code}"
|
||||||
if resp.status_code == 400:
|
if last_resp.status_code == 400:
|
||||||
detail = f"{detail} (Diese HA-Kalender-Integration unterstützt kein Löschen — z.B. Google-Calendar via HA ist read-only für Updates/Löschen)"
|
detail = f"{detail} — Vermutlich unterstützt deine HA-Kalender-Integration kein Löschen. Bitte in HA Developer Tools → Services testen mit calendar.delete_event"
|
||||||
raise Exception(f"HA delete_event ({resp.status_code}): {detail}")
|
raise Exception(f"HA delete_event ({last_resp.status_code}): {detail}")
|
||||||
|
|
||||||
|
|
||||||
def _parse_ha_event(ev: dict, cal_db_id: int, cal_name: str, cal_color: str) -> dict:
|
def _parse_ha_event(ev: dict, cal_db_id: int, cal_name: str, cal_color: str) -> dict:
|
||||||
|
|||||||
Reference in New Issue
Block a user