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

如何实现基于数据库条目的Slash Command动态Options?

为Discord Slash Command添加基于数据库条目动态变化的选项

需求描述

要给sell命令添加动态选项:用户执行命令时,仅显示其数据库中数量不为空的股票符号作为可选值。例如用户userx的数据库中IMPJ和IMGR的值为“1”和“748”,其余条目为None,执行sell命令时就只显示这两个选项。

尝试的错误代码

@stocks.command(name="sell", description="Sell your stocks")
cursor.execute("SELECT bank, IMAW, IMBG, IMGR, IMPJ, MACB, MAY FROM economy WHERE user_id = %s", (user_id,))
user_data = cursor.fetchone()

choices = []
if user_data:
    bank_balance, imaw_quantity, imbg_quantity, imgr_quantity, impj_quantity, macb_quantity, may_quantity = user_data
    
    quantities = [imaw_quantity, imbg_quantity, imgr_quantity, impj_quantity, macb_quantity, may_quantity]
    items = ["IMAW", "IMBG", "IMGR", "IMPJ", "MACB", "MAY"]

    for quantity, item in zip(quantities, items):
        if quantity:
            choices.append(item)

print(choices)

@option("symbol", description="Choose what stock you want to sell", choices=choices)

错误信息

File "/GIS_Main/Cogs/economy.py",
line 890
cursor.execute("SELECT bank, IMAW, IMBG, IMGR, IMPJ, MACB, MAY FROM economy WHERE user_id = %s", (user_id,))
^
SyntaxError: invalid syntax

错误原因:Python不允许在@x.command()装饰器和命令的async def定义之间直接插入执行代码,装饰器仅用于修饰函数/方法,中间不能放置可执行语句。


解决方案:用自动补全(Autocomplete)实现动态选项

Slash Command的静态choices参数无法在运行时根据用户数据动态更新,必须使用Autocomplete功能来实现需求,具体步骤如下:

1. 编写Autocomplete回调函数

该函数会在用户触发命令时被调用,查询当前用户的数据库数据,返回可用的股票选项:

async def stock_autocomplete(interaction: discord.Interaction, current: str) -> list[app_commands.Choice[str]]:
    # 查询当前用户的股票数据
    cursor.execute("SELECT IMAW, IMBG, IMGR, IMPJ, MACB, MAY FROM economy WHERE user_id = %s", (interaction.user.id,))
    user_data = cursor.fetchone()
    
    choices = []
    if user_data:
        quantities = list(user_data)
        items = ["IMAW", "IMBG", "IMGR", "IMPJ", "MACB", "MAY"]
        
        # 筛选数量不为空且匹配用户输入的股票
        for quantity, item in zip(quantities, items):
            if quantity and item.lower().startswith(current.lower()):
                choices.append(app_commands.Choice(name=item, value=item))
    
    # 最多返回25个选项(Discord的限制)
    return choices[:25]

2. 修改Sell命令定义

在@option装饰器中指定autocomplete参数为上述回调函数,替换原来的静态choices:

@stocks.command(name="sell", description="Sell your stocks")
@app_commands.describe(symbol="Choose what stock you want to sell")
@app_commands.autocomplete(symbol=stock_autocomplete)
async def sell(interaction: discord.Interaction, symbol: str):
    # 这里编写命令的核心逻辑,比如处理股票出售操作
    await interaction.response.send_message(f"你选择出售的股票是:{symbol}")

关键注意事项

  • Autocomplete回调函数必须是异步的,需接收interaction(用于获取当前用户ID)和current(用户当前输入的内容,用于过滤选项)两个参数。
  • 必须返回app_commands.Choice对象列表,每个对象包含name(显示给用户的文本)和value(传递给命令函数的实际值)。
  • 若使用同步数据库驱动,建议用asyncio.to_thread包裹数据库操作,避免阻塞事件循环:
# 在autocomplete函数中修改数据库查询部分
await asyncio.to_thread(
    cursor.execute,
    "SELECT IMAW, IMBG, IMGR, IMPJ, MACB, MAY FROM economy WHERE user_id = %s",
    (interaction.user.id,)
)
user_data = await asyncio.to_thread(cursor.fetchone)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 00:46:03