I'm trying to do something like the 'tempmute' command, but an error keeps popping up
:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 939, in invoke
await ctx.command.invoke(ctx)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 863, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: NotFound: 404 Not Found (error code: 10011): Unknown Role
And here is the command code
#commands.command()
#commands.has_permissions(ban_members=True)
async def tempmute(self, ctx, member: discord.Member = None, * time):
if not member:
await ctx.send(embed=discord.Embed(title='Вы должны указать участника!', color=random.choice(colors)))
else:
LMUTED = discord.utils.get(ctx.message.guild.roles, name='LMUTED')
if not LMUTED:
perms=discord.Permissions(send_messages=False)
await ctx.guild.create_role(name='LMUTED',
colour=discord.Colour(0x0000FF),
permissions = perms)
await ctx.send(f'Я создал роль `{LMUTED}`!')
await member.add_roles(member, LMUTED)
await ctx.send(f'Я замьютил {member} на {time}!')
await s(time * 60)
await ctx.remove_roles(member, LMUTED)
Make sure you know how to read python errors.
But the main issue here is that you don't assign LMUTED a value after you create a new role, so it is still None and thus discord.py fails to add the role.
Also, keep in mind that when you do things that expire over time, simply sleeping/waiting in the method is not a good way to handle it, as the thread might be locked. Instead you should use some sort of scheduler. Basically a thing that waits a certain amount of time before running some code.
Related
I tried to make a purge command, here is my code:
#bot.command(pass_context=True)
#commands.has_permissions(administrator=True)
async def purge(ctx, limit: int):
await ctx.channel.purge(limit=limit)
await ctx.message.delete()
await ctx.send(f'Deleted {limit} messages. Done by {ctx.author.mention}.')
await asyncio.sleep(2)
await bot.delete.message.most_recent()
but when i try to run the command, it deletes the messages but gives this error when it tries to delete the message:
Ignoring exception in command purge:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "main.py", line 312, in purge
await ctx.message.delete()
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/message.py", line 1023, in delete
await self._state.http.delete_message(self.channel.id, self.id)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/http.py", line 250, in request
raise NotFound(r, data)
discord.errors.NotFound: 404 Not Found (error code: 10008): Unknown Message
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 939, in invoke
await ctx.command.invoke(ctx)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 863, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: NotFound: 404 Not Found (error code: 10008): Unknown Message
Any help?
You can try this instead:
#bot.command(pass_context=True)
#commands.has_permissions(administrator=True)
async def purge(ctx, limit: int):
await ctx.channel.purge(limit=limit)
await ctx.message.delete()
await ctx.send(f'Deleted {limit} messages. Done by {ctx.author.mention}.', delete_after = 2)
The delete_after deletes the message sent by bot after specific number of seconds.
Late answer but I think this might help you. Using your code all what you have to do is save the message that you just sent into a variable and then, delete that message.
#bot.command()
#commands.has_permissions(administrator=True)
async def purge(ctx, limit: int):
await ctx.channel.purge(limit=limit)
await ctx.message.delete()
message = await ctx.send(f'Deleted {limit} messages. Done by {ctx.author.mention}.')
await asyncio.sleep(2)
await message.delete()
I'm trying to make a simple command that allows a user to give themselves a role, but if the role doesn't exist, it will create the role first, then give them the role. Here is my current code:
#bot.command()
async def SetRole(ctx, arg):
roles = ctx.guild.roles
user = ctx.message.author
#check if role does not exist
if arg not in [role.name for role in roles]:
await ctx.guild.create_role(name=arg)
await user.add_roles(discord.utils.get(roles, name=arg))
The expected result when I run $SetRole test_role if test_role does not exist, would be that the bot creates the role and then gives me the role. However, the role is created but is not given to me. Here is there error and stack trace:
Ignoring exception in command SetRole:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "main.py", line 17, in SetRole
await user.add_roles(discord.utils.get(roles, name=arg))
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/member.py", line 777, in add_roles
await req(guild_id, user_id, role.id, reason=reason)
AttributeError: 'NoneType' object has no attribute 'id'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 939, in invoke
await ctx.command.invoke(ctx)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 863, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'NoneType' object has no attribute 'id'
If I run the command a second time, the role is successfully given to me. What I presume is happening is for some reason, the user.add_roles() is happening before the create_role most likely because of some weirdness with async. How can I make sure that it adds the role after its created?
This isn't a race condition, just that discord.py doesn't track and mutate objects everywhere
A better implementation would be:
from typing import Union
#bot.command()
async def SetRole(ctx, role: Union[Role, str]):
if isinstance(role, str):
role = await ctx.guild.create_role(name=role)
await user.add_roles(role)
Union is just a way to represent "any of the given types", so discord.py [cleverly] either return a role or a string as fallback, we can then create the role if it doesn't already exist by checking if role is a string
This might need a little explaining. I made a command that sudo's someone called p!sudo [member.mention] [message]. It works like this:
#client.command()
async def sudo(ctx, member: discord.Member, *, message=None):
await ctx.message.delete()
webhooks = await ctx.channel.webhooks()
for webhook in webhooks:
await webhook.delete()
webhook = await ctx.channel.create_webhook(name=member.name)
await webhook.send(str(message),
username=member.name,
avatar_url=member.avatar_url)
Now, I want to make another command that sudo's everyone in the server. Here's what I got:
#client.command()
async def sudoall(ctx, *, message=None):
for member in ctx.guild.member:
webhooks = await ctx.channel.webhooks()
for webhook in webhooks:
await webhook.delete()
webhook = await ctx.channel.create_webhook(name=member.name)
await webhook.send(str(message),
username=member.name,
avatar_url=member.avatar_url)
However, I get this error message:
Ignoring exception in command sudoall:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "main.py", line 34, in sudoall
for member in ctx.guild.member:
AttributeError: 'Guild' object has no attribute 'member'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 903, in invoke
await ctx.command.invoke(ctx)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 859, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'Guild' object has no attribute 'member'
Use ctx.guild.members to get the list of members belonging in a guild
So im trying to make a discord bot, and I want to make a command that sends a message to all channels.
#client.command(pass_context = True)
async def send_all(ctx):
channel = client.get_all_channels()
await channel.send("I sent this to all channels")
At first(When I make the bot online), there are no errors. But when I run the command, no output comes out in discord and in the console, this comes:
Traceback (most recent call last):
File "C:\Users\User\anaconda3\lib\site-packages\discord\ext\commands\bot.py", line 903, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\User\anaconda3\lib\site-packages\discord\ext\commands\core.py", line 859, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\User\anaconda3\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: can't send non-None value to a just-started generator
for channel in client.get_all_channels():
# get_all_channels also include voice channels, just check if it's not
if isinstance(channel, discord.TextChannel):
await channel.send('whatever')
You can also:
for guild in client.guilds:
for channel in guild.text_channels:
await channel.send('whatever')
Bot.get_all_channels yields a GuildChannel obj - means it's an iterator, to learn more about iterators check this answer
Reference:
Bot.get_all_channels
Bot.guilds
Guild.text_channels
So I'm trying to make a kick command so that if the reason is nothing, then it says "no reason" instead of none. Don't ask why.
Here's my code:
#client.command()
#commands.has_permissions(kick_members=True)
async def kick(ctx, user: discord.Member, *, reason: str):
if reason is None:
await user.kick()
await ctx.send(f"**{user}** has been kicked for **no reason**.")
else:
await user.kick(reason=reason)
await ctx.send(f"**{user}** has been kicked for **{reason}**.")
And here's the error:
Ignoring exception in command kick:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 903, in invoke
await ctx.command.invoke(ctx)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 847, in invoke
await self.prepare(ctx)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 784, in prepare
await self._parse_arguments(ctx)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 699, in _parse_arguments
kwargs[name] = await self.transform(ctx, param)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 535, in transform
raise MissingRequiredArgument(param)
discord.ext.commands.errors.MissingRequiredArgument: reason is a required argument that is missing.
I don't understand why it says that "reason is a required argument that is missing" because I said that if reason is None it would say no reason?
If you assign None to the reason, then you can check it. For example reason = None. After that you can check in the commmand if the reason is None. Here is the code:
#client.command()
#commands.has_permissions(kick_members=True)
async def kick(ctx, user: discord.Member, *, reason = None):
if not reason:
await user.kick()
await ctx.send(f"**{user}** has been kicked for **no reason**.")
else:
await user.kick(reason=reason)
await ctx.send(f"**{user}** has been kicked for **{reason}**.")
You're getting that error because your function looks like this:
async def kick(ctx, user: discord.Member, *, reason: str):
Reason is not optional here, so it is a required argument. That means that calling this function without that argument will result in an error. Adding in a default value makes it optional.
def function(requiredArgument, optionalArgument=defaultValue)
In this case, defaultValue should be None. Now, when you don't pass in anything for that argument, it's default value will be used. That way, you no longer have to add a reason.