Files
tw/core/adapters/qianniu_adapter.py

93 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import re
import logging
import json
from pathlib import Path
from typing import List, Tuple
from core.adapters.base import BaseAdapter
from core.schema import StandardMessage, StandardResponse
logger = logging.getLogger("cs_agent")
class QianniuAdapter(BaseAdapter):
"""
千牛适配器:支持识别消息来源(客户 vs 商家人工)。
"""
def __init__(self, ws_client=None):
self.ws_client = ws_client
self._default_group_id = "20252916034"
def platform_id(self) -> str:
return "qianniu"
def _resolve_group_id(self, acc_id: str) -> str:
try:
config_path = Path("config/transfer_groups.json")
if config_path.exists():
with open(config_path, "r", encoding="utf-8") as f:
cfg = json.load(f)
return cfg.get(acc_id, self._default_group_id)
except Exception: pass
return self._default_group_id
async def translate_inbound(self, raw: dict) -> Tuple[StandardMessage, str]:
"""
返回: (标准消息, 消息方向)
direction: 'in' (客户发给商家), 'out' (商家人工在后台回复)
"""
if not isinstance(raw, dict): raw = {}
acc_id = str(raw.get("acc_id") or raw.get("shop_id") or "")
from_id = str(raw.get("from_id") or raw.get("cy_id") or "")
msg_text = str(raw.get("msg") or raw.get("content") or "")
# 判断方向:如果 from_id 包含了店铺名或 acc_id通常说明是商家自己在说话
# 或者逆向接口通常有一个特定的标识,这里我们做一个通用的逻辑判断
direction = "in"
user_id = from_id
# 逻辑:如果发送者 ID 等于 店铺 ID说明是【商家人工回复】
if from_id == acc_id and acc_id != "":
direction = "out"
# 此时 cy_id (客户ID) 通常在另一个字段里
user_id = str(raw.get("cy_id") or "")
msg = StandardMessage(
platform=self.platform_id(),
msg_id=str(raw.get("msg_id", "")),
user_id=user_id,
user_name=str(raw.get("from_name", "")),
content=msg_text,
image_urls=self._extract_urls(msg_text),
acc_id=acc_id,
acc_type=str(raw.get("acc_type") or "AliWorkbench"),
raw_data=raw
)
return msg, direction
async def translate_outbound(self, res: StandardResponse, user_id: str):
if not self.ws_client: return
if not res or (not res.should_reply and not res.need_transfer): return
meta = res.metadata if isinstance(res.metadata, dict) else {}
acc_id = meta.get("acc_id", "")
acc_type = meta.get("acc_type", "AliWorkbench")
if "[转移会话]" in res.reply_content:
content = res.reply_content
elif res.need_transfer:
group_id = self._resolve_group_id(acc_id)
content = f"正在为您转接|[转移会话],分组{group_id},无原因"
else:
content = res.reply_content
try:
await self.ws_client.send(customer_id=user_id, acc_id=acc_id, acc_type=acc_type, content=content, msg_type=res.msg_type)
except Exception as e:
logger.error(f"[QianniuAdapter] 发送失败: {e}")
def _extract_urls(self, text: str) -> List[str]:
if not text: return []
image_exts = (".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp")
candidates = re.findall(r'https?://[^\s#]+', text)
return [u for u in candidates if any(ext in u.lower() for ext in image_exts)]