"""Synology Chat — incoming webhook으로 응답 전송.""" from __future__ import annotations import json import logging import re import httpx from config import settings logger = logging.getLogger(__name__) def _strip_markdown(text: str) -> str: """마크다운 문법 제거 — Synology Chat은 렌더링 안 됨.""" text = re.sub(r'\*\*(.+?)\*\*', r'\1', text) # **bold** text = re.sub(r'\*(.+?)\*', r'\1', text) # *italic* text = re.sub(r'`(.+?)`', r'\1', text) # `code` text = re.sub(r'^#{1,6}\s+', '', text, flags=re.MULTILINE) # ### headers text = re.sub(r'^\s*[-*]\s+', '• ', text, flags=re.MULTILINE) # - list → • return text async def send_to_synology(text: str, *, raw: bool = False) -> bool: """Incoming webhook URL로 메시지 전송. raw=True면 마크다운 제거 안 함.""" if not settings.synology_incoming_url: logger.warning("Synology incoming URL not configured") return False if not raw: text = _strip_markdown(text) payload = json.dumps({"text": text}, ensure_ascii=False) try: async with httpx.AsyncClient(verify=False, timeout=10.0) as client: resp = await client.post( settings.synology_incoming_url, data={"payload": payload}, ) if resp.status_code == 200: return True logger.error("Synology send failed: %d %s", resp.status_code, resp.text) return False except Exception: logger.exception("Failed to send to Synology Chat") return False