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")
Related
This code is trying to check how many members are online and offline however it comes up with an error message that says guilds cannot be iterated. If the code would work it would send a message with the number of members and how many are online and offline any help would be appreciated.
count1=0
count2=0
#client.command()
async def stats(ctx):
for member in ctx.guild:
if member.status == status.online:
count1 = +1
else:
count2 = +1
embed = discord.Embed(title=ctx.guild.name+"Stats", color=0x000)
embed.add_field(name="Member Count", value=ctx.guild.member_count)
embed.add_field(name="Online", value="f'{coun1}' :green_circle:", inline=True)
embed.add_field(name="Offline", value ="f'{count2}' :red_circle:", inline = True)
await ctx.send(embed=embed)
A online member status can be dnd, idle or streaming:
#client.command()
async def stats(ctx):
count = 0
for member in ctx.guild.members: # .members was added
if member.status != status.oflline:
count =+ 1
embed = discord.Embed(title=ctx.guild.name+"Stats", color=0x000)
embed.add_field(name="Member Count", value=ctx.guild.member_count)
embed.add_field(name="Online", value="f'{count}' :green_circle:", inline=True)
embed.add_field(name="Offline", value ="f'{ctx.guild.member_count - count}' :red_circle:", inline = True)
await ctx.send(embed=embed)
First I looped through all the members from the guild and added them to the online_members list or offline_members list and stored nicknames for all users (this way you can use it later if you would like to make some type of list of users). Also, I used discord.Status.offline instead of online because Discord has a few other status types and some users wouldn't be counted (list of all status types).
My code (with lists of members):
#client.command()
async def stats(ctx):
online_members = []
offline_members = []
for member in ctx.guild.members:
if member.status is not discord.Status.offline:
online_members.append(member.name)
else:
offline_members.append(member.name)
embed = discord.Embed(title=f'"{ctx.guild.name}" Stats', color=0x000)
embed.add_field(name="Member Count", value=ctx.guild.member_count)
embed.add_field(name="Online", value=f'{len(online_members)} :green_circle:', inline=True)
embed.add_field(name="Offline", value =f'{len(offline_members)} :red_circle:', inline = True)
await ctx.send(embed=embed)
If you prefer to use your code:
#client.command()
async def stats(ctx):
count=0 #put these at the beginning of your command so it will reset every time, otherwise, your starting number would be the sum of all earlier commands
for member in ctx.guild.members: #you forgot to get members
if member.status != discord.Status.offline:
count += 1 #you can't use "= +1" - "+= 1" is correct
all_users = ctx.guild.member_count
embed = discord.Embed(title=f'**{ctx.guild.name}** "Stats"', color=0x000)
embed.add_field(name="Member Count", value=all_users)
embed.add_field(name="Online", value=f'"{count}" :green_circle:', inline=True) #your "f" was in wrong place
embed.add_field(name="Offline", value =f'"{all_users - count}" :red_circle:', inline = True)
await ctx.send(embed=embed)
Remember to enable intents.members and intents.presences!
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')
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 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
So I have a piece of code and it requires user input multiple times (and what is inputed is not alway the same). Instead of passing the code to everyone in my discord I would like to make it directly into a discord bot so everyone can use it. How do I all the bot to take in a user msg after a code is given
here is an example of kinda what I want:
-.botcalc
--this is discord bot, enter first number:
-1
--enter second number:
-2
--1+2 = 3
There are two ways you could write this command: one is using the "conversation" style in your question
from discord.ext.commands import Bot
bot = Bot("!")
def check(ctx):
return lambda m: m.author == ctx.author and m.channel == ctx.channel
async def get_input_of_type(func, ctx):
while True:
try:
msg = await bot.wait_for('message', check=check(ctx))
return func(msg.content)
except ValueError:
continue
#bot.command()
async def calc(ctx):
await ctx.send("What is the first number?")
firstnum = await get_input_of_type(int, ctx)
await ctx.send("What is the second number?")
secondnum = await get_input_of_type(int, ctx)
await ctx.send(f"{firstnum} + {secondnum} = {firstnum+secondnum}")
The second is to use converters to accept arguments as part of the command invocation
#bot.command()
async def calc(ctx, firstnum: int, secondnum: int):
await ctx.send(f"{firstnum} + {secondnum} = {firstnum+secondnum}")
Using wait_for
async def botcalc(self, ctx):
author = ctx.author
numbers = []
def check(m):
return m.author == author
for _ in ('first', 'second'):
await ctx.send(f"enter {_} number")
num = ""
while not num.isdigit():
num = await client.wait_for('message', check=check)
numbers.append[int(num)]
await channel.send(f'{numbers[0]}+{numbers[1]}={sum{numbers)}')
edit
Added a check