优化定时订阅内容
This commit is contained in:
@@ -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.robot_cmd.robot_command import Feature, PermissionStatus, GroupBotManager
|
||||||
from utils.decorator.points_decorator import plugin_points_cost
|
from utils.decorator.points_decorator import plugin_points_cost
|
||||||
from wechat_ipad import WechatAPIClient
|
from wechat_ipad import WechatAPIClient
|
||||||
|
from utils.decorator.async_job import async_job
|
||||||
|
|
||||||
|
|
||||||
# ================= Redis 管理器 =================
|
# ================= Redis 管理器 =================
|
||||||
@@ -113,8 +114,9 @@ class WeatherPlugin(MessagePluginInterface):
|
|||||||
self.feature = self.register_feature()
|
self.feature = self.register_feature()
|
||||||
self.redis_manager = None
|
self.redis_manager = None
|
||||||
self._config = {}
|
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:
|
def initialize(self, context: Dict[str, Any]) -> bool:
|
||||||
"""初始化"""
|
"""初始化"""
|
||||||
@@ -136,14 +138,11 @@ class WeatherPlugin(MessagePluginInterface):
|
|||||||
def start(self) -> bool:
|
def start(self) -> bool:
|
||||||
self.LOG.info(f"[{self.name}] 插件已启动")
|
self.LOG.info(f"[{self.name}] 插件已启动")
|
||||||
self.status = PluginStatus.RUNNING
|
self.status = PluginStatus.RUNNING
|
||||||
self.task = asyncio.create_task(self._daily_scheduler())
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def stop(self) -> bool:
|
def stop(self) -> bool:
|
||||||
self.LOG.info(f"[{self.name}] 插件已停止")
|
self.LOG.info(f"[{self.name}] 插件已停止")
|
||||||
self.status = PluginStatus.STOPPED
|
self.status = PluginStatus.STOPPED
|
||||||
if self.task:
|
|
||||||
self.task.cancel()
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def can_process(self, message: Dict[str, Any]) -> bool:
|
def can_process(self, message: Dict[str, Any]) -> bool:
|
||||||
@@ -160,9 +159,7 @@ class WeatherPlugin(MessagePluginInterface):
|
|||||||
sender = message.get("sender")
|
sender = message.get("sender")
|
||||||
roomid = message.get("roomid", "")
|
roomid = message.get("roomid", "")
|
||||||
gbm: GroupBotManager = message.get("gbm")
|
gbm: GroupBotManager = message.get("gbm")
|
||||||
bot: WechatAPIClient = message.get("bot")
|
self.bot: WechatAPIClient = message.get("bot")
|
||||||
|
|
||||||
if not self.bot_client: self.bot_client = bot
|
|
||||||
|
|
||||||
if roomid and gbm.get_group_permission(roomid, self.feature) == PermissionStatus.DISABLED:
|
if roomid and gbm.get_group_permission(roomid, self.feature) == PermissionStatus.DISABLED:
|
||||||
return False, "没有权限"
|
return False, "没有权限"
|
||||||
@@ -202,7 +199,7 @@ class WeatherPlugin(MessagePluginInterface):
|
|||||||
|
|
||||||
# 反馈时告诉用户标准名
|
# 反馈时告诉用户标准名
|
||||||
msg = f"✅ 订阅成功!\n已锁定城市:{city_info['adm1']} - {std_city_name}\n每天 08:00 推送早报。"
|
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: 顺便存历史 (用于明天对比)
|
# Step C: 顺便存历史 (用于明天对比)
|
||||||
# 使用 ID 获取天气,避免再次 Geo 查询
|
# 使用 ID 获取天气,避免再次 Geo 查询
|
||||||
@@ -217,7 +214,7 @@ class WeatherPlugin(MessagePluginInterface):
|
|||||||
if not self.redis_manager: return False, "数据库不可用"
|
if not self.redis_manager: return False, "数据库不可用"
|
||||||
unique_id = f"{roomid}_{sender}" if roomid else f"private_{sender}"
|
unique_id = f"{roomid}_{sender}" if roomid else f"private_{sender}"
|
||||||
self.redis_manager.remove_subscription(unique_id)
|
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, "取消成功"
|
return True, "取消成功"
|
||||||
|
|
||||||
# 3. 普通查询 (保持原逻辑,但也建议先 lookup 再查,或者复用 lookup)
|
# 3. 普通查询 (保持原逻辑,但也建议先 lookup 再查,或者复用 lookup)
|
||||||
@@ -230,35 +227,12 @@ class WeatherPlugin(MessagePluginInterface):
|
|||||||
weather_text = await self._get_weather_text_response(input_city)
|
weather_text = await self._get_weather_text_response(input_city)
|
||||||
if not weather_text: return False, "查询失败"
|
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, "发送成功"
|
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):
|
async def _execute_daily_push(self):
|
||||||
"""执行全量推送 (基于 ID 聚合)"""
|
"""执行全量推送 (基于 ID 聚合)"""
|
||||||
@@ -305,9 +279,9 @@ class WeatherPlugin(MessagePluginInterface):
|
|||||||
|
|
||||||
await asyncio.sleep(0.5)
|
await asyncio.sleep(0.5)
|
||||||
try:
|
try:
|
||||||
if self.bot_client:
|
if self.bot:
|
||||||
await self.bot_client.send_text_message(target_id, final_msg,
|
await self.bot.send_at_message(target_id, final_msg,
|
||||||
sender_id if room_id else None)
|
[sender_id])
|
||||||
except Exception as send_e:
|
except Exception as send_e:
|
||||||
self.LOG.error(f"推送给 {target_id} 失败: {send_e}")
|
self.LOG.error(f"推送给 {target_id} 失败: {send_e}")
|
||||||
|
|
||||||
@@ -448,7 +422,7 @@ class WeatherPlugin(MessagePluginInterface):
|
|||||||
sunrise = data.get('sunrise', '-')
|
sunrise = data.get('sunrise', '-')
|
||||||
sunset = data.get('sunset', '-')
|
sunset = data.get('sunset', '-')
|
||||||
moon_phase = data.get('moonPhase', '')
|
moon_phase = data.get('moonPhase', '')
|
||||||
moon_icon = data.get('moonPhaseIcon', '') # 假设API有这个,或者直接用 phase
|
moon_icon = data.get('moonPhaseIcon', '') # 假设API有这个,或者直接用 phase
|
||||||
|
|
||||||
stats = []
|
stats = []
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user