Reputation: 138
So, this may seem like a bit of an odd question, but I recently created a command for my discord bot that takes the user step-by-step through creating an embed. It works perfectly, but I wanted to implement a way to finish off the command even without all of the fields being filled. So if the user types "finish" while building the embed, it will take them to the part of the building process that asks them what channels they want to send the embed to. Here is my code:
@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.')
Is there any way I can do this? Thanks.
Upvotes: 0
Views: 318
Reputation: 15689
You can create a custom error yourself, CommandInvokeError
will be called everytime something fails in the command itself, not the best option imo, here's how:
class CancelledCommand(commands.CheckFailure):
pass
# Somewhere (in the check func)
raise CancelledCommand('Command has been cancelled')
# In the error handler
if isinstance(error, CancelledCommand):
...
Also, 4 things about the check function
str.lower()
it's a method, not an attribute, so you need to call it.m.content
will never be None
.m.channel == m.channel
doesn't make any sense at all, I think you meant m.channel == ctx.channel
m.author == ctx.author
Here's the check improved:
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
Upvotes: 1