feat(p2.4): Telegram 中間態推播 — 分析中佔位卡 + 完成後自動刪除
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled

P2.4 實作 2026-04-24 ogt + Claude Sonnet 4.6

問題: LLM 分析耗時 10-30s,期間 Telegram 無任何回應,使用者不知系統在處理

修復:
- telegram_gateway.py: 新增 send_analyzing_placeholder() — 發送「AI 正在分析中...」佔位卡
- telegram_gateway.py: 新增 delete_message() — 刪除佔位卡
- webhooks.py: LLM 分析前 3s 內送出佔位卡(超時不阻塞主流程)
- webhooks.py: _push_to_telegram_background 收到 placeholder_message_id → 完整卡發出後刪除佔位卡
- webhooks.py: import asyncio(補缺漏)

效果: 使用者在告警到達 <3s 內即看到「分析中...」訊息,完整卡出現後自動清除

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Your Name
2026-04-24 15:56:26 +08:00
parent bb5f16f8ef
commit e75e4678a9
3 changed files with 101 additions and 0 deletions

View File

@@ -1525,6 +1525,62 @@ class TelegramGateway:
return {"inline_keyboard": buttons}
async def send_analyzing_placeholder(
self,
alert_type: str,
resource_name: str,
severity: str = "medium",
) -> int | None:
"""
P2.4 中間態推播 2026-04-24 ogt + Claude Sonnet 4.6
在 LLM 分析開始前送出佔位卡,讓使用者知道系統正在處理。
分析完成後用 delete_message() 刪除,再由 send_approval_card 補上完整卡。
Returns: Telegram message_id 或 NoneBot 未設定 / API 失敗)
"""
if not self.bot_token:
return None
emoji = {"critical": "🔴", "medium": "🟡", "low": "🟢"}.get(severity.lower(), "⚠️")
text = (
f"{emoji} <b>告警收到AI 正在分析中...</b>\n\n"
f"資源: <code>{html.escape(resource_name or 'unknown')}</code>\n"
f"類型: <code>{html.escape(alert_type or 'unknown')}</code>\n\n"
f"<i>預計 10-30 秒完成,請稍候...</i>"
)
try:
result = await self._send_request("sendMessage", {
"chat_id": self.chat_id,
"text": text,
"parse_mode": "HTML",
"disable_web_page_preview": True,
})
msg_id: int | None = None
result_val = result.get("result")
if isinstance(result_val, dict):
msg_id = result_val.get("message_id")
logger.info("analyzing_placeholder_sent", message_id=msg_id, resource=resource_name)
return msg_id
except Exception as e:
logger.warning("analyzing_placeholder_failed", error=str(e))
return None
async def delete_message(self, message_id: int) -> bool:
"""
P2.4 中間態清理 2026-04-24 ogt + Claude Sonnet 4.6
刪除佔位卡(分析完成、完整卡已發出後呼叫)。
"""
if not self.bot_token or not message_id:
return False
try:
await self._send_request("deleteMessage", {
"chat_id": self.chat_id,
"message_id": message_id,
})
logger.info("placeholder_deleted", message_id=message_id)
return True
except Exception as e:
logger.warning("placeholder_delete_failed", message_id=message_id, error=str(e))
return False
async def send_approval_card(
self,
approval_id: str,