Trying to ask user confirmation for discord.py bot command, but doing so neglects the "if and elif block" entirely - discord

I have imported everything needed for the command.
So, the issue here is, in the condition for executing the command (checking if the user said yes/no or something weird which terminates the command)
#commands.command()
#commands.has_permissions(manage_channels=True)
async def nuke(self, ctx,*, channel = None, reason = None):
if reason is None:
reason = "No reason was specified!"
if channel is None:
channel = ctx.channel
p = time.strftime(f'Today at %H:%M %p')
embei = discord.Embed(color=0xa3a3ff, title = ":warning: ALERT ALERT ALERT :warning: ", description=f"{ctx.author.mention} Are you sure you want to delete {ctx.channel.mention}? y/n")
await ctx.send(embed=embei)
msg = await self.client.wait_for('message', check=lambda message:message.author == ctx.author and message.channel.id == ctx.channel.id)
if msg.content.lower in ("y", "yes"):
embedis = discord.Embed(color=0xa3a3ff, title=f"Channel ({ctx.channel.name}) has been nuked :boom:", description=f"Nuked by: {ctx.author.name}#{ctx.author.discriminator} \n **Reason:** {reason}")
embedis.set_image(url = "https://66.media.tumblr.com/23dad7011515a9c21647fefb07e1c0e0/dd0cbd9bb94e2a45-1e/s640x960/a02fc34abff6953c59adafc190de6e5276969175.gif")
embedis.set_footer(text=f"Rylie - Thanks for using this bot! - {p} - {self.client.version}", icon_url = str(self.client.user.avatar_url))
await ctx.channel.delete(reason=reason)
channel = await ctx.channel.clone()
await channel.send(embed=embedis)
elif msg.content.lower in ("n", "no"):
embegs = discord.Embed(color=0xa3a3ff, title = ":red_circle: NOTICE :red_circle:", description = f"{ctx.channel.mention} was not nuked!")
embegs.set_footer(text=f"Rylie - Thanks for using this bot! - {p} - {self.client.version}", icon_url = str(self.client.user.avatar_url))
await ctx.send(embed=embegs)
else:
embers = discord.Embed(color=0xa3a3ff, title = ":red_circle: NOTICE :red_circle:", description = "No proper response was given, action was terminated")
embers.set_footer(text=f"Rylie - Thanks for using this bot! - {p} - {self.client.version}", icon_url = str(self.client.user.avatar_url))
await ctx.send(embed=embers)
The part with the issue
msg = await self.client.wait_for('message', check=lambda message:message.author == ctx.author and message.channel.id == ctx.channel.id)
if msg.content.lower in ("y", "yes"):
embedis = discord.Embed(color=0xa3a3ff, title=f"Channel ({ctx.channel.name}) has been nuked :boom:", description=f"Nuked by: {ctx.author.name}#{ctx.author.discriminator} \n **Reason:** {reason}")
embedis.set_image(url = "https://66.media.tumblr.com/23dad7011515a9c21647fefb07e1c0e0/dd0cbd9bb94e2a45-1e/s640x960/a02fc34abff6953c59adafc190de6e5276969175.gif")
embedis.set_footer(text=f"Rylie - Thanks for using this bot! - {p} - {self.client.version}", icon_url = str(self.client.user.avatar_url))
await ctx.channel.delete(reason=reason)
channel = await ctx.channel.clone()
await channel.send(embed=embedis)
elif msg.content.lower in ("n", "no"):
embegs = discord.Embed(color=0xa3a3ff, title = ":red_circle: NOTICE :red_circle:", description = f"{ctx.channel.mention} was not nuked!")
embegs.set_footer(text=f"Rylie - Thanks for using this bot! - {p} - {self.client.version}", icon_url = str(self.client.user.avatar_url))
await ctx.send(embed=embegs)
else:
embers = discord.Embed(color=0xa3a3ff, title = ":red_circle: NOTICE :red_circle:", description = "No proper response was given, action was terminated")
embers.set_footer(text=f"Rylie - Thanks for using this bot! - {p} - {self.client.version}", icon_url = str(self.client.user.avatar_url))
await ctx.send(embed=embers)
when I execute the command, it does ask me for the confirmation as expected, however, the reply here doesn't matter as it always executes the else statement. I thought the issue was with indentation and so I tried fixing that but that too didn't work. Does anyone know about the issue here I might be facing?
Extra: Before Adding user confirmation, the code was working absolutely fine! (It created a clone of the channel, sent the embed there saying it nuked the original channel, and deleted the original channel)

For this question of mine, the string.lower() is a method which I need to call, which was mentioned to me by Lukasz. I was using the string.lower() in the wrong way.
To Fix the problem I had, I declared two lists a and b
a=["y", "yes"]
b = ["n", "no"]
and changed
if msg.content.lower in ("y", "yes"):
elif msg.content.lower in ("n", "no"):
to
if msg.content in a:
elif msg.content in b:
and the issue was fixed.

Related

EMBED SYSTEM [IDLE PYTHON]

So i have an embed system working in the below code:
#client.event
async def on_message(message):
if message.content.startswith('!emsay'):
embedVar = discord.Embed(title="Title", description="desc", color=0x00ff00)
await message.channel.send(embed=embedVar)
My problem is yes when i do !emsay it dose put the embed in but is there a way that after i put !emsay i can change the title and description without going into python to type out a whole new embed?
This is what i currently have:(im fine with this)Discord screenshot of embed I would like to make it so after i use the command !emsay i can enter a title and description through discord.
Thanks : )
sorry if iv overcomplicated this
Try this:
#client.event
async def on_message(message):
if message.content.startswith('!emsay'):
count = 0
def check(author):
def inner_check(message):
if message.author != author:
return False
return inner_check
while count < 2:
if (count == 0):
await message.channel.send("Write a title for embed")
title = await client.wait_for("message", check=check, timeout=30)
elif (count == 1):
await message.channel.send("Write a desc for embed")
desc = await client.wait_for("message", check=check, timeout=30)
count += 1
embedVar = discord.Embed(title = title.content, description = desc.content, color = 0x00ff00)
await message.channel.send(embed=embedVar)
If you don't write title and desc, you can get a TimeoutError and you can change timeout if you want.
How to use?

Discord.py snipe command is sniping messages from other channels

I recently made a snipe command for my discord bot but I have one problem. Snipe command snipes a message from other channels when I for example want to snipe a message in general. Here is my code:
#bot.event
async def on_message_delete(message):
if message.attachments:
bob = message.attachments[0]
bot.sniped_messages[message.guild.id] = (bob.proxy_url, message.content, message.author, message.channel.name, message.created_at)
else:
bot.sniped_messages[message.guild.id] = (message.content,message.author, message.channel.name, message.created_at)
#bot.command(aliases=['s'])
async def snipe(ctx):
try:
bob_proxy_url, contents,author, channel_name, time = bot.sniped_messages[ctx.guild.id]
except:
contents,author, channel_name, time = bot.sniped_messages[ctx.guild.id]
try:
embed = discord.Embed(description=contents , color=discord.Color.purple(), timestamp=time)
embed.set_image(url=bob_proxy_url)
embed.set_author(name=f"{author.name}#{author.discriminator}", icon_url=author.avatar_url)
embed.set_footer(text=f"Deleted in : #{channel_name}")
await ctx.channel.send(embed=embed)
except:
embed = discord.Embed(description=contents , color=discord.Color.purple(), timestamp=time)
embed.set_author(name=f"{author.name}#{author.discriminator}", icon_url=author.avatar_url)
embed.set_footer(text=f"Deleted in : #{channel_name}")
await ctx.channel.send(embed=embed)
snipe_message_author = {}
snipe_message_content = {}
#client.event
async def on_message_delete(message):
snipe_message_author[message.channel.id] = message.author
snipe_message_content[message.channel.id] = message.content
#client.command(name = 'snipe')
async def snipe(ctx):
channel = ctx.channel
try:
em = discord.Embed(description = f"`{snipe_message_content[channel.id]}`\nMessage sent by {snipe_message_author[channel.id]}!", color = 0x00c230)
em.set_author(name = f"Last deleted message in #{channel.name}")
em.set_thumbnail(url="https://cdn.discordapp.com/avatars/352793093105254402/8a2018de21ad29973696bfbf92fc31cd.png?size=4096")
em.set_footer(text = f"Snipe requested by {ctx.message.author}")
await ctx.send(embed = em)
except:
embed = discord.Embed(colour = 0x00c230)
embed.set_author(name=f"There are no deleted messages in #{ctx.channel}!")
embed.set_thumbnail(url="https://cdn.discordapp.com/avatars/352793093105254402/8a2018de21ad29973696bfbf92fc31cd.png?size=4096")
embed.set_footer(text=f"Snipe requested by {ctx.message.author}")
await ctx.channel.send(embed=embed)
Thats what I use and it works properly.
Since I added [message.channel.id] to the variables it only checks for snipes in that channel. This is how it looks like in Discord

Reroll Giveaway command not responding when command run?

I am trying to make a discord giveaway reroll command.
The problem is that when the command is run it is not responding/rerolling the giveaway.
I've looked on multiple sites with the same command and all of them did not work/have a fix for this.
I also tried without the embeds to see if that was the problem with the code.
Below is the reroll command code -
(if the giveaway command code is needed I can provide it)
#client.command()
#commands.has_permissions(kick_members=True)
async def reroll(ctx, channel : discord.TextChannel, id_ : int):
try:
new_msg = await channel.fetch_message(id_)
except:
embed = discord.Embed(title="Command Error โ›” - GameBot", description=f"**The Id Of A Channel Was Entered Incorrectly!** ๐ŸŽ‰", color=0x992d22)
await ctx.send(embed=embed)
return
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(client.user))
winner = random.choice(users)
embed = discord.Embed(title="Giveaways ๐ŸŽ‰ - GameBot", description=f"**Giveaway Has Been Rerolled!** \n \n**Winner -** \n`{winner.mention}`", color=0xe74c3c)
await ctx.send(embed=embed)
Below is the giveaway command code -
#client.command()
#commands.has_permissions(kick_members=True)
async def giveaway(ctx):
embed = discord.Embed(title="Giveaway Setup ๐ŸŽ‰ - GameBot", description=f'**{ctx.author.mention} Giveaway Setup Is Now Starting... Please Answer These Questions Within 30 Seconds!**', color=0xe74c3c)
await ctx.send(embed=embed)
questions = ["**What Channel Should The Giveaway Be Hosted In?** `EX : #general` ๐ŸŽ‰",
"**What Is The Duration Of The Giveaway?** `EX : S/M/H/D` ๐ŸŽ‰",
"**What Is The Giveaway Prize?** `EX : Gift Card` ๐ŸŽ‰"]
answers = []
def check(m):
return m.author == ctx.author and m.channel == ctx.channel
for i in questions:
await ctx.send(i)
try:
msg = await client.wait_for('message', timeout=30.0, check=check)
except asyncio.TimeoutError:
embed = discord.Embed(title="Command Error โ›” - GameBot", description=f"**Please Answer All Of The Questions In Time... Be Prepared!** ๐ŸŽ‰", color=0x992d22)
await ctx.send(embed=embed)
else:
answers.append(msg.content)
try:
c_id = int(answers[0][2:-1])
except:
embed = discord.Embed(title="Command Error โ›” - GameBot", description=f"**Please Provide A Valid Channel For Me To Host The Giveaway In!** `EX : #general` ๐ŸŽ‰", color=0x992d22)
await ctx.send(embed=embed)
return
channel = client.get_channel(c_id)
time = convert(answers[1])
if time == -1:
embed = discord.Embed(title="Command Error โ›” - GameBot", description=f"**The Time Constraint You Answered With Was Not A Valid Unit!** `EX : S/M/H/D` ๐ŸŽ‰", color=0x992d22)
await ctx.send(embed=embed)
return
elif time == -2:
embed = discord.Embed(title="Command Error โ›” - GameBot", description=f"**The Time Must Include An Integer!** `EX : 1S, 1M, 1H, 1D` ๐ŸŽ‰", color=0x992d22)
await ctx.send(embed=embed)
return
prize = answers[2]
embed = discord.Embed(title="Giveaway Setup ๐ŸŽ‰ - GameBot", description=f'**Giveaway Channel -** \n`{channel.mention}` \n**Duration -** \n`{answers[1]}`', color=0xe74c3c)
await ctx.send(embed=embed)
givembed = discord.Embed(title="Giveaways ๐ŸŽ‰ - GameBot", description=f'**Giveaway Prize/Description -** \n`{prize}`', color=0x2ecc71)
givembed.add_field(name = "**Host -**", value=ctx.author.mention)
givembed.set_footer(text = f"Ending {answers[1]} From Now! ๐ŸŽ‰")
my_msg = await channel.send(embed=givembed)
await my_msg.add_reaction("๐ŸŽ‰")
await asyncio.sleep(time)
new_msg = await channel.fetch_message(my_msg.id)
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(client.user))
winner = random.choice(users)
embed = discord.Embed(title="Giveaways ๐ŸŽ‰ - GameBot", description=f"**Giveaway Has Ended!** \n \n**Winner -** \n`{winner.mention}` \n**Prize -** \n`{prize}`", color=0xe74c3c)
await ctx.send(embed=embed)
Almost everything about the code is correct. However I guess you are requesting the users in a wrong/not working way. You can try to request the users in another way, this seems to be the source where the error comes from.
Try out the following:
users = [u for u in await new_msg.reactions[0].users().flatten() if u != client.user]
winner = random.choice(users)
The full code would be:
#client.command()
#commands.has_permissions(kick_members=True)
async def giveaway(ctx):
# Giveaway code
#client.command()
#commands.has_permissions(kick_members=True)
async def reroll(ctx, channel: discord.TextChannel, id_: int):
try:
new_msg = await channel.fetch_message(id_)
except:
embed = discord.Embed(title="Command Error โ›” - GameBot",
description=f"**The Id Of A Channel Was Entered Incorrectly!** ๐ŸŽ‰", color=0x992d22)
await ctx.send(embed=embed)
return
user_list = [u for u in await new_msg.reactions[0].users().flatten() if u != client.user]
winner = random.choice(user_list)
embed = discord.Embed(title="Giveaways ๐ŸŽ‰ - GameBot",
description=f"**Giveaway Has Been Rerolled!** \n \n**Winner -** \n`{winner.mention}`",
color=0xe74c3c)
await ctx.send(embed=embed)

Poll question which adds the correct amount of reactions. (d.py)

I am trying to make a poll command which adds the correct amount of reactions such as A B C D E etc.
I have already tried this but it was a simple yes or no poll command.
elif message.content.startswith('m/qpoll'):
question = message[8:]
await message.delete()
message = await message.channel.send(f"**New poll:** {question}")
await message.add_reaction('โŒ')
await message.add_reaction('โœ”๏ธ')
What i am trying to achieve is a command which adds A B C reactions if there is three possible answers and A B C D E if there is five possible answers etc.
The command the user has to use is preferred to be in this format:
m/poll "question" "answer 1" "answer 2" "answer 3"
The command needs to be under a on_message statement as the command package does not work as well for my bot.
A simple way to do it, without using discord.ext.commands :
elif message.content.startswith('m/qpoll'):
content = message.content[8:]
items = content.split(" ")
question = items[0]
answers = '\n'.join(items[1:])
await message.delete()
message = await message.channel.send(f"**New poll:** {question}\n{answers}")
reactions = ['A', 'B', 'C', 'D', 'E'] #replace the letters with your reactions
for i in range(len(items[1:]))
await message.add_reaction(reactions[i])
Here's the poll command I made for my bot
#commands.command()
async def poll(self, ctx):
"""
Conduct a poll (interactive)
?poll
"""
member = ctx.author
member: Member
maker = []
await ctx.send("```What is the Question โ“```")
em = ["๐Ÿงช", "๐Ÿงฌ", "๐Ÿš€", "๐Ÿ–Œ๏ธ", "๐Ÿงจ"]
def mcheck(m):
return m.author == member
try:
msg = await self.bot.wait_for('message', timeout=20.0, check=mcheck)
maker.append(msg.content)
except TimeoutError:
return await ctx.send("```Poll timed out โณ```")
await ctx.send("```How many options do you want?```")
try:
msg = await self.bot.wait_for('message', timeout=20.0, check=mcheck)
except TimeoutError:
return await ctx.send("```Poll timed out โณ```")
i = int(msg.content)
if i > 5:
return await ctx.send("```A maximum of 5 options for polls```")
await ctx.send("```Enter your options โœ”```")
for i in range(i):
try:
await ctx.send(f"```{i + 1}) ```")
msg = await self.bot.wait_for('message', timeout=20.0, check=mcheck)
maker.append(msg.content)
await msg.add_reaction("โœ…")
except TimeoutError:
return await ctx.send("```Poll timed out โณ```")
poller = Embed(color=0x5EE34)
poller.title = maker[0]
des = ''
for j in range(1, len(maker)):
des += f"```{em[j - 1]} {maker[j]}```\n"
poller.description = des
pr = await ctx.send(embed=poller)
for j in range(i + 1):
await pr.add_reaction(em[j])
def reac_check(r, u):
return pr.id == r.message.id and r.emoji in em
eopt = {e: 0 for e in em}
while True:
try:
reaction, user = await self.bot.wait_for('reaction_add', timeout=20.0, check=reac_check)
e = str(reaction.emoji)
except TimeoutError:
await ctx.send("```Poll Finished โœ…```")
break
if e in eopt.keys() and user != self.bot.user:
eopt[e] += 1
eopt = {k: v for k, v in sorted(eopt.items(), key=lambda item: item[1], reverse=True)}
most = next(iter(eopt))
loc = em.index(most)
poller.title = "Results ๐Ÿ†"
poller.description = f"```Folks chose ๐Ÿ“œ\n{maker[loc + 1]}```"
return await ctx.send(embed=poller)
As a rule of thumb avoid using on_message to create commands. You can read about commands.Bot() in the docs.
That said you should be able adapt the above example to suit your needs.

Discord bot ctx is being displayed as argument

Thats a test code where im trying to work in classes. Even tho in commands it displayes ctx as required arg instead and it works only if i put it before self.
class Quiz:
def __init__(self, question, answer):
self.question = question
self.answer = answer
#bot.command(pass_context=True)
async def quiz(self, ctx):
fido = Quiz("Starter mass?", "yeah")
nope = Quiz("WHAT?", "lel")
await ctx.send(fido.question)
def check(m):
return m.content == 'heh'
msg = await bot.wait_for('message', check=check)
await ctx.send('Right {.author}!'.format(msg))
Error:
discord.ext.commands.errors.MissingRequiredArgument: ctx is a required argument that is missing.
How can I fix this?
As crazy as it sounds, remove the self argument from your method. The commands decorator will take care of this. (You can also use a command cog)
class Quiz:
def __init__(self, question, answer):
self.question = question
self.answer = answer
#bot.command(pass_context=True)
async def quiz(ctx):
fido = Quiz("Starter mass?", "yeah")
nope = Quiz("WHAT?", "lel")
await ctx.send(fido.question)
def check(m):
return m.content == 'heh'
msg = await bot.wait_for('message', check=check)
await ctx.send('Right {.author}!'.format(msg))
Also your check function doesn't work correctly. It always uses the fido question and says you are correct only after responding with 'heh'.
#bot.command(pass_context=True)
async def quiz(ctx):
fido = Quiz("Starter mass?", "yeah")
nope = Quiz("WHAT?", "lel")
question = random.choice((fido, nope))
await ctx.send(question.question)
check = lambda m: m.content.lower() == question.answer
msg = await bot.wait_for('message', check=check)
await ctx.send(f'Right **{msg.author.name}**!')

Resources