初始提交:识流 AI 助手项目
微信自动回复机器人,基于截图+OCR识别消息,支持关键词规则和 AI(OpenAI/DeepSeek/Dify)自动回复。 技术栈:PySide6 + Flask + Vue3 + RapidOCR + SQLite 注:OCR大模型文件(.onnx / .pdiparams)不纳入版本控制,需单独下载。 🤖 Generated with [Qoder][https://qoder.com]
This commit is contained in:
72
app/infrastructure/router/backend/messages.py
Normal file
72
app/infrastructure/router/backend/messages.py
Normal file
@@ -0,0 +1,72 @@
|
||||
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})
|
||||
Reference in New Issue
Block a user