From cfae6cfe30b0fcb1370a2fb8ef1e9766f3bbb6fc Mon Sep 17 00:00:00 2001 From: liuwei Date: Tue, 21 Apr 2026 14:45:50 +0800 Subject: [PATCH] =?UTF-8?q?feat(value=5Frank):=20=E6=96=87=E6=9C=AC?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E7=BB=9F=E4=B8=8080=E7=A7=92=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=92=A4=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增文本发送封装,身价插件所有文本回复统一登记自动撤回 - 撤回时长默认80秒,可通过 text_auto_revoke_seconds 配置调整 - 社交关系图图片发送保持不撤回,仅文本消息执行撤回策略 --- plugins/value_rank/config.toml | 1 + plugins/value_rank/main.py | 59 ++++++++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/plugins/value_rank/config.toml b/plugins/value_rank/config.toml index e0cfea8..58f063f 100644 --- a/plugins/value_rank/config.toml +++ b/plugins/value_rank/config.toml @@ -35,6 +35,7 @@ default_graph_nodes = 12 max_graph_nodes = 24 graph_edge_pool_limit = 300 social_graph_template_path = "plugins/value_rank/templates/social_graph.html" +text_auto_revoke_seconds = 80 default_trend_days = 7 max_trend_days = 30 diff --git a/plugins/value_rank/main.py b/plugins/value_rank/main.py index 4e20f9c..3ece5fd 100644 --- a/plugins/value_rank/main.py +++ b/plugins/value_rank/main.py @@ -15,6 +15,7 @@ from db.base import BaseDBOperator from db.connection import DBConnectionManager from utils.decorator.plugin_decorators import plugin_stats_decorator from utils.markdown_to_image import html_to_image +from utils.revoke.message_auto_revoke import MessageAutoRevoke from utils.robot_cmd.robot_command import PermissionStatus, GroupBotManager from utils.wechat.contact_manager import ContactManager @@ -558,6 +559,7 @@ class ValueRankPlugin(MessagePluginInterface): self.max_graph_nodes = 24 self.graph_edge_pool_limit = 300 self.social_graph_template_path = "plugins/value_rank/templates/social_graph.html" + self.text_auto_revoke_seconds = 80 self.default_trend_days = 7 self.max_trend_days = 30 self.mention_batch_size = 200 @@ -593,6 +595,7 @@ class ValueRankPlugin(MessagePluginInterface): self.social_graph_template_path = str( cfg.get("social_graph_template_path", self.social_graph_template_path) ).strip() + self.text_auto_revoke_seconds = int(cfg.get("text_auto_revoke_seconds", self.text_auto_revoke_seconds)) self.default_trend_days = int(cfg.get("default_trend_days", self.default_trend_days)) self.max_trend_days = int(cfg.get("max_trend_days", self.max_trend_days)) self.mention_batch_size = int(cfg.get("mention_batch_size", self.mention_batch_size)) @@ -639,41 +642,42 @@ class ValueRankPlugin(MessagePluginInterface): roomid = message.get("roomid", "") gbm: GroupBotManager = message.get("gbm") bot = message.get("bot") + revoke: MessageAutoRevoke = message.get("revoke") if roomid and gbm.get_group_permission(roomid, self.feature) == PermissionStatus.DISABLED: return False, "没有权限" if not roomid: - await bot.send_text_message(sender, "该功能仅支持群聊使用。", sender) + await self._send_text_with_auto_revoke(bot, sender, "该功能仅支持群聊使用。", sender, revoke) return True, "非群聊" if command == "我的身价": text = await self._build_my_value_text(roomid, sender) - await bot.send_text_message(roomid, text, sender) + await self._send_text_with_auto_revoke(bot, roomid, text, sender, revoke) return True, "查询成功" if command == "身价排行": limit = self._parse_rank_limit(content) text = await self._build_ranking_text(roomid, limit) - await bot.send_text_message(roomid, text, sender) + await self._send_text_with_auto_revoke(bot, roomid, text, sender, revoke) return True, "查询成功" if command == "社交热度榜": limit = self._parse_rank_limit(content) text = await self._build_social_hot_text(roomid, limit) - await bot.send_text_message(roomid, text, sender) + await self._send_text_with_auto_revoke(bot, roomid, text, sender, revoke) return True, "查询成功" if command == "搭子榜": limit = self._parse_rank_limit(content) text = await self._build_partner_pairs_text(roomid, limit) - await bot.send_text_message(roomid, text, sender) + await self._send_text_with_auto_revoke(bot, roomid, text, sender, revoke) return True, "查询成功" if command == "社交桥梁榜": limit = self._parse_rank_limit(content) text = await self._build_social_bridge_text(roomid, limit) - await bot.send_text_message(roomid, text, sender) + await self._send_text_with_auto_revoke(bot, roomid, text, sender, revoke) return True, "查询成功" if command == "社交关系图": @@ -682,38 +686,67 @@ class ValueRankPlugin(MessagePluginInterface): if image_path: await bot.send_image_message(roomid, Path(image_path)) return True, "查询成功" - await bot.send_text_message(roomid, "📊 近期社交关系数据不足,暂时无法绘制关系图。", sender) + await self._send_text_with_auto_revoke(bot, roomid, "📊 近期社交关系数据不足,暂时无法绘制关系图。", sender, revoke) return True, "数据不足" if command == "我的趋势": days = self._parse_trend_days(content) text = await self._build_my_trend_text(roomid, sender, days) - await bot.send_text_message(roomid, text, sender) + await self._send_text_with_auto_revoke(bot, roomid, text, sender, revoke) return True, "查询成功" if command == "身价周报": text = await self._build_weekly_report_text(roomid) - await bot.send_text_message(roomid, text, sender) + await self._send_text_with_auto_revoke(bot, roomid, text, sender, revoke) return True, "查询成功" if command == "身价说明": - await bot.send_text_message(roomid, self._build_explain_text(), sender) + await self._send_text_with_auto_revoke(bot, roomid, self._build_explain_text(), sender, revoke) return True, "查询成功" if command == "重算身价": # 重算属于管理动作,只允许机器人管理员或群管理员执行,避免被滥用。 if not GroupBotManager.is_admin_for_group(sender, roomid): - await bot.send_text_message(roomid, "仅管理员可执行重算身价。", sender) + await self._send_text_with_auto_revoke(bot, roomid, "仅管理员可执行重算身价。", sender, revoke) return True, "权限不足" stat_date = datetime.now().strftime("%Y-%m-%d") user_count = self._recompute_group_snapshot(roomid, stat_date) - await bot.send_text_message(roomid, f"✅ 重算完成,已更新 {user_count} 名成员。", sender) + await self._send_text_with_auto_revoke(bot, roomid, f"✅ 重算完成,已更新 {user_count} 名成员。", sender, revoke) return True, "重算成功" - await bot.send_text_message(roomid, f"❌命令格式错误\n{self.command_format}", sender) + await self._send_text_with_auto_revoke(bot, roomid, f"❌命令格式错误\n{self.command_format}", sender, revoke) return True, "命令错误" + async def _send_text_with_auto_revoke( + self, + bot: Any, + target: str, + text: str, + sender: str, + revoke: Optional[MessageAutoRevoke], + ) -> None: + """发送文本并自动撤回(仅文本生效,图片不走该逻辑)。 + + 说明: + 1. 业务要求统一文本自动撤回,默认 80 秒; + 2. 若当前上下文无 revoke 能力,则仅发送不撤回,避免影响主流程; + 3. 撤回异常不抛出,防止影响消息主链路。 + """ + client_msg_id, create_time, new_msg_id = await bot.send_text_message(target, text, sender) + if not revoke: + return + try: + revoke.add_message_to_revoke( + target, + client_msg_id, + create_time, + new_msg_id, + max(1, int(self.text_auto_revoke_seconds)), + ) + except Exception as e: + self.LOG.warning(f"[{self.name}] 文本自动撤回登记失败: target={target}, error={e}") + def get_schedule_actions(self) -> List[Dict[str, Any]]: """声明可调度动作:每日重算 + 每周周报。""" return [