ForcePilot/backend/package/yuxi/channel/extensions/taobao/tools.py

258 lines
11 KiB
Python
Raw Normal View History

from __future__ import annotations
import logging
from datetime import datetime, timedelta
logger = logging.getLogger(__name__)
TRADE_STATUS_MAP = {
"WAIT_BUYER_PAY": "等待买家付款",
"WAIT_SELLER_SEND_GOODS": "等待卖家发货",
"WAIT_BUYER_CONFIRM_GOODS": "等待买家确认收货",
"TRADE_FINISHED": "交易完成",
"TRADE_CLOSED": "交易关闭",
"TRADE_CLOSED_BY_TAOBAO": "交易被淘宝关闭",
}
class TaobaoTools:
def __init__(self, client):
self._client = client
async def query_order(self, order_id: str, session: str | None = None) -> str:
try:
data = await self._client.get_trade_fullinfo(int(order_id), session)
trade = data.get("trade_fullinfo_get_response", {}).get("trade", {})
status = TRADE_STATUS_MAP.get(trade.get("status", ""), trade.get("status", "未知"))
payment = trade.get("payment", "未知")
buyer_nick = trade.get("buyer_nick", "")
orders = trade.get("orders", {}).get("order", [])
lines = [
f"📦 订单 {order_id}",
f"状态: {status}",
f"金额: ¥{payment}",
f"买家: {buyer_nick}",
]
if orders:
lines.append("商品:")
for o in orders if isinstance(orders, list) else [orders]:
lines.append(f" - {o.get('title', '未知')} ×{o.get('num', 1)} ¥{o.get('price', 0)}")
return "\n".join(lines)
except Exception as e:
logger.exception("Query order failed: %s", order_id)
return f"查询订单 {order_id} 失败: {e}"
async def query_logistics(self, order_id: str, session: str | None = None) -> str:
try:
data = await self._client.get_logistics_trace(int(order_id), session)
resp = data.get("logistics_trace_search_response", {})
traces = resp.get("trace_list", resp.get("traces", []))
if not traces:
return f"📦 订单 {order_id} 暂无物流信息"
lines = [f"📦 订单 {order_id} 物流轨迹:"]
for t in (traces if isinstance(traces, list) else [traces])[:10]:
lines.append(f" [{t.get('time', '')}] {t.get('status_desc', t.get('desc', ''))}")
return "\n".join(lines)
except Exception as e:
logger.exception("Query logistics failed: %s", order_id)
return f"查询物流 {order_id} 失败: {e}"
async def query_item(self, item_id: str, session: str | None = None) -> str:
try:
data = await self._client.get_item(int(item_id), session)
item = data.get("item_get_response", {}).get("item", {})
title = item.get("title", "未知商品")
price = item.get("price", "")
desc = item.get("desc", "")[:200]
lines = [f"🛒 {title}"]
if price:
lines.append(f"价格: ¥{price}")
if desc:
lines.append(f"描述: {desc}")
return "\n".join(lines)
except Exception as e:
logger.exception("Query item failed: %s", item_id)
return f"查询商品 {item_id} 失败: {e}"
async def query_refund(self, refund_id: str, session: str | None = None) -> str:
try:
data = await self._client.qianniu_refund_get(refund_id, session)
refund = data.get("qianniu_refund_get_response", {})
status = refund.get("status", "未知")
amount = refund.get("refund_amount", refund.get("amount", "未知"))
reason = refund.get("refund_reason", refund.get("reason", "未知"))
return f"🔙 退款 {refund_id}\n状态: {status}\n退款金额: ¥{amount}\n申请原因: {reason}"
except Exception as e:
logger.exception("Query refund failed: %s", refund_id)
return f"查询退款 {refund_id} 失败: {e}"
async def query_buyer_tags(self, buyer_nick: str, session: str | None = None) -> str:
try:
data = await self._client.qianniu_buyer_tag_get(buyer_nick, session)
tags = data.get("qianniu_buyer_tag_get_response", {}).get("tags", [])
if not tags:
return f"买家 {buyer_nick} 暂无标签"
tag_names = [t.get("tag_name", str(t)) for t in tags] if isinstance(tags, list) else [str(tags)]
return f"买家 {buyer_nick} 标签: {', '.join(tag_names)}"
except Exception as e:
logger.exception("Query buyer tags failed: %s", buyer_nick)
return f"查询买家标签失败: {e}"
async def transfer_human(self, buyer_nick: str, reason: str = "", session: str | None = None) -> str:
try:
if not hasattr(self._client, "qianniu_cloudkefu_forward"):
return "转人工功能暂不可用(千牛客服转发 API 未接入)"
await self._client.qianniu_cloudkefu_forward(
buyer_nick=buyer_nick,
to_nick="", # 不指定分配到哪个客服,由分流系统自动分配
session=session,
)
return f"已将买家 {buyer_nick} 转接人工客服" + (f",原因: {reason}" if reason else "")
except Exception as e:
logger.exception("Transfer to human failed: %s", buyer_nick)
return f"转人工失败: {e}"
async def query_chat_history(self, buyer_nick: str, session: str | None = None) -> str:
end = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
begin = (datetime.now() - timedelta(hours=24)).strftime("%Y-%m-%d %H:%M:%S")
try:
data = await self._client.get_chatlogs(buyer_nick, begin, end, session)
logs_data = data.get("openim_chatlogs_get_response", {}).get("chatlogs", {})
logs = logs_data.get("chatlog", [])
if not logs:
return "无近24小时聊天记录"
lines = ["近24小时聊天记录:"]
for log in (logs if isinstance(logs, list) else [logs])[:10]:
role = "买家" if log.get("role") == "buyer" else "客服"
msg = str(log.get("message", ""))[:100]
lines.append(f" [{log.get('time', '')}] {role}: {msg}")
return "\n".join(lines)
except Exception as e:
logger.exception("Query chat history failed: %s", buyer_nick)
return f"查询聊天记录失败: {e}"
def get_agent_tools(self) -> list[dict]:
return [
{
"name": "taobao_query_order",
"description": "查询淘宝订单详情,获取订单状态、金额、买家、商品列表等信息",
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string", "description": "淘宝订单号(tid)"},
},
"required": ["order_id"],
},
"handler": self.query_order,
},
{
"name": "taobao_query_logistics",
"description": "查询淘宝订单物流轨迹",
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string", "description": "淘宝订单号(tid)"},
},
"required": ["order_id"],
},
"handler": self.query_logistics,
},
{
"name": "taobao_query_item",
"description": "查询淘宝商品详情,包括标题、价格、描述等",
"parameters": {
"type": "object",
"properties": {
"item_id": {"type": "string", "description": "淘宝商品ID(num_iid)"},
},
"required": ["item_id"],
},
"handler": self.query_item,
},
{
"name": "taobao_query_refund",
"description": "查询淘宝退款/售后状态和详情",
"parameters": {
"type": "object",
"properties": {
"refund_id": {"type": "string", "description": "退款单号(refund_id)"},
},
"required": ["refund_id"],
},
"handler": self.query_refund,
},
{
"name": "taobao_query_buyer_tags",
"description": "查询买家标签VIP/黑名单等)",
"parameters": {
"type": "object",
"properties": {
"buyer_nick": {"type": "string", "description": "买家淘宝昵称"},
},
"required": ["buyer_nick"],
},
"handler": self.query_buyer_tags,
},
{
"name": "taobao_transfer_human",
"description": "将当前会话转接人工客服",
"parameters": {
"type": "object",
"properties": {
"buyer_nick": {"type": "string", "description": "买家淘宝昵称"},
"reason": {
"type": "string",
"description": "转接原因(可选)",
},
},
"required": ["buyer_nick"],
},
"handler": self.transfer_human,
},
{
"name": "taobao_query_chat_history",
"description": "查询与指定买家的近24小时聊天记录",
"parameters": {
"type": "object",
"properties": {
"buyer_nick": {"type": "string", "description": "买家淘宝昵称"},
},
"required": ["buyer_nick"],
},
"handler": self.query_chat_history,
},
]
async def execute_agent_tool(self, tool_name: str, params: dict, context: dict) -> dict:
tool_map = {
"taobao_query_order": self.query_order,
"taobao_query_logistics": self.query_logistics,
"taobao_query_item": self.query_item,
"taobao_query_refund": self.query_refund,
"taobao_query_buyer_tags": self.query_buyer_tags,
"taobao_transfer_human": self.transfer_human,
"taobao_query_chat_history": self.query_chat_history,
}
handler = tool_map.get(tool_name)
if handler is None:
return {"success": False, "error": f"Unknown tool: {tool_name}"}
try:
session = context.get("session") or context.get("access_token")
result = await handler(**params, session=session)
return {"success": True, "result": result}
except Exception as e:
return {"success": False, "error": str(e)}