6.8 KiB
6.8 KiB
消息总结定时任务使用说明
功能概述
已为 message_summary 插件添加了定时任务功能,每天早上 9:00 自动总结昨天的群聊信息并发送到群聊中。
实现原理
参考了 game_task 插件的定时任务策略,在 message_summary 插件初始化时注册定时任务:
async_job.at_times(["09:00"])(self.daily_summary_job)
核心修改
1. plugins/message_summary/main.py
添加导入
from datetime import datetime, timedelta
from utils.decorator.async_job import async_job
import asyncio
在 __init__ 中注册定时任务
def __init__(self):
super().__init__()
self.message_storage = None
self.revoke = None
self.feature = self.register_feature()
# 注册定时任务:每天早上9点总结昨天的聊天信息
async_job.at_times(["09:00"])(self.daily_summary_job)
添加定时任务方法
async def daily_summary_job(self):
"""定时任务:每天早上9点总结昨天的聊天信息"""
# 计算昨天的时间范围
yesterday = datetime.now() - timedelta(days=1)
yesterday_start = yesterday.replace(hour=0, minute=0, second=0, microsecond=0)
yesterday_end = yesterday.replace(hour=23, minute=59, second=59, microsecond=999999)
# 获取所有启用了群机器人的群聊
all_groups = GroupBotManager.get_group_list()
# 筛选出开启了总结功能的群聊
enabled_groups = []
for group_id in all_groups:
if GroupBotManager.get_group_permission(group_id, self.feature) == PermissionStatus.ENABLED:
enabled_groups.append(group_id)
# 为每个群生成总结
for group_id in enabled_groups:
# 获取昨天的聊天记录
chat_content = self.message_storage.get_messages_by_date_range(
group_id, all_contacts, yesterday_start, yesterday_end
)
# 生成并发送总结
summary, image_path = await self._generate_summary(chat_content, group_name)
# 发送到群聊...
2. db/message_storage.py
添加了按时间范围查询消息的方法:
def get_messages_by_date_range(self, group_id: str, start_time: datetime, end_time: datetime) -> List[Dict]:
"""获取指定时间范围内的消息"""
sql = """
SELECT timestamp, sender, content, message_type
FROM messages
WHERE timestamp >= %s AND timestamp <= %s
AND message_type in (1, 49)
AND group_id = %s
AND length(content) > 6
AND CHAR_LENGTH(content) < 300
AND content NOT LIKE '/%'
ORDER BY timestamp ASC
"""
params = (start_time.strftime('%Y-%m-%d %H:%M:%S'),
end_time.strftime('%Y-%m-%d %H:%M:%S'),
group_id)
return self.execute_query(sql, params) or []
3. utils/wechat/message_to_db.py
添加了对应的包装方法:
def get_messages_by_date_range(self, group_id, all_contacts: dict, start_time: datetime, end_time: datetime):
"""获取指定时间范围内的消息"""
messages = self.message_db.get_messages_by_date_range(group_id, start_time, end_time)
result_str = self._format_messages_optimized(messages, all_contacts)
return result_str
使用方法
1. 启用插件
确保 message_summary 插件已启用,并且已在插件配置中开启。
2. 配置群权限
对于需要自动总结的群聊,需要开启"群总结能力"功能:
- 通过机器人群管理命令设置群权限为
ENABLED - 功能键:
SUMMARY_CAPABILITY
3. 自动运行
- 定时任务会在每天早上 9:00 自动执行
- 只会总结昨天(00:00:00 - 23:59:59)的聊天记录
- 只有消息数量超过 50 条的群才会生成总结(按消息条数统计,不是字符数)
4. 手动触发
除了定时任务外,原有的手动总结功能仍然保留:
- 在群聊中发送
#总结或#summary - 会总结最近 8 小时的聊天记录
特性说明
-
智能过滤
- 只总结文本消息(message_type 1 和 49)
- 过滤掉命令消息(以
/开头) - 过滤掉过短(<6字)和过长(>300字)的消息
-
权限控制
- 只有开启了总结功能的群才会自动总结
- 使用
GroupBotManager管理群权限
-
消息数量过滤
- 只有消息数量 >= 50 条的群才会生成总结
- 先统计消息数量,不足 50 条直接跳过,避免浪费资源
- 按消息条数统计,不是按字符数
-
错误处理
- 如果某个群的总结失败,不会影响其他群
- 详细的日志记录便于排查问题
-
性能优化
- 群之间间隔 2 秒,避免 API 请求过快
- 使用现有的消息格式化方法,保持一致性
日志示例
2026-01-09 09:00:00 | INFO | 开始执行每日聊天总结任务
2026-01-09 09:00:00 | INFO | 总结时间范围: 2026-01-08 00:00:00 至 2026-01-08 23:59:59
2026-01-09 09:00:00 | INFO | 找到 3 个开启定时总结的群聊
2026-01-09 09:00:01 | INFO | 群 test_group_1 昨天有 234 条消息,开始获取内容
2026-01-09 09:00:01 | INFO | 群 test_group_2 昨天只有 35 条消息,不足50条,跳过总结
2026-01-09 09:00:01 | INFO | 群 test_group_3 昨天有 156 条消息,开始获取内容
2026-01-09 09:00:02 | INFO | 获取到 234 条消息(时间范围:2026-01-08 00:00:00 至 2026-01-08 23:59:59),格式化后长度: 12580
2026-01-09 09:00:02 | INFO | 开始为群 测试群1 生成总结,消息数量: 234,内容长度: 12580
2026-01-09 09:00:15 | INFO | 成功发送群 测试群 的昨日总结图片
2026-01-09 09:00:17 | INFO | 每日聊天总结任务执行完成
注意事项
- 时间精度:定时任务使用系统时间,确保服务器时间准确
- 数据库时区:确保数据库时区设置正确,存储的 timestamp 使用的是本地时间
- API 限流:如果总结的群很多,注意调整
await asyncio.sleep(2)的间隔时间 - 消息量:如果某个群昨天的消息量很大(>5000条),可能需要调整
max_results参数
自定义配置
如需修改执行时间,可以修改 message_summary/main.py 中的定时任务注册:
# 改为每天早上 8:00
async_job.at_times(["08:00"])(self.daily_summary_job)
# 改为每天晚上 22:00
async_job.at_times(["22:00"])(self.daily_summary_job)
# 改为每天多个时间点
async_job.at_times(["09:00", "21:00"])(self.daily_summary_job)
测试方法
为了测试定时任务功能,可以临时修改时间:
# 临时修改为当前时间后 1 分钟(用于测试)
import datetime
next_minute = (datetime.datetime.now() + datetime.timedelta(minutes=1)).strftime("%H:%M")
async_job.at_times([next_minute])(self.daily_summary_job)
测试完成后记得改回 ["09:00"]。