|
@@ -920,6 +920,13 @@ class BusinessAssistantRuntime:
|
|
|
text=human_text,
|
|
text=human_text,
|
|
|
sender_id=owner_id,
|
|
sender_id=owner_id,
|
|
|
)
|
|
)
|
|
|
|
|
+ await self._notify_feishu_message(
|
|
|
|
|
+ conversation=conversation,
|
|
|
|
|
+ message=message,
|
|
|
|
|
+ sender=connection.get("user") or {},
|
|
|
|
|
+ settings=settings,
|
|
|
|
|
+ direction="human",
|
|
|
|
|
+ )
|
|
|
await pause_conversation_for_human(
|
|
await pause_conversation_for_human(
|
|
|
conversation["conversation_id"],
|
|
conversation["conversation_id"],
|
|
|
hours=int(settings.get("human_pause_hours") or 24),
|
|
hours=int(settings.get("human_pause_hours") or 24),
|
|
@@ -1028,7 +1035,7 @@ class BusinessAssistantRuntime:
|
|
|
sender_id=int(sender.get("id") or 0),
|
|
sender_id=int(sender.get("id") or 0),
|
|
|
metadata={"content_type": "text" if text else "unsupported"},
|
|
metadata={"content_type": "text" if text else "unsupported"},
|
|
|
)
|
|
)
|
|
|
- await self._notify_feishu_customer_message(
|
|
|
|
|
|
|
+ await self._notify_feishu_message(
|
|
|
conversation=conversation,
|
|
conversation=conversation,
|
|
|
message=message,
|
|
message=message,
|
|
|
sender=sender,
|
|
sender=sender,
|
|
@@ -1137,33 +1144,55 @@ class BusinessAssistantRuntime:
|
|
|
"matched_entry_ids": decision["matched_entry_ids"],
|
|
"matched_entry_ids": decision["matched_entry_ids"],
|
|
|
},
|
|
},
|
|
|
)
|
|
)
|
|
|
|
|
+ await self._notify_feishu_message(
|
|
|
|
|
+ conversation=current,
|
|
|
|
|
+ message={
|
|
|
|
|
+ **response,
|
|
|
|
|
+ "text": decision["reply"],
|
|
|
|
|
+ "date": response.get("date") or int(utc_now().timestamp()),
|
|
|
|
|
+ },
|
|
|
|
|
+ sender={},
|
|
|
|
|
+ settings=settings,
|
|
|
|
|
+ direction="assistant",
|
|
|
|
|
+ )
|
|
|
|
|
|
|
|
- async def _notify_feishu_customer_message(
|
|
|
|
|
|
|
+ async def _notify_feishu_message(
|
|
|
self,
|
|
self,
|
|
|
*,
|
|
*,
|
|
|
conversation: dict[str, Any],
|
|
conversation: dict[str, Any],
|
|
|
message: dict[str, Any],
|
|
message: dict[str, Any],
|
|
|
sender: dict[str, Any],
|
|
sender: dict[str, Any],
|
|
|
settings: dict[str, Any],
|
|
settings: dict[str, Any],
|
|
|
|
|
+ direction: str = "incoming",
|
|
|
) -> None:
|
|
) -> None:
|
|
|
webhook_url = str(settings.get("feishu_webhook_url") or "")
|
|
webhook_url = str(settings.get("feishu_webhook_url") or "")
|
|
|
if not settings.get("feishu_webhook_enabled") or not webhook_url:
|
|
if not settings.get("feishu_webhook_enabled") or not webhook_url:
|
|
|
return
|
|
return
|
|
|
|
|
+ if direction != "incoming" and not settings.get("feishu_outgoing_message_enabled"):
|
|
|
|
|
+ return
|
|
|
conversation_id = str(conversation["conversation_id"])
|
|
conversation_id = str(conversation["conversation_id"])
|
|
|
message_id = int(message.get("message_id") or 0)
|
|
message_id = int(message.get("message_id") or 0)
|
|
|
- if not await claim_feishu_message_notification(conversation_id, message_id):
|
|
|
|
|
|
|
+ if not message_id or not await claim_feishu_message_notification(
|
|
|
|
|
+ conversation_id, message_id, direction=direction
|
|
|
|
|
+ ):
|
|
|
return
|
|
return
|
|
|
- user_name = " ".join(
|
|
|
|
|
|
|
+ sender_name = " ".join(
|
|
|
str(item).strip()
|
|
str(item).strip()
|
|
|
for item in (sender.get("first_name"), sender.get("last_name"))
|
|
for item in (sender.get("first_name"), sender.get("last_name"))
|
|
|
if str(item or "").strip()
|
|
if str(item or "").strip()
|
|
|
)
|
|
)
|
|
|
- if not user_name:
|
|
|
|
|
- user_name = (
|
|
|
|
|
|
|
+ if not sender_name:
|
|
|
|
|
+ sender_name = (
|
|
|
f"@{sender.get('username')}"
|
|
f"@{sender.get('username')}"
|
|
|
if sender.get("username")
|
|
if sender.get("username")
|
|
|
else str((message.get("chat") or {}).get("id") or "未知")
|
|
else str((message.get("chat") or {}).get("id") or "未知")
|
|
|
)
|
|
)
|
|
|
|
|
+ if direction == "incoming":
|
|
|
|
|
+ title = sender_name
|
|
|
|
|
+ elif direction == "human":
|
|
|
|
|
+ title = f"{sender_name} · 托管账号"
|
|
|
|
|
+ else:
|
|
|
|
|
+ title = "智能接待 · 托管账号"
|
|
|
preview_text = str(
|
|
preview_text = str(
|
|
|
message.get("text") or message.get("caption") or ""
|
|
message.get("text") or message.get("caption") or ""
|
|
|
).strip()
|
|
).strip()
|
|
@@ -1172,7 +1201,8 @@ class BusinessAssistantRuntime:
|
|
|
else:
|
|
else:
|
|
|
message_content = "消息已隐藏"
|
|
message_content = "消息已隐藏"
|
|
|
lines = [message_content]
|
|
lines = [message_content]
|
|
|
- telegram_username = str(sender.get("username") or "").strip().lstrip("@")
|
|
|
|
|
|
|
+ chat_user = sender if direction == "incoming" else conversation.get("customer") or {}
|
|
|
|
|
+ telegram_username = str(chat_user.get("username") or "").strip().lstrip("@")
|
|
|
telegram_chat_url = (
|
|
telegram_chat_url = (
|
|
|
f"https://t.me/{telegram_username}"
|
|
f"https://t.me/{telegram_username}"
|
|
|
if re.fullmatch(r"[A-Za-z0-9_]{1,64}", telegram_username)
|
|
if re.fullmatch(r"[A-Za-z0-9_]{1,64}", telegram_username)
|
|
@@ -1188,14 +1218,14 @@ class BusinessAssistantRuntime:
|
|
|
try:
|
|
try:
|
|
|
await self.feishu.send_card(
|
|
await self.feishu.send_card(
|
|
|
webhook_url,
|
|
webhook_url,
|
|
|
- title=user_name,
|
|
|
|
|
|
|
+ title=title,
|
|
|
lines=lines,
|
|
lines=lines,
|
|
|
link_url=telegram_chat_url,
|
|
link_url=telegram_chat_url,
|
|
|
signing_secret=str(settings.get("feishu_webhook_signing_secret") or ""),
|
|
signing_secret=str(settings.get("feishu_webhook_signing_secret") or ""),
|
|
|
)
|
|
)
|
|
|
except FeishuWebhookError as exc:
|
|
except FeishuWebhookError as exc:
|
|
|
await mark_feishu_message_notification(
|
|
await mark_feishu_message_notification(
|
|
|
- conversation_id, message_id, status="failed", error=str(exc)
|
|
|
|
|
|
|
+ conversation_id, message_id, status="failed", error=str(exc), direction=direction
|
|
|
)
|
|
)
|
|
|
await update_runtime_status(
|
|
await update_runtime_status(
|
|
|
{
|
|
{
|
|
@@ -1205,7 +1235,7 @@ class BusinessAssistantRuntime:
|
|
|
)
|
|
)
|
|
|
return
|
|
return
|
|
|
await mark_feishu_message_notification(
|
|
await mark_feishu_message_notification(
|
|
|
- conversation_id, message_id, status="sent"
|
|
|
|
|
|
|
+ conversation_id, message_id, status="sent", direction=direction
|
|
|
)
|
|
)
|
|
|
await update_runtime_status(
|
|
await update_runtime_status(
|
|
|
{
|
|
{
|
|
@@ -1266,6 +1296,17 @@ class BusinessAssistantRuntime:
|
|
|
text=notice,
|
|
text=notice,
|
|
|
metadata={"action": "handoff", "reason": reason},
|
|
metadata={"action": "handoff", "reason": reason},
|
|
|
)
|
|
)
|
|
|
|
|
+ await self._notify_feishu_message(
|
|
|
|
|
+ conversation=updated,
|
|
|
|
|
+ message={
|
|
|
|
|
+ **response,
|
|
|
|
|
+ "text": notice,
|
|
|
|
|
+ "date": response.get("date") or int(utc_now().timestamp()),
|
|
|
|
|
+ },
|
|
|
|
|
+ sender={},
|
|
|
|
|
+ settings=settings,
|
|
|
|
|
+ direction="assistant",
|
|
|
|
|
+ )
|
|
|
except TelegramBotApiError as exc:
|
|
except TelegramBotApiError as exc:
|
|
|
await update_runtime_status(
|
|
await update_runtime_status(
|
|
|
{
|
|
{
|