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

Python 3.x discord.py机器人Purge命令仅测试服可用问题排查

Discord机器人Purge命令跨服务器报错问题排查与修复

问题背景

使用discord.py v2.2.3 + Python 3.11.3开发的Discord机器人,Purge(消息清理)命令在测试服务器运行正常,但在其他服务器仅成功过一两次,现在调用必触发错误提示。

相关代码

clean_message方法

async def clean_message(self, interaction: Interaction, amount: int, check: Callable) -> Any:
        if isinstance((channel := interaction.channel), (CategoryChannel, ForumChannel, PartialMessageable)):
            return
        assert channel is not None
        try:
            msgs = [
                m async for m in channel.history(
                    limit=300,
                    before=Object(id=interaction.id),
                    after=None
                ) if check(m) == True and UTC.localize((datetime.now() - timedelta(days=365))) <= m.created_at  # default 14
            ][:amount]
            await channel.delete_messages(msgs)
        except Exception as e:
            msg = await self.bot.error(
                f"I'm sorry, I am unable to purge messages in **{channel}**!", interaction
            )
            if msg:
                await msg.delete(delay=5)
        else:
            if len(msgs) < 1:
                msg = await self.bot.error(
                    f"No messages found in **{channel}**!", interaction
                )
                if msg:
                    await msg.delete(delay=5)
            else:
                msg = await self.bot.success(
                    f"Succesfully purged **{len(msgs)}** messages from **{channel}**!", interaction
                )
                if msg:
                    await msg.delete(delay=5)

Purge命令调用代码

@app_commands.command(
    name='purge',
    description="Purges messages in channel"
)
@app_commands.default_permissions(manage_messages=True)
@app_commands.describe(
    amount='Amount of messages to purge (Default: 20)',
    user='Only purge messages by user',
    content='Only purge messages by content'
)
async def purge_command(self, interaction: Interaction, amount: Optional[int], user: Optional[User], content: Optional[str]):
    if not amount:
        amount = 20
    if amount < 1:
        return await self.bot.error("Can't purge messages! Amount too small!", interaction)
    if amount > 150:
        return await self.bot.error("Can't purge messages! Amount too Large!", interaction)

    if user == None and content == None:
        def check(x): return x.pinned == False
    else:
        if user != None and content != None:
            def check(x): return x.author.id == user.id and x.content.lower(
            ) == content.lower() and x.pinned == False
        elif user != None and content == None:
            def check(x): return x.author.id == user.id and x.pinned == False
        else:
            assert content is not None
            def check(x): return x.conetent.lower(
            ) == content.lower() and x.pinned == False
    await interaction.response.defer()
    await self.clean_message(
        interaction=interaction,
        amount=amount,
        check=check
    )

问题排查与修复方案

1. 修复拼写错误

在purge_command的最后一个check函数里,x.conetent是拼写错误,应改为x.content。这个错误会直接触发AttributeError,导致命令执行失败。

2. 修正时间判断逻辑

Discord API仅允许删除14天以内的消息,代码中写的365天会导致尝试删除超期消息时触发API错误。同时:

  • datetime.now()获取的是本地时间,而Discord消息的created_at是UTC时间,需改用datetime.utcnow()避免时区偏差
  • 无需使用UTC.localize,utcnow()返回的已是UTC时区的datetime对象

修改后的时间判断条件:

datetime.utcnow() - timedelta(days=14) <= m.created_at

3. 优化异常处理,暴露具体错误

当前异常处理仅返回通用提示,无法得知具体错误原因(如权限不足、消息超期、空列表删除等)。建议在except块中打印错误信息:

except Exception as e:
    print(f"Purge错误详情: {str(e)}")  # 打印错误到控制台
    msg = await self.bot.error(
        f"I'm sorry, I am unable to purge messages in **{channel}**!\n错误详情: {str(e)}", interaction
    )
    if msg:
        await msg.delete(delay=5)

4. 避免删除空消息列表

当没有符合条件的消息时,msgs会是空列表,调用channel.delete_messages(msgs)会触发API错误。需在删除前判断列表是否为空:

if msgs:
    await channel.delete_messages(msgs)
else:
    raise ValueError("没有可删除的消息")

5. 确认机器人权限

确保机器人在目标服务器拥有以下权限:

  • 管理消息(Manage Messages):用于删除消息
  • 查看消息历史(Read Message History):用于获取频道消息历史

6. 优化check函数写法(可选)

合并重复逻辑,让代码更简洁:

def check(x):
    if x.pinned:
        return False
    if user and x.author.id != user.id:
        return False
    if content and x.content.lower() != content.lower():
        return False
    return True

修复后关键代码示例

修正后的purge_command检查函数

else:
    assert content is not None
    def check(x): return x.content.lower() == content.lower() and x.pinned == False

修正后的clean_message时间判断与空列表处理

msgs = [
    m async for m in channel.history(
        limit=300,
        before=Object(id=interaction.id),
        after=None
    ) if check(m) and datetime.utcnow() - timedelta(days=14) <= m.created_at
][:amount]
if msgs:
    await channel.delete_messages(msgs)
else:
    raise ValueError("未找到符合条件的消息")

内容的提问来源于stack exchange,提问作者Frank Austin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 23:12:50