From bb12647e8d4fb0d86a2b9b28b9789a3a866dfcf7 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 25 Apr 2026 10:31:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(telegram):=20=E7=BE=A4=E7=B5=84=E5=91=8A?= =?UTF-8?q?=E8=AD=A6=E5=8D=A1=E7=89=87=E5=8A=A0=E5=85=A5=E5=AE=8C=E6=95=B4?= =?UTF-8?q?=E4=BA=92=E5=8B=95=E6=8C=89=E9=88=95=EF=BC=88=E6=89=B9=E5=87=86?= =?UTF-8?q?/=E6=8B=92=E7=B5=95/=E6=9A=AB=E9=BB=98/=E8=A9=B3=E6=83=85/?= =?UTF-8?q?=E9=87=8D=E8=A8=BA/=E6=AD=B7=E5=8F=B2=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - _send_approval_card_to_group 加 alert_category + notification_type 參數 - 群組卡片改用 _build_inline_keyboard(與 DM 相同的完整六鍵佈局) - send_approval_card → _send_approval_card_to_group 傳遞兩參數 - TYPE-1 通知補 read-only 詳情/歷史按鈕(鬼魂按鈕鐵律合規) Co-Authored-By: Claude Sonnet 4.6 --- apps/api/src/services/telegram_gateway.py | 37 ++++++++++++++++++----- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/apps/api/src/services/telegram_gateway.py b/apps/api/src/services/telegram_gateway.py index d7544c30..304b8cf6 100644 --- a/apps/api/src/services/telegram_gateway.py +++ b/apps/api/src/services/telegram_gateway.py @@ -1860,6 +1860,8 @@ class TelegramGateway: nemotron_validation=nemotron_validation, nemotron_latency_ms=nemotron_latency_ms, incident_id=incident_id, + alert_category=alert_category, + notification_type=notification_type, ) ) @@ -1893,6 +1895,8 @@ class TelegramGateway: nemotron_validation: str = "", nemotron_latency_ms: float = 0.0, incident_id: str = "", + alert_category: str = "", + notification_type: str = "", ) -> None: """ 發送告警卡片到 SRE 群組 — 與個人 chat 相同的完整 v7.0 格式 @@ -1940,7 +1944,16 @@ class TelegramGateway: nemotron_latency_ms=nemotron_latency_ms, ) text = message.format_with_nemotron() if nemotron_enabled else message.format() - resp = await self.send_to_group(text=text) + + # 2026-04-25 ogt + Claude Sonnet 4.6: 群組卡片使用完整 _build_inline_keyboard + # 統帥決策: 群組成員為受信任 SRE,完整批准/拒絕/暫默/詳情/重診/歷史按鈕從 DM 移植至群組 + _group_keyboard = self._build_inline_keyboard( + approval_id=approval_id, + incident_id=incident_id, + alert_category=alert_category, + notification_type=notification_type, + ) + resp = await self.send_to_group(text=text, reply_markup=_group_keyboard) # 2026-04-10 Claude Sonnet 4.6: 儲存 message_id 到 Redis,供 append_incident_update 使用 # tg_msg:{incident_id} → Telegram message_id (TTL 24h) @@ -1967,10 +1980,13 @@ class TelegramGateway: severity: str = "info", ) -> dict: """ - TYPE-1 純資訊通知 — 無按鈕,FYI 類告警 + TYPE-1 純資訊通知 — FYI 類告警 用於: severity=info 成功類 / Backup 完成 / AlertChainHealthy 等 - 格式: 簡潔文字,無 InlineKeyboard + 格式: 簡潔文字 + [詳情][歷史] 查類按鈕(read-only,2-part info 格式,ADR-050) + + 2026-04-25 ogt + Claude Sonnet 4.6: 補充 read-only 按鈕(鬼魂按鈕鐵律: + detail/history 已有 handler 且無副作用,符合三條件才加) Args: incident_id: 事件 ID @@ -1987,16 +2003,23 @@ class TelegramGateway: ) if alertname: text += f"🔔 告警: {html.escape(alertname)}\n" - text += ( - f"\n{html.escape(message)}\n" - f"\n此為純資訊通知,無需操作。" - ) + text += f"\n{html.escape(message)}" + + # read-only 查類按鈕(2-part info 格式,handler 已在 handle_callback 實作) + # detail/history 均在 INFO_ACTIONS 白名單,無 nonce 無副作用 + keyboard = { + "inline_keyboard": [[ + {"text": "📋 詳情", "callback_data": f"detail:{incident_id}"}, + {"text": "📊 歷史", "callback_data": f"history:{incident_id}"}, + ]] + } return await self._send_request( "sendMessage", { "chat_id": settings.OPENCLAW_TG_CHAT_ID, "text": text, "parse_mode": "HTML", + "reply_markup": keyboard, }, )