117 lines
4.1 KiB
Python
117 lines
4.1 KiB
Python
import json
|
||
import logging
|
||
import re
|
||
import websockets
|
||
|
||
logger = logging.getLogger("cs_agent")
|
||
|
||
_OUTBOUND_BLOCK_MARKERS = (
|
||
"【历史记录摘要】",
|
||
"【详细记录】",
|
||
"【订单摘要】",
|
||
"【订单详情】",
|
||
"<think",
|
||
"think_never_used",
|
||
'[{"name":',
|
||
)
|
||
|
||
_HISTORY_LEAK_PATTERNS = [
|
||
r'\[\d{4}-\d{2}-\d{2}[^\]]*\]\s*(客户|客服)[::]',
|
||
r'\[\d{2}:\d{2}:\d{2}\]\s*(客户|客服|我)[::]',
|
||
r'(根据|查看|查询|翻看)(历史|聊天|对话)(记录|内容)',
|
||
r'历史(记录|对话|消息)(显示|表明|中)',
|
||
r'之前的(聊天|对话|记录)(中|里|显示)',
|
||
r'共\d+条(历史|对话)?消息',
|
||
r'订单号[::]\s*\d{10,}',
|
||
r'(状态|金额|数量)[::].*(状态|金额|数量)[::]',
|
||
]
|
||
|
||
|
||
def _sanitize_outbound_text(content: str) -> str:
|
||
if not content:
|
||
return ""
|
||
cleaned = str(content).strip()
|
||
if "[转移会话]" in cleaned:
|
||
return cleaned
|
||
if any(marker in cleaned for marker in _OUTBOUND_BLOCK_MARKERS):
|
||
logger.warning("[WebSocketSend] 拦截到内部内容外发,替换为安全兜底回复")
|
||
return "我在帮你看记录,稍等哈"
|
||
for pattern in _HISTORY_LEAK_PATTERNS:
|
||
if re.search(pattern, cleaned):
|
||
logger.warning(f"[WebSocketSend] 检测到历史记录泄露模式: {pattern[:30]}...")
|
||
return "我在帮你看记录,稍等哈"
|
||
return cleaned
|
||
|
||
|
||
async def send_text_flow(client, cy_id, acc_type, content):
|
||
"""主动发送文本消息。"""
|
||
message = {
|
||
"msg_id": "",
|
||
"acc_id": "",
|
||
"msg": _sanitize_outbound_text(content),
|
||
"from_id": client.reply_id,
|
||
"from_name": client.reply_id,
|
||
"cy_id": cy_id,
|
||
"acc_type": acc_type,
|
||
"msg_type": 0,
|
||
"cy_name": "",
|
||
}
|
||
await client.send_message(message)
|
||
|
||
|
||
async def send_image_flow(client, cy_id, acc_type, image_path):
|
||
"""主动发送图片消息。"""
|
||
message = {
|
||
"msg_id": "",
|
||
"acc_id": "",
|
||
"msg": image_path,
|
||
"from_id": client.reply_id,
|
||
"from_name": client.reply_id,
|
||
"cy_id": cy_id,
|
||
"acc_type": acc_type,
|
||
"msg_type": 1,
|
||
"cy_name": "",
|
||
}
|
||
await client.send_message(message)
|
||
|
||
|
||
async def send_message_flow(client, message):
|
||
"""发送消息到服务器。"""
|
||
if client.websocket and client.websocket.state == websockets.protocol.State.OPEN:
|
||
try:
|
||
payload = dict(message) if isinstance(message, dict) else {}
|
||
if int(payload.get("msg_type", 0) or 0) == 0:
|
||
payload["msg"] = _sanitize_outbound_text(payload.get("msg", ""))
|
||
msg_json = json.dumps(payload, ensure_ascii=False)
|
||
await client.websocket.send(msg_json)
|
||
pretty = json.dumps(payload, ensure_ascii=False, indent=2)
|
||
client.logger.info(f"[{client.get_time()}] 发送成功:\n{pretty}")
|
||
client._activity_log(
|
||
"send_message_success",
|
||
trace_id=payload.get("_trace_id", ""),
|
||
acc_id=payload.get("acc_id", ""),
|
||
customer_id=payload.get("cy_id") or payload.get("from_id", ""),
|
||
msg_type=payload.get("msg_type", 0),
|
||
msg=payload.get("msg", ""),
|
||
)
|
||
except Exception as e:
|
||
client.logger.info(f"[{client.get_time()}] 发送失败: {e}")
|
||
payload = message if isinstance(message, dict) else {}
|
||
client._activity_log(
|
||
"send_message_error",
|
||
trace_id=payload.get("_trace_id", ""),
|
||
acc_id=payload.get("acc_id", ""),
|
||
customer_id=payload.get("cy_id") or payload.get("from_id", ""),
|
||
error=str(e),
|
||
)
|
||
else:
|
||
client.logger.info(f"[{client.get_time()}] 错误: 连接未打开")
|
||
payload = message if isinstance(message, dict) else {}
|
||
client._activity_log(
|
||
"send_message_skipped",
|
||
trace_id=payload.get("_trace_id", ""),
|
||
reason="socket_not_open",
|
||
acc_id=payload.get("acc_id", ""),
|
||
customer_id=payload.get("cy_id") or payload.get("from_id", ""),
|
||
)
|