Add discord role to someone in direct message - python

I have a discord bot where you can activate your key with !activate.
At the event i want the bot to give the message.author the PREMIUM MEMBER role at my discord.
How can i make that work
I'm using #client.event and not ctx.
Thanks for your answers!

Try this
def check_activation_key(activation_key):
# do your check here, return True or False
#client.event
async def on_message(message):
if message.content.startswith('!activate ') and message.channel == message.author.dm_channel: # !activate, dms only
activation_key = message.content[10:]
if check_activation_key(activation_key):
guild = client.get_guild(ID_OF_SERVER_TO_ASSIGN_ROLE_IN) # right click and "copy id"
role = guild.get_role(ID_OF_ROLE_TO_ASSIGN) # right click and "copy id"
await guild.get_member(message.author.id).add_roles(role)
if message.content.startswith('!unactivate') and message.channel == message.author.dm_channel:
guild = client.get_guild(ID_OF_SERVER_TO_TAKE_ROLE_IN)
if ('PREMIUM MEMBER' in [role.name for role in guild.get_member(message.author.id).roles]):
await guild.get_member(message.author.id).remove_roles(guild.get_role(ID_OF_ROLE_GOES_HERE))
else:
await message.channel.send('You did not verify yet')
A drawback is that this does not support multiple servers, only 1, but you can make different activator commands with different server IDs.
Get the ID of a guild by right clicking the icon/banner and choosing "copy id". Get the ID of a role by right clicking a role (either in server settings or in someones profile) and choosing "copy id".

You'll need the guild object that the bot is in, so then it knows where to get the role from. Additionally, the message.author object will return a User, not a Member, but we'll need the Member object in order to add a role.
#client.event
async def on_message(message):
if message.content.lower().startswith("!activate") and not message.guild:
guild = client.get_guild(112233445566778899) # the guild's ID
role = discord.utils.get(guild.roles, name="PREMIUM MEMBER") # or you can use id=
member = await guild.fetch_member(message.author.id)
await member.add_roles(role)
References:
Guild.fetch_member()
Client.get_guild()
utils.get()
Guild.roles
Member.add_roles()

Related

Make discord.py bot react to emoji added in dm

I'm trying to make a simple test bot that could do something when a reaction is added to a message that the bot send to the user dm. Now I'm stuck after the intial trigger that send the dm and add the emoji to react to. Any help to make that work?
import discord
import time
client = discord.Client()
intents = discord.Intents.default()
intents.members = True
#client.event
async def on_ready():
print("testing")
#client.event
async def on_raw_reaction_add(payload):
message_id = payload.message_id
if message_id == 968972405206827028:
guild_id = payload.guild_id
guild = discord.utils.find(lambda g : g.id == guild_id, client.guilds)
if payload.emoji.name == '✅':
role = discord.utils.get(guild.roles, name='role')
user = await client.fetch_user(payload.user_id)
embedVar = discord.Embed(title="Some order", description='Welcome to your order, %s \n Please select your payment method of choice:' % (payload.member.name), color=0x00ff00)
dm = await user.send(embed=embedVar)
await dm.add_reaction(some_emoji)
await dm.add_reaction(some_emoji)
client.run("MY_TOKEN")
Your code is trying to get a particular guild from the payload guild_id attribute, which in a DM doesn't exist.
In discord.py, DMs aren't considered guilds, hence there is no particular ID. If you're setting this system up for a particular server, I'd recommend you use something as client.get_guild(your_id_here), which will give you the Guild object if the bot is in that guild.
In short terms, guild_id is invalid since DMs are not guilds (servers). Find a way to work around that.
My solutions would be:
is it for a specific server? Get the guild by ID and perform your operations
is it for any server? Perhaps use databases to store IDs and perform accordingly
Hope this helps!

Trying to have a bot that adds role to someone in a server if they send a certain thing to the bot in DMS discord.py

I want a bot that gives users a certain role in my server if they send a certain phrase to the bot in DMs.
This is what I have so far:
if message.guild is None:
if passphrase in message.content:
await message.channel.send("You've been verified!")
serv = client.get_guild(00000000000000000000)
role = serv.get_role(000000000000000000000)
if message.author in serv.members:
message.author.add_roles(role, reason="Member was verified via DMs.")
await message.channel.send("You've been verified!")
If the passphrase is in the message, the user gets "You've been verified!" in their DM but the user doesn't get the role specified in the server.
How do I fix this?
message.author is a discord.User object. Is has not add_roles method you need to get it as a guild member using serv.get_member(message.author.id).
add_roles is a coroutine therefore you need to await it using await keyword
Your code should looks like this:
if message.guild is None:
if passphrase in message.content:
await message.channel.send("You've been verified!")
serv = client.get_guild(00000000000000000000)
role = serv.get_role(000000000000000000000)
member = serv.get_member(message.author.id)
if member us not None
await member.add_roles(role, reason="Member was verified via DMs.")
await message.channel.send("You've been verified!")

How can i create roles and put them on top?discord.py

my bot has a command called mute and basically, it creates a role and gives it to the person but the problem is when it does that ppl with higher roles still are able to talk. how can I put the mute role on top of every role in the server? and I mean in every server, not just one
So you can't put the mute role above the bot role, but the following should help:
#commands.command()
async def mute(self, ctx, member: discord.Member):
guild = ctx.guild
role = await guild.create_role(name='muted', hoist=True)
all_roles = await guild.fetch_roles()
num_roles = len(all_roles)
print(f'The server has {num_roles} roles.')
await role.edit(reason=None, position=num_roles - 2)
print('Created new role!')
await member.add_roles(role)
await ctx.send(f'{member} has been muted.)
So what we did is check how many roles the server has, create a new role and put it to the top/under the bot role.
If you're changing a role to a position lower than the top, I would suggest using the role.edit method, passing a position value.
However, as for your question, which is putting a role at the top after creating this, you should use the discord.Client.move_role()
As for actually creating the role:
If you're on the rewrite, use this
guild = ctx.guild
await guild.create_role(name="role name")
and change "role name" with the name of the role you want to create. If you want to make the role depending on what the user says you can do something likes this:
#client.command()
async def rolecreate(ctx, arg):
guild = ctx.guild
await guild.create_role(name=arg)
Here, you'd have to do (lets say your prefix is !): "!rolecreate Moderator" and it would only create a role.
For the async branch:
author = ctx.message.author
await client.create_role(author.server, name="role name")
Just in case you want the bot to have a command that adds the role here you go:
For the rewrite branch
role = discord.utils.get(ctx.guild.roles, name="role to add name")
user = ctx.message.author
await user.add_roles(role)
If you want to add a role mentioned in the command, you do for example:
#client.command()
async def addrole(ctx, arg):
role = discord.utils.get(ctx.guild.roles, name=arg)
user = ctx.message.author
await user.add_roles(role)
For the async branch:
user = ctx.message.author
role = discord.utils.get(user.server.roles, name="role to add name")
await client.add_roles(user, role)
Hope this helped!

Discord.py - Give Someone a Role, but in the PM's and with the Server ID

I want to do something like that:
If someone writes the command !GiveRole to the Bot in PM's, the next thing should be the Server ID, after that the Role, would something like that be possible, because i know that it is not hard to give someone a role with the bot, but is it possible to do it with the PM's and Server ID?
Thanks.
Try this, but I'm not sure if it's gonna work.
#bot.command()
async def giverole(ctx, guild, role):
if isinstance(ctx.channel, discord.DMChannel) == False: # Checking if this is a DM Channel
return
guild = bot.get_guild(int(guild)) # Getting guild
if guild is None: # Checking if the guild exists
await ctx.send("Invalid guild ID!")
return
role = guild.get_role(int(role)) # Getting role
if role is None: # Checking if the role exists
await ctx.send("Invalid role ID!")
return
await guild.get_member(ctx.guild.id).add_roles(role) # Give role to member
await ctx.send(f"You received **{role.name}** role!")

Discord bot fails to add a role to a user using discord.py

I simply want my bot to add a role to a user in discord. Although the syntax seems simply, apparently I'm doing something wrong.I'm new to python, so I'd appreciate some pointers in the right direction!
bot = commands.Bot(command_prefix='!')
def getdiscordid(discordname):
for guild in bot.guilds:
for member in guild.members:
if member.name == discordname:
return member.id
#bot.command(name='role')
async def role(ctx):
await ctx.message.channel.send("Testing roles")
discordid = getdiscordid("Waldstein")
print ("id: " , discordid)
member = bot.get_user(discordid)
print ("member: ", member)
role = get(ctx.message.guild.roles, name="Egg")
print("role: ", role.name)
await member.add_roles(role)
print("done")
# error handler
#bot.event
async def on_command_error(ctx, error):
if isinstance(error, commands.errors.CheckFailure):
await ctx.send(error)
bot.run(TOKEN)
In this example he successfully retrieves the member, he can't find the Egg role, and doesn't add the role. [Edit: I corrected the line to retrieve the role, that works but still no added role. Added the error handler]
The key issue is that add_roles() adds roles to a Member object not a user.
Made a couple of tweaks...
Changed the get id to get member and return the member object.
changed the name of the command to add_role() to avoid using role as the command and a variable.
changed to await member.add_roles(role)
Try:
def get_member(discordname):
for guild in bot.guilds:
for member in guild.members:
if member.name == discordname:
return member
#bot.command(name='add_role')
async def add_role(ctx):
await ctx.message.channel.send("Testing roles")
member = get_member("Waldstein")
print(f'member is {member} type {type(member)}')
role = get(ctx.guild.roles, name="Egg")
print("role: ", role.name)
await member.add_roles(role)
print("done")
For the answer's sake, I'm writing the whole discord.utils.get instead of just get. Here's your command rewritten:
import discord
#bot.command()
async def role(ctx):
await ctx.send("Testing roles!")
member = discord.utils.get(bot.get_all_members(), name="Waldstein")
# be careful when getting objects via their name, as if there are duplicates,
# then it might not return the one you expect
print(f"id: {member.id}")
print(f"member: {member}")
role = discord.utils.get(ctx.guild.roles, name="Egg") # you can do it by ID as well
print(f"role: {role.name}")
await member.add_roles(role) # adding to a member object, not a user
print("Done!")
If this doesn't work, try printing out something like so:
print(ctx.guild.roles)
and it should return each role that the bot can see. This way you can manually debug it.
One thing that might cause this issue is that if the bot doesn't have the necessary permissions, or if its role is below the role you're attempting to get i.e. Egg is in position 1 in the hierarchy, and the bot's highest role is in position 2.
References:
Guild.roles
Client.get_all_members()
Member.add_roles()
utils.get()
commands.Context - I noticed you were using some superfluous code, take a look at this to see all the attributes of ctx

Categories

Resources