Discord.py中等待用户输入时如何阻止命令误触发及误存?
问题解决方案
整体逻辑拆分两个核心校验环节,覆盖你遇到的两类问题:
1. 为wait_for添加消息校验规则,过滤无效输入
原有写法未做任何消息筛选,等待阶段收到的所有消息都会被存入msg,包括用户发送的带命令前缀的指令。需要传入自定义check函数,仅接收符合规则的消息:
- 消息发送者必须是触发当前命令的原用户,避免其他用户的消息被误收
- 消息必须发送在触发命令的同一频道内,杜绝跨频道消息干扰
- 消息内容不能匹配Bot的命令前缀规则,直接将所有指令类消息排除在等待接收范围外
2. 增加交互状态锁,阻止等待类命令被重复触发
使用全局集合存储当前处于命令交互等待阶段的用户ID,每次执行命令前先校验当前用户是否已在等待流程中:如果是就直接给出提示、终止重复触发的逻辑,等待当前交互流程完全结束(无论正常收到输入还是超时)后,再移除用户的状态标记,避免用户同时卡在多个交互流程中。
完整修正代码示例
from discord.ext import commands # Bot初始化配置与原代码保持一致 client = commands.Bot(command_prefix = '!c ', case_insensitive=True) # 记录处于交互等待状态的用户ID集合 pending_users = set() @client.command() async def YourName(ctx): # 校验用户是否已在待交互队列中,拦截重复触发 if ctx.author.id in pending_users: await ctx.send("你当前还有未完成的输入流程,请先完成上一步操作哦~") return # 将当前用户加入待交互集合,加状态锁 pending_users.add(ctx.author.id) try: await ctx.send('Enter name: ') # 定义wait_for的匹配校验规则 def check(msg): return ( # 消息发送者为原命令触发人 msg.author == ctx.author # 消息发送在原触发频道 and msg.channel == ctx.channel # 消息内容不是带命令前缀的指令 and not msg.content.startswith(client.command_prefix) ) # 带校验规则的wait_for,可自行设置超时时间避免永久阻塞 msg = await client.wait_for("message", check=check, timeout=30) # 此处可追加收到合法输入后的业务逻辑 await ctx.send(f"已记录你的名称:{msg.content}") except TimeoutError: await ctx.send("等待输入超时,请重新触发命令。") # 无论流程正常结束还是超时,都释放用户的状态锁 finally: pending_users.discard(ctx.author.id)
最终运行效果
- 等待输入阶段用户发送带
!c前缀的指令时,会因不满足check规则被排除,不会被存入msg变量;这类指令会正常进入Bot的指令解析流程,但重复触发的YourName命令会因状态锁被拦截,直接给出提示而不会新开启等待流程 - 彻底避免命令类消息被误存为交互输入、同一用户同时触发多个等待类交互的问题
内容的提问来源于stack exchange,提问作者Daniel Tran
相关产品推荐
相关产品推荐

