Only allow specific roles to use a command - discord.py

I've been making a command to change a user's role, but currently, everyone can use it. I've tried doing a few things.
Here is my code:
async def addrole(ctx, user: discord.Member, role: discord.Role):
await user.add_roles(role)
await ctx.send(f"I gave {user.name} the role {role.name}")
Here is the only thing that I've been able to think of:
allowed = ["Role 1"]
if message.author.role in allowed:
async def addrole(ctx, user: discord.Member, role: discord.Role):
await user.add_roles(role)
await ctx.send(f"I gave {user.name} the role {role.name}")
Thanks in advance!

Just add #commands.has_any_roles():
#bot.command()
#commands.has_any_roles("Role 1", "Role 2")
async def addrole(ctx, user: discord.Member, role: discord.Role):
await user.add_roles(role)
await ctx.send(f"I gave {user.name} the role {role.name}")
If the user isn't allowed to use the command, it will raise a commands.MissingAnyRole error.

Related

I want to improve my kick command in discord.py

I have made a bot in discord.py which has a kick command. But I want the bot to say "please tell me whom to kick" when someone uses the command without saying whom to kick. I mean if someone uses the kick command without mentioning whom to kick, the bot will say "please tell me whom to kick".
I am trying to make a good bot so please help me.
async def kick(ctx, member : discord.Member, *, reason=None):
if (ctx.message.author.permissions_in(ctx.message.channel).kick_members):
await member.kick(reason=reason)
await ctx.send(f"{member.mention} has successfully been kickded for {reason}")
if not (ctx.message.author.permissions_in(ctx.message.channel).kick_members):
await ctx.send("You don't perms to play football with Araforce and kick them. Sed")
if not user:
await ctx.message.delete()
msg = await ctx.send("You are a bit idiot, don't you know I can't kick anyone if you don't tell whom to kick? Tell me whom to kick and the go away.")
await sleep(4.7)
await msg.delete()
return
if not reason:
await ctx.message.delete()
msg2 = await ctx.send("Hmm.. Why I will kick him? Specify a reason please.")
await sleep(4.7)
await msg2.delete()
return```
async def kick(ctx, user: discord.User = None, *, reason=None):
if not user:
await ctx.message.delete()
msg = await ctx.send("You must specify a user.")
await sleep(4.7)
await msg.delete()
return
if not reason:
await ctx.message.delete()
msg2 = await ctx.send("You must specify a reason.")
await sleep(4.7)
await msg2.delete()
return
I changed ifs to the error handler, which is necessary because if you won't pass one of the arguments (user or reason) you would get an error.
Full code:
#client.command()
async def kick(ctx, member: discord.Member, *, reason): #if you will change "member" and "reason" to something else remember to also change it in error handler
await member.kick(reason=reason)
await ctx.send(f"{member.mention} has successfully been kicked for {reason}")
#kick.error #cool mini error handler
async def kick_error(ctx, error):
if isinstance(error, discord.ext.commands.errors.MissingRequiredArgument):
if str(error) == "member is a required argument that is missing.": #change this if you changed "member"
await ctx.message.delete()
await ctx.send("You are a bit idiot, don't you know I can't kick anyone if you don't tell whom to kick? Tell me whom to kick and then go away.", delete_after=4.7) #you don't have to use "await sleep" you can use "delete_after" parameter
elif str(error) == "reason is a required argument that is missing.": #change this if you changed "reason"
await ctx.message.delete()
await ctx.send("Hmm.. Why I will kick him? Specify a reason please.", delete_after=4.7)
elif isinstance(error, discord.ext.commands.errors.MissingPermissions):
await ctx.send("You don't have perms to play football with Araforce and kick them. Sed")
Discord error handling example

How to make multiple reaction roles

So I'm working on a reaction role cog, and the commands work so far. There's just one problem. When I create two different reaction roles, it only works for the second one. It's because I only have one dictionary and it updates that every time. I think I've seen people use a payload for reaction roles, but I have no idea what that does and if it would fix my problem. Is there a way to use payload to fix my problem? Thanks!! Here's my code:
import discord
from discord.ext import commands
from discord.ext.commands import BucketType, cooldown, CommandOnCooldown
import random
import json
reaction_title = ""
reactions = {}
reaction_message_id = ""
class ReactionRoles(commands.Cog):
"""Reaction roles!!\nYou need manage roles permissions to use these"""
def __init__(self, bot):
self.bot = bot
# Bot Commands
#commands.command(aliases=['rcp'])
async def reaction_create_post(self, ctx):
"""Creates an embed that shows all the reaction roles commands"""
embed = discord.Embed(title="Create Reaction Post", color=discord.Colour.dark_purple())
embed.set_author(name="Botpuns")
embed.add_field(name="Set Title", value=".rst [New Title]", inline=False)
embed.add_field(name="Add Role", value=".rar [#Role] [EMOJI]", inline=False)
embed.add_field(name="Remove Role", value=".rrr [#Role]", inline=False)
embed.add_field(name="Reaction Send Post", value=".rsp", inline=False)
await ctx.send(embed=embed)
await ctx.message.delete()
#commands.command(aliases=['rst'])
async def reaction_set_title(self, ctx, *, new_title):
global reaction_title
reaction_title = new_title
await ctx.send(f"The title for the message is now `{new_title}`")
await ctx.message.delete()
#commands.command(aliases=['rar'])
async def reaction_add_role(self, ctx, role: discord.Role, reaction):
global reactions
reactions[role.name] = reaction
await ctx.send(f"Role `{role.name}` has been added with the emoji {reaction}")
await ctx.message.delete()
print(reactions)
#commands.command(aliases=['rrr'])
async def reaction_remove_role(self, ctx, role: discord.Role):
if role.name in reactions:
del reactions[role.name]
await ctx.send(f"Role `{role.name}` has been deleted")
await ctx.message.delete()
else:
await ctx.send("That role wasn't even added smh")
print(reactions)
#commands.command(aliases=['rsp'])
async def reaction_send_post(self, ctx):
description = "React to add roles\n"
for role in reactions:
description += f"`{role}` - {reactions[role]}\n"
embed = discord.Embed(title=reaction_title, description=description, color=discord.Colour.purple())
embed.set_author(name="Botpuns")
message = await ctx.send(embed=embed)
global reaction_message_id
reaction_message_id = str(message.id)
for role in reactions:
await message.add_reaction(reactions[role])
await ctx.message.delete()
#commands.Cog.listener()
async def on_reaction_add(self, reaction, user):
if not user.bot:
message = reaction.message
if str(message.id) == reaction_message_id:
# Add roles to user
role_to_give = ""
for role in reactions:
if reactions[role] == reaction.emoji:
role_to_give = role
role_for_reaction = discord.utils.get(user.guild.roles, name=role_to_give)
await user.add_roles(role_for_reaction)
#commands.Cog.listener()
async def on_reaction_remove(self, reaction, user):
if not user.bot:
message = reaction.message
if str(message.id) == reaction_message_id:
# Add roles to user
role_to_remove = ""
for role in reactions:
if reactions[role] == reaction.emoji:
role_to_remove = role
role_for_reaction = discord.utils.get(user.guild.roles, name=role_to_remove)
await user.remove_roles(role_for_reaction)
def setup(bot):
bot.add_cog(ReactionRoles(bot))

How to do a prisoner role in discord.py 1.5.0?

I've tried 3 times to do this code, my plan is removing all roles from an user, writing the roles in an ctx.send() to send a message with the old roles in the channel, after that, send a message that says the user was imprisoned and the reason and give the prisoner role.
'BabaYaga' is the adm's role; 'D 001' is the prisoner role
Code 01:
# Detentos 3
#client.command()
#commands.has_any_role('BABAYAGA')
async def det(ctx, member: discord.Member = None, role = discord.Guild.roles, *, reason = None):
if member == None:
await ctx.send('Say the user')
return
if reason == None:
await ctx.send('Say the reason')
return
Roles = member.roles
for _ in Roles:
print(Roles)
await client.remove_roles(member, *Roles)
await member.add_role(ctx, member, role)
await ctx.send(f'{member} was arrested for {reason}')
Code 02:
# Detentos 2
#client.command()
#commands.has_any_role('BABAYAGA')
async def det(ctx, member: discord.Member, *,reason):
role = discord.utils.get(ctx.guild.roles, name = 'D 001')
await ctx.send(f'{member.roles}')
for _ in member.roles:
await member.remove_roles(member.top_role)
await ctx.message.add_reaction(emoji=self.tick)
await member.add_roles(role)
await ctx.send(f'{member} was arrested for {reason}')
Code 03:
# Detentos
#client.command()
#commands.has_any_role('BABAYAGA')
async def det(self, ctx, member: discord.Member, *, reason = None):
if reason == None:
await ctx.send('Say the reason!')
return
roles = discord.utils.get(member.guild.roles) # member's roles
role = discord.utils.get(ctx.guild.roles, name = 'D 001') # Det's role
await ctx.message.add_reaction(emoji=self.tick)
await member.edit(member.guild.roles)
await ctx.send(f'{discord.Member} preso por {reason}')
await ctx.send(f'cargos do {discord.Member}: {member.roles}')
Code 04:
# Detentos
#client.command()
#commands.has_any_role('BABAYAGA')
async def det(self, ctx, member: discord.Member = None, *, reason = None):
if reason == None:
await ctx.send('Say the reason! :angry: :angry:')
return
if member == None:
await ctx.send('Say the user')
return
rolesserver = ['D 001', 'D 002', 'D 003', 'D 004', 'testers']
await ctx.send(f'{member.roles}')
for roles in rolesserver:
await client.remove_roles(member, *roles)
await ctx.send(f'<#{member.id}> was arrested for {reason}')
I don't know what is my error there. Can anyone help me?
There are a lot of mistakes in your code snippets. Here's a correct way of doing it:
#client.command()
#commands.has_any_role('BABAYAGA')
async def det(ctx, member: discord.Member, *, reason):
await ctx.send(f'Removed ", ".join([role.name for role in member.roles])')
for role in member.roles:
await member.remove_roles(role)
await ctx.message.add_reaction(emoji=self.tick)
role = discord.utils.get(ctx.guild.roles, name = 'D 001')
await member.add_roles(role)
await ctx.send(f'{member} was arrested for {reason}')
Some advices:
The get method returns a single item from an iterable so writing get(member.guild.roles) won't work, you can just type roles = member.guild.roles
You must set a variable in your for loops or else, you can't cycle through your member's roles, so your for _ in member.roles must become for role in member.roles.
To have a nice message with all your member's roles, you can use the join method combined with list comprehension (eg. ', '.join([role.name for role in member.roles]))
remove_roles is a discord.Member method so you have to use it this way: member.remove_roles(role)

How to use the User ID to kick,ban and unban a user

I just learned how to code a discord bot with python.
Ban command
#bot.command()
async def ban(ctx, member: Member = None, *, reason):
await member.ban(reason=reason)
Kick command
#bot.command()
async def kick(ctx, member: Member = None, *, reason):
await member.kick(reason=reason)
Unban command
#bot.command()
async def unban(ctx, *, member):
banned_users = await ctx.guild.bans()
member_name, member_discriminator = member.split('#')
for ban_entry in banned_users:
user = ban_entry.user
if (user.name, user.discriminator) == (member_name, member_discriminator):
await ctx.guild.unban(user)
But how can I use the User ID to kick,ban and unban someone?
If member is on server, you can normal ban/kick by ID
If member isn't on server, you must use await client.fetch_user(ID).ban

Ban and Unban commands to work in all servers

I've been programming a discord bot letely, and for its ban command here is the code i use:
#client.command(aliases=['Ban'])
async def ban(ctx, member: discord.Member, days: int = 1):
if get(ctx.author.roles, id=548841535223889923):
await member.ban(delete_message_days=days)
await ctx.send("Banned {}".format(ctx.author))
else:
await ctx.send(ctx.author.mention + " you don't have permission to use this command.".format(ctx.author))
However, if i try to use this on other servers, it just tells me i dont have the required role..
So how do I get the role ID for a new server the bot joins automatically or is there some other way to make this work?
You can use a check for permissions instead of looking for a specific role ID
import discord
from discord.ext import commands
#client.command(aliases=["Ban"])
#commands.has_permission(ban_members=True)
async def...
you can use a has_permission, like this:
#client.command(aliases=["Ban"])
#commands.has_permission(administrator=True)
async def ban(ctx, member: discord.Member, days: int = 1):
await member.ban(delete_message_days=days)
await ctx.send("Banned {}".format(ctx.author))
You can then add a missing permissions error handler:
#client.event
async def on_command_error(ctx, error):
if isinstance(error, commands.MissingPermissions):
await ctx.send("You do not have the permissions required for this command.")
return
raise error

Resources