How can my bot give a user a role through a command - python

For example, I want that if I enter !Cuff #user that this user gets the role of cuff. Does anyone know how to do this?
if message.content.startswith('!cuff'):
args = message.content.split(' ')
if len(args) == 2:
member: Member = discord.utils.find(lambda m: args[1] in m.name, message.guild.members)
if member:
role = get(message.server.roles, name='Cuff')
await client.add_roles('{}'.format(member.name))

If you want to make a command, you should use discord.ext.commands instead of on_message event. Then, you can get the discord.Member object easily with passing arguments.
Also, client object has no attribute add_roles. You should use discord.Member.add_roles(role) and message object has no attribute server, it has guild instead.
from discord.ext import commands
client = commands.Bot(command_prefix="!")
#client.command()
async def cuff(ctx, member: discord.Member=None):
if not member:
return # or you can send message to the channel that says "you have to pass member argument"
role = get(ctx.guild.roles, name='Cuff')
await member.add_roles(role)

Related

Discord.py- Give role to a user

I am trying to give a user a role using the discord.py, but I keep getting the same error.
discord.ext.commands.errors.MissingRequiredArgument: role is a required argument that is missing.
from discord.ext import commands
from discord.utils import get
import discord
import methods
# Intents
intents = discord.Intents.default()
intents.message_content = True
intents.members = True
# Object for discord
client = discord.Client(intents=intents)
bot = commands.Bot(command_prefix='/', intents=intents)
TOKEN = 'active_token'
channel_name = 'ladder'
role_name = 'Ladder Participant'
#bot.command()
async def join_ladder(ctx, role: discord.Role, user: discord.Member):
"""
This command lets you join the ladder.
!join_ladder
"""
if methods.check_ladder_active(): # Method returns True or False
role = discord.utils.get(user.guild.roles, name=role_name)
await user.add_roles(role)
await ctx.send('You are now apart of the ladder.')
# ADD USERS NAME TO ACTUAL LADDER
else:
await ctx.send('Ladder is inactive.')
#bot.command()
async def leave_ladder(ctx, user: discord.Member):
"""
This command lets you leave the ladder:
!leave_ladder
"""
if methods.check_ladder_active():
role = ctx.guild.get_role('1055287896376082463') # add role id
await user.remove_roles(role)
await ctx.send('You are no longer apart of the ladder.')
# REMOVE USER FROM LADDER FILE
else:
ctx.send('Ladder is inactive')
I have tried two different ways of giving the user the role, the !join_ladder is the most recent way I've tried and the !leave_ladder was the first way but instead of user.remove_roles(role) it was user.add_roles(role).
The problem is that your commands have required arguments that you didn't provide when calling them, like this command:
async def join_ladder(ctx, role: discord.(Role, user: discord.Member):
The role and user arguments are required, so when you're just calling the command like this (prefix) join_ladder, discord.py cannot find the required arguments because they're missing. The most simple way to fix this is to just remove the arguments that you're not using in your function or provide them when using the command.
async def join_ladder(ctx, user: discord.Member):
Here is an relevant example.
Also, I see that you have both discord.Client and discord.ext.commands.Bot instance, please pick one of them and remove the other.
Thank you for your help, this is my new code for anyone wondering.
#bot.command()
async def join_ladder(ctx):
"""
This command lets you join the ladder.
!join_ladder
"""
if methods.check_ladder_active(): # Method returns True or False
role = discord.utils.get(ctx.guild.roles, name=role_name)
await ctx.author.add_roles(role)
await ctx.send('You are now apart of the ladder.')
# ADD USERS NAME TO ACTUAL LADDER
else:
await ctx.send('Ladder is inactive.')

I wanted to know if there is any way to turn the bot command into an on_message event command?

Here is the code I am working with:
import discord
import random
import asyncio
from discord.ext import commands
from discord.ext.commands import bot
from discord.utils import get
def IsTeam(role):
Value = False
AllTeams = [] # Add all teams in here.
if role in AllTeams:
Value = True
return Value
#bot.command()
async def sign(ctx, member: discord.Member=None, *, arg=None):
if not member:
await ctx.send("Please provide a username.")
elif arg == None:
await ctx.send("Please provide a team.")
else:
try:
Role = discord.utils.get(ctx.guild.roles, name=arg)
if Role == None:
await ctx.send("This is an invalid role.")
else:
pass
except:
await ctx.send("Unexpected Error Occured.")
return
if Role >= ctx.author.top_role:
await ctx.send("You cannot add a role that is higher then your current role.")
else:
if IsTeam(Role):
if Role in ctx.author.roles:
await member.add_roles(Role)
await ctx.send(f'{member.mention} has been signed to `{role}`')
I wanted to know if I can make the
#bot.command()
async def sign(ctx, member: discord.Member=None, *, arg=None):
command into an event on_message such as like:
#bot.event()
async def on_message(ctx, member: discord.Member=None, *, arg=None):
while doing the same things the command does.
sorry if I am not explaining this clearly.
As I understand, you're trying to give a role to a user when someone mentions him/her with a specific prefix. In this case, your prefix is a emoji+ sign. You can use the on_message event for this. But in the on_message event, you can only use the message parameter. And also, you need to get the emoji id by typing \:TeamEmoji: in your discord chat. It will return something like <:TeamEmoji:123456789>. So you can basically do:
#bot.event
async def on_message(message):
if message.content.startswith('<:TeamEmoji:1234567890> sign'):
role = discord.utils.get(message.guild.roles, name='role name')
member = message.mentions[0]
await member.add_roles(role)
await message.channel.send('Successfully signed to <:TEAM:123456789>')

Issue with giving roles with a command Discord Py

I have made a command to set someone ROLE, However, it's throwing errors.
Command raised an exception: AttributeError: 'str' object has no attribute 'add_roles'
Is there anything wrong I have did? I am using the latest discord py version.
#bot.command()
async def set_role(ctx,member = None,val: int = None):
ab = member
ab = ab.replace("<","")
ab = ab.replace(">","")
ab = ab.replace("#","")
ab = ab.replace("!","")
user = bot.get_user(int(ab))
if val == 1:
role = discord.utils.get(ctx.guild.roles, name="Test")
await user.add_roles(role)
await ctx.send('Updated')
user = bot.get_user(int(ab))
This creates a user object. It is not affiliated to a guild / discord server. By design you cannot do add_roles.
Reason being your bot might not share a guild with this user. Or your bot might share multiple guilds with this user. But how does it know which guild you are actually adressing?
You need to create a member object. This could be done with:
member = ctx.guild.get_member(int(ab))
Now you have a member object and you can await add_roles.
await member.add_roles(role)
https://discordpy.readthedocs.io/en/latest/api.html#discord.Member.add_roles
to give a role to a member u need to give the member and the name of the role as inputs.
for example:
" ?set_role #clay#9871 example "
the bot gonna search for a role name 'example' from the guild roles
if the bot didn't find the role it will send "role not found" that's what the "try" and "except" for
#bot.command()
async def set_role(ctx,member :discord.Member,role):
try:
add_role= discord.utils.get(ctx.guild.roles, name=role)
await member.add_roles(add_role)
await ctx.send('Updated')
except:
await ctx.send("role not found!")

Add role to user with user mention

I was trying to make a bot that is able to add a role to a user with a user mention. I also want to pass the role in the command.
So the syntax should be:
!addrole ROLENAME #user
I tried this:
import discord
from discord.ext import commands
from discord.ext.commands import Bot
from discord.utils import get
def read_token():
with open("token.txt", "r") as f:
lines = f.readlines()
return lines[0].strip()
token = read_token()
bot = commands.Bot(command_prefix='!')
#bot.command(pass_context=True)
async def addrole(ctx, arg1, member: discord.Member):
role = get(member.guild.roles, name={arg1})
await member.add_roles(role)
bot.run(token)
but it doesn't work. I receive the error:
AttributeError: 'NoneType' object has no attribute 'id'
You're already using a converter for member, use one for role too:
from discord import Member, Role
#bot.command()
async def addrole(ctx, member: Member, *, role: Role):
await member.add_roles(role)
The , *, allows you to supply role names that have multiple words.

How do you remove a role from a user?

I'm trying to remove a role from a user with a command but I'm not quite sure how the command works.
Here is the code:
#bot.command(pass_context=True)
#commands.has_role('staff')
async def mute(ctx, user: discord.Member):
await bot.remove_roles(user, 'member')
await bot.say("{} has been muted from chat".format(user.name))
It looks like remove_roles needs a Role object, not just the name of the role. We can use discord.utils.get to get the role
from discord.utils import get
#bot.command(pass_context=True)
#commands.has_role('staff')
async def mute(ctx, user: discord.Member):
role = get(ctx.message.server.roles, name='member')
await bot.remove_roles(user, role)
await bot.say("{} has been muted from chat".format(user.name))
I don't know what happens if you try to remove a role that the target member doesn't have, so you might want to throw in some checks. This might also fail if you try to remove roles from an server admin, so you might want to check for that too.
To remove a role, you'll need to use the remove_roles() method. It works like this:
member.remove_roles(role)
The "role" is a role object, not the (role's) name, so it should be:
role_get = get(member.guild.roles, id=role_id)
await member.remove_roles(role_get)
With your code:
#bot.command(pass_context=True)
#commands.has_role('staff')
async def mute(ctx, user: discord.Member):
role_get = get(member.guild.roles, id=role_id) #Returns a role object.
await member.remove_roles(role_get) #Remove the role (object) from the user.
await bot.say("{} has been muted from chat".format(user.name))
The remove_roles() function takes two parameters, the first of which is the user from which the role and the role itself are removed. It is possible not to write user: discord.Member in the function parameters, leave only ctx. You also need the role you want to delete. This can be done by:
role = get (ctx.author.guild.roles, name = "the name of the role you want to remove")
#also include 'from discord.utils import get'
And then to remove the obtained role (object), call the function:
await ctx.author.remove_roles (role)
So, the final code should look something like this:
from discord.utils import get
#bot.command(pass_context=True)
#commands.has_role('staff')
async def mute(ctx):
role = get (ctx.author.guild.roles, name = "the name of the role you want to remove")
await ctx.author..remove_roles(role)
await ctx.send("{} has been muted from chat".format(user.name))
Try that:
import discord
from discord.ext import commands
#bot.command()
#commands.has_role('staff')
async def mute(ctx, user: discord.Member):
role = discord.utils.get(ctx.guild, name='member')
await user.remove_roles(role)
await ctx.send(f'{user.name} has been muted from chat')

Categories