如何将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")
关键改造点
- 预填选项实现:通过
app_commands.choices定义下拉选项,用户输入斜杠命令时会自动弹出预填弹窗,无需手动输入字符串。 - 斜杠命令上下文:使用
discord.Interaction替代原前缀命令的ctx,所有交互操作需遵循Discord的3秒响应超时规则。 - 权限控制:保留
app_commands.checks.has_permissions确保仅管理员可使用命令。 - 交互响应优化:根据是否有等级变更,分别发送公开通知或私有通知,同时处理DM发送失败的异常情况。
内容的提问来源于stack exchange,提问作者Barut
相关产品推荐
相关产品推荐

