discord.py checking permissions within code - python

I've tried this but it didn't work(i marked the error line), I hope you can help me
#bot.event
async def on_message(message):
if 'https://' in message.content.lower():
if(message.channel.name.startswith("ticket")):
print("")
else:
>>>>>>if(has_permissions(manage_messages = True))
print("")
else:
await message.delete()
embed = discord.Embed(title=f'Message Deleted',description=f'**User** : ``{str(message.author)}``\n**Reason** : ``Url/Link detected in the Message``', color=0xFF0000 )
await message.channel.send(embed=embed)

You have an indentation error (you must add one indent after your first else):
#bot.event
async def on_message(message):
if 'https://' in message.content.lower():
if(message.channel.name.startswith("ticket")):
print("")
else:
if(has_permissions(manage_messages = True))
print("")
else:
await message.delete()
embed = discord.Embed(title=f'Message Deleted',description=f'**User** : ``{str(message.author)}``\n**Reason** : ``Url/Link detected in the Message``', color=0xFF0000 )
await message.channel.send(embed=embed)
To check for permissions withing your code, you can use Member.guild_permissions:
if ctx.author.guild_permissions.manage_messages:
print('You have permission')

Related

MissingRequiredArgument: context is a required argument that is missing

Im Still New (Because I Took A Break And Forgot Almost Everything). I Was Coding An AFK Bot And This Happened...
Error: MissingRequiredArgument: context is a required argument that is missing.
Code:
#client.command()
async def start(ctx,context,user: discord.Member):
def check(m):
return m.author == ctx.author and m.channel == ctx.channel
name = context.author.display_name
author = context.author
guild = context.guild
AFKrole = discord.utils.get(guild.roles, name="AFK")
if not AFKrole:
AFKrole = await guild.create_role(name="AFK")
await context.author.edit(nick=f"[AFK]{name}")
await author.add_roles(AFKrole)
await ctx.send(f"AFK Mode Started For **{author}**.")
gt = await client.wait_for('message', check=check, timeout=180)
if gt.content.lower() == "afk stop":
await context.author.edit(nick=f"{name}")
await author.remove_roles(AFKrole)
await ctx.send(f"AFK Mode Stopped For **{author}**.")
else:
pass
please help.
Remove context parameter and replace any context part in the code with just ctx. ctx is already context.
Ex.
name = ctx.author.display_name
author = ctx.author
guild = ctx.guild

Cogs Help In Discord Py

I am trying to create a command wherein if you react on the embed, the bot sends something back. If I add this code to a cog, it won't work. If possible, can you tell me why?
#bot.command(aliases=['test','t'])
async def Test(self, ctx):
TestEmbed = discord.Embed(title="Definition", description="This is just a test embed", color=11027200)
TestEmbed.add_field(name="\u200b", value="▹❁❁▹❁◃❁❁◃",inline=False)
emojis = ['⬅️','➡️']
TestEmbedAdd = await ctx.send(embed=TestEmbed)
for emoji in emojis:
await TestEmbedAdd.add_reaction(emoji)
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) in ['⬅️', '➡️']
try:
reaction, user = await bot.wait_for('reaction_add', timeout=5, check=check)
if reaction.emoji == '➡️':
await ctx.send("Reaction 2!")
elif reaction.emoji == '⬅️':
await ctx.send("Reaction 1!")
except asyncio.TimeoutError:
await ctx.send("Time is out!")
With the help of the people in the comment section, I have found the problem with my code. I had to change bot.command into commands.command. (I've tried both bot and command, and it still works splendidly). The other crucial thing I had to add was "self" under bot.wait_for. Without the self, the command wouldn't work. Thank you so much for the help.
#commands.command(aliases=['test','t'])
async def Testing(self, ctx):
TestEmbed = discord.Embed(title="Definition", description="This is just a test embed", color=11027200)
TestEmbed.add_field(name="\u200b", value="▹❁❁▹❁◃❁❁◃",inline=False)
emojis = ['⬅️','➡️']
TestEmbedAdd = await ctx.send(embed=TestEmbed)
for emoji in emojis:
await TestEmbedAdd.add_reaction(emoji)
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) in ['⬅️', '➡️']
try:
reaction, user = await self.bot.wait_for('reaction_add', timeout=5, check=check)
if reaction.emoji == '➡️':
await ctx.send("Reaction 2!")
elif reaction.emoji == '⬅️':
await ctx.send("Reaction 1!")
except asyncio.TimeoutError:
await ctx.send("Time is out!")
you need #commands.command instead of #bot.command

Bot will not log an automod event if user has blocked the bot

If someone says a bad word that triggers the automod, the bot will delete the message, DM the user, and log it in a log channel.
The problem is if someone blocks the bot and says a bad word, the bot can't DM the user which doesn't allow the bot to log the event in a log channel.
I tried multiple ways to fix this by adding if and else and except but those do not help. Below is the current code that I have already, so how can I make the bot still log the event if the offender has blocked the bot?
#commands.Cog.listener()
async def on_message(self, message):
curseWord = ['bad words here']
msg_content = message.content.lower()
if any(word in msg_content for word in curseWord):
if message.channel.type == discord.ChannelType.private:
return
if message.author.id == 330988962162147329: #johnny
return
if message.author.id == 467715040087244800: #me
return
if message.author.id == 261578097978114050: #devvy
return
if message.author.id == 835307493558321172: #examplebot
return
await message.delete()
embed=discord.Embed(title="No No Word", description=f"{message.author.mention}, Hey! Those words arent allowed here!", color=0x00FFFF)
embed.timestamp = datetime.datetime.utcnow()
author = message.author
pfp = author.avatar_url
embed.set_author(name=f"{author.name}", icon_url=pfp)
await message.channel.send(embed=embed)
dmembed=discord.Embed(title="AutoMod", description="You were caught saying a bad word!", color=0x00FFFF)
dmembed.add_field(name="**Message:**", value=f"{msg_content}", inline=False)
pfp = author.avatar_url
dmembed.add_field(name="**Server:**", value=f"{message.guild.name}", inline=False)
dmembed.set_author(name=f"{author.name}", icon_url=pfp)
dmembed.timestamp = datetime.datetime.utcnow()
with open('logchannel.json', 'r', encoding='utf-8') as fp:
log_channel = json.load(fp)
try:
await message.author.send(embed=dmembed)
if log_channel:
log_channel = message.guild.get_channel(log_channel[str(message.guild.id)])
logembed=discord.Embed(title="Bot Log", description="Bad Word Said", color=0x00FFFF)
logembed.add_field(name="**Message:**", value=f"{msg_content}", inline=False)
logembed.add_field(name="**Member:**", value=f"{message.author.name}", inline=False)
author = message.author
pfp = author.avatar_url
logembed.set_author(name=f"{author}", icon_url=pfp)
logembed.timestamp = datetime.datetime.utcnow()
await log_channel.send(embed=logembed)
else:
await log_channel.send(embed=logembed)
except (AttributeError, KeyError):
await log_channel.send(embed=logembed)
Try/except
When you have a try/except in your code, Python will try to execute the code, and if there is and error he will execute the code in the except section. So a code in the try section may be not executed.
What in your code needs a try/except ?
In your code, the things which could raise an error are :
await message.author.send(embed=dmembed) #DM closed
log_channel = ...(log_channel[str(message.guild.id)]) #key error
await log_channel.send(embed=logembed) #NoneType has no attribute send (if the channel doesn't exist)
Which means that if there is an error on the first possibility, all the following code in the try will not be executed.
Solution
I advise you to have two try/except, the first for the DM, and the second for the log.
You code with my solution is now :
try:
await message.author.send(embed=dmembed)
except:
pass #ignore error if DM are closed
try:
if log_channel:
log_channel = message.guild.get_channel(log_channel[str(message.guild.id)])
logembed=discord.Embed(title="Bot Log", description="Bad Word Said", color=0x00FFFF)
logembed.add_field(name="**Message:**", value=f"{msg_content}", inline=False)
logembed.add_field(name="**Member:**", value=f"{message.author.name}", inline=False)
author = message.author
pfp = author.avatar_url
logembed.set_author(name=f"{author}", icon_url=pfp)
logembed.timestamp = datetime.datetime.utcnow()
await log_channel.send(embed=logembed)
else: #You can remove that, because if `log_channel` is not, you can't send an embed
await log_channel.send(embed=logembed) #So you can also remove that
except (AttributeError, KeyError):
await log_channel.send(embed=logembed) #Same here, if the above code raises an error, this code can be executed without raising another error.
pass

Discord.py bot.wait_for

#commands.command()
async def verify(self, ctx, length=10):
verify_characters = []
for _ in range(length):
verify_characters.append(random.choice(string.ascii_letters + string.digits + "!§$%&/()=?`-.<>"))
verify_msg = "".join(verify_characters)
print(verify_msg)
await ctx.author.send(f"Verify with the number {verify_msg}")
answer = await bot.wait_for('message', check=lambda message: message.author == ctx.author)
print("done")
if verify_msg == answer:
await ctx.author.send("Verified")
else:
await ctx.author.send(f"Verify again!")
Im trying to do a verify system, but after the bot.wait_for task nothing happens, i guess something in the line is wrong, has anybody solutions?
If you want it to be a dm command we can use the restriction #commands.dm_only()
However we then also have to check where the answer was given, we do that via some kind of custom check. I have modified your command a bit, but you can make the changes again personally.
Take a look at the following code:
#commands.dm_only() # Make it a DM-only command
#commands.command()
async def verify(self, ctx, length=10):
def check(m):
return ctx.author == m.author and isinstance(m.channel, discord.DMChannel)
verify_characters = []
for _ in range(length):
verify_characters.append(random.choice(string.ascii_letters + string.digits + "!§$%&/()=?`-.<>"))
verify_msg = "".join(verify_characters)
print(verify_msg)
await ctx.author.send(f"Verify with the number: {verify_msg}")
try: # Try to get the answer
answer = await bot.wait_for("message", check=check)
print(answer.content)
if verify_msg == answer.content:
await ctx.author.send("Verified!")
else:
await ctx.author.send("Verify again!")
except: # Used if you for example want to set a timelimit
pass
Edited to show full answer.
Hey ho done it lol.
Basically the message object contains a lot of data, so you need to pull the content of the message using answer.conent.
https://discordpy.readthedocs.io/en/latest/api.html?highlight=message#discord.Message.content for reference
#bot.command()
async def verify(ctx):
length=10
verify_characters = []
for _ in range(length):
verify_characters.append(random.choice(string.ascii_letters + string.digits + "!§$%&/()=?`-.<>"))
verify_msg = "".join(verify_characters)
print(verify_msg)
await ctx.author.send(f"Verify with the number {verify_msg}")
answer = await bot.wait_for('message')
print(answer.content)
print("done")
if verify_msg == answer.content:
await ctx.author.send("Verified")
else:
await ctx.author.send(f"Verify again!")
Give that a test run and let me know what happens ;)

Implementation of user.bot discord.py rewrite

I'm doin a command that checks if a user is a bot or a normal user
#client.command()
async def maybebot(ctx, user: discord.Member):
embed = discord.Embed(title="Cheks if a user is a bot", description="Let's find out!")
if user.bot == True:
embed.add_field(name="And..", value="It is!")
if user.bot == False:
embed.add_field(name="And...", value="It's not!")
await ctx.send(embed=embed)
This is not working, no traceback, no error. What i should do?
#client.command()
async def maybebot(ctx, user: discord.Member):
embed = discord.Embed(title="Checks if a user is a bot", description="Let's find out!")
if user.bot:
embed.add_field(name="And...", value="It is!")
else:
embed.add_field(name="And...", value="It's not!")
await ctx.send(embed=embed)

Categories

Resources