# aider-watch-client api_client | 2026-04-20 @ Asia/Taipei """HTTP POST events to awoooi with HMAC-SHA256 sign + exponential backoff. 失敗永不 raise — caller 檢查 return bool 決定是否走 buffer。""" from __future__ import annotations import hmac, hashlib, json, time from typing import Any import requests from aider_watch_client.config import get def sign_body(body: bytes, secret: str) -> str: """回傳 'sha256=' 給 X-Aider-Signature header。""" return "sha256=" + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest() def post_events(events: list[dict[str, Any]]) -> bool: """POST batch to awoooi aider/events endpoint. True = 2xx; False = 失敗,caller 走 buffer。絕不 raise。""" url = get("AIDER_API_URL", required=True) secret = get("AIDER_WEBHOOK_SECRET", required=True) body = json.dumps({"events": events}, ensure_ascii=False).encode() sig = sign_body(body, secret) backoff = 1 for _ in range(3): try: r = requests.post( url, data=body, headers={"Content-Type": "application/json", "X-Aider-Signature": sig, "X-Aider-Client": "aiderw/0.2.0"}, timeout=5, ) if 200 <= r.status_code < 300: return True if r.status_code == 429 or r.status_code >= 500: time.sleep(backoff); backoff *= 4 continue # 400/401/403 不重試 — client 端 payload 問題 return False except Exception: time.sleep(backoff); backoff *= 4 return False