Files
cma-management/backend/app/api/lead.py
T
项目Bot 4cad2b73c4
ci/woodpecker/push/main Pipeline was successful
fix(lead): 客户咨询通知改走系统总线8660→任总DM,替掉已下线的 ai-cs 通道
- ai-cs 用户/profile 已不存在,旧 runuser 调用必然失败且被 except: pass 吞掉
- 线索只落 /root/leads/leads.json,任总侧零通知(线上活缺陷)
- 新通道:POST 127.0.0.1:8660/bus/send,notice_class=fallback,收件人不变(200653946)
- 新增 /root/leads/notify.log 落痕,杜绝静默失败
2026-10-22 16:47:25 +08:00

87 lines
3.4 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.
"""AI获客 - 客户咨询接口"""
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
import json, os, datetime, urllib.request
router = APIRouter(prefix="/api/cma/lead", tags=["AI获客"])
# 客户咨询通知唯一通道:系统总线中继 8660 → 任总 DM。
# 2026-10-22 起取代旧的 ai-cs routing-live.py(该 profile/user 已下线,runuser 必然失败且异常被吞,
# 导致线索静默丢失通知)。中继类别按契约取 fallback(无会话兜底),company 类被中继直接拒绝。
BUS_RELAY_URL = "http://127.0.0.1:8660/bus/send"
BUS_KEY_FILE = "/srv/hermes/shared/.secrets/bus_relay.key"
BOSS_USERID = "200653946" # 任富海
NOTIFY_LOG = "/root/leads/notify.log"
class LeadRequest(BaseModel):
name: str
phone: str
requirement: str = ""
source: str = "sxbh.ltd"
def _log_notify(ok, detail):
"""通知结果落痕(旧实现 except: pass 静默吞异常,导致线索漏通知无人知晓)"""
try:
os.makedirs(os.path.dirname(NOTIFY_LOG), exist_ok=True)
with open(NOTIFY_LOG, "a", encoding="utf-8") as f:
f.write("%s %s %s\n" % (datetime.datetime.now().isoformat(timespec="seconds"),
"OK" if ok else "FAIL", detail))
except Exception:
pass
def notify_boss(name, phone, requirement):
"""客户咨询通知:经系统总线中继 8660 推任总 DM。失败不阻断主流程,但必须留痕。"""
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
content = (
"## 新客户咨询(sxbh.ltd 官网)\n"
f"> 姓名:{name}\n"
f"> 电话:{phone}\n"
f"> 需求:{requirement or '(未填)'}\n"
f"> 时间:{now}\n\n"
"承诺 30 分钟内联系。"
)
try:
with open(BUS_KEY_FILE, encoding="utf-8") as f:
key = f.read().strip()
if not key:
raise RuntimeError("bus key empty")
payload = json.dumps({
"touser": BOSS_USERID,
"msgtype": "markdown",
"content": content,
"notice_class": "fallback",
}, ensure_ascii=False).encode("utf-8")
req = urllib.request.Request(
BUS_RELAY_URL, data=payload,
headers={"Content-Type": "application/json",
"X-API-Key": key,
"X-Notice-Class": "fallback"},
method="POST",
)
with urllib.request.urlopen(req, timeout=10) as resp:
body = resp.read().decode("utf-8", "ignore")[:300]
_log_notify(True, body)
return True
except Exception as e:
_log_notify(False, "%s: %s" % (type(e).__name__, e))
return False
@router.post("")
def create_lead(data: LeadRequest):
"""接收客户咨询并保存"""
record = data.model_dump()
record["timestamp"] = datetime.datetime.now().isoformat()
record["status"] = "new"
log_dir = "/root/leads"
os.makedirs(log_dir, exist_ok=True)
with open(f"{log_dir}/leads.json", "a") as f:
f.write(json.dumps(record, ensure_ascii=False) + "\n")
# 客户咨询通知唯一通道:推任总 DM(经 ai-cs 分流);不再推 8800 全员群
# (2026-10-22 裁定:8800 仅限内容类群发,客户线索含个人信息,不得进全员群)
notify_boss(data.name, data.phone, data.requirement)
return {"success": True, "message": "咨询已提交,我们将在30分钟内联系您"}