mirror of
https://github.com/Nezumi-2711/astrbot_plugin_qq_group_daily_analysis.git
synced 2026-09-22 13:38:43 +00:00
feat(auto_analysis_time): 将 auto_analysis_time 配置改为 list,满足支持配置每日多个时间点总结的需求 (#79)
This commit is contained in:
+7
-4
@@ -34,10 +34,13 @@
|
|||||||
"hint": "默认分析最近几天的消息,建议1-7天"
|
"hint": "默认分析最近几天的消息,建议1-7天"
|
||||||
},
|
},
|
||||||
"auto_analysis_time": {
|
"auto_analysis_time": {
|
||||||
"type": "string",
|
"type": "list",
|
||||||
"description": "自动分析时间",
|
"description": "自动分析时间列表",
|
||||||
"default": "09:00",
|
"default": ["09:00"],
|
||||||
"hint": "每日自动分析的时间,格式HH:MM"
|
"hint": "每日自动分析的时间点列表,格式HH:MM,支持多个时间点",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"enable_auto_analysis": {
|
"enable_auto_analysis": {
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
|
|||||||
+9
-5
@@ -58,9 +58,13 @@ class ConfigManager:
|
|||||||
"""获取分析天数"""
|
"""获取分析天数"""
|
||||||
return self.config.get("analysis_days", 1)
|
return self.config.get("analysis_days", 1)
|
||||||
|
|
||||||
def get_auto_analysis_time(self) -> str:
|
def get_auto_analysis_time(self) -> list[str]:
|
||||||
"""获取自动分析时间"""
|
"""获取自动分析时间列表"""
|
||||||
return self.config.get("auto_analysis_time", "09:00")
|
val = self.config.get("auto_analysis_time", ["09:00"])
|
||||||
|
# 兼容旧版本字符串配置
|
||||||
|
if isinstance(val, str):
|
||||||
|
return [val]
|
||||||
|
return val if isinstance(val, list) else ["09:00"]
|
||||||
|
|
||||||
def get_enable_auto_analysis(self) -> bool:
|
def get_enable_auto_analysis(self) -> bool:
|
||||||
"""获取是否启用自动分析"""
|
"""获取是否启用自动分析"""
|
||||||
@@ -266,9 +270,9 @@ class ConfigManager:
|
|||||||
self.config["analysis_days"] = days
|
self.config["analysis_days"] = days
|
||||||
self.config.save_config()
|
self.config.save_config()
|
||||||
|
|
||||||
def set_auto_analysis_time(self, time_str: str):
|
def set_auto_analysis_time(self, time_val: str | list[str]):
|
||||||
"""设置自动分析时间"""
|
"""设置自动分析时间"""
|
||||||
self.config["auto_analysis_time"] = time_str
|
self.config["auto_analysis_time"] = time_val
|
||||||
self.config.save_config()
|
self.config.save_config()
|
||||||
|
|
||||||
def set_enable_auto_analysis(self, enabled: bool):
|
def set_enable_auto_analysis(self, enabled: bool):
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class AutoScheduler:
|
|||||||
self.retry_manager = retry_manager # 保存引用
|
self.retry_manager = retry_manager # 保存引用
|
||||||
self.html_render_func = html_render_func
|
self.html_render_func = html_render_func
|
||||||
self.scheduler_task = None
|
self.scheduler_task = None
|
||||||
self.last_execution_date = None # 记录上次执行日期,防止重复执行
|
self.last_executed_target = None # 记录上次执行的具体时间点,防止重复执行
|
||||||
|
|
||||||
def set_bot_instance(self, bot_instance):
|
def set_bot_instance(self, bot_instance):
|
||||||
"""设置bot实例(保持向后兼容)"""
|
"""设置bot实例(保持向后兼容)"""
|
||||||
@@ -146,18 +146,55 @@ class AutoScheduler:
|
|||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
target_time = datetime.strptime(
|
|
||||||
self.config_manager.get_auto_analysis_time(), "%H:%M"
|
|
||||||
).replace(year=now.year, month=now.month, day=now.day)
|
|
||||||
|
|
||||||
# 如果今天的目标时间已过,设置为明天
|
# 获取时间配置列表
|
||||||
if now >= target_time:
|
time_config = self.config_manager.get_auto_analysis_time()
|
||||||
target_time += timedelta(days=1)
|
# 兼容处理:确保是列表
|
||||||
|
if isinstance(time_config, str):
|
||||||
|
time_config = [time_config]
|
||||||
|
|
||||||
|
# 解析所有时间点
|
||||||
|
target_times = []
|
||||||
|
for t_str in time_config:
|
||||||
|
try:
|
||||||
|
t = datetime.strptime(t_str, "%H:%M").replace(
|
||||||
|
year=now.year,
|
||||||
|
month=now.month,
|
||||||
|
day=now.day,
|
||||||
|
second=0,
|
||||||
|
microsecond=0,
|
||||||
|
)
|
||||||
|
target_times.append(t)
|
||||||
|
except ValueError:
|
||||||
|
logger.error(f"时间格式错误: {t_str}, 应为 HH:MM")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not target_times:
|
||||||
|
logger.warning("未配置有效的时间点,使用默认 09:00")
|
||||||
|
target_times = [
|
||||||
|
datetime.now().replace(
|
||||||
|
hour=9, minute=0, second=0, microsecond=0
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
# 排序时间点
|
||||||
|
target_times.sort()
|
||||||
|
|
||||||
|
# 寻找下一个执行时间
|
||||||
|
next_target = None
|
||||||
|
for t in target_times:
|
||||||
|
if t > now:
|
||||||
|
next_target = t
|
||||||
|
break
|
||||||
|
|
||||||
|
# 如果今天的时间点都过了,取明天的第一个时间点
|
||||||
|
if not next_target:
|
||||||
|
next_target = target_times[0] + timedelta(days=1)
|
||||||
|
|
||||||
# 计算等待时间
|
# 计算等待时间
|
||||||
wait_seconds = (target_time - now).total_seconds()
|
wait_seconds = (next_target - now).total_seconds()
|
||||||
logger.info(
|
logger.info(
|
||||||
f"定时分析将在 {target_time.strftime('%Y-%m-%d %H:%M:%S')} 执行,等待 {wait_seconds:.0f} 秒"
|
f"下一次自动分析将在 {next_target.strftime('%Y-%m-%d %H:%M:%S')} 执行,等待 {wait_seconds:.0f} 秒"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 等待到目标时间
|
# 等待到目标时间
|
||||||
@@ -165,25 +202,33 @@ class AutoScheduler:
|
|||||||
|
|
||||||
# 执行自动分析
|
# 执行自动分析
|
||||||
if self.config_manager.get_enable_auto_analysis():
|
if self.config_manager.get_enable_auto_analysis():
|
||||||
# 检查今天是否已经执行过,防止重复执行
|
# 检查此具体时间点是否已执行过,防止重复执行
|
||||||
if self.last_execution_date == target_time.date():
|
# 使用精确到分钟的时间戳作为唯一标识
|
||||||
logger.info(
|
target_key = next_target.strftime("%Y-%m-%d %H:%M")
|
||||||
f"今天 {target_time.date()} 已经执行过自动分析,跳过执行"
|
|
||||||
)
|
if self.last_executed_target == target_key:
|
||||||
# 等待到明天再检查
|
logger.info(f"时间点 {target_key} 已经执行过自动分析,跳过")
|
||||||
await asyncio.sleep(3600) # 等待1小时后再检查
|
# 等待一小段时间,避免紧接着的循环再次触发(虽然逻辑上应该取下一个时间了)
|
||||||
|
await asyncio.sleep(60)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
logger.info("开始执行定时分析")
|
logger.info(f"开始执行定时分析 ({target_key})")
|
||||||
await self._run_auto_analysis()
|
await self._run_auto_analysis()
|
||||||
self.last_execution_date = target_time.date() # 记录执行日期
|
|
||||||
|
self.last_executed_target = target_key # 记录执行的具体时间点
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"定时分析执行完成,记录执行日期: {self.last_execution_date}"
|
f"定时分析执行完成,记录执行时间点: {self.last_executed_target}"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logger.info("自动分析已禁用,跳过执行")
|
logger.info("自动分析已禁用,跳过执行")
|
||||||
break
|
# 禁用后虽然跳过执行,但也需要sleep避免死循环占用CPU,通常start/stop会控制task的存活
|
||||||
|
# 这里sleep多久都行,因为会被stop_scheduler取消
|
||||||
|
await asyncio.sleep(60)
|
||||||
|
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
logger.info("定时任务调度器被取消")
|
||||||
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"定时任务调度器错误: {e}")
|
logger.error(f"定时任务调度器错误: {e}")
|
||||||
# 等待5分钟后重试
|
# 等待5分钟后重试
|
||||||
|
|||||||
Reference in New Issue
Block a user