I'm trying to make a discord bot that puts roles based on which emoji you choose. Up to here it works well, but what I want to do is always keep the emoji counter always at 1 and if a user presses the button the role is assigned and if he represses it the role will have to be removed but always keeping the counter at 1
import discord
from discord.ext import commands
class AutoRole(commands.Cog):
def __init__(self, client):
self.client=client
#commands.Cog.listener()
async def on_ready(self):
print("AutoRole: ON")
#commands.Cog.listener()
async def on_raw_reaction_add(self,payload):
messageID = 874997842748506112
if messageID == payload.message_id:
member = payload.member
guild = member.guild
emoji = payload.emoji.name
if emoji == '❤️':
role = discord.utils.get(guild.roles, name="Red")
elif emoji == '💛':
role = discord.utils.get(guild.roles, name="Yellow")
await member.add_roles(role)
#commands.Cog.listener()
async def on_raw_reaction_remove(self,payload):
messageID = 874997842748506112
if messageID == payload.message_id:
guild = await(self.client.fetch_guild(payload.guild_id))
emoji = payload.emoji.name
if emoji == '❤️':
role = discord.utils.get(guild.roles, name="Red")
elif emoji == '💛':
role = discord.utils.get(guild.roles, name="Yellow")
member = await(guild.fetch_member(payload.user_id))
if member is not None:
await member.remove_roles(role)
else:
print("Member not found")
#commands.command()
async def Modulo_AutoRole(self, ctx):
embed = discord.Embed(
title="Title",
description="Description",
color=0x1abc9c
)
msg = await ctx.send(embed=embed)
await msg.add_reaction('❤️')
await msg.add_reaction('💛')
def setup(client):
client.add_cog(AutoRole(client))
If you want the bot to remove the reaction from the message after their role has been assigned to them you add something like this to your code in on_raw_reaction_add after you assign the role.
msg = await self.bot.get_channel(payload.channel_id).fetch_message(payload.message_id)
await msg.remove_reaction(reaction, payload.member)
However because you want the emoji counter to stay at 1 (just the bot), you won't be able to have on_raw_reaction_remove. I'd make the on_raw_reaction_add method check the payload.member has the role, add it if they don't, and remove it if they do, then remove the reaction. Also another thing, while this isn't required, it's recommend to check the reaction was added by a bot (payload.member.bot)
Right after you get the role role = discord.utils.get(guild.roles, name="Red"), check if the user has the role like this:
role = discord.utils.get(guild.roles, name="Red")
has_role = False
for user_role in payload.member.roles:
if role.id == user_role.id:
has_role = True
if has_role:
await payload.member.remove_roles(role)
else:
await payload.member.add_roles(role)
The code above goes through all the roles the member has and checks if they have the role (has_role).
If they don't have the role (has_role is False), then the bot adds the role.
If they do have the role (has_role is True), then the bot removes the role from the Member.
Related
** want to make reaction role which if user react message on specific channel will get role
but it doesn't work**
#client.event
async def on_reaction_add(member):
ChannelID = 932268491556405268
role = discord.utils.get(member.guild.roles, id=941124409341648957)
if member.message.channel.id != ChannelID:
return
if member.emoji == "1️⃣":
await member.add_roles(role, reason=None, atomic=True)
You can use the payload object from on_raw_reaction_add to do what you want
#client.event
async def on_raw_reaction_add(payload): # Requires Intents.reactions
channel = client.get_channel(...)
guild = client.get_guild(payload.guild_id)
role = discord.utils.get(guild.roles, id=...)
if str(payload.emoji) == "1️⃣":
await payload.member.add_roles(role, atomic=True)
await channel.send(...)
Below is the currently working code for my case
I'm working on a bot for my Discord server and trying to assign a role to a user with a reaction.
My current status looks like this: (I used the latest Python/Discord.py version)
import discord
from discord.ext import commands
bot = commands.Bot(intents=intents)
class GetRole(commands.Cog):
def __init__(self, bot):
self.bot = bot
#bot.event
async def on_raw_reacion_add(payload):
ourMessageID = YourMessageID
if ourMessageID == payload.message_id:
member = payload.member
guild = member.guild
if payload.emoji.name == '<:YouTube:864980517630902302>':
role = discord.utils.get(guild.roles, name="YouTube")
elif payload.emoji.name == '<:Twitch:864980843176787988>':
role = discord.utils.get(guild.roles, name="Twitch")
elif payload.emoji.name == '<:Discord:864980938068852757>':
role = discord.utils.get(guild.roles, name="Discord")
elif payload.emoji.name == '<a:alert:864983948987990081>':
role = discord.utils.get(guild.roles, name="Community-Events")
await member.add_roles(role)
(the message meant by the MessageID has already been sent)
It does not produce errors in Visual Studio code, but the roles are still not added to the user who reacts to the message.
Maybe it is because of the versions of Discord.py, but I don't know exactly.
Make sure the appropriate intents are enabled. As per the Discord.py API Reference, both the members and reactions intents are required to use the on_raw_reaction_add event. Enable them in the developer portal, and add the intents in your code like so:
intents = discord.Intents.default()
intents.members = True
intents.reactions = True
bot = commands.Bot(intents=intents)
This is now the working code:
#commands.Cog.listener()
async def on_raw_reaction_add(self, payload):
print("test")
print(payload.emoji.name)
ourMessageID = 867876893411508234
if ourMessageID == payload.message_id:
member = payload.member
guild = member.guild
if payload.emoji.name == 'YouTube':
role = discord.utils.get(guild.roles, name="YouTube")
elif payload.emoji.name == 'Twitch':
role = discord.utils.get(guild.roles, name="Twitch")
elif payload.emoji.name == 'Discord':
role = discord.utils.get(guild.roles, name="Discord")
elif payload.emoji.name == 'alert':
role = discord.utils.get(guild.roles, name="Community-Events")
await member.add_roles(role)
I had typos and used (I think) outdated evets etc. Now everything works again at least for me
I have made my discord bot give and remove roles on reacting and unreacting. How do I make it so that when the user reacts to a emoji while already having reacted to a different one before, the previous one gets removed? So that the roles won't stack up...?
Here is my code for adding a role:
#commands.Cog.listener()
async def on_raw_reaction_add(self, payload):
message_id = payload.message_id
if message_id == 810784018953666580:
guild_id = payload.guild_id
guild = discord.utils.find(lambda g: g.id == guild_id, self.client.guilds)
if payload.emoji.name == 'grey_B19FF9':
role = guild.get_role(810471074500182036)
elif payload.emoji.name == 'skyblue_11A7BB':
role = guild.get_role(810471062449291296)
else:
role = discord.utils.get(guild.roles, name=payload.emoji.name)
if role is not None:
member = payload.member
if member is not None:
await member.add_roles(role)
print("Done.")
else:
print("Member not found.")
else:
print("Role not found")
and this is for removing the role:
#commands.Cog.listener()
async def on_raw_reaction_remove(self, payload):
message_id = payload.message_id
if message_id == 810784018953666580:
guild_id = payload.guild_id
guild = discord.utils.find(lambda g: g.id == guild_id, self.client.guilds)
if payload.emoji.name == 'grey_B19FF9':
role = guild.get_role(810471074500182036)
elif payload.emoji.name == 'skyblue_11A7BB':
role = guild.get_role(810471062449291296)
else:
role = discord.utils.get(guild.roles, name=payload.emoji.name)
if role is not None:
guild = await self.client.fetch_guild(payload.guild_id)
member = await guild.fetch_member(payload.user_id)
if member is not None:
await member.remove_roles(role)
print("Done.")
else:
print("Member not found.")
else:
print("Role not found")
any help would be much appreciated!
What happens when this code runs ? I think the method remove_roles takes a list of roles so you should turn that role argument into a list before removing, same goes for add_roles
You should also look into member.roles to check the roles of a member, depending on what is inside that list, you should have enough information to be able to remove the role that you don't want
I'm making a bot that i saw from this youtube video
Here's the code I wrote
#client.event
async def on_raw_reaction_add(payload):
message_id = payload.message_id
if message_id == [message id]:
guild_id = payload.guild_id
guild = discord.utils.find(lambda g :g.id == guild_id, client.guilds)
role = discord.utils.get(guild.roles, name=payload.emoji.name)
if role is not None:
member_user = discord.utils.find(lambda m : m.id == payload.member.id, guild.members)
if member_user is not None:
await member_user.add_roles(role)
print("Done")
else:
print("Member not Found")
print(member_user)
else:
print("Role not Found")
But every time I react, the console gives me Member not Found and a None for the user ID.
Am I doing something wrong with getting the user ID? Or is the problem somewhere else entirely?
First time coding anything in python btw. Thanks in advance :)
You can't use guild.members if you haven't set up your Intents correctly, and seeing as you're following an out-dated YouTube tutorial I assume you haven't.
When creating your commands.Bot instance, pass in intents, and enable the members intent:
intents = discord.Intents.default()
intents.members = True
client = commands.Bot(command_prefix=..., intents=intents)
Afterwards, enable them on your bot's dashboard. Info on how to do that is in the docs: https://discordpy.readthedocs.io/en/latest/intents.html#privileged-intents
We have done it like this to asign users a role based on the reaction they give to the welcome message. You can try it and see if it works for your case as well
#bot.event
async def on_raw_reaction_add(payload):
guild = bot.get_guild(payload.guild_id)
rolesDict = {role.name : role for role in guild.roles}
member = guild.get_member(payload.user_id)
user = bot.get_user(payload.user_id)
if(payload.message_id == 769218692948295721):
for roleName in ["Role1", "Role2", "Role3"]:
await member.remove_roles(rolesDict.get(roleName))
if(str(payload.emoji) == "\U0001F986"):
role = rolesDict.get("Role1")
await member.add_roles(role)
elif(str(payload.emoji) == "🐦"):
role = rolesDict.get("Role2")
await member.add_roles(role)
elif(str(payload.emoji) == "👪"):
role = rolesDict.get("Role3")
await member.add_roles(role)
So I want the bot to auto assign roles when a user has reacted to a message with a specific emoji. But my code does not work. How can I fix this????
#client.event
async def on_raw_reaction_add(payload):
messgae_id = payload.message_id
if messgae_id == "759765065380659261":
user = payload.user_id
for roles in user.roles:
if roles in DefaultRoles:
return
if payload.emoji.name == "smiling_imp":
role = discord.utils.get(user.server.roles, name = "Demon")
await user.add_role(user, role)
For the standard discord emojis, you can't use the name, you need to use the unicode symbol.
So not 'smiling_imp' but '😈'
To get unicode emojis you can add \ before the standard emoji before sending it (don't think it works on mobile)
After Discord.py 1.0, "server" is changed to "guild"
if message_id == ________________:
# Find the guild name
guild_id = payload.guild_id
guild = discord.utils.find(lambda g :g.id == guild_id, client.guilds)
# Get your guild role
if payload.emoji.name == '😈':
role = discord.utils.get(guild.roles, name='Demon')
# Find the member you are trying to assign role to
member = discord.utils.find(lambda m : m.id == payload.user_id, guild.members)
# Assign role
await member.add_roles(role)