fix(awooop): mirror telegram outbound messages
This commit is contained in:
@@ -29,6 +29,7 @@ import os
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from datetime import UTC, datetime
|
||||
from uuid import NAMESPACE_URL, UUID, uuid5
|
||||
|
||||
import httpx
|
||||
import structlog
|
||||
@@ -79,6 +80,26 @@ def _is_noisy_failure_update(status_line: str) -> bool:
|
||||
or "AI 診斷工具失敗" in status_line
|
||||
)
|
||||
|
||||
|
||||
def _legacy_outbound_run_id(chat_id: str, provider_message_id: str) -> UUID:
|
||||
"""Legacy Telegram 發送尚未有 run_id 時,產生穩定 soft run_id 供 Channel Hub 串接。"""
|
||||
return uuid5(NAMESPACE_URL, f"awoooi:legacy-telegram:{chat_id}:{provider_message_id}")
|
||||
|
||||
|
||||
def _infer_outbound_message_type(text: str, payload: dict) -> str:
|
||||
"""將既有 Telegram 訊息映射成 AwoooP outbound_message 的有限分類。"""
|
||||
if "reply_to_message_id" in payload:
|
||||
if "失敗" in text or "錯誤" in text or "FAILED" in text:
|
||||
return "error"
|
||||
return "final"
|
||||
if payload.get("reply_markup"):
|
||||
return "approval_request"
|
||||
if "ACTION REQUIRED" in text or "待審" in text or "審批" in text:
|
||||
return "approval_request"
|
||||
if "失敗" in text or "錯誤" in text or "FAILED" in text:
|
||||
return "error"
|
||||
return "final"
|
||||
|
||||
# 2026-04-27 Claude Sonnet 4.6: B3 — LLM 動態 Telegram 按鈕 Feature Flag
|
||||
# true → 優先使用 ActionPlan.recommended_actions 動態生成按鈕
|
||||
# false → 維持現有 callback_action_spec.yaml 路徑(預設,向下相容)
|
||||
@@ -1511,6 +1532,11 @@ class TelegramGateway:
|
||||
result_val = result.get("result")
|
||||
if isinstance(result_val, dict) and "message_id" in result_val:
|
||||
span.set_attribute("telegram.message_id", result_val["message_id"])
|
||||
await self._mirror_outbound_message(
|
||||
method=method,
|
||||
payload=payload,
|
||||
provider_message_id=str(result_val["message_id"]),
|
||||
)
|
||||
|
||||
span.set_status(trace.Status(trace.StatusCode.OK))
|
||||
return result
|
||||
@@ -1541,6 +1567,52 @@ class TelegramGateway:
|
||||
)
|
||||
raise TelegramGatewayError(safe_error) from None
|
||||
|
||||
async def _mirror_outbound_message(
|
||||
self,
|
||||
*,
|
||||
method: str,
|
||||
payload: dict,
|
||||
provider_message_id: str,
|
||||
) -> None:
|
||||
"""將 legacy Telegram 出站訊息鏡像到 AwoooP,不改變實際發送行為。"""
|
||||
if method != "sendMessage":
|
||||
return
|
||||
|
||||
chat_id = str(payload.get("chat_id") or "")
|
||||
text = str(payload.get("text") or payload.get("caption") or "")
|
||||
if not chat_id or not text:
|
||||
return
|
||||
|
||||
try:
|
||||
from src.core.context import get_current_project_id
|
||||
from src.db.base import get_db_context
|
||||
from src.services.channel_hub import record_outbound_message
|
||||
|
||||
project_id = get_current_project_id() or "awoooi"
|
||||
run_id = _legacy_outbound_run_id(chat_id, provider_message_id)
|
||||
async with get_db_context(project_id) as db:
|
||||
await record_outbound_message(
|
||||
db,
|
||||
project_id=project_id,
|
||||
run_id=run_id,
|
||||
channel_type="telegram",
|
||||
channel_chat_id=chat_id,
|
||||
message_type=_infer_outbound_message_type(text, payload),
|
||||
content=text,
|
||||
provider_message_id=provider_message_id,
|
||||
send_status="sent",
|
||||
triggered_by_state="legacy_gateway",
|
||||
is_shadow=False,
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.warning(
|
||||
"telegram_outbound_mirror_failed",
|
||||
method=method,
|
||||
chat_id=chat_id,
|
||||
provider_message_id=provider_message_id,
|
||||
error=str(exc),
|
||||
)
|
||||
|
||||
async def _build_inline_keyboard(
|
||||
self,
|
||||
approval_id: str,
|
||||
|
||||
Reference in New Issue
Block a user