重构message_handler 删除分页机制

This commit is contained in:
xiaoxi68
2025-11-09 20:24:27 +08:00
parent a1e75270d5
commit f42929938d
+47 -114
View File
@@ -63,129 +63,62 @@ class MessageHandler:
start_time = end_time - timedelta(days=days)
messages = []
message_seq = 0
query_rounds = 0
max_rounds = self.config_manager.get_max_query_rounds()
# 一次性获取,移除分页与多轮查询
max_messages = self.config_manager.get_max_messages()
consecutive_failures = 0
max_failures = 3
query_rounds = 0
logger.info(f"开始获取群 {group_id}{days} 天的消息记录")
logger.info(f"时间范围: {start_time.strftime('%Y-%m-%d %H:%M:%S')}{end_time.strftime('%Y-%m-%d %H:%M:%S')}")
while query_rounds < max_rounds:
try:
# 构造请求参数
payloads = {
"group_id": int(group_id) if group_id.isdigit() else group_id,
"count": 200,
}
# 添加 message_seq(如果不是第一轮)
if message_seq:
payloads["message_seq"] = message_seq
# 单次请求,按配置的 max_messages 作为 count
try:
payloads = {
"group_id": int(group_id) if group_id.isdigit() else group_id,
"count": int(max_messages),
}
# 尝试调用 API
result = None
api_error = None
if hasattr(bot_instance, 'call_action'):
try:
# aiocqhttp (CQHttp) 方式
result = await bot_instance.call_action("get_group_msg_history", **payloads)
except Exception as api_err:
api_error = api_err
logger.error(f"{group_id} API 调用失败: {api_err}")
# 第一次失败就放弃(该 API 不支持)
if query_rounds == 0:
logger.error(f"{group_id} 当前 OneBot 实现不支持 get_group_msg_history API")
return []
elif hasattr(bot_instance, 'api'):
# QQ官方 bot (botClient) 方式 - 官方API不支持历史消息
logger.error(f"{group_id} 检测到 QQ 官方 Bot,官方 API 不支持获取历史消息")
return []
else:
logger.error(f"{group_id} 未知的 bot_instance 类型,无法调用 API")
logger.error(f"bot_instance 类型: {type(bot_instance)}")
result = None
if hasattr(bot_instance, 'call_action'):
try:
# aiocqhttp (CQHttp) 方式
result = await bot_instance.call_action("get_group_msg_history", **payloads)
query_rounds = 1
except Exception as api_err:
logger.error(f"{group_id} API 调用失败: {api_err}")
logger.error(f"{group_id} 当前 OneBot 实现可能不支持 get_group_msg_history API")
return []
elif hasattr(bot_instance, 'api'):
# QQ 官方 bot (botClient) 不支持历史消息
logger.error(f"{group_id} 检测到 QQ 官方 Bot,官方 API 不支持获取历史消息")
return []
else:
logger.error(f"{group_id} 未知的 bot_instance 类型,无法调用 API,类型: {type(bot_instance)}")
return []
if not result or "messages" not in result:
logger.warning(f"{group_id} API返回无效结果: {result}")
consecutive_failures += 1
if consecutive_failures >= max_failures:
break
continue
if not result or "messages" not in result:
logger.warning(f"{group_id} API返回无效结果: {result}")
return []
round_messages = result.get("messages", [])
if not round_messages:
logger.info(f"{group_id} 没有更多消息,结束获取")
break
# 重置失败计数
consecutive_failures = 0
# 过滤时间范围内的消息
valid_messages_in_round = 0
oldest_msg_time = None
has_out_of_range_message = False
for msg in round_messages:
try:
msg_time = datetime.fromtimestamp(msg.get("time", 0))
# 记录本轮最老的消息时间
if oldest_msg_time is None or msg_time < oldest_msg_time:
oldest_msg_time = msg_time
# 检查是否已经超出时间范围
if msg_time < start_time:
has_out_of_range_message = True
# 继续处理本轮剩余消息,但不再查询下一轮
continue
# 过滤掉机器人自己的消息
sender_id = str(msg.get("sender", {}).get("user_id", ""))
if self.bot_manager and self.bot_manager.should_filter_bot_message(sender_id):
continue
if msg_time >= start_time and msg_time <= end_time:
messages.append(msg)
valid_messages_in_round += 1
except Exception as msg_error:
logger.warning(f"{group_id} 处理单条消息失败: {msg_error}")
round_messages = result.get("messages", [])
if not round_messages:
logger.info(f"{group_id} 未获取到消息")
# 过滤时间范围内的消息并过滤机器人自身消息
for msg in round_messages:
try:
msg_time = datetime.fromtimestamp(msg.get("time", 0))
if not (start_time <= msg_time <= end_time):
continue
# 如果本轮有消息已经超出时间范围,立即停止获取
if has_out_of_range_message:
logger.info(f"{group_id} 已获取到时间范围外的消息(最老消息时间: {oldest_msg_time.strftime('%Y-%m-%d %H:%M:%S')}),停止获取。共获取 {len(messages)} 条消息")
break
# 如果本轮没有获取到任何有效消息,停止获取
if valid_messages_in_round == 0:
logger.warning(f"{group_id} 本轮未获取到有效消息,停止获取")
break
# 如果已经获取到足够的消息(达到 max_messages),停止获取
if len(messages) >= max_messages:
logger.info(f"{group_id} 已达到消息数量限制({len(messages)} 条,限制 {max_messages} 条),停止获取")
break
message_seq = round_messages[0]["message_id"]
query_rounds += 1
# 添加延迟避免请求过快
if query_rounds % 5 == 0:
await asyncio.sleep(0.5)
except Exception as e:
logger.error(f"{group_id} 获取消息失败 (第{query_rounds+1}轮): {e}")
consecutive_failures += 1
if consecutive_failures >= max_failures:
logger.error(f"{group_id} 连续失败 {max_failures} 次,停止获取")
break
await asyncio.sleep(1)
sender_id = str(msg.get("sender", {}).get("user_id", ""))
if self.bot_manager and self.bot_manager.should_filter_bot_message(sender_id):
continue
messages.append(msg)
except Exception as msg_error:
logger.warning(f"{group_id} 处理单条消息失败: {msg_error}")
continue
except Exception as e:
logger.error(f"{group_id} 获取消息失败: {e}")
return []
# ========== 最终清理步骤:严格过滤和限制 ==========
original_count = len(messages)
@@ -287,4 +220,4 @@ class MessageHandler:
emoji_statistics=emoji_statistics,
activity_visualization=activity_visualization,
token_usage=TokenUsage()
)
)