Py-Cord中dmuser命令重复执行3次,为何发送3次DM并记录?
Py-Cord命令重复执行3次的排查方案
问题描述
我编写了一个Py-Cord命令,用于匿名向用户发送私信并记录交互,但该命令会重复执行3次——发送3条私信、生成3条记录,而预期应该仅执行一次。代码如下:
@bot.command(name="dmuser", description="Send an anonymous DM to a user") @guild_only() async def dmuser(ctx, user: discord.Option(discord.Member, "Who to send the DM to?"), msg): if ctx.author.id in blocked_users_dmuser: await ctx.respond("Hm, it seems like you don't have permission to run this. Please contact TheMineCommander#5367 or use /support if you believe this is an error.", ephemeral=True) return elif user not in ctx.guild.members: await ctx.respond("This user is not in your guild.", ephemeral=True) return else: dmchannel = await bot.create_dm(user) uuid = random.choices(string.ascii_lowercase + string.digits, k=20) uuid = ''.join(uuid) msg = msg.replace("\n", "\n") await dmchannel.send(f"You got an anonymous DM from **{ctx.guild}**!\n--\n```\n{msg}\n```\n--\nIf you would like to report this message, please contact TheMineCommander#5367.\nThe message UUID is `{uuid}`.") async with aiohttp.ClientSession() as session: webhook = discord.Webhook.from_url('https://discord.com/api/webhooks/1091580748131217519/URL CUT OUT FOR SECURITY', session=session) await webhook.send(f"Author: {ctx.author.id}, {ctx.author.name}\nFrom server: {ctx.guild.name}, {ctx.guild.id}\nRecipient: {user},\nUUID: {uuid}\n\n\n```\n{msg}\n```") await ctx.respond("Sent DM!", ephemeral=True)
可能的原因及解决办法
- 命令重复注册:检查代码是否多次加载了该命令(比如同一个文件被重复import,或者
bot.start()被调用了多次)。Py-Cord会为每个注册的命令实例触发一次执行,重复注册直接导致多次执行。解决:确保命令只被注册一次,bot.start()只调用一次。 - Discord API重试机制:网络波动时,Discord可能会多次发送命令触发的事件,导致bot重复响应。解决:添加幂等性校验——比如用
ctx.interaction.id作为唯一标识,维护一个已处理请求的集合,执行前先检查该ID是否已经处理过,避免重复执行。 - 多Bot实例:确认代码只初始化了一个
Bot对象,如果不小心创建了多个实例并启动,每个实例都会响应命令。解决:全局只保留一个bot实例,检查代码中是否有重复初始化的逻辑。 - 热重载工具干扰:如果使用了热重载工具(比如
discord.ext.commands.reload),可能会导致命令被重复注册。解决:关闭热重载,重启bot后测试。
临时修复示例(添加幂等校验)
可以在命令开头加入简单的幂等校验,避免重复执行:
# 全局维护已处理的请求ID集合(重启后清空,长期可用数据库/Redis替代) processed_interactions = set() @bot.command(name="dmuser", description="Send an anonymous DM to a user") @guild_only() async def dmuser(ctx, user: discord.Option(discord.Member, "Who to send the DM to?"), msg): # 校验是否已处理过该请求 if ctx.interaction.id in processed_interactions: return processed_interactions.add(ctx.interaction.id) # 原有的命令逻辑...
内容的提问来源于stack exchange,提问作者TheMineCommander
相关产品推荐
相关产品推荐

