"""Microsoft Teams Workflows(수신 webhook) 로 어댑티브 카드 한 장을 보낸다.""" import os import httpx from common.logger import LOG WEBHOOK_URL_ENV = "TEAMS_WEBHOOK_URL" TIMEOUT_SEC = 10.0 def is_configured() -> bool: return bool(os.environ.get(WEBHOOK_URL_ENV, "").strip()) def _webhook_url() -> str: return os.environ.get(WEBHOOK_URL_ENV, "").strip() def _card(title: str, detail: str) -> dict: """Adaptive Card 1.2 — Teams Workflows 가 받는 최소 모양(search_console_alerts.py 와 같은 스키마).""" return { "type": "message", "attachments": [{ "contentType": "application/vnd.microsoft.card.adaptive", "contentUrl": None, "content": { "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.2", "body": [ {"type": "TextBlock", "text": title, "weight": "Bolder", "wrap": True}, {"type": "TextBlock", "text": detail, "wrap": True}, ], }, }], } async def send(title: str, detail: str) -> bool: """설정된 경우에만 보낸다.""" url = _webhook_url() if not url: return False if not url.startswith("https://"): LOG.w("[alert] TEAMS_WEBHOOK_URL_INVALID — https 가 아니다") return False try: async with httpx.AsyncClient(timeout=TIMEOUT_SEC, follow_redirects=False) as client: response = await client.post(url, json=_card(title, detail)) response.raise_for_status() return True except httpx.HTTPError: LOG.w("[alert] TEAMS_DELIVERY_FAILED") return False