重构:新增定时插件业务逻辑内聚到各自插件目录

- daily_news 插件内置百度新闻与60s图片获取逻辑,移除对 base.func_news 的业务依赖\n- epic_free 插件内置周五判断与免费游戏抓取逻辑,移除对 base.func_epic 的业务依赖\n- daily_ranking 插件内置排行生成与积分奖励逻辑,不再依赖 MessageStorage 业务封装\n- sehuatang_push 改为引用插件目录内的抓取与PDF生成实现,将核心业务代码迁入插件目录\n- 确保新插件可独立承载自身业务逻辑,平台层仅提供调度与基础设施能力
This commit is contained in:
liuwei
2026-04-16 16:16:07 +08:00
parent 547c5533d7
commit bb73d07809
6 changed files with 717 additions and 16 deletions

View File

@@ -1,10 +1,13 @@
# -*- coding: utf-8 -*-
from datetime import datetime, timedelta
from typing import Any, Dict, List, Optional, Tuple
from base.plugin_common.message_plugin_interface import MessagePluginInterface
from base.plugin_common.plugin_interface import PluginStatus
from db.message_storage import MessageStorageDB
from db.points_db import PointSource, PointsDBOperator
from utils.robot_cmd.robot_command import GroupBotManager
from utils.wechat.message_to_db import MessageStorage
from utils.wechat.contact_manager import ContactManager
class DailyRankingPlugin(MessagePluginInterface):
@@ -44,11 +47,16 @@ class DailyRankingPlugin(MessagePluginInterface):
def __init__(self):
super().__init__()
self.feature = self.register_feature()
self.message_storage: Optional[MessageStorage] = None
self.message_db: Optional[MessageStorageDB] = None
self.points_db: Optional[PointsDBOperator] = None
def initialize(self, context: Dict[str, Any]) -> bool:
# 与历史系统逻辑保持一致,直接复用 MessageStorage 的排行生成能力。
self.message_storage = MessageStorage()
db_manager = context.get("db_manager")
if db_manager is None:
return False
# 排行业务逻辑下沉到插件内,仅复用 DB Operator 作为数据访问层。
self.message_db = MessageStorageDB(db_manager)
self.points_db = PointsDBOperator(db_manager)
return True
def start(self) -> bool:
@@ -89,8 +97,8 @@ class DailyRankingPlugin(MessagePluginInterface):
}
if not self.bot:
return {"success": False, "summary": "bot 未注入", "detail": {}}
if not self.message_storage:
return {"success": False, "summary": "message_storage 未初始化", "detail": {}}
if not self.message_db or not self.points_db:
return {"success": False, "summary": "排行依赖未初始化", "detail": {}}
target_groups = [str(g).strip() for g in (context.get("target_groups") or []) if str(g).strip()]
if not target_groups:
@@ -105,7 +113,7 @@ class DailyRankingPlugin(MessagePluginInterface):
failed_groups = {}
for gid in target_groups:
try:
ok, text = await self.message_storage.generate_and_send_ranking(gid, {})
ok, text = await self._generate_and_send_ranking(gid)
if ok and text:
await self.bot.send_text_message(gid, text)
success_groups.append(gid)
@@ -121,3 +129,48 @@ class DailyRankingPlugin(MessagePluginInterface):
"failed_groups": failed_groups,
},
}
async def _generate_and_send_ranking(self, group_id: str) -> Tuple[bool, str]:
"""生成并奖励发言排行(插件内实现)。"""
if not self.message_db or not self.points_db:
return False, "排行依赖未初始化"
yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
rows = self.message_db.get_speech_ranking(yesterday, group_id, limit=20)
if not rows:
return False, f"📊 {yesterday} 没有发言记录"
contact_manager = ContactManager.get_instance()
ranking_lines = [f"🏆 {yesterday} 发言排行榜 🏆"]
for rank, row in enumerate(rows, start=1):
wxid = row.get("wx_id")
speech_count = int(row.get("speech_count") or 0)
display_name = contact_manager.get_group_name(group_id, wxid) or wxid
reward = 0
if rank == 1:
reward = 30
ranking_lines.append(f"🥇🐲 {rank}.{display_name}: {speech_count}次 🔥 +{reward}积分")
elif rank == 2:
reward = 20
ranking_lines.append(f"🥈 {rank}.{display_name}: {speech_count}次 ✨ +{reward}积分")
elif rank == 3:
reward = 10
ranking_lines.append(f"🥉 {rank}.{display_name}: {speech_count}次 👏 +{reward}积分")
elif rank <= 10:
reward = 5
ranking_lines.append(f"🌟 {rank}.{display_name}: {speech_count}次 +{reward}积分")
else:
reward = 3
ranking_lines.append(f"👍 {rank}.{display_name}: {speech_count}次 +{reward}积分")
if reward > 0:
self.points_db.add_points(
wxid,
group_id,
reward,
PointSource.OTHER,
f"{yesterday}发言排行第{rank}名奖励",
)
return True, "\n".join(ranking_lines)