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

如何将Discord.py普通命令转为带预填选项的全局斜杠命令?

将Discord.py前缀命令改造为全局斜杠命令(带预填选项弹窗)

改造说明

基于官方discord.py的app_commands模块实现斜杠命令,通过预定义选项实现下拉弹窗效果,同时保留原业务逻辑。

改造后完整代码

import discord
from discord import app_commands
from discord.ext import commands

# 假设你的bot实例定义如下(根据实际情况调整)
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix="!", intents=intents)

# 全局斜杠命令:编辑用户Raid完成次数
@bot.tree.command(name="edit", description="编辑指定用户的Raid完成次数")
@app_commands.checks.has_permissions(administrator=True)
@app_commands.describe(
    user="需要编辑的用户",
    raid_type="目标Raid类型",
    change="完成次数变更方向"
)
@app_commands.choices(
    raid_type=[
        app_commands.Choice(name="Thaemine", value="Thaemine"),
        app_commands.Choice(name="Voldike", value="Voldike"),
        app_commands.Choice(name="Akkan", value="Akkan"),
        app_commands.Choice(name="Brelshaza", value="Brelshaza"),
        app_commands.Choice(name="Kayangel", value="Kayangel"),
    ],
    change=[
        app_commands.Choice(name="增加1次", value="+1"),
        app_commands.Choice(name="减少1次", value="-1"),
    ]
)
async def edit(interaction: discord.Interaction, user: discord.User, raid_type: app_commands.Choice[str], change: app_commands.Choice[str]):
    # 提取选项的实际值
    raid_type_val = raid_type.value
    change_val = change.value

    # 数据库检查与初始化
    if not get_user(user.id):
        insert_or_update_user(user.id)

    # 获取变更前的用户数据
    user_data_before = get_user(user.id)
    rank_before = None
    if raid_type_val == "Thaemine":
        rank_before = user_data_before[2]
    elif raid_type_val == "Voldike":
        rank_before = user_data_before[4]
    elif raid_type_val == "Akkan":
        rank_before = user_data_before[6]
    elif raid_type_val == "Brelshaza":
        rank_before = user_data_before[8]
    elif raid_type_val == "Kayangel":
        rank_before = user_data_before[10]

    # 更新完成次数
    value = 1 if change_val == "+1" else -1
    update_raid_completion(user.id, raid_type_val, value)

    # 获取变更后的用户数据并更新排名
    user_data_after = get_user(user.id)
    completion = None
    rank_after = None
    if raid_type_val == "Thaemine":
        completion = user_data_after[1]
        update_rank(user.id, raid_type_val, completion)
        rank_after = get_user(user.id)[2]
    elif raid_type_val == "Voldike":
        completion = user_data_after[3]
        update_rank(user.id, raid_type_val, completion)
        rank_after = get_user(user.id)[4]
    elif raid_type_val == "Akkan":
        completion = user_data_after[5]
        update_rank(user.id, raid_type_val, completion)
        rank_after = get_user(user.id)[6]
    elif raid_type_val == "Brelshaza":
        completion = user_data_after[7]
        update_rank(user.id, raid_type_val, completion)
        rank_after = get_user(user.id)[8]
    elif raid_type_val == "Kayangel":
        completion = user_data_after[9]
        update_rank(user.id, raid_type_val, completion)
        rank_after = get_user(user.id)[10]

    # 处理交互响应(必须在3秒内完成)
    if rank_before != rank_after:
        # 排名变更时发送公开通知
        general_channel = discord.utils.get(interaction.guild.channels, name="general")
        await interaction.response.send_message(f'恭喜 {user.mention} 在 {raid_type_val} 中达到**{rank_after}**等级!完成次数:{completion}')
        # 发送DM通知用户
        dm_msg = f'你的 {raid_type_val} 完成次数已{"增加" if change_val == "+1" else "减少"}1次。当前次数:{completion},等级:{rank_after}'
    else:
        # 无排名变更时仅发送私有通知
        await interaction.response.send_message(f'已更新 {user.mention} 的 {raid_type_val} 完成次数,当前次数:{completion}', ephemeral=True)
        dm_msg = f'你的 {raid_type_val} 完成次数已{"增加" if change_val == "+1" else "减少"}1次。当前次数:{completion},等级无变化'

    # 尝试发送DM给用户
    try:
        await user.send(dm_msg)
    except discord.Forbidden:
        await interaction.followup.send(f'无法发送DM给 {user.mention},请检查用户隐私设置', ephemeral=True)

# 命令同步(首次运行需要执行,之后可注释或改为管理员命令)
@bot.event
async def on_ready():
    print(f'已登录为 {bot.user}')
    try:
        synced = await bot.tree.sync()
        print(f'已同步 {len(synced)} 条全局命令')
    except Exception as e:
        print(f'同步命令失败:{e}')

# 可选:管理员手动同步命令的前缀命令
@bot.command()
@commands.has_permissions(administrator=True)
async def sync(ctx):
    synced = await bot.tree.sync()
    await ctx.send(f'已同步 {len(synced)} 条全局命令')

# 替换为你的bot令牌
bot.run("YOUR_BOT_TOKEN")

关键改造点

  1. 预填选项实现:通过app_commands.choices定义下拉选项,用户输入斜杠命令时会自动弹出预填弹窗,无需手动输入字符串。
  2. 斜杠命令上下文:使用discord.Interaction替代原前缀命令的ctx,所有交互操作需遵循Discord的3秒响应超时规则。
  3. 权限控制:保留app_commands.checks.has_permissions确保仅管理员可使用命令。
  4. 交互响应优化:根据是否有等级变更,分别发送公开通知或私有通知,同时处理DM发送失败的异常情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 04:14:53