使用discord.py开发Discord机器人,斜杠命令无法同步至内置命令助手
问题:Discord.py 斜杠命令无法显示在命令提示弹窗中
我正在使用discord.py库开发Python版Discord机器人,希望slash commands(斜杠命令)能在用户开始输入斜杠命令时,显示在Discord的命令提示弹窗中。据我了解,目前有两种实现方式:interactions库或discord.ext.commands包。但现在切换到interactions库有一定难度,且我不确定这能否解决我的问题。除了命令无法显示在提示窗中,以下代码功能正常(尽管不够美观)。请问我缺少什么配置才能让机器人与命令助手正确同步?
## Import statements import configparser from discord.ext import commands import discord import typing from dataclasses import dataclass, field #Load in config file/config settings config = configparser.RawConfigParser() try: config.read('config.properties') except: print("Failed to read config.properties - Make sure the file exists") exit #Dataclass of a User which we will store in a queue @dataclass class User: social_name: str = "" alt_name: str = "" username: str = "" discord_user_id: int = 0 @dataclass class Queue: name: str = "" rate: int = 1 vc_optional: bool = True vc_id: int = 0 users_at_bat: list[User] = field(default_factory=list) user_list: list[User] = field(default_factory=list) locked: bool = False ACTIVE_QUEUES = list() def getActiveQueuesList(): return [q.name for q in ACTIVE_QUEUES] def getQueuesString(): queues = "<Type: None>" if len(ACTIVE_QUEUES) > 0: queues = ACTIVE_QUEUES[0].name if len(ACTIVE_QUEUES) > 1: for q in ACTIVE_QUEUES[1::]: queues.append(", " + q.name) return queues def insertUserIntoQueue(queueName, user): success = False for q in ACTIVE_QUEUES: if q.name == queueName: success = True q.user_list.append(user) return success #Starting the discord bot bot = commands.Bot(command_prefix=".", intents=discord.Intents.all()) @bot.listen('on_ready') async def on_ready(): print("Hello! Chromes Py-Bot is ready!") channel = bot.get_channel(int(config.get('Discord', 'BOT_LOG_ID'))) await channel.send("Hello! Chromes Py-Bot is ready!") @bot.command( name="ping", description="Ping command" ) async def ping(ctx): await ctx.send("pong!") @bot.command( name="helpme", description="not gonna help ya btw" ) async def helpme(ctx): await ctx.send("no") @bot.command( name="getQueues", description="Get the queues locked or not" ) async def getQueues(ctx): await ctx.send(f"There are {len(ACTIVE_QUEUES)} active queues: {getQueuesString()}") @bot.command( name="createQueue", description="it's a little on the nose ik" ) async def createQueue(ctx, name: str, rate: typing.Optional[int] = 1, vc_id: typing.Optional[int] = 0, vc_optional: typing.Optional[bool] = True): if name in getActiveQueuesList(): await ctx.send(f"Failed to create queue {name} because a queue already exists with that name.") return queue = Queue(name, rate, vc_optional, vc_id) ACTIVE_QUEUES.append(queue) await ctx.send(f"Created queue: {queue.name}") @bot.command( name="deleteQueue", description="deletes the queue based on the name you put in" ) async def deleteQueue(ctx, name): for q in ACTIVE_QUEUES[::-1]: if q.name == name: ACTIVE_QUEUES.remove(q) await ctx.send(f"There are now {len(ACTIVE_QUEUES)} active queues: {getQueuesString()}") @bot.command( name="joinQueue", description="joins the author into the specified queue" ) async def joinQueue(ctx, queue: str, username: typing.Optional[str] = ""): author = ctx.author alt_name = "" if author.nick is not None: alt_name = author.nick user = User(author.display_name, alt_name, username, author.id) if insertUserIntoQueue(queue, user): await ctx.send(str(user) + " added to the queue: " + queue) else: await ctx.send(str(user) + " failed to be added to the queue: " + queue) bot.run(config.get('Discord', 'BOT_TOKEN'))
解决方案
你当前用的@bot.command()是前缀触发命令(比如.ping),并非Discord官方的斜杠命令。要让命令出现在斜杠提示弹窗里,需要使用discord.py原生支持的应用命令(Application Commands),步骤如下:
1. 替换命令装饰器与交互逻辑
把所有@bot.command()替换为@bot.tree.command(),同时修改命令的参数与回复方式:
- 原来的
ctx参数要换成discord.Interaction对象 - 回复消息需用
await interaction.response.send_message(),而不是ctx.send()
示例:修改ping命令
@bot.tree.command(name="ping", description="Ping command") async def ping(interaction: discord.Interaction): await interaction.response.send_message("pong!")
2. 同步命令到Discord服务器
必须将命令同步到Discord的命令列表,弹窗才会显示。在on_ready事件中添加同步代码:
- 服务器同步:即时生效,适合开发测试,需要在配置文件中添加服务器ID
- 全局同步:生效时间约1小时,适合正式发布,有速率限制
修改后的on_ready示例:
@bot.listen('on_ready') async def on_ready(): print("Hello! Chromes Py-Bot is ready!") # 同步到指定服务器(替换为你的服务器ID,需在config.properties中添加GUILD_ID字段) guild_id = int(config.get('Discord', 'GUILD_ID')) guild = discord.Object(id=guild_id) # 将全局命令复制到指定服务器 bot.tree.copy_global_to(guild=guild) # 执行同步 await bot.tree.sync(guild=guild) # 如果需要全局同步,注释上面三行,使用下面一行 # await bot.tree.sync() channel = bot.get_channel(int(config.get('Discord', 'BOT_LOG_ID'))) await channel.send("Hello! Chromes Py-Bot is ready! 斜杠命令已同步!")
3. 处理带参数的命令
对于带参数的命令(比如createQueue),直接保留参数定义即可,discord.py会自动适配为斜杠命令的选项:
@bot.tree.command(name="createqueue", description="创建一个新队列") async def create_queue(interaction: discord.Interaction, name: str, rate: typing.Optional[int] = 1, vc_id: typing.Optional[int] = 0, vc_optional: typing.Optional[bool] = True): if name in getActiveQueuesList(): await interaction.response.send_message(f"创建队列失败:{name} 已存在") return queue = Queue(name, rate, vc_optional, vc_id) ACTIVE_QUEUES.append(queue) await interaction.response.send_message(f"已创建队列:{queue.name}")
4. 权限检查
确保机器人在Discord开发者门户的OAuth2设置中,勾选了applications.commands权限,重新邀请机器人到服务器时需要包含该权限。
内容的提问来源于stack exchange,提问作者PlatPlayZ
相关产品推荐
相关产品推荐

