实现消息回复状态机制替代_seen_messages集合
- Task #1673: 在user_messages表添加reply_status和fail_count字段 - 实现mark_message_replied和mark_message_send_failed方法 - SQLite UPDATE语法修复:改用子查询方式避免ORDER BY+LIMIT错误 - 在gui.py中集成发送成功/失败状态标记 - 事不过三原则:连续3次发送失败后强制标记为已回复
This commit is contained in:
@@ -1380,6 +1380,9 @@ class MsgBotApp(ctk.CTk):
|
||||
ok = self.monitor._paste_and_send(platform, answer, force_retry=(attempt > 0))
|
||||
if ok:
|
||||
self._log(f"[{platform}] 🤖 已自动回复: {answer[:60]}...")
|
||||
# ⭐ Task #1673: 发送成功,标记消息已回复
|
||||
if msg:
|
||||
self.monitor.mark_message_replied(platform, msg)
|
||||
return # 成功直接退出
|
||||
else:
|
||||
if attempt < max_retries - 1:
|
||||
@@ -1394,6 +1397,9 @@ class MsgBotApp(ctk.CTk):
|
||||
self.after(int(retry_delay * 1000), lambda d=data: self._execute_reply(d))
|
||||
else:
|
||||
self._log(f"[{platform}] ⚠ 自动回复发送失败(连续{max_retries}次),用户可能在接管,本轮跳过")
|
||||
# ⭐ Task #1673: 连续3次发送失败,标记消息发送失败
|
||||
if msg:
|
||||
self.monitor.mark_message_send_failed(platform, msg)
|
||||
finally:
|
||||
self.monitor._sending_event.clear()
|
||||
# ⭐ 回复完成或失败后清除进行中标志
|
||||
|
||||
+107
-2
@@ -558,12 +558,25 @@ class MessageHistory:
|
||||
platform TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
content_hash TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
reply_status INTEGER DEFAULT 1,
|
||||
fail_count INTEGER DEFAULT 0
|
||||
)
|
||||
""")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_user_content_hash ON user_messages(content_hash)")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_user_platform_time ON user_messages(platform, created_at)")
|
||||
conn.commit()
|
||||
else:
|
||||
# ⭐ Task #1673: 检查并添加 reply_status 和 fail_count 字段(如果不存在)
|
||||
cursor = conn.execute("PRAGMA table_info(user_messages)")
|
||||
columns = [row[1] for row in cursor.fetchall()]
|
||||
if 'reply_status' not in columns:
|
||||
logger.info("[msg-history] user_messages表添加 reply_status 字段")
|
||||
conn.execute("ALTER TABLE user_messages ADD COLUMN reply_status INTEGER DEFAULT 1")
|
||||
if 'fail_count' not in columns:
|
||||
logger.info("[msg-history] user_messages表添加 fail_count 字段")
|
||||
conn.execute("ALTER TABLE user_messages ADD COLUMN fail_count INTEGER DEFAULT 0")
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
@@ -609,6 +622,93 @@ class MessageHistory:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def mark_message_replied(self, platform: str, content: str):
|
||||
"""标记消息已回复(reply_status=0)"""
|
||||
# ⭐ Task #1673: 用数据库状态机制替代内存中的_seen_messages集合
|
||||
self._ensure_user_messages_table()
|
||||
conn = self._get_conn()
|
||||
try:
|
||||
# ⭐ Task #1676: SQLite不支持UPDATE+ORDER BY+LIMIT,改用子查询找到最大id
|
||||
# 先找到最近一条匹配消息的id
|
||||
cursor = conn.execute(
|
||||
"""SELECT id FROM user_messages
|
||||
WHERE platform=? AND content=? AND reply_status=1
|
||||
ORDER BY id DESC LIMIT 1""",
|
||||
(platform, content.strip())
|
||||
)
|
||||
row = cursor.fetchone()
|
||||
if row:
|
||||
msg_id = row[0]
|
||||
# 更新该条消息的 reply_status 为 0(已回复)
|
||||
conn.execute(
|
||||
"UPDATE user_messages SET reply_status=0 WHERE id=?",
|
||||
(msg_id,)
|
||||
)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
logger.error(f"[{platform}] 标记消息已回复失败: {e}")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def mark_message_send_failed(self, platform: str, content: str):
|
||||
"""标记消息发送失败(增加 fail_count,连续3次失败则标记为已回复)"""
|
||||
# ⭐ Task #1673: 发送失败的事不过三原则
|
||||
self._ensure_user_messages_table()
|
||||
conn = self._get_conn()
|
||||
try:
|
||||
# ⭐ Task #1676: SQLite不支持UPDATE+ORDER BY+LIMIT,改用子查询找到最大id
|
||||
# 先找到最近一条匹配消息的id
|
||||
cursor = conn.execute(
|
||||
"""SELECT id FROM user_messages
|
||||
WHERE platform=? AND content=? AND reply_status=1
|
||||
ORDER BY id DESC LIMIT 1""",
|
||||
(platform, content.strip())
|
||||
)
|
||||
row = cursor.fetchone()
|
||||
if row:
|
||||
msg_id = row[0]
|
||||
# 增加 fail_count
|
||||
conn.execute(
|
||||
"UPDATE user_messages SET fail_count=fail_count+1 WHERE id=?",
|
||||
(msg_id,)
|
||||
)
|
||||
# 检查 fail_count 是否达到3次
|
||||
cursor = conn.execute(
|
||||
"SELECT fail_count FROM user_messages WHERE id=?",
|
||||
(msg_id,)
|
||||
)
|
||||
row = cursor.fetchone()
|
||||
if row and row[0] >= 3:
|
||||
# 连续3次失败,强制标记为已回复
|
||||
conn.execute(
|
||||
"UPDATE user_messages SET reply_status=0 WHERE id=?",
|
||||
(msg_id,)
|
||||
)
|
||||
logger.info(f"[{platform}] 消息连续3次发送失败,强制标记为已回复: {content[:40]}")
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
logger.error(f"[{platform}] 标记消息发送失败失败: {e}")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def is_message_already_replied(self, platform: str, content: str) -> bool:
|
||||
"""检查消息是否已回复(reply_status=0)"""
|
||||
# ⭐ Task #1673: 轮询时检查 reply_status,为0则跳过
|
||||
self._ensure_user_messages_table()
|
||||
conn = self._get_conn()
|
||||
try:
|
||||
cursor = conn.execute(
|
||||
"""SELECT COUNT(*) FROM user_messages
|
||||
WHERE platform=? AND content=? AND reply_status=0""",
|
||||
(platform, content.strip())
|
||||
)
|
||||
return cursor.fetchone()[0] > 0
|
||||
except Exception as e:
|
||||
logger.error(f"[{platform}] 检查消息是否已回复失败: {e}")
|
||||
return False
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def record_user_message(self, platform: str, content: str):
|
||||
"""记录用户消息到user_messages表(环形缓冲区,max 10条/平台)"""
|
||||
# ⭐ Task #1655: 确保表存在(防御性编程)
|
||||
@@ -651,8 +751,9 @@ class MessageHistory:
|
||||
" ORDER BY created_at ASC LIMIT ?"
|
||||
")", (platform, count - 9)
|
||||
)
|
||||
# ⭐ Task #1673: 添加 reply_status 和 fail_count 字段
|
||||
conn.execute(
|
||||
"INSERT INTO user_messages (platform, content, content_hash, created_at) VALUES (?, ?, ?, ?)",
|
||||
"INSERT INTO user_messages (platform, content, content_hash, created_at, reply_status, fail_count) VALUES (?, ?, ?, ?, 1, 0)",
|
||||
(platform, content.strip(), content_hash, local_time)
|
||||
)
|
||||
conn.commit()
|
||||
@@ -10335,6 +10436,10 @@ class MessageMonitor:
|
||||
if matched_r:
|
||||
logger.debug(f"[{platform}] 回复公共子串跳过: {ts[:50]}")
|
||||
continue
|
||||
# ⭐ Task #1673: 先检查数据库中的 reply_status,为0则跳过
|
||||
if self._msg_history and self._msg_history.is_message_already_replied(platform, ts):
|
||||
logger.debug(f"[{platform}] 数据库查重跳过(reply_status=0): {ts[:50]}")
|
||||
continue
|
||||
if ts in seen:
|
||||
logger.debug(f"[{platform}] seen去重跳过: {ts[:50]}")
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user