Files
awoooi/apps/api/src/services/notifications/telegram.py
Your Name ee2cc2bfc3
Some checks failed
CD Pipeline / tests (push) Failing after 1m23s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
Code Review / ai-code-review (push) Successful in 15s
fix(alerts): 收斂 Telegram 告警到 SRE 戰情室
2026-06-12 11:06:16 +08:00

96 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Telegram Notification Provider — 接線 TelegramGateway 到 NotificationManager
2026-04-25 修復 L2系統執行反饋完全丟失
根本原因:執行完成後的推送通知未配置任何 providerTelegram 曾有 Gateway 實作
但從未註冊為 NotificationProvider導致執行失敗的卡片無法推送回 Telegram
本模組:直接複用既有 TelegramGateway.send_alert_notification(),將執行結果格式化並推送
"""
from src.core.config import settings
from src.core.logging import get_logger
from .base import (
ExecutionStatus,
NotificationMessage,
NotificationProvider,
NotificationResult,
NotificationStatus,
)
logger = get_logger("awoooi.notifications.telegram")
class TelegramWebhookProvider(NotificationProvider):
"""透過既有 TelegramGateway 發送執行結果卡片"""
@property
def name(self) -> str:
return "telegram"
@property
def enabled(self) -> bool:
"""檢查 Telegram bot token 與 AwoooI SRE 戰情室是否配置。"""
return bool(settings.OPENCLAW_TG_BOT_TOKEN) and bool(settings.SRE_GROUP_CHAT_ID)
def _format(self, msg: NotificationMessage) -> str:
"""格式化執行結果為 Telegram 訊息"""
title = f"{msg.status_emoji} <b>{msg.status_text}</b>"
lines = [
title,
"━━━━━━━━━━━━━━━━━━━",
f"🎯 <code>{msg.action_title[:120]}</code>",
f"🧭 Namespace: <code>{msg.namespace}</code> | Op: <code>{msg.operation_type}</code>",
f"{msg.risk_emoji} 風險: {msg.risk_level.upper()} | Pods: {msg.affected_pods}",
f"📝 Approval: <code>{msg.approval_id[:12]}</code>",
]
if msg.duration_ms is not None:
lines.append(f"⏱️ 耗時: {msg.duration_ms}ms")
if msg.error_message:
lines.append(f"❗ 錯誤: <code>{msg.error_message[:200]}</code>")
if msg.signers:
lines.append(f"👥 簽核: {msg.signers_display}")
return "\n".join(lines)
async def send(self, message: NotificationMessage) -> NotificationResult:
"""推送執行結果到 Telegram"""
if not self.enabled:
return NotificationResult(
status=NotificationStatus.SKIPPED,
provider=self.name,
message="Telegram bot token or chat_id not configured",
)
try:
from src.services.telegram_gateway import get_telegram_gateway
gateway = get_telegram_gateway()
text = self._format(message)
resp = await gateway.send_alert_notification(text=text, parse_mode="HTML")
return NotificationResult(
status=NotificationStatus.SUCCESS,
provider=self.name,
message="Telegram notification sent",
response_data=resp if isinstance(resp, dict) else None,
)
except Exception as e:
logger.exception("telegram_notification_exception", error=str(e))
return NotificationResult(
status=NotificationStatus.FAILED,
provider=self.name,
message="Exception during send",
error=str(e)[:300],
)
async def test_connection(self) -> bool:
"""測試 Telegram 連接"""
if not self.enabled:
return False
try:
from src.services.telegram_gateway import get_telegram_gateway
gw = get_telegram_gateway()
await gw.send_alert_notification(text="🔔 AWOOOI Telegram provider 連線測試")
return True
except Exception as e:
logger.error("telegram_connection_test_failed", error=str(e))
return False