feat(value_rank): 文本消息统一80秒自动撤回

- 新增文本发送封装,身价插件所有文本回复统一登记自动撤回

- 撤回时长默认80秒,可通过 text_auto_revoke_seconds 配置调整

- 社交关系图图片发送保持不撤回,仅文本消息执行撤回策略
This commit is contained in:
liuwei
2026-04-21 14:45:50 +08:00
parent 7d82557699
commit cfae6cfe30
2 changed files with 47 additions and 13 deletions

View File

@@ -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

View File

@@ -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 [