feat:尝试增加不回答已撤回消息的功能,并每小时删除一次存留超过1小时的撤回消息

feat:尝试增加不回答已撤回消息的功能,并每小时删除一次存留超过1小时的撤回消息
This commit is contained in:
HYY
2025-03-14 09:34:22 +08:00
committed by GitHub
4 changed files with 100 additions and 39 deletions

View File

@@ -20,7 +20,7 @@ from .chat_stream import chat_manager
from ..memory_system.memory import hippocampus, memory_graph from ..memory_system.memory import hippocampus, memory_graph
from .bot import ChatBot from .bot import ChatBot
from .message_sender import message_manager, message_sender from .message_sender import message_manager, message_sender
from .storage import MessageStorage
# 创建LLM统计实例 # 创建LLM统计实例
llm_stats = LLMStatistics("llm_statistics.txt") llm_stats = LLMStatistics("llm_statistics.txt")
@@ -148,3 +148,13 @@ async def generate_schedule_task():
await bot_schedule.initialize() await bot_schedule.initialize()
if not bot_schedule.enable_output: if not bot_schedule.enable_output:
bot_schedule.print_schedule() bot_schedule.print_schedule()
@scheduler.scheduled_job("interval", seconds=3600, id="remove_recalled_message")
async def remove_recalled_message() -> None:
"""删除撤回消息"""
try:
storage = MessageStorage()
await storage.remove_recalled_message(time.time())
except Exception:
logger.exception("删除撤回消息失败")

View File

@@ -8,6 +8,9 @@ from nonebot.adapters.onebot.v11 import (
PrivateMessageEvent, PrivateMessageEvent,
NoticeEvent, NoticeEvent,
PokeNotifyEvent, PokeNotifyEvent,
GroupRecallNoticeEvent,
FriendRecallNoticeEvent,
) )
from ..memory_system.memory import hippocampus from ..memory_system.memory import hippocampus
@@ -76,6 +79,24 @@ class ChatBot:
raw_message += "(这是一个类似摸摸头的友善行为,而不是恶意行为,请不要作出攻击发言)" raw_message += "(这是一个类似摸摸头的友善行为,而不是恶意行为,请不要作出攻击发言)"
await self.directly_reply(raw_message, event.user_id, event.group_id) await self.directly_reply(raw_message, event.user_id, event.group_id)
if isinstance(event, GroupRecallNoticeEvent) or isinstance(event, FriendRecallNoticeEvent):
user_info = UserInfo(
user_id=event.user_id,
user_nickname=get_user_nickname(event.user_id) or None,
user_cardname=get_user_cardname(event.user_id) or None,
platform="qq",
)
group_info = GroupInfo(group_id=event.group_id, group_name=None, platform="qq")
chat = await chat_manager.get_or_create_stream(
platform=user_info.platform, user_info=user_info, group_info=group_info
)
await self.storage.store_recalled_message(event.message_id, time.time(), chat)
async def handle_message(self, event: MessageEvent, bot: Bot) -> None: async def handle_message(self, event: MessageEvent, bot: Bot) -> None:
"""处理收到的消息""" """处理收到的消息"""

View File

@@ -4,7 +4,7 @@ from typing import Dict, List, Optional, Union
from loguru import logger from loguru import logger
from nonebot.adapters.onebot.v11 import Bot from nonebot.adapters.onebot.v11 import Bot
from ...common.database import db
from .message_cq import MessageSendCQ from .message_cq import MessageSendCQ
from .message import MessageSending, MessageThinking, MessageRecv, MessageSet from .message import MessageSending, MessageThinking, MessageRecv, MessageSet
@@ -24,6 +24,14 @@ class Message_Sender:
def set_bot(self, bot: Bot): def set_bot(self, bot: Bot):
"""设置当前bot实例""" """设置当前bot实例"""
self._current_bot = bot self._current_bot = bot
def get_recalled_messages(self, stream_id: str) -> list:
"""获取所有撤回的消息"""
recalled_messages = []
recalled_messages = list(db.recalled_messages.find({"stream_id": stream_id}, {"message_id": 1}))
# 按thinking_start_time排序时间早的在前面
return recalled_messages
async def send_message( async def send_message(
self, self,
@@ -32,36 +40,41 @@ class Message_Sender:
"""发送消息""" """发送消息"""
if isinstance(message, MessageSending): if isinstance(message, MessageSending):
message_json = message.to_dict() recalled_messages = self.get_recalled_messages(message.chat_stream.stream_id)
message_send = MessageSendCQ(data=message_json) is_recalled = False
# logger.debug(message_send.message_info,message_send.raw_message) for recalled_message in recalled_messages:
message_preview = truncate_message(message.processed_plain_text) if message.reply_to_message_id == recalled_message["message_id"]:
if ( is_recalled = True
message_send.message_info.group_info logger.warning(f"消息“{message.processed_plain_text}”已被撤回,不发送")
and message_send.message_info.group_info.group_id break
): if not is_recalled:
try: message_json = message.to_dict()
await self._current_bot.send_group_msg( message_send = MessageSendCQ(data=message_json)
group_id=message.message_info.group_info.group_id, # logger.debug(message_send.message_info,message_send.raw_message)
message=message_send.raw_message, message_preview = truncate_message(message.processed_plain_text)
auto_escape=False, if message_send.message_info.group_info and message_send.message_info.group_info.group_id:
) try:
logger.success(f"[调试] 发送消息“{message_preview}”成功") await self._current_bot.send_group_msg(
except Exception as e: group_id=message.message_info.group_info.group_id,
logger.error(f"[调试] 发生错误 {e}") message=message_send.raw_message,
logger.error(f"[调试] 发送消息“{message_preview}”失败") auto_escape=False,
else: )
try: logger.success(f"[调试] 发送消息“{message_preview}”成功")
logger.debug(message.message_info.user_info) except Exception as e:
await self._current_bot.send_private_msg( logger.error(f"[调试] 发生错误 {e}")
user_id=message.sender_info.user_id, logger.error(f"[调试] 发送消息“{message_preview}”失败")
message=message_send.raw_message, else:
auto_escape=False, try:
) logger.debug(message.message_info.user_info)
logger.success(f"[调试] 发送消息“{message_preview}”成功") await self._current_bot.send_private_msg(
except Exception as e: user_id=message.sender_info.user_id,
logger.error(f"[调试] 发生错误 {e}") message=message_send.raw_message,
logger.error(f"[调试] 发送消息“{message_preview}”失败") auto_escape=False,
)
logger.success(f"[调试] 发送消息“{message_preview}”成功")
except Exception as e:
logger.error(f"[调试] 发生错误 {e}")
logger.error(f"[调试] 发送消息“{message_preview}”失败")
class MessageContainer: class MessageContainer:
@@ -144,9 +157,7 @@ class MessageManager:
self.containers[chat_id] = MessageContainer(chat_id) self.containers[chat_id] = MessageContainer(chat_id)
return self.containers[chat_id] return self.containers[chat_id]
def add_message( def add_message(self, message: Union[MessageThinking, MessageSending, MessageSet]) -> None:
self, message: Union[MessageThinking, MessageSending, MessageSet]
) -> None:
chat_stream = message.chat_stream chat_stream = message.chat_stream
if not chat_stream: if not chat_stream:
raise ValueError("无法找到对应的聊天流") raise ValueError("无法找到对应的聊天流")
@@ -173,8 +184,8 @@ class MessageManager:
if thinking_time > global_config.thinking_timeout: if thinking_time > global_config.thinking_timeout:
logger.warning(f"消息思考超时({thinking_time}秒),移除该消息") logger.warning(f"消息思考超时({thinking_time}秒),移除该消息")
container.remove_message(message_earliest) container.remove_message(message_earliest)
else:
else:
if ( if (
message_earliest.is_head message_earliest.is_head
and message_earliest.update_thinking_time() > 30 and message_earliest.update_thinking_time() > 30
@@ -188,9 +199,7 @@ class MessageManager:
f"\033[1;34m[调试]\033[0m 消息“{truncate_message(message_earliest.processed_plain_text)}”正在发送中" f"\033[1;34m[调试]\033[0m 消息“{truncate_message(message_earliest.processed_plain_text)}”正在发送中"
) )
await self.storage.store_message( await self.storage.store_message(message_earliest, message_earliest.chat_stream, None)
message_earliest, message_earliest.chat_stream, None
)
container.remove_message(message_earliest) container.remove_message(message_earliest)

View File

@@ -24,4 +24,25 @@ class MessageStorage:
except Exception: except Exception:
logger.exception("存储消息失败") logger.exception("存储消息失败")
async def store_recalled_message(self, message_id: str, time: str, chat_stream:ChatStream) -> None:
"""存储撤回消息到数据库"""
if "recalled_messages" not in db.list_collection_names():
db.create_collection("recalled_messages")
else:
try:
message_data = {
"message_id": message_id,
"time": time,
"stream_id":chat_stream.stream_id,
}
db.recalled_messages.insert_one(message_data)
except Exception:
logger.exception("存储撤回消息失败")
async def remove_recalled_message(self, time: str) -> None:
"""删除撤回消息"""
try:
db.recalled_messages.delete_many({"time": {"$lt": time-300}})
except Exception:
logger.exception("删除撤回消息失败")
# 如果需要其他存储相关的函数,可以在这里添加 # 如果需要其他存储相关的函数,可以在这里添加