From 2e391d599d08ea7a7c11442bc2845a1191494c3d Mon Sep 17 00:00:00 2001
From: yj <2077506045@qq.com>
Date: 星期四, 07 八月 2025 17:55:58 +0800
Subject: [PATCH] 新增消息聚会,短时间内同一用户发送的消息聚合才后发送给AI

---
 app/services/message_processor.py |   98 +++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 91 insertions(+), 7 deletions(-)

diff --git a/app/services/message_processor.py b/app/services/message_processor.py
index 11b1bf6..5ac473c 100644
--- a/app/services/message_processor.py
+++ b/app/services/message_processor.py
@@ -5,6 +5,7 @@
 import json
 import time
 import re
+import xml.etree.ElementTree as ET
 from typing import Dict, Any, Optional, List, Tuple
 from datetime import datetime
 from sqlalchemy.orm import Session
@@ -27,6 +28,69 @@
 
     def __init__(self):
         pass
+
+    def extract_refer_message_content(self, callback_data: Dict[str, Any]) -> str:
+        """
+        鎻愬彇寮曠敤娑堟伅鐨勫唴瀹癸紙message_type涓�80014锛�
+
+        Args:
+            callback_data: 鍥炶皟鏁版嵁
+
+        Returns:
+            缁勫悎鍚庣殑娑堟伅鍐呭锛坈ontent + title锛屼腑闂寸┖涓�琛岋級
+        """
+        try:
+            data = callback_data.get("data", {})
+            content = data.get("content", "")
+            title = data.get("title", "")
+
+            # 瑙f瀽XML鍐呭锛屾彁鍙杕sg>appmsg>refermsg>content鏍囩涓殑鍐呭
+            refer_content = ""
+            xml_title = ""
+            try:
+                # 瑙f瀽XML
+                root = ET.fromstring(content)
+
+                # 鏌ユ壘msg>appmsg>refermsg>content璺緞
+                appmsg = root.find("appmsg")
+                if appmsg is not None:
+                    # 鎻愬彇XML涓殑title锛堝鏋滃瓨鍦級
+                    title_element = appmsg.find("title")
+                    if title_element is not None and title_element.text:
+                        xml_title = title_element.text.strip()
+
+                    # 鎻愬彇寮曠敤娑堟伅鍐呭
+                    refermsg = appmsg.find("refermsg")
+                    if refermsg is not None:
+                        content_element = refermsg.find("content")
+                        if content_element is not None and content_element.text:
+                            refer_content = content_element.text.strip()
+
+            except ET.ParseError as e:
+                logger.warning(f"XML瑙f瀽澶辫触: {str(e)}, content={content}")
+                # 濡傛灉XML瑙f瀽澶辫触锛屼娇鐢ㄥ師濮媍ontent
+                refer_content = content
+
+            # 纭畾鏈�缁堜娇鐢ㄧ殑title锛氫紭鍏堜娇鐢╔ML涓殑title锛屽叾娆′娇鐢╠ata.title
+            final_title = xml_title if xml_title else title
+
+            # 缁勫悎鍐呭锛歳efer_content鍦ㄥ墠锛宖inal_title鍦ㄥ悗锛屼腑闂寸┖涓�琛�
+            if refer_content and final_title:
+                combined_content = f"{refer_content}\n\n{final_title}"
+            elif refer_content:
+                combined_content = refer_content
+            elif final_title:
+                combined_content = final_title
+            else:
+                combined_content = content  # 濡傛灉閮芥病鏈夛紝浣跨敤鍘熷content
+
+            logger.info(f"寮曠敤娑堟伅鍐呭鎻愬彇瀹屾垚: refer_content_length={len(refer_content)}, xml_title_length={len(xml_title)}, data_title_length={len(title)}, final_title_length={len(final_title)}")
+            return combined_content
+
+        except Exception as e:
+            logger.error(f"鎻愬彇寮曠敤娑堟伅鍐呭寮傚父: error={str(e)}")
+            # 寮傚父鎯呭喌涓嬭繑鍥炲師濮媍ontent
+            return callback_data.get("data", {}).get("content", "")
 
     def parse_at_mentions(self, ai_answer: str) -> Tuple[str, List[str]]:
         """
@@ -83,9 +147,10 @@
         Returns:
             鏄惁鏄湁鏁堢殑缇よ亰娑堟伅
         """
-        # 妫�鏌ユ秷鎭被鍨嬫槸鍚︽槸缇よ亰娑堟伅锛�80001锛�
+        # 妫�鏌ユ秷鎭被鍨嬫槸鍚︽槸缇よ亰娑堟伅锛�80001锛夋垨寮曠敤娑堟伅锛�80014锛�
         message_type = callback_data.get("messageType")
-        if message_type != "80001":
+        print(f"data: {callback_data}")
+        if message_type not in ["80001", "80014"]:
             logger.info(f"蹇界暐闈炵兢鑱婃秷鎭�: messageType={message_type}")
             return False
 
@@ -150,11 +215,23 @@
         if not self.is_valid_group_message(callback_data):
             return False
 
-        data = callback_data.get("data", {})
-        from_user = data.get("fromUser")
+        # 瀵煎叆娑堟伅鑱氬悎鏈嶅姟锛堝欢杩熷鍏ラ伩鍏嶅惊鐜緷璧栵級
+        from app.services.message_aggregator import message_aggregator
 
-        # 灏嗘暣涓洖璋冨唴瀹硅浆鎴怞SON瀛楃涓插瓨鍌ㄥ埌Redis闃熷垪
-        return redis_queue.enqueue_message(from_user, callback_data)
+        # 灏濊瘯灏嗘秷鎭坊鍔犲埌鑱氬悎涓�
+        should_process_immediately, aggregated_data = message_aggregator.add_message_to_aggregation(callback_data)
+
+        if should_process_immediately:
+            # 闇�瑕佺珛鍗冲鐞嗭紙涓嶈仛鍚堟垨鑱氬悎瓒呮椂锛�
+            data = aggregated_data.get("data", {}) if aggregated_data else callback_data.get("data", {})
+            from_user = data.get("fromUser")
+
+            # 灏嗘秷鎭姞鍏edis闃熷垪
+            return redis_queue.enqueue_message(from_user, aggregated_data or callback_data)
+        else:
+            # 娑堟伅宸茶鑱氬悎锛屼笉闇�瑕佺珛鍗冲鐞�
+            logger.info(f"娑堟伅宸叉坊鍔犲埌鑱氬悎闃熷垪锛岀瓑寰呰仛鍚堝鐞�: fromUser={callback_data.get('data', {}).get('fromUser')}")
+            return True
 
     def ensure_contact_exists(self, from_group: str, w_id: str, db: Session) -> bool:
         """
@@ -230,8 +307,15 @@
             from_group = data.get("fromGroup")
             content = data.get("content")
             w_id = data.get("wId")
+            message_type = message_data.get("messageType")
 
-            logger.info(f"寮�濮嬪鐞嗘秷鎭�: from_user={from_user}, from_group={from_group}")
+            logger.info(f"寮�濮嬪鐞嗘秷鎭�: from_user={from_user}, from_group={from_group}, message_type={message_type}")
+
+            # 鏍规嵁娑堟伅绫诲瀷澶勭悊鍐呭
+            if message_type == "80014":
+                # 寮曠敤娑堟伅锛岄渶瑕佹彁鍙朮ML涓殑鍐呭骞朵笌title缁勫悎
+                content = self.extract_refer_message_content(message_data)
+                logger.info(f"寮曠敤娑堟伅鍐呭澶勭悊瀹屾垚: content_length={len(content)}")
 
             # 浣跨敤涓婁笅鏂囩鐞嗗櫒纭繚鏁版嵁搴撲細璇濇纭鐞�
             with next(get_db()) as db:

--
Gitblit v1.9.1