优化定时订阅内容

This commit is contained in:
liuwei
2025-12-17 13:56:52 +08:00
parent 5ed8f48afc
commit 4bf44a5592

View File

@@ -13,6 +13,7 @@ from utils.decorator.plugin_decorators import plugin_stats_decorator
from utils.robot_cmd.robot_command import Feature, PermissionStatus, GroupBotManager
from utils.decorator.points_decorator import plugin_points_cost
from wechat_ipad import WechatAPIClient
from utils.decorator.async_job import async_job
# ================= Redis 管理器 =================
@@ -113,8 +114,9 @@ class WeatherPlugin(MessagePluginInterface):
self.feature = self.register_feature()
self.redis_manager = None
self._config = {}
self.bot_client = None
self.task = None
# 使用统一的异步定时任务系统,避免手写休眠循环
async_job.at_times(["08:00"])(self._execute_daily_push)
self.bot: WechatAPIClient = None
def initialize(self, context: Dict[str, Any]) -> bool:
"""初始化"""
@@ -136,14 +138,11 @@ class WeatherPlugin(MessagePluginInterface):
def start(self) -> bool:
self.LOG.info(f"[{self.name}] 插件已启动")
self.status = PluginStatus.RUNNING
self.task = asyncio.create_task(self._daily_scheduler())
return True
def stop(self) -> bool:
self.LOG.info(f"[{self.name}] 插件已停止")
self.status = PluginStatus.STOPPED
if self.task:
self.task.cancel()
return True
def can_process(self, message: Dict[str, Any]) -> bool:
@@ -160,9 +159,7 @@ class WeatherPlugin(MessagePluginInterface):
sender = message.get("sender")
roomid = message.get("roomid", "")
gbm: GroupBotManager = message.get("gbm")
bot: WechatAPIClient = message.get("bot")
if not self.bot_client: self.bot_client = bot
self.bot: WechatAPIClient = message.get("bot")
if roomid and gbm.get_group_permission(roomid, self.feature) == PermissionStatus.DISABLED:
return False, "没有权限"
@@ -202,7 +199,7 @@ class WeatherPlugin(MessagePluginInterface):
# 反馈时告诉用户标准名
msg = f"✅ 订阅成功!\n已锁定城市:{city_info['adm1']} - {std_city_name}\n每天 08:00 推送早报。"
await bot.send_text_message(roomid or sender, msg, sender)
await self.bot.send_text_message(roomid or sender, msg, sender)
# Step C: 顺便存历史 (用于明天对比)
# 使用 ID 获取天气,避免再次 Geo 查询
@@ -217,7 +214,7 @@ class WeatherPlugin(MessagePluginInterface):
if not self.redis_manager: return False, "数据库不可用"
unique_id = f"{roomid}_{sender}" if roomid else f"private_{sender}"
self.redis_manager.remove_subscription(unique_id)
await bot.send_text_message(roomid or sender, "✅ 已取消天气订阅。", sender)
await self.bot.send_text_message(roomid or sender, "✅ 已取消天气订阅。", sender)
return True, "取消成功"
# 3. 普通查询 (保持原逻辑,但也建议先 lookup 再查,或者复用 lookup)
@@ -230,35 +227,12 @@ class WeatherPlugin(MessagePluginInterface):
weather_text = await self._get_weather_text_response(input_city)
if not weather_text: return False, "查询失败"
await bot.send_text_message(roomid or sender, weather_text, sender)
await self.bot.send_text_message(roomid or sender, weather_text, sender)
return True, "发送成功"
# ================= 定时任务系统 =================
async def _daily_scheduler(self):
"""每日 08:00 调度器"""
self.LOG.info("⏰ 天气订阅定时任务已启动...")
while self.status == PluginStatus.RUNNING:
try:
now = datetime.datetime.now()
target_time = now.replace(hour=8, minute=0, second=0, microsecond=0)
if now > target_time:
target_time += datetime.timedelta(days=1)
wait_seconds = (target_time - now).total_seconds()
self.LOG.info(f"⏳ 下一次天气推送将在 {wait_seconds:.0f} 秒后")
await asyncio.sleep(wait_seconds)
if self.bot_client and self.redis_manager:
await self._execute_daily_push()
await asyncio.sleep(60)
except asyncio.CancelledError:
break
except Exception as e:
self.LOG.error(f"定时任务异常: {e}")
await asyncio.sleep(60)
async def _execute_daily_push(self):
"""执行全量推送 (基于 ID 聚合)"""
@@ -305,9 +279,9 @@ class WeatherPlugin(MessagePluginInterface):
await asyncio.sleep(0.5)
try:
if self.bot_client:
await self.bot_client.send_text_message(target_id, final_msg,
sender_id if room_id else None)
if self.bot:
await self.bot.send_at_message(target_id, final_msg,
[sender_id])
except Exception as send_e:
self.LOG.error(f"推送给 {target_id} 失败: {send_e}")
@@ -448,7 +422,7 @@ class WeatherPlugin(MessagePluginInterface):
sunrise = data.get('sunrise', '-')
sunset = data.get('sunset', '-')
moon_phase = data.get('moonPhase', '')
moon_icon = data.get('moonPhaseIcon', '') # 假设API有这个或者直接用 phase
moon_icon = data.get('moonPhaseIcon', '') # 假设API有这个或者直接用 phase
stats = []