Discord机器人按钮/选择菜单:能否让主逻辑等待用户选择结果?
Discord.py选择菜单等待用户输入并传递结果到主流程的实现方案
完全可行,你可以通过自定义View类结合异步等待机制,实现等待用户选择后将结果传递到主逻辑中执行后续操作,避免回调嵌套或循环刷屏的问题。
修正后的完整代码
import os import asyncio from discord.ext import commands import discord class CharacterSelectView(discord.ui.View): def __init__(self, choices): super().__init__(timeout=60) # 设置60秒超时,防止无限等待 self.result = None # 创建角色选择菜单 select_menu = discord.ui.Select(placeholder="请选择一个角色") for char in choices: select_menu.options.append( discord.SelectOption(label=char['name'], description=char['unit']) ) select_menu.callback = self.on_selection_made self.add_item(select_menu) async def on_selection_made(self, interaction: discord.Interaction): # 记录用户选择的结果 self.result = interaction.values[0] # 给用户发送确认消息(仅用户可见) await interaction.response.send_message(f"已选择:{self.result}", ephemeral=True) # 停止View,触发等待结束 self.stop() async def get_result(self): # 等待用户交互完成或超时 await self.wait() return self.result TOKEN = '{bot_token}' prefix = "!" client = commands.Bot(command_prefix=prefix, case_insensitive=True) test_case = [{"name" : "John", "unit" : "Fighter"}, {"name" : "Filip", "unit" : "Monk"}] @client.event async def on_ready(): print(f"We have logged in as {client.user}") @client.event async def on_message(message): if not message.author.bot: # 创建选择菜单视图 select_view = CharacterSelectView(test_case) # 发送菜单消息 await message.channel.send(content="请选择一个角色", view=select_view) # 等待用户选择,获取结果 user_choice = await select_view.get_result() # 主流程中处理选择结果 if user_choice: print(f"用户选择了:{user_choice}") # 这里可以添加后续逻辑,比如根据选择发送不同内容 if user_choice == "John": await message.channel.send("你挑选了战士John,准备好战斗了吗?") elif user_choice == "Filip": await message.channel.send("武僧Filip加入队伍,精通近战技巧!") else: print("用户未在超时内选择") await message.channel.send("选择超时,请重新发起指令") # 必须调用此方法处理其他命令 await client.process_commands(message) client.run(TOKEN)
核心实现要点
- 自定义View封装逻辑:将选择菜单和结果存储、等待逻辑封装到
CharacterSelectView中,代码更模块化。 - 异步等待机制:通过
await self.wait()阻塞主流程,直到用户完成选择或超时,解决了原代码不等待就继续执行的问题。 - 超时处理:初始化View时设置
timeout参数,避免无限等待用户输入,超时后result为None,可以在主流程中处理超时场景。 - 回调停止View:用户选择后调用
self.stop()结束等待,让主流程继续执行后续操作,无需在回调中嵌套业务逻辑。
原代码的问题说明
- 原
Select_character类的callback返回值无效:discord.py的回调函数不处理返回值,无法将结果传递到主流程。 - 原
on_message中直接打印choice_made会立即执行:没有等待用户选择,且变量未定义,会引发错误。 - while循环刷屏:循环中重复发送消息而不是等待交互,导致频繁刷屏,而上述方案通过异步等待避免了这个问题。
内容的提问来源于stack exchange,提问作者Aceinfurno
相关产品推荐
相关产品推荐

