Discord.py 2.0 - 获取 HybridCommand 的上下文
Discord.py 2.0 - Getting context for a HybridCommand
我正在尝试编写我的帮助命令的斜杠命令版本,我想检查用户是否可以 运行 命令。
这是我的代码:
@app_commands.command(name="help")
async def help(self, interaction: discord.Interaction, input: str = None):
embed = discord.Embed(title="Test")
cmd = self.bot.get_command(input)
ctx: commands.Context = await self.bot.get_context(interaction)
try:
await cmd.can_run(ctx)
embed.add_field(name="Usable by you:", value="Yes")
except commands.CommandError as exc:
embed.add_field(name="Usable by you:", value=f"No:\n{exc}")
await ctx.send(embed=embed)
现在,如果我想检查普通命令 (commands.Command
),这可以正常工作,但是这不适用于混合命令 (commands.HybridCommand
)。我读到 the docs for bot.get_context
上面写着:
In order for the custom context to be used inside an interaction-based context (such as HybridCommand) then this method must be overridden to return that class.
但是我不确定这到底是什么意思。我如何覆盖它以及我需要什么 class return?
为了完成,这是我尝试在 HybridCommand 上使用它时遇到的错误:
discord.app_commands.errors.CommandInvokeError: Command 'help' raised an exception: AttributeError: '_MissingSentinel' object has no attribute 'guild'
同样,当我在普通命令中使用它时,它工作正常。
如有任何指点,我将不胜感激!
编辑:我的意思的一个例子:
@commands.command()
@commands.has_permissions(administrator=True)
async def test1(self, ctx):
print("Test1")
@commands.hybrid_command()
@commands.has_permissions(administrator=True)
async def test2(self, ctx):
print("Test 2")
如果您输入 /help test1
,它会正常工作,但在 /help test2
时会出错。没有权限检查它似乎也能正常工作。
当前答案
这可以通过在终端中使用 pip install git+https://github.com/rapptz/discord.py
将 discord.py 至少更新为 commit 36f039a1bffb835a555be8a43976397ba6eb9c76
来解决。
过时的答案
说明
似乎 discord.py 有一个错误导致了这个错误。在 _check_can_run
混合命令中,它使用 interaction._baton
作为命令上下文来检查。 interaction._baton
设置为缺失的标记值,因此当 discord.py
尝试像使用常规 Context
对象一样使用它时会出错。
这可以很简单地修补,尽管我不确定是否有任何意外的副作用。只需将 interaction._baton
设置为您刚刚获取的上下文。我已经用两个测试用例对其进行了测试,它们都有效:
代码
@bot.tree.command(name="help", guild=discord.Object(id=703732969160048731))
async def help_command(interaction: discord.Interaction, parameter: str = None):
embed = discord.Embed(title="Test")
cmd = bot.get_command(parameter)
ctx: commands.Context = await bot.get_context(interaction)
interaction._baton = ctx # sketchy, but it works
try:
await cmd.can_run(ctx)
embed.add_field(name="Usable by you:", value="Yes")
except commands.CommandError as exc:
embed.add_field(name="Usable by you:", value=f"No:\n{exc}")
await ctx.send(embed=embed)
我正在尝试编写我的帮助命令的斜杠命令版本,我想检查用户是否可以 运行 命令。
这是我的代码:
@app_commands.command(name="help")
async def help(self, interaction: discord.Interaction, input: str = None):
embed = discord.Embed(title="Test")
cmd = self.bot.get_command(input)
ctx: commands.Context = await self.bot.get_context(interaction)
try:
await cmd.can_run(ctx)
embed.add_field(name="Usable by you:", value="Yes")
except commands.CommandError as exc:
embed.add_field(name="Usable by you:", value=f"No:\n{exc}")
await ctx.send(embed=embed)
现在,如果我想检查普通命令 (commands.Command
),这可以正常工作,但是这不适用于混合命令 (commands.HybridCommand
)。我读到 the docs for bot.get_context
上面写着:
In order for the custom context to be used inside an interaction-based context (such as HybridCommand) then this method must be overridden to return that class.
但是我不确定这到底是什么意思。我如何覆盖它以及我需要什么 class return?
为了完成,这是我尝试在 HybridCommand 上使用它时遇到的错误:
discord.app_commands.errors.CommandInvokeError: Command 'help' raised an exception: AttributeError: '_MissingSentinel' object has no attribute 'guild'
同样,当我在普通命令中使用它时,它工作正常。
如有任何指点,我将不胜感激!
编辑:我的意思的一个例子:
@commands.command()
@commands.has_permissions(administrator=True)
async def test1(self, ctx):
print("Test1")
@commands.hybrid_command()
@commands.has_permissions(administrator=True)
async def test2(self, ctx):
print("Test 2")
如果您输入 /help test1
,它会正常工作,但在 /help test2
时会出错。没有权限检查它似乎也能正常工作。
当前答案
这可以通过在终端中使用 pip install git+https://github.com/rapptz/discord.py
将 discord.py 至少更新为 commit 36f039a1bffb835a555be8a43976397ba6eb9c76
来解决。
过时的答案
说明
似乎 discord.py 有一个错误导致了这个错误。在 _check_can_run
混合命令中,它使用 interaction._baton
作为命令上下文来检查。 interaction._baton
设置为缺失的标记值,因此当 discord.py
尝试像使用常规 Context
对象一样使用它时会出错。
这可以很简单地修补,尽管我不确定是否有任何意外的副作用。只需将 interaction._baton
设置为您刚刚获取的上下文。我已经用两个测试用例对其进行了测试,它们都有效:
代码
@bot.tree.command(name="help", guild=discord.Object(id=703732969160048731))
async def help_command(interaction: discord.Interaction, parameter: str = None):
embed = discord.Embed(title="Test")
cmd = bot.get_command(parameter)
ctx: commands.Context = await bot.get_context(interaction)
interaction._baton = ctx # sketchy, but it works
try:
await cmd.can_run(ctx)
embed.add_field(name="Usable by you:", value="Yes")
except commands.CommandError as exc:
embed.add_field(name="Usable by you:", value=f"No:\n{exc}")
await ctx.send(embed=embed)