Files

73 lines
4.3 KiB
Python
Raw Permalink Normal View History

from datetime import datetime
from flask import jsonify, request
from app.infrastructure.service.backend.ai import call_ai
from app.infrastructure.service.backend.db import find_rule_reply, get_conn, get_setting
from app.infrastructure.service.logging.log_service import log_event, new_trace_id
def register_message_routes(app):
@app.route("/api/messages/receive", methods=["POST"])
def api_receive_message():
trace_id = new_trace_id("api")
data = request.get_json(silent=True) or request.form.to_dict() or {}
content = (data.get("content") or "").strip()
wx_user_id = (data.get("wx_user_id") or "").strip()
wx_nickname = (data.get("wx_nickname") or "").strip()
is_friend_request = int(data.get("is_friend_request") or 0)
ocr_confidence = str(data.get("ocr_confidence") or "").strip()
ocr_bubble_side = str(data.get("ocr_bubble_side") or "").strip()
if not content and not is_friend_request:
log_event("WARNING", "api", "api.messages.receive", trace_id, "validate", "failed", "消息内容为空且非好友请求", reason="content_empty")
return jsonify({"error": "content is empty"}), 400
conn = get_conn()
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
try:
with conn.cursor() as cur:
cur.execute("INSERT INTO messages (wx_user_id, wx_nickname, direction, content, is_friend_request, reply_strategy, reply_reason, ocr_confidence, ocr_bubble_side, created_at) VALUES (%s, %s, 'in', %s, %s, %s, %s, %s, %s, %s)", (wx_user_id, wx_nickname, content, is_friend_request, "none", "received", ocr_confidence, ocr_bubble_side, now))
in_msg_id = cur.lastrowid
auto_on = str(get_setting("auto_reply_enabled", "1") or "1").strip().lower() in ["1", "true", "yes", "on"]
full_auto_on = str(get_setting("full_auto_reply_enabled", "0") or "0").strip().lower() in ["1", "true", "yes", "on"]
reply_text = ""
used_rule_id = None
reply_strategy = "none"
reply_reason = ""
if not auto_on:
reply_reason = "auto_reply_disabled"
else:
rule = find_rule_reply(content)
if rule:
reply_text = (rule.get("reply_text") or "").strip()
used_rule_id = rule.get("id")
reply_strategy = "rule"
reply_reason = f"rule_hit:{used_rule_id}"
elif full_auto_on:
reply_strategy = "full_auto"
reply_reason = "full_auto_enabled"
reply_text = call_ai(content, wx_user_id)
else:
reply_reason = "rule_miss"
should_reply = auto_on and bool(reply_text)
reply_msg_id = None
if should_reply:
is_ai_reply = 0 if used_rule_id else 1
cur.execute("INSERT INTO messages (wx_user_id, wx_nickname, direction, content, is_ai_reply, rule_id, reply_strategy, reply_reason, created_at) VALUES (%s, %s, 'out', %s, %s, %s, %s, %s, %s)", (wx_user_id, wx_nickname, reply_text, is_ai_reply, used_rule_id, reply_strategy, reply_reason, now))
reply_msg_id = cur.lastrowid
conn.commit()
except Exception as exc:
conn.rollback()
log_event("ERROR", "api", "api.messages.receive", trace_id, "persist", "failed", "消息入库或回复处理失败", reason="db_error", extra={"error": str(exc)})
raise
finally:
conn.close()
log_event("INFO", "audit", "audit.decision", trace_id, "decision", "ok", "回复决策完成", reason=reply_reason or "none", extra={"wx_user_id": wx_user_id, "strategy": reply_strategy, "should_reply": should_reply, "rule_id": used_rule_id or ""})
log_event("INFO", "api", "api.messages.receive", trace_id, "done", "ok", "消息处理完成", extra={"in_message_id": in_msg_id, "reply_message_id": reply_msg_id or "", "should_reply": should_reply})
return jsonify({"success": True, "should_reply": should_reply, "reply_text": reply_text, "in_message_id": in_msg_id, "reply_message_id": reply_msg_id})