import asyncio from typing import Optional, Dict, Any from nonebot import get_driver, get_plugin_config, logger from nonebot.adapters.onebot.v11 import Bot from nonebot.plugin import PluginMetadata from nonebot.exception import MockApiException from nonebot.adapters import Bot from nonebot.typing import T_State from .config import Config # 插件元信息 __plugin_meta__ = PluginMetadata( name="auto_recall", description="一个通用的消息撤回插件,监控所有发出的消息并在指定时间后撤回", usage="无需手动调用,插件会自动监控并撤回消息", config=Config, ) # 获取插件配置 plugin_config = get_plugin_config(Config) # 注册 API 调用后钩子 @Bot.on_called_api async def handle_api_result( bot: Bot, exception: Optional[Exception], api: str, data: Dict[str, Any], result: Any ): """拦截 send_msg API 调用,监控发出的消息""" if api != "send_msg" or exception: return # 获取消息 ID message_id = result.get("message_id") if not message_id: logger.warning("未找到 message_id,无法撤回消息") return # 获取撤回延迟时间 recall_delay = plugin_config.recall_delay # 启动异步任务,延迟撤回消息 asyncio.create_task(recall_message_after_delay(bot, message_id, recall_delay)) async def recall_message_after_delay(bot: Bot, message_id: int, delay: int): """在指定时间后撤回消息""" await asyncio.sleep(delay) # 等待指定时间 try: await bot.delete_msg(message_id=message_id) # 撤回消息 except Exception as e: if "success" in str(e).lower() or "timeout" in str(e).lower(): # 忽略成功和超时的错误 return logger.error(f"撤回消息失败: {str(e)}")