Important note: I'm not using the rewrite.
I've been trying to unban specific users on a message in discord.py with a command.
Example:
On the command "!unban," the bot unbans a user who was not mentioned in the command.
I've tried something like
#client.event
async def on_message(message):
if message.content == x:
await message.guild.unban('[User ID], *, reason=none')
which results in
await self._state.http.unban(user.id, self.id, reason=reason)
AttributeError: 'str' object has no attribute 'id'
If anybody could help me out, I'd appreciate it. I'm pretty lost.
The proper usage of that command is guild.unban(user, reason=None). The asterisk is not required in a call to the function, and =None indicates that reason is optional. If you do not have a reason:
In your case:
await message.guild.unban(userID)
Should do the job, so long as your user ID is in the format of a snowflake object (e.g. a User object for that user!)
Related
I am trying to get the User ID when I mention them in a command.
I have a command to warn members, and I want to keep track of a member's warnings. So I want their User ID to keep track of the same. But when I try to get a User ID when I mention them, it says Command raised an exception: AttributeError: 'str' object has no attribute 'id'.
The code I used to get the User ID is -
#commands.command()
async def getID(self, ctx, member):
ctx.send(member.id)
Note that I am using Cogs, that's why I passed in self first.
Thank you in advance.
In your definition (self, ctx, member) - your bot gets just text from discord and without anything library will think of member as a string object and thus it does not have attribute 'id', as your error says. The library's solution to this: type-hinting, if you provide type-hint like this ..., member: discord.Member) - the library will try to convert provided input into discord.Member object, which will have member.id as its attribute.
ctx.send is a coroutine and thus should be awaited
So MRE would look something like this
#commands.command()
async def getID(self, ctx: commands.Context, member: discord.Member):
await ctx.send(member.id)
If I want to remove an ID-specified role within a function, how can I do that?
#bot.command()
async def aa(ctx,member:discord.Member):
role_muted = discord.utils.get(ctx.guild.roles, name='test01')
await member.remove_roles(role_muted)
What I want is to specify an ID in a function like this.
#bot.command()
async def aa(ctx):
member = 414087251992117211 #ID User
role_muted = discord.utils.get(ctx.guild.roles, name='test01')
await member.remove_roles(role_muted)
how can i do it The reason I have to do this is because I will continue to develop such as When you receive this Role within 3 days if not online it will remove your Role.
Use Guild.get_member(id) to get a member by their ID. You can get the Guild either from the ctx if you want it to run in the guild where you call the command, or from a Guild ID that you store somewhere using Bot.get_guild(id).
If you want to pass the ID in as an argument to the function and have it convert to a member automatically, use a Converter.
Can you give an example? I tried to do as you said. but an error occurred
#bot.command()
async def aa(ctx):
member = discord.Guild.get_member(414087251992117211)
role_muted = discord.utils.get(ctx.guild.roles, name='test01')
await member.remove_roles(role_muted)
Error
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'NoneType' object has no attribute 'remove_roles'
#UpFeR Pattamin, please comment on a reply instead of posting a new one. You're getting this error because you're not specifying which guild you are talking about. If you want to get the one that the command was executed in, I'm pretty sure you need to do ctx.guild.get_member().
I used this command, but the bot not ban anyone and does not write an error to the console.
#bot.command()
async def massban(ctx):
for user in ctx.guild.members:
try:
await user.ban()
except:
pass
As Fixator also mentioned, you won't be able to see the error as far as you're excepting every error and passing it.
#bot.command()
async def massban(ctx):
for user in ctx.guild.members:
try:
await user.ban()
except Exception as error:
print(error)
pass
That's how you can catch the error without interrupting the for-loop.
Please also doublecheck the permissions of your bot and the member listing.
If you sure that bot has a ban perms on server.
Check if bot has enough cache for that operation. For example, send len(guild.members) into channel before iterating over members. If it says 1-2, you, most likely, dont have enough intents.
Bot can't ban users that has roles above bot's top role:
I am trying to make a simple moderator bot.
the code looks something like this.
import discord
from discord.ext import commands
from random import choice
import os
client = commands.Bot(command_prefix=commands.when_mentioned_or("%"), description='A simple Moderator bot')
def colour():
l = [ 1752220, 3066993, 3447003, 10181046, 15844367, 15105570, 15158332, 3426654, 16580705 ]
return choice(l)
#client.event
async def on_ready():
change_status.start()
print("The Bot is online!")
#client.command()
#commands.has_permissions(administrator=True)
async def kick(ctx, user : discord.Member = None, *,reason = "No reason provided"):
await user.kick(reason = reason)
await ctx.send("Kicked the user.")
#client.command()
#commands.has_permissions(administrator=True)
async def ban(ctx, user : discord.Member = None, *,reason = "No reason provided"):
await user.ban(reason = reason)
await ctx.send("Banned the user")
#client.command()
#commands.has_permissions(administrator=True)
async def warn(ctx, user : discord.Member = None, *,reason = "No reason provided"):
await user.send(f"You have been **Warned** by **{ctx.author.name}** in the **{ctx.guild.name}** for the reason: **{reason}** ")
await ctx.send("Warned the user")
client.run(os.environ['token'])
In this only warn command is working successfully rest all the commands throws an error which looks like this.
Ignoring exception in command kick:
Traceback (most recent call last):
File "main.py", line 140, in kick
await user.kick(reason = reason)
File "/app/.heroku/python/lib/python3.6/site-packages/discord/member.py", line 524, in kick
await self.guild.kick(self, reason=reason)
File "/app/.heroku/python/lib/python3.6/site-packages/discord/guild.py", line 1886, in kick
await self._state.http.kick(user.id, self.id, reason=reason)
File "/app/.heroku/python/lib/python3.6/site-packages/discord/http.py", line 241, in request
raise Forbidden(r, data)
discord.errors.Forbidden: 403 Forbidden (error code: 50013): Missing Permissions
It is throwing a missing permission but I am the owner of the server and even added the bot as an admistrator.
Even tried by making an administrator role and giving all the permissions to it but still no luck.
This error is coming again and again.
Even if anyone know how to check between multiple roles like if anyone has administrator or kick member permission then do this, please let me know how to do that.
Thanks in advance for the help.
If any more information needed, do let me know.
The error you are getting on the last line from your console; discord.errors.Forbidden: 403 Forbidden (error code: 50013): Missing Permissions Is because the bot is missing permissions to perform these actions against the given permissions the bot currently has.
This could occur from the following;
Sufficient Bot permissions haven't been enabled from the invite link
The member has a higher or equal role than the bot
The #everyone role has no permissions
Moreover, these issues aren't at fault with the code you have written and is something that can be fixed in your server with the role hierarchy or bot invite link permissions.
I would also recommend comparing roles to make sure users can't attempt moderation on a higher level member in the first place, this could also help to mitigate the problem
With this, you can use >= and the top_role attribute which would compare the roles that the user compared to the member you are attempting to take moderation on, if your permissions are lower than the member you are attempting to moderate, it will prevent the rest of the code running. Here is a simple way of doing this,
if member.top_role >= ctx.author.top_role:
await ctx.send(f"You can only moderate members below your role")
return
I want to use regex to look at and accept literally ANY incoming message from a user and assign them a role. But ONLY if that user does not have a role already assigned to them. I don't get any errors when running the code, but it does not work.
Here is what I have:
#client.event
async def on_message(message):
match = re.search(r'(.*?)', message.content)
member = message.author
role = discord.utils.get(member.guild.roles, name="Creators")
if message.author == client.user:
return
if role not in member.roles:
if match and message.channel.id == target_channel:
# add member to role
# send message to to users
await message.channel.send(
f'Hi {message.author}, welcome to the server! Don\'t forget to choose your #roles'
)
await discord.Member.add_roles(member, role)
You wrote:
await discord.Member.add_roles(member, role)
https://discordpy.readthedocs.io/en/latest/api.html?highlight=add_role#discord.Member.add_roles
As you can see from the documentation the passed arguments is *roles, reason=None, atomic=True. roles is something you have to specify, reason and atomic are optional.
You tried passing member which is not a valid argument.
discord.Member is a class. You need to get an instance of that class. ctx.author is an instance of discord.Member.
So the final call should be:
await ctx.author.add_roles(role)
To get the Member object from on_message, you can use member = message.author.
Then simply do member.add_roles(role).
Thanks for the help guys, it turns out it was something very minor (and dumb on my part) that prevented it from working.
when comparing message.channel.id.id to target_channel, I forgot that the channel id object does not come in as a string, but target_channel was set up as a string, so it failed to see them as equal. Simply converting message.channel.id to string did the trick.