Unbanning a member from all guilds the bot is in - python

I am trying to unban a member from all guilds that the bot is in.
My issue is when i run the command with the banned users ID in it i get the following error.
Traceback (most recent call last):
File "C:\Users\Shadow\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\bot.py", line 1114, in invoke_application_command
await ctx.command.invoke(ctx)
File "C:\Users\Shadow\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\commands\core.py", line 375, in invoke
await injected(ctx)
File "C:\Users\Shadow\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\commands\core.py", line 132, in wrapped
raise ApplicationCommandInvokeError(exc) from exc
discord.errors.ApplicationCommandInvokeError: Application Command raised an exception: NotFound: 404 Not Found (error code: 10007): Unknown Member
These are the steps I have tried.
async for guild in self.bot.fetch_guilds():
userr = await guild.fetch_member(id)
if userr in guild.bans:
await guild.unban(userr)
await ctx.send("Unbanned the user.")
I am expecting the bot to unban the specified ID from all the servers the bot is in.
FULL CODE:
#commands.slash_command(name="unban", description="When you have specified the user name and hashtag the bot will unban that user from all servers.")
async def unban(self, ctx, id: discord.SlashCommandOptionType.string):
async for guild in self.bot.fetch_guilds():
try:
user = await guild.fetch_member(ctx.author.id)
except discord.NotFound:
continue
head_admin = discord.utils.get(guild.roles, name="Head Admin")
developer = discord.utils.get(guild.roles, name="Developer")
owner = discord.utils.get(guild.roles, name="Owner")
if head_admin or developer or owner in user.roles:
async for guild in self.bot.fetch_guilds():
userr = await guild.fetch_member(id)
if userr in guild.bans:
await guild.unban(userr)
await ctx.send("Unbanned the user.")

I'm fairly certain this is because your id parameter is a string and it should be an int. Or you should be casting it to an int. Additionally, I think naming it id is bad practice as it will conflict with a builtin.
#commands.slash_command(name="unban", description="When you have specified the user name and hashtag the bot will unban that user from all servers.")
async def unban(self, ctx, user_id):
try:
user_id = int(user_id)
except ValueError:
# not an actual int
# send message here
return
async for guild in self.bot.fetch_guilds():
try:
user = await guild.fetch_member(ctx.author.id)
except discord.NotFound:
continue
head_admin = discord.utils.get(guild.roles, name="Head Admin")
developer = discord.utils.get(guild.roles, name="Developer")
owner = discord.utils.get(guild.roles, name="Owner")
if head_admin or developer or owner in user.roles:
async for guild in self.bot.fetch_guilds():
userr = await guild.fetch_member(user_id)
if userr in guild.bans:
await guild.unban(userr)
await ctx.send("Unbanned the user.")
Then just use the user_id as the parameter instead. You can get that by right-clicking on a user with the developer settings turned on.

After doing some troubleshooting messing around with different user converters I have found the solution to my problem.
I had changed the user_id input to a user input which then you would put the user ID in.
It then loops through the guilds and unbans the user from all guilds.
If the user is not detected in a guilds ban list it will continue going through them.
#commands.slash_command(name="unban", description="When you have specified the user name and hashtag the bot will unban that user from all servers.")
async def unban(self, ctx, userr: discord.User):
async for guild in self.bot.fetch_guilds():
try:
user = await guild.fetch_member(ctx.author.id)
except discord.NotFound:
continue
head_admin = discord.utils.get(guild.roles, name="Head Admin")
developer = discord.utils.get(guild.roles, name="Developer")
owner = discord.utils.get(guild.roles, name="Owner")
if head_admin or developer or owner in user.roles:
try:
async for guild in self.bot.fetch_guilds():
await guild.unban(userr)
except:
continue
await ctx.send("Unbanned the user.")
else:
await ctx.respond("You don't have permission to run this command.")

Related

Discord.py (rewrite) mute command always returns the same response

I'm currently trying to build a discord.py mute command that sends an embed asking if the user is sure that they want to mute, and then when a reaction is added the mute is carried out and the embed is edited. I have run into some errors trying to do so.
#bot.command()
#commands.has_permissions(manage_guild=True)
async def mute(ctx, message, member: discord.Member = None):
guild = ctx.guild
user = member
if member == None:
await ctx.send(f'**{ctx.message.author},** please mention somebody to mute.')
return
if member == ctx.message.author:
await ctx.send(f'**{ctx.message.author},** you cannot mute yourself, silly.')
return
for role in guild.roles:
if role.name == "Muted":
if role in user.roles:
await ctx.send("**{}** is already muted.".format(user))
return
embedcheck=discord.Embed(title="Mute", colour=0xFFD166, description=f'Are you sure you want to mute **{user}?**')
embeddone=discord.Embed(title="Muted", colour=0x06D6A0,description=f'The mute has been done. **{user}** cannot talk in any channels anymore.')
embedfail=discord.Embed(title="Not Muted",colour=0xEF476F,description=f'The mute did not carry out as I did not receive a reaction in time.')
msg = await ctx.send(embed=embedcheck)
await message.add_reaction('✅','❌')
try:
def check(rctn, user):
return user.id == ctx.author.id and str(rctn) == '✅'
reaction, user = await bot.wait_for('reaction_add', timeout=60.0, check=check)
except asyncio.TimeoutError:
await msg.edit(embed=embedfail)
else:
for role in guild.roles:
if role.name == "Muted":
await member.add_roles(role)
await msg.edit(embed=embeddone)
When I run the command I always get the same output, "...please mention somebody to mute," even though I have mentioned somebody. When I don't mention anybody, I get the error
raise MissingRequiredArgument(param)
discord.ext.commands.errors.MissingRequiredArgument: message is a required argument that is missing.
Leave out message in async def mute(ctx, message, member: discord.Member = None) and change await message.add_reaction(...) to await msg.add_reaction(...).
#bot.command()
#commands.has_permissions(manage_guild=True)
async def mute(ctx, member: discord.Member = None):
guild = ctx.guild
user = member
if member == None:
await ctx.send(f'**{ctx.message.author},** please mention somebody to mute.')
return
if member == ctx.message.author:
await ctx.send(f'**{ctx.message.author},** you cannot mute yourself, silly.')
return
for role in guild.roles:
if role.name == "Muted":
if role in user.roles:
await ctx.send("**{}** is already muted.".format(user))
return
embedcheck=discord.Embed(title="Mute", colour=0xFFD166, description=f'Are you sure you want to mute **{user}?**')
embeddone=discord.Embed(title="Muted", colour=0x06D6A0,description=f'The mute has been done. **{user}** cannot talk in any channels anymore.')
embedfail=discord.Embed(title="Not Muted",colour=0xEF476F,description=f'The mute did not carry out as I did not receive a reaction in time.')
msg = await ctx.send(embed=embedcheck)
await msg.add_reaction('✅')
await msg.add_reaction('❌')
try:
def check(rctn, user):
return user.id == ctx.author.id and str(rctn) == '✅'
reaction, user = await bot.wait_for('reaction_add', timeout=60.0, check=check)
except asyncio.TimeoutError:
await msg.edit(embed=embedfail)
else:
for role in guild.roles:
if role.name == "Muted":
await member.add_roles(role)
await msg.edit(embed=embeddone)
You mentioned a user that went to message instead of member. Not mentioning anyone leaves message empty and sends you an error because it is a required argument.
I didn't check if it will mute but this should fix your MissingRequiredArgument error.

Assign discord role when user reacts to message in certain channel

I want a user to be assigned a role when they choose a certain reaction in my welcome-and-roles discord channel. I've looked everywhere and can't find code in python that works with the most up-to-date version of discord.py. Here is what I have so far:
import discord
client = discord.Client()
TOKEN = os.getenv('METABOT_DISCORD_TOKEN')
#client.event
async def on_reaction_add(reaction, user):
role_channel_id = '700895165665247325'
if reaction.message.channel.id != role_channel_id:
return
if str(reaction.emoji) == "<:WarThunder:745425772944162907>":
await client.add_roles(user, name='War Thunder')
print("Server Running")
client.run(TOKEN)
Use on_raw_reaction_add instead of on_reaction_add, As on_reaction_add will only work if the message is in bot's cache while on_raw_reaction_add will work regardless of the state of the internal message cache.
All the IDS, Role IDs, Channel IDs, Message IDs..., are INTEGER not STRING, that is a reason why your code not works, as its comparing INT with STR.
Also you need to get the role, you can't just pass in the name of the role
Below is the working code
#client.event
async def on_raw_reaction_add(payload):
if payload.channel_id == 123131 and payload.message_id == 12121212: #channel and message IDs should be integer:
if str(payload.emoji) == "<:WarThunder:745425772944162907>":
role = discord.utils.get(payload.member.guild.roles, name='War Thunder')
await payload.member.add_roles(role)
Edit: For on_raw_reaction_remove
#client.event
async def on_raw_reaction_remove(payload):
if payload.channel_id == 123131 and payload.message_id == 12121212: #channel and message IDs should be integer:
if str(payload.emoji) == "<:WarThunder:745425772944162907>":
#we can't use payload.member as its not a thing for on_raw_reaction_remove
guild = bot.get_guild(payload.guild_id)
member = guild.get_member(payload.user_id)
role = discord.utils.get(guild.roles, name='War Thunder')
await member.add_roles(role)

unban command discord.py rewrite

I need an efficent discord.py command for unban users by their tag, not their name and discriminator. how i can do?
This is the code that I made and it works with *unban name#1234.
#client.command()
#commands.has_any_role(702909770956406885, 545323952428417064, 545323570587369472)
async def unban(ctx, *, member):
banned_user = await ctx.guild.bans()
member_name, member_discriminator = member.split("#")
for ban_entry in banned_user:
user = ban_entry.user
if (user.name, user.discriminator) == (member_name, member_discriminator):
await ctx.guild.unban(user)
embed = discord.Embed(title="Fatto!", description=f"Ho sbannato {user.mention}!", color=discord.Color.green())
await ctx.send(embed=embed)
return
How can i make it work with tags? I know you can't directly tag a banned user but with his id you can do it. Thank you for answers!
Hope this helps
from discord.ext.commands import has_permissions
#bot.command()
#has_permissions(ban_members=True)
async def unban(ctx, userId: discord.User.id):
user = get(id=userId)
await ctx.guild.unban(user)
Use the member object as a parameter in your unban function.
Ex:
#client.command()
#commands.has_any_role(702909770956406885, 545323952428417064, 545323570587369472)
async def unban(ctx, *, member: discord.Member):
await ctx.guild.unban(member)
Then in discord you could execute the command by mentioning the user.
Ex: *unban #aleee
#client.command(description="bans a user with specific reason (only admins)") #ban
#commands.has_permissions(administrator=True)
async def ban (ctx, member:discord.User=None, reason =None):
try:
if (reason == None):
await ctx.channel.send("You have to specify a reason!")
return
if (member == ctx.message.author or member == None):
await ctx.send("""You cannot ban yourself!""")
else:
message = f"You have been banned from {ctx.guild.name} for {reason}"
await member.send(message)
await ctx.guild.ban(member, reason=reason)
print(member)
print(reason)
await ctx.channel.send(f"{member} is banned!")
except:
await ctx.send(f"Error banning user {member} (cannot ban owner or bot)")

discord.py check if a user has a particular role

I'm trying to get this to check if the user has the role that's tagged or not.
discord.utils.get(ctx.guild.roles, name=rolename)
and
discord.utils.get(user.roles, name=rolename)
#bot.command()
#commands.has_permissions(manage_roles=True)
async def giverole(ctx, user: discord.Member, rolename: discord.Role):
role = discord.utils.get(ctx.guild.roles, name=rolename)
if(not role in user.roles):
await user.add_roles(rolename)
embed=discord.Embed(title=f"{user.name} Has been added to a role called: {rolename.name}", color=discord.Color.dark_purple())
await ctx.send(embed=embed)
else:
await ctx.send(f"Hey {ctx.author.name}, {user.name} already has the role called: {rolename.name}")
No errors just keeps giving the role instead of checking if the user has the role or not.
#bot.command()
#commands.has_permissions(manage_roles=True)
async def giverole(ctx, user: discord.Member=None, rolename:discord.Role=None):
if rolename in user.roles:
await ctx.send("Person already has role")
else:
await user.add_roles(rolename)
await ctx.send("Person doesn't have the role and it has been given to him/her")
Make sure the bot's role is higher than the role you're trying to give the user though because if It's not then you'll get error 50013 Missing Permissions.
This is the fix
#commands.has_permissions(manage_roles=True)
async def giverole(ctx, user: discord.Member=None, rolename:discord.Role=None):
if rolename not in user.roles:
await user.add_roles(rolename)
await ctx.send("Person doesn't have the role and it has been given to him/her")
else:
await ctx.send("Person already has role")```

Discord.py Reaction bot that gives a role

How do I make a bot that would give people roles when they reacted to a specific thing? So far I have this but it does not work
#client.event
async def on_ready():
channel = client.get_channel('513546504481406979')
role = discord.utils.get(user.server.roles, name="testrole")
message = await bot.send_message(channel, "React to me!")
while True:
reaction = await bot.wait_for_reaction(emoji="👍", message=message)
await bot.add_roles(reaction.message.author, role)
wait_for_reaction returns a (reaction, user) tuple. You only need the user portion to assign the role:
reaction, reactor = await bot.wait_for_reaction(emoji="👍", message=message)
await bot.add_roles(reactor, role)

Categories