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)}