You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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)遍历的是用户的私信历史,而非服务器频道内的消息。用户发送的命令消息是在服务器频道里,所以这段代码根本找不到要删除的目标,自然无法执行删除操作。

修复步骤

  1. 修改删除逻辑,遍历服务器频道消息
    需要遍历用户所在服务器的文本频道,查找该用户发送的命令消息以及机器人对应的回复。修改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)
    
  2. 确保机器人拥有足够权限
    检查机器人角色是否开启以下权限:

    • 读取消息历史(Read Message History)
    • 管理消息(Manage Messages)
      缺少权限会导致无法遍历或删除消息。
  3. 优化效率(可选)
    如果只需要处理用户触发禁言时的最近消息,可以在check_command_limit方法中记录用户发送命令的频道,直接针对该频道执行删除操作,无需遍历所有频道。

内容的提问来源于stack exchange,提问作者Blake Word

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 08:37:48