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

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()结束等待,让主流程继续执行后续操作,无需在回调中嵌套业务逻辑。

原代码的问题说明

  1. 原Select_character类的callback返回值无效:discord.py的回调函数不处理返回值,无法将结果传递到主流程。
  2. 原on_message中直接打印choice_made会立即执行:没有等待用户选择,且变量未定义,会引发错误。
  3. while循环刷屏:循环中重复发送消息而不是等待交互,导致频繁刷屏,而上述方案通过异步等待避免了这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 21:48:18