首页 > 解决方案 > Discord.py:在检查中使用特殊响应导致不同的输出

问题描述

所以,这可能看起来有点奇怪,但我最近为我的不和谐机器人创建了一个命令,让用户逐步创建嵌入。它工作得很好,但我想实现一种方法来完成命令,即使没有填写所有字段。因此,如果用户在构建嵌入时键入“完成”,它将带他们进入构建过程的一部分,询问他们要将嵌入发送到哪些通道。这是我的代码:

  @embed.command()
  @commands.has_permissions(manage_permissions = True) 
  @commands.bot_has_permissions(manage_permissions = True)
  async def build(self, ctx):

    channel = ctx.channel
    content = f''

    def check(m):
        if m.channel == m.channel and m.content == "CANCEL":
            raise ValueError("Cancelled command")
        return m.content.lower is not None and m.channel == channel and m.content.lower

    # The first round: TITLE

    beggining = await ctx.send('Alright! Let\'s get started! What would you like the **title** of your embed to be?')

    firstin = await self.bot.wait_for("message", check=check)

    await firstin.delete() # Delete the first input

    await beggining.delete()
    firstembed=discord.Embed(title=f'{firstin.content}')

    # The second round: MAIN BODY

    theembed = await ctx.send(content=content, embed=firstembed)

    asking = await ctx.send('Got it! What would you like the **main body** of your embed to be?')

    secondin = await self.bot.wait_for("message", check=check)
    
    await secondin.delete() # Delete the second input

    secondembed=discord.Embed(title=firstin.content, description=secondin.content)
    await theembed.edit(content=content, embed=secondembed)

    await asking.edit(content='Okay. Now, what would you like the **footer** of your embed to be?')

    # The third round: FOOTER

    thirdin = await self.bot.wait_for("message", check=check)

    await thirdin.delete() # Delete the third input

    thirdembed=discord.Embed(title=firstin.content, description=secondin.content)
    thirdembed.set_footer(text=thirdin.content)
    await theembed.edit(content=content, embed=thirdembed)

    await asking.edit(content='Sounds good. Now, what would you like the **hex color code** of your embed to be?')

    # Fourth round: COLOR

    fourthin = await self.bot.wait_for("message", check=check)

    await fourthin.delete() # Delete the fourth input

    readableHex = int(hex(int(fourthin.content.replace("#", ""), 16)), 0)

    fourthembed=discord.Embed(title=firstin.content, description=secondin.content, color=readableHex)
    fourthembed.set_footer(text=thirdin.content)
    await theembed.edit(content=content, embed=fourthembed)

    await asking.edit(content='Cool. What would you like the **image link** of your embed to be?')

    # The fifth round: IMAGE

    fifthin = await self.bot.wait_for("message", check=check)

    await fifthin.delete() # Delete the fifth input

    fifthembed=discord.Embed(title=firstin.content, description=secondin.content, color=readableHex)
    fifthembed.set_footer(text=thirdin.content)
    fifthembed.set_image(url=fifthin.content)
    await theembed.edit(content=content, embed=fifthembed)

    await asking.edit(content='Now, what would you like the **thumbnail image link** of your embed to be?')

    # The sixth round: THUMBNAIL

    sixthin = await self.bot.wait_for("message", check=check)

    await sixthin.delete() # Delete the sixth input

    sixthembed=discord.Embed(title=firstin.content, description=secondin.content, color=readableHex)
    sixthembed.set_footer(text=thirdin.content)
    sixthembed.set_image(url=fifthin.content)
    sixthembed.set_thumbnail(url=sixthin.content)
    await theembed.edit(content=content, embed=sixthembed)

    await asking.edit(content='Now, what would you like the **author name** of your embed to be?')

    # The sevnth round: AUTHOR NAME

    seventhin = await self.bot.wait_for("message", check=check)

    await seventhin.delete() # Delete the seventh input

    seventhembed=discord.Embed(title=firstin.content, description=secondin.content, color=readableHex)
    seventhembed.set_footer(text=thirdin.content)
    seventhembed.set_image(url=fifthin.content)
    seventhembed.set_thumbnail(url=sixthin.content)
    seventhembed.set_author(name=seventhin.content)
    await theembed.edit(content=content, embed=seventhembed)
    
    await asking.edit(content='Almost done! What would you like the **author icon link** of your embed to be? You can also mention someone or yourself to use their avatar.')

    # The eighth round: AUTHOR ICON

    eighthin = await self.bot.wait_for("message", check=check)

    await eighthin.delete() # Delete the eighth input

    if (eighthin.mentions.__len__()>0):
        for user in eighthin.mentions:
            eighthinavatar = user.avatar_url
    else: eighthinavatar = eighthin.content

    eighthembed=discord.Embed(title=firstin.content, description=secondin.content, color=readableHex)
    eighthembed.set_footer(text=thirdin.content)
    eighthembed.set_image(url=fifthin.content)
    eighthembed.set_thumbnail(url=sixthin.content)
    eighthembed.set_author(name=seventhin.content, icon_url=eighthinavatar)
    await theembed.edit(content=content, embed=eighthembed)

    await asking.edit(content='Done! Now please mention the channels you would like to send your embed to!')

    # The ninth round: CHANNELS

    ninthin = await self.bot.wait_for("message", check=check)

    if (ninthin.channel_mentions.__len__()>0):
        for channel in ninthin.channel_mentions:
            await channel.send(content=content, embed=eighthembed)
    
    await ninthin.add_reaction(check_mark)

  @build.error
  async def build_error(self, ctx, error):
    if isinstance(error, commands.errors.CommandInvokeError):
      await ctx.send(f'{x_mark} The embed has been terminated, you will have to start over. This was either due to cancellation or an incorrect argument.')

有什么办法可以做到这一点吗?谢谢。

标签: pythondiscorddiscord.pyembeddiscord.py-rewrite

解决方案


您可以自己创建一个自定义错误,CommandInvokeError每次命令本身失败时都会调用它,而不是 imo 的最佳选择,方法如下:

class CancelledCommand(commands.CheckFailure):
    pass

# Somewhere (in the check func)
raise CancelledCommand('Command has been cancelled')

# In the error handler
if isinstance(error, CancelledCommand):
    ...

另外,关于检查功能的4件事

  1. str.lower()它是一个方法,而不是一个属性,所以你需要调用它。
  2. m.content永远不会None
  3. m.channel == m.channel根本没有任何意义,我想你的意思是m.channel == ctx.channel
  4. 你可能应该检查m.author == ctx.author

这是改进的检查:

def check(m):
    if m.channel == ctx.channel and m.author == ctx.author:
        if m.content.lower() == 'finish':
            raise CancelledCommand('Command has been cancelled')
        return True
    return False

推荐阅读