Hi so I've changed the code from past questions to try and simplify it, however now I'm having another problem,
So I have this code which checks for a certain role and changes the roles, however when I input the command into discord which is //leave #name time reason, neither the 'if' or 'elif' statements run.
I get no feedback, no errors, just no reaction from the bot whatsoever.
Here's the code, if someone can tell me what's going on for the statements to not run properly I'd appreciate it.
(I've tried interchanging the 'elif' statements with 'if' statements but to no avail.)
#client.command()
#commands.has_role(876994087214018571)
async def leave(ctx, member: discord.Member = None, time: str = '', *, reason: str = ''):
if not member:
member = ctx.author
loa = ctx.guild.get_role(848032714715561985)
mod = ctx.guild.get_role(848032880709074944)
smod = ctx.guild.get_role(851617257138028645)
amod = ctx.guild.get_role(848057125283954688)
if member.has_role(848032880709074944):
await member.add_roles(loa)
await member.remove_roles(mod)
await ctx.send("I have filed your Leave, take care, we look forward to your return!")
elif member.has_role(851617257138028645):
await member.add_roles(loa)
await member.remove_roles(smod)
await ctx.send("I have filed your Leave, take care, we look forward to your return!")
elif member.has_role(848057125283954688):
await member.add_roles(loa)
await member.remove_roles(amod)
await ctx.send("I have filed your Leave, take care, we look forward to your return!")
modLogEmbed = discord.Embed(title='Leave Logs',
description="A member of Staff is going on leave! " + '<#' + str(member.id) + '>', color=0x000000)
modLogEmbed.add_field(name="Time",
value=(time), inline=False)
modLogEmbed.add_field(name="Reason for Leave:",
value=(reason), inline=False)
modLogEmbed.set_footer(text="LeaveManager Bot")
modLogEmbed.set_author(name='Leave Manager')
botLogChannel = client.get_channel(874959002172268685)
await botLogChannel.send(embed=modLogEmbed)
Also I really do sincerely apologise for the way the code is set out, I genuinely can't figure out how to get it to layout properly like other members questions.
Well, member.has_roles is the problem, member does not have the attribute 'has_role'
maybe try this- using find and lambda to find if your id in any element of roles
I've test it using other role, it works fine.
#commands.command()
#commands.has_role(876994087214018571)
async def leave(ctx, member: discord.Member = None, time: str = '', *, reason: str = ''):
if not member:
member = ctx.author
loa = ctx.guild.get_role(848032714715561985)
mod = ctx.guild.get_role(848032880709074944)
smod = ctx.guild.get_role(851617257138028645)
amod = ctx.guild.get_role(848057125283954688)
result = find(lambda x: x.id == 848032880709074944, member.roles)
if result:
await member.add_roles(loa)
await member.remove_roles(mod)
await ctx.send("I have filed your Leave, take care, we look forward to your return!")
await ctx.send('done')
Related
What i am specifically looking for is that i want is for the exception to be thrown on ("you must mention someone to x") and for the exception of if the person isn't in the guild to throw that message instead of using the cooldown.
#tasks.loop(count=1)
async def load_interaction_commands(self):
""" Load interaction commands. """
self.bot.interaction_commands = []
cooldown = commands.Cooldown(1, 600, commands.BucketType.user)
mapping = commands.CooldownMapping(cooldown)
for cmd, aliases in COMMANDS.items():
async def interaction_callback(cls, ctx, user: discord.Member):
if not user:
await ctx.send(f"You must mention someone to {ctx.command}.")
elif user == ctx.author:
await ctx.send("You can't {} yourself, silly!".format(ctx.command.name))
elif not discord.utils.find(lambda m: m.id == user.id, ctx.guild.members):
await ctx.send("you cant {} someone not in the server silly!")
else:
await cls.interact(ctx, user)
interaction_callback = commands.command(name=cmd, aliases=aliases)(interaction_callback)
interaction_callback._buckets = mapping
interaction_callback.__commands_cooldown__ = cooldown
interaction_callback.cog = self
self.bot.add_command(interaction_callback)
self.bot.interaction_commands.append(interaction_callback)
I am using discordpy to build a discord bot. One of the features that I want it to have, is to be able to give a random percentage about a user.
Example:
user1: !w #user2
bot: #user2 is x% y
I am unsure how to draw the userid of user2 from the message sent by user1. Does anyone have any suggestions?
You can use the id attribute of discord.Member.
Example:
#bot.command()
def w(ctx, user: discord.Member):
user_id = user.id
print(user_id)
#client.event
async def on_message(message):
if message.content.startswith('w!cool '):
if message.mentions == []:
await message.channel.send("You should mention someone!\n```\nw!cool <mention>\n```")
return
coolness_tosend=""
for i in message.mentions:
coolness_tosend=coolness_tosend+"<#" + str(i.id) + "> is " + str(random.choice(range(100))) + "\% cool.\n"
await message.channel.send(coolness_tosend)
Links:
discord.Message.mentions in API reference
discord.Message in API reference
Do note, though, that w!cool alone without arguments won't work. It prevents conflict with commands such as w!coolpic. Don't forget to do an import random!
You've asked a question in the title and the description doesn't match it ;-;
Here's a basic code according to what you've asked in the description, customize it as you like :)
Make sure to replace 'client' with whatever you've used
#client.command()
async def cool(ctx, user: discord.Member = None):
pctg = (random.randint(0, 100))
if user == None:
await ctx.send('Mention a user')
else:
await ctx.send(f"{user.name} is {pctg}% cool")
If you want the mentioned user's ID as bot's reply then use the following -
#client.command()
async def uid(ctx, user: discord.Member):
uid = user.id
await ctx.send(uid)
WCOOL_NO_MENTION_ERROR = "You should mention someone!\n" \
+ "```\n" \
+ "w!cool <mention> ...\n" \
+ "```"
#client.event
async def on_message(message):
if message.content.startswith('w!cool '):
if not message.mentions:
return await message.channel.send(WCOOL_NO_MENTION_ERROR)
# Create a string for the response
response = str()
for mention in message.mentions:
percentage = random.choice(range(0, 100+1))
response += f"<#{mention.id}> is {percentage}% cool."
response += "\n"
await message.channel.send(response)
elif message.content == "w!cool":
return await message.channel.send(WCOOL_NO_MENTION_ERROR)
Based on my older answer from my other account but it's a little bit more readable. It works pretty much the same way with some things improved (such as caring about the situation when nothing comes after w!cool)
Also if anyone is reading this, don't use discord.py! It is unmaintained, so use a fork of it, such as Pycord.
I was wondering how I can make my mute command mute someone for a certain amount of time. For example p/mute #User 1h would mute someone for 1 hour.
#client.command()
#commands.has_permissions(manage_roles = True)
async def mute(ctx, member : discord.Member = None):
if member == None:
await ctx.send("Please mention a user to mute")
else:
user = member
role = discord.utils.get(ctx.guild.roles, name="Muted")
if role is None:
await ctx.send("Please make a muted role name `Muted` or make sure to name the role `Muted` and not `muted` or `MUTED`")
else:
await user.add_roles(role)
await ctx.send(f"{member.name} has been muted by {ctx.author.name}")
This site has an example on one way to do this, however I found it needed some slight modifications to work - it was giving me errors in some spots prior to my edits. Below code worked in my server:
#client.command(aliases=['tempmute'])
#commands.has_permissions(manage_messages=True)
async def mute(ctx, member: discord.Member=None, time=None, *, reason=None):
if not member:
await ctx.send("You must mention a member to mute!")
return
elif not time:
await ctx.send("You must mention a time!")
return
else:
if not reason:
reason="No reason given"
#Now timed mute manipulation
try:
time_interval = time[:-1] #Gets the numbers from the time argument, start to -1
duration = time[-1] #Gets the timed manipulation, s, m, h, d
if duration == "s":
time_interval = time_interval * 1
elif duration == "m":
time_interval = time_interval * 60
elif duration == "h":
time_interval = time_interval * 60 * 60
elif duration == "d":
time_interval = time_interval * 86400
else:
await ctx.send("Invalid duration input")
return
except Exception as e:
print(e)
await ctx.send("Invalid time input")
return
guild = ctx.guild
Muted = discord.utils.get(guild.roles, name="Muted")
if not Muted:
Muted = await guild.create_role(name="Muted")
for channel in guild.channels:
await channel.set_permissions(Muted, speak=False, send_messages=False, read_message_history=True, read_messages=False)
else:
await member.add_roles(Muted, reason=reason)
muted_embed = discord.Embed(title="Muted a user", description=f"{member.mention} Was muted by {ctx.author.mention} for {reason} to {time}")
await ctx.send(embed=muted_embed)
await asyncio.sleep(int(time_interval))
await member.remove_roles(Muted)
unmute_embed = discord.Embed(title='Mute over!', description=f'{ctx.author.mention} muted to {member.mention} for {reason} is over after {time}')
await ctx.send(embed=unmute_embed)
This should create a new role called "Muted" in your server if it doesn't already exist, move the targeted member into said role for the time denoted, and then remove them from the role once time expires.
Example command using code (prefix of .):
.tempmute #SomeUser 10s Because I said so!
I have a pretty easy way of doing that. That will be efficient and less code required. I have been using that in my Bots for a long time. I have answered another question of the one user here: Bot unmuting member when use tempmute command
In the answer there I have explained on how to write a perfect command.
This command is completely another command. You don't have to modify your mute command. But just create a new command named tempmute.
I will copy and paste my answer from there to here. Please pay attention to every single statement. :)
TEMPMUTE Command.
Step 1: Define the function and permissions
We are going to define the function with some permissions restrictions on the use. People with the permissions specified permissions.
Before you use this, you need to have the following in your code:
from discord.ext import commands
(Ignore if you have it)
Here is how:
#bot.command()
#commands.has_permissions(manage_roles=True)
async def tempmute(ctx, member: discord.Member, time, *, reason=None):
You can add many more permission if you want and use True or False to allow or deny.
Step 2: Making a role finding condition. If the role doesn't exist then create a Muted role, if exist then use it.
So I am creating a condition for if the role exist. It will check if the role exist. If it exist then we will simply use it but if it doesn't we will create one with specific permissions.
Here is how:
if discord.utils.get(ctx.guild.roles, name="Muted"):
mute_role = discord.utils.get(ctx.guild.roles, name="Muted")
else:
perms = discord.Permissions(send_messages=False, add_reactions=False, connect=False, speak=False)
await bot.create_role(name="Muted", permissions=perms)
mute_role = discord.utils.get(ctx.guild.roles, name="Muted")
Step 3: Checking if someone is muted or not.
Now I am creating a condition for if the member is muted or not. We will through the member's roles and check it.
Here is how:
if mute_roles in member.roles:
await ctx.channel.send(f"{member.mention} is already muted!")
else:
# code here (more steps will explain how)
Step 4: Adding conditions and muting the member.
Now we will add restriction permissions for this command. Who all people can't be muted and who all can be.
First we add our first condition, that administrators can not be muted.
Here is how:
if member.guild_permissions.administrator:
isadminembed=discord.Embed(title="Tempmute", description=f"Hi {ctx.author.mention}, you can't mute {member.mention} as they are a Server Administrator.", color=discord.Colour.red())
isadminembed.set_author(name="Bot")
await ctx.channel.send(embed=isadminembed)
Now we will add else condition, that all other members except administrators can be muted.
Here is how:
else:
time_conversion = {"s": 1, "m": 60, "h": 3600, "d": 86400, "w": 604800, "M": 2419200, "y": 29030400}
mute_time = int(time[:-1]) * time_conversion[time[-1]]
await member.add_roles(mute_role)
mutedembed=discord.Embed(title="Tempmute", description=f"The member, {member.mention} has been muted by the moderator {ctx.author.mention}. \n \nTime: {mute_time} seconds \nReason: {reason}", color=discord.Colour.random())
mutedembed.set_author(name="Bot")
await ctx.channel.send(embed=mutedembed)
await asyncio.sleep(mute_time)
await member.remove_roles(mute_role)
await ctx.channel.send(f"{member.mention} has been unmuted!")
I have added time conversion here. The time input has to be:
1s for one second, 1m for one minute, etc. You can use it for years too.
Tempmute Command Compiled
This is all the code compiled together as the command.
#bot.command()
#commands.has_permissions(manage_roles=True)
async def tempmute(ctx, member: discord.Member, time, *, reason=None):
if discord.utils.get(ctx.guild.roles, name="Muted"):
mute_role = discord.utils.get(ctx.guild.roles, name="Muted")
else:
perms = discord.Permissions(send_messages=False, add_reactions=False, connect=False, speak=False)
await bot.create_role(name="Muted", permissions=perms)
mute_role = discord.utils.get(ctx.guild.roles, name="Muted")
if mute_roles in member.roles:
await ctx.channel.send(f"{member.mention} is already muted!")
else:
if member.guild_permissions.administrator:
isadminembed=discord.Embed(title="Tempmute", description=f"Hi {ctx.author.mention}, you can't mute {member.mention} as they are a Server Administrator.", color=discord.Colour.red())
isadminembed.set_author(name="Bot")
await ctx.channel.send(embed=isadminembed)
else:
time_conversion = {"s": 1, "m": 60, "h": 3600, "d": 86400, "w": 604800, "M": 2419200, "y": 29030400}
mute_time = int(time[:-1]) * time_conversion[time[-1]]
await member.add_roles(mute_role)
mutedembed=discord.Embed(title="Tempmute", description=f"The member, {member.mention} has been muted by the moderator {ctx.author.mention}. \n \nTime: {mute_time} seconds \nReason: {reason}", color=discord.Colour.random())
mutedembed.set_author(name="Bot")
await ctx.channel.send(embed=mutedembed)
await asyncio.sleep(mute_time)
await member.remove_roles(mute_role)
await ctx.channel.send(f"{member.mention} has been unmuted!")
TEMPMUTE Command Error Handling
Step 1: Defining the function as an event.
We will define the function in the script as tempmute command's error and declare it as an error.
Here is how:
#bot.error
async def tempmute_error(ctx, error):
Step 2: Adding the instance of the error.
We will now add a condition for the error. Our error will be: MissingRequiredArgument error as the command can lack necessary arguments.
So the isinstance will check the error and then do the stuff.
Here is how:
if isinstance(error, discord.ext.commands.MissingRequiredArgument):
tempmuteerrorembed=discord.Embed(title=f"Missing Argument! {error}", description=f"Hello {ctx.author.mention}! You have not entered the needed argument. \n Either you forgot to **mention the member** or you forgot to **enter the time of the mute** you want. \n \n Please check this again and add the necessary argument in the command. \n \nThis is the syntax: \n```!tempmute <mention member> <time: 1s, 2h, 4y etc..> <reason (optional)>```", color=discord.Colour.red())
tempmuteerrorembed.set_author(name="Bot")
await ctx.send(embed=tempmuteerrorembed)
This will work for MissingRequiredArguement and show the error with the syntax in it for the command's correct usage.
TEMPMUTE Command Error Handling Compiled
Here is the compiled code of Error Handling of TEMPMUTE Command.
#bot.error
async def tempmute_error(ctx, error):
if isinstance(error, discord.ext.commands.MissingRequiredArgument):
tempmuteerrorembed=discord.Embed(title=f"Missing Argument! {error}", description=f"Hello {ctx.author.mention}! You have not entered the needed argument. \n Either you forgot to **mention the member** or you forgot to **enter the time of the mute** you want. \n \n Please check this again and add the necessary argument in the command. \n \nThis is the syntax: \n```!tempmute <mention member> <time: 1s, 2h, 4y etc..> <reason (optional)>```", color=discord.Colour.red())
tempmuteerrorembed.set_author(name="Bot")
await ctx.send(embed=tempmuteerrorembed)
I hope I was able to explain to you the answer and how to write the command. Please ask in the comments for any issue that arises.
Thank You! :D
#bot.command()
#commands.has_permissions(manage_messages=True)
async def clear(ctx,member : discord.Member,amount=200):
await ctx.channel.purge(limit=amount)
if amount > 200:
await ctx.send(f"{member.mention}merci de clear entre 0-200 message(s)")
else:
await ctx.send(f"j'ai clear {amount} message(s)",delete_after=5)```
error:
File "C:\Users\dzzdz\PycharmProjects\pythonProject12\venv\lib\site-packages\discord\ext\commands\core.py", line 451, in _actual_conversion
ret = await instance.convert(ctx, argument)
File "C:\Users\dzdz\PycharmProjects\pythonProject12\venv\lib\site-packages\discord\ext\commands\converter.py", line 195, in convert
raise MemberNotFound(argument) discord.ext.commands.errors.MemberNotFound: Member "300" not found.
In this error, we can see that the command works only if I do !clear # (amount).
If I remove the discord.member it's working. I can't remove the discord.member because one can't have an optional argument that comes before a default argument.
So what can I do?
Here are some errors that I noticed:
First) Since you are looking for the author of the message, member is not relevant here at all. We can simply use ctx.author for this and then display it as desired.
Second) You have a logic error in your code. Your if amount >200 statement is not considered the way your code is and then more than 200 messages can be deleted without the error message showing up.
One possible code would be:
#client.command() / #bot.command() / #commands.command() # Depends on what you use
#commands.has_permissions(manage_messages=True)
async def clear(ctx, amount=200):
if amount > 200:
await ctx.send(f"{ctx.author.mention} merci de clear entre 0-200 message(s)")
return # Do not proceed
else:
await ctx.send(f"j'ai clear {amount} message(s)", delete_after=5)
await ctx.channel.purge(limit=amount) # Clear messages if lower than 200
I interpreted your question as "I want to have a user, but if I don't mention the person I get an error. Help?" There are a few ways to do this of course, so I will show you two of them.
Method 1: Using None
If you do not want to use any extra imports, you can move your member to the front and make it None. For both the methods, you will need to use an if statement to change your member to the ctx.author.
#bot.command()
#commands.has_permissions(manage_messages=True)
async def clear(ctx,amount=200,member : discord.Member=None): # moved the member to the right
if member == None: # if no one is mentioned
member = ctx.author # default to ctx.author
await ctx.channel.purge(limit=amount)
if amount > 200:
await ctx.send(f"{member.mention}merci de clear entre 0-200 message(s)")
else:
await ctx.send(f"j'ai clear {amount} message(s)",delete_after=5)
Method 2: Using typing.Optional.
This is often used as an optional argument. This allows for your member to be left in the middle.
import typing
# ...
# other code
#bot.command()
#commands.has_permissions(manage_messages=True)
async def clear(ctx, member: typing.Optional[discord.Member]=None, amount=200): # member is kept in the middle
if member == None: # if no one is mentioned
member = ctx.author # default to ctx.author
await ctx.channel.purge(limit=amount)
if amount > 200:
await ctx.send(f"{member.mention}merci de clear entre 0-200 message(s)")
else:
await ctx.send(f"j'ai clear {amount} message(s)",delete_after=5)
This is my discord.py bot. When I type m!rate (person) It sends me a text like this. However, I don't want the (' and ',) at the beginning and end of the message.
This is my code:
#client.command()
async def rate(ctx, *member):
if len(member) == 0:
await ctx.send("You forgot to mention someone")
else:
value = random.randint(1,10)
await ctx.send(f"I rate {member} {value}/10")
When I change it, the message works but the error doesn't. I can't find any solution.
Using * in a parameter makes the function pass positional arguments into a tuple, hence the brackets. This is usually for when you want to unpack an arbitrary amount of arguments.
To fix it, just remove *, and also add a type for the parameter if you want:
#client.command()
async def rate(ctx, member: discord.Member = None): # setting a default value of None
if not member: # testing to see if the default value is None
await ctx.send("You forgot to mention someone")
else:
value = random.randint(1,10)
await ctx.send(f"I rate {member.mention} {value}/10")
References:
Using * in Python
discord.Member
Member.mention
If you want your bot to mention one person per command :
#client.command()
async def rate(ctx, *member):
if member:
"".join(member)
value = random.randint(1,10)
for user in ctx.guild.members:
if user.name.lower() == member.lower() or user.nick.lower() == member.lower():
await ctx.send(f"I rate {user.mention} {value}/10")
else:
await ctx.send("Member not found!")
else:
await ctx.send("You forgot to mention someone")
If you want your bot to mention multiple people per command :
#client.command()
async def rate(ctx, *members):
if members:
embed = Discord.embed(color = discord.color.blue(), title = "title")
count = 0
for member in members:
value = random.randint(1,10)
for user in ctx.guild.members:
if user.name.lower() == member.lower() or user.nick.lower() == member.lower():
embed.add_field(name = f"{user.mention}", value = f"I rate him {value}/10")
count += 1
if count != 0:
await ctx.send(embed=embed)
else:
await ctx.send("Members not found!")
else:
await ctx.send("You forgot to mention someone")