如何用Python实现Discord用户自动超时后删除机器人与用户消息
问题描述
我设置了触发机制:用户过快重复发送机器人命令时,会被禁言30分钟。同时希望机器人自动删除两类消息:
- 用户发送的垃圾命令消息(如
!help) - 机器人自身的命令回复(如help命令的输出)
以此保持聊天整洁。但日志显示删除方法已执行完成,消息却从未被实际删除,求解决办法。
相关代码
async def timeout_user(self, user): guild = user.guild # 获取禁言角色 timeout_role = discord.utils.get(guild.roles, name="Timeout") # 给用户添加禁言角色 await user.add_roles(timeout_role) # 删除用户的垃圾命令消息 await self.remove_spam_commands(user) # 发送私信通知用户 timeout_message = "因测试外的不当行为被禁言" await user.send(timeout_message) # 在指定频道发送通知 timeout_channel = discord.utils.get(guild.channels, name="testing") if timeout_channel: await timeout_channel.send(f"{user.mention},因测试外的不当行为被禁言") # 30分钟后移除禁言角色 await asyncio.sleep(1800) await user.remove_roles(timeout_role) async def remove_spam_commands(self, user): print("开始删除垃圾命令...") # 调试打印 async for message in user.history(limit=15): if message.content.startswith('!'): await message.delete() print(f"已删除用户 {user.id} 的消息:{message.content}") print("垃圾命令删除完成。") # 调试打印 @commands.Cog.listener() async def on_message(self, message): print("触发on_message事件!") print(f"收到来自 {message.author} 的消息:{message.content}") if message.author.bot: return # 测试:指定用户发消息时的处理 user_id = message.author.id if user_id == QUARTERMASTER_ID: await message.channel.send("这是机器人的测试消息。") await message.delete() print(f"已删除Quartermaster的消息:{message.content}") else: print("消息并非来自Quartermaster。") # 更新用户命令使用次数 user_id = message.author.id await self.check_command_limit(message.author) self.command_limits[user_id]['count'] += 1
日志信息
开始删除垃圾命令... 垃圾命令删除完成。 (因文本敏感,消息输出已移除) 触发on_message事件! (因文本敏感,消息输出已移除) 触发on_message事件!
问题分析与解决方案
核心问题
remove_spam_commands方法中使用user.history(limit=15)遍历的是用户的私信历史,而非服务器频道内的消息。用户发送的命令消息是在服务器频道里,所以这段代码根本找不到要删除的目标,自然无法执行删除操作。
修复步骤
修改删除逻辑,遍历服务器频道消息
需要遍历用户所在服务器的文本频道,查找该用户发送的命令消息以及机器人对应的回复。修改remove_spam_commands方法并传入guild参数:async def remove_spam_commands(self, user, guild): print("开始删除垃圾命令...") # 遍历服务器内所有文本频道 for channel in guild.text_channels: try: # 遍历频道内最近15条消息 async for message in channel.history(limit=15): # 删除用户发送的命令消息 if message.author == user and message.content.startswith('!'): await message.delete() print(f"已删除频道 {channel.name} 中用户 {user.id} 的消息:{message.content}") # 删除机器人对该用户命令的回复 elif message.author.bot: if message.reference and message.reference.message_id: try: referenced_msg = await channel.fetch_message(message.reference.message_id) if referenced_msg.author == user and referenced_msg.content.startswith('!'): await message.delete() print(f"已删除机器人在频道 {channel.name} 的回复:{message.content}") except discord.NotFound: continue except discord.Forbidden: # 无权限操作的频道直接跳过 print(f"无权限操作频道 {channel.name},跳过") continue print("垃圾命令删除完成。")同时在
timeout_user方法中调用时传入guild:await self.remove_spam_commands(user, guild)确保机器人拥有足够权限
检查机器人角色是否开启以下权限:- 读取消息历史(Read Message History)
- 管理消息(Manage Messages)
缺少权限会导致无法遍历或删除消息。
优化效率(可选)
如果只需要处理用户触发禁言时的最近消息,可以在check_command_limit方法中记录用户发送命令的频道,直接针对该频道执行删除操作,无需遍历所有频道。
内容的提问来源于stack exchange,提问作者Blake Word
相关产品推荐
相关产品推荐

