I am following Anson the Developers tutorial, (here's a link) and I coded exactly as he did, I got no errors, except a warning Parameter 'payload' value is not used and I have made sure that:
The bot has proper permissions to assign roles
The bot is online
The emojis and the roles have the same names
heres the code for reference:
import discord
client = discord.Client()
#client.event
async def on_message(message):
if message.author == client.user:
return
#client.event
async def on_raw_reaction_add(payload):
message_id = payload.message_id
if message_id == '756794977148993597':
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 = discord.utils.find(lambda m: m.id == payload.user_id, guild.members)
if member is not None:
await member.add_roles(role)
print("done")
else:
print("member not found")
else:
print("role not found")
client.run('REDACTED')
I have tried a lot of troubleshooting and any help would be appreciated!
You should not use utils.find in your case.
client.get_guild to get the guild by id.
guild.get_member to get the member by id. also you can use guild.get_member_named if you want to use a name.
#client.event
async def on_raw_reaction_add(payload):
if payload.message_id == 756794977148993597:
guild = client.get_guild(payload.guild_id)
role = discord.utils.get(guild.roles, name=payload.emoji.name)
if role is not None:
member = guild.get_member(payload.user_id)
if member is not None:
await member.add_roles(role)
print("done")
else:
print("member not found")
else:
print("role not found")
Related
I try to remove a role using on_raw_rwaction_remove an remove_roles:
Because I don't have the guild_id/member_id in on_raw_reaction_remove I try to get it myself but got this error:
Ignoring exception in on_raw_reaction_remove - AttributeError: 'NoneType' object has no attribute 'request
(and line 45 [guild = await(bot.fetch_guild(payload.guild_id))] causes the error)
Here's the code I'm currently using:
#commands.Cog.listener()
async def on_raw_reaction_remove(self, payload):
ourMessageID = 867876893411508234
if ourMessageID == payload.message_id:
guild = await(bot.fetch_guild(payload.guild_id))
print("fetch successful")
if payload.emoji.name == 'YouTube':
role = discord.utils.get(guild.roles, name="YouTube")
print("Role checked")
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")
member = await(guild.fetch_member(payload.user_id))
print(member)
if member is not None:
await member.remove_roles(role)
else:
print("Member not found")
(I get no response from the two print's)
If I could do something different/simpler, please let me know!
The payload itslef doesn't have guild id but it does have the channel_id, user_id and message_id so you can use the channel id to fetch the channel object and then you can use message id to get the message object and get guild_id from it
#bot.event
async def on_raw_reaction_add(payload):
channel = await bot.fetch_channel(payload.channel_id) # returns channel object
message = await channel.fetch_message(payload.message_id)# returns message object
guild_id = message.guild.id #returns guild id
#REST OF THE CODE
This has worked for me now, thanks for the help:
#commands.Cog.listener()
async def on_raw_reaction_remove(self, payload):
ourMessageID = 867876893411508234
if ourMessageID == payload.message_id:
emoji = payload.emoji.name
guild = await self.bot.fetch_guild(payload.guild_id)
member = await guild.fetch_member(payload.user_id)
#REST OF THE CODE
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)
I get a member not found error when trying to remove a role on reaction remove (on_raw_reaction_remove).
It works to add the role to the member, but it can't remove the role afterwards.
My guess is that it can't properly get the ID for the member, but I don't really know how to fix it.
#client.event
async def on_raw_reaction_add(payload):
message_id = payload.message_id
if message_id == xxxx: #ID depends on message
guild_id = payload.guild_id
guild = discord.utils.find(lambda g : g.id == guild_id, client.guilds)
if payload.emoji.name == 'xxx':
role = discord.utils.get(guild.roles, name="xxx")
elif payload.emoji.name == 'xxxx':
role = discord.utils.get(guild.roles, name="xxx")
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.")
#client.event
async def on_raw_reaction_remove(payload):
message_id = payload.message_id
if message_id == xxxx: #ID depends on message
guild_id = payload.guild_id
guild = client.get_guild(payload.guild_id)
if payload.emoji.name == 'wexxed':
role = discord.utils.get(guild.roles, name="xxxx")
elif payload.emoji.name == 'xxxx':
role = discord.utils.get(guild.roles, name="xxx")
else:
role = discord.utils.get(guild.roles, name = payload.emoji.name)
if role is not None:
member = guild.get_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.")
payload.member only works with on_raw_reaction_add(), so, instead of using it, you have to fetch the user:
from discord.utils import get
#client.event
async def on_raw_reaction_remove(payload):
guild = await client.fetch_guild(payload.guild_id)
member = get(guild.members, id=payload.user_id)
(...)
PS: If you have discord.py 1.5.0 and didn't set up your Intents, you should look at this answer, or else, your events won't work right.
So currently I have a discord Bot, and I want to make it welcome any new users in #joining and give them the nickname "[0] Member Name". I'm not getting any errors but neither of these functions are working!
EDIT: Re-Wrote Some Code and I'm Now Getting This Error:
EDIT 2: Still Unable to Edit Nicknames, but when a User Leaves the Server I get these errors from the Function to check if the User is a Staff Member. I don't get errors from the message.author, but when the message author leaves, I start getting this error. I tried resetting the message.author when anyone leaves the server but this didn't help! I don't have any ideas on how to stop these errors!
Ignoring exception in on_message
Traceback (most recent call last):
File "C:\Users\Evan\Anaconda3\envs\testing\lib\site-packages\discord\client.py", line 270, in _run_event
await coro(*args, **kwargs)
File "C:/Users/Evan/PycharmProjects/Bot/bot.py", line 107, in on_message
top_role = message.author.top_role
AttributeError: 'User' object has no attribute 'top_role'
My New Edited Code vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
import discord
import asyncio
import time
# id = 630529690792230923
messages = joined = 0
client = discord.Client()
#client.event
async def on_ready():
print(f'Logged in as: {client.user.name}')
print(f"User ID: {client.user.id}")
print('-----')
async def update_stats():
await client.wait_until_ready()
global messages, joined
while not client.is_closed():
try:
with open("stats.txt", "a") as f:
f.write(f"Time: {int(time.time())}, Messages: {messages}, Members Joined: {joined}\n"),
messages = 0
joined - 0
await asyncio.sleep(3600)
except Exception as e:
print(e)
await asyncio.sleep(3600)
#client.event
async def on_raw_reaction_add(payload):
message_id = payload.message_id
if message_id == 638155786559684608:
guild_id = payload.guild_id
guild = discord.utils.find(lambda g: g.id == guild_id, client.guilds)
if payload.emoji.name == 'Test':
role = discord.utils.get(guild.roles, name='new role')
else:
role = discord.utils.get(guild.roles, name=payload.emoji.name)
if role is not None:
member = discord.utils.find(lambda m: m.id == payload.user_id, guild.members)
if member is not None:
await member.add_roles(role)
print("done")
else:
print("Member Not Found")
#client.event
async def on_raw_reaction_remove(payload):
message_id = payload.message_id
if message_id == 638155786559684608:
guild_id = payload.guild_id
guild = discord.utils.find(lambda g: g.id == guild_id, client.guilds)
if payload.emoji.name == 'Test':
role = discord.utils.get(guild.roles, name='new role')
else:
role = discord.utils.get(guild.roles, name=payload.emoji.name)
if role is not None:
member = discord.utils.find(lambda m: m.id == payload.user_id, guild.members)
if member is not None:
await member.remove_roles(role)
print("done")
#client.event
async def on_member_join(member):
global joined
joined += 1
rule_channel = member.guild.get_channel(channel_id=630530486858547223)
newusermessage = f"""Welcome to CB:NL {member.mention}! Have a Great Time And Make Sure to Look At {rule_channel}"""
channel = member.guild.get_channel(channel_id=630563931412496434)
role = member.guild.get_role(role_id=630533613947060244)
if member is not None:
await member.add_roles(role)
print("done")
await member.edit(str([f"[0] {member.display_name}"]))
await channel.send(newusermessage)
#client.event
async def on_member_remove(member):
discord.message.author = member
#client.event
async def on_message(message):
global messages
messages += 1
id = client.get_guild(630529690792230923)
bad_words = ["test"]
channels = ["bot-commands", "staff-general"]
pn = 1
author = message.author
top_role = message.author.top_role
staff_role = message.author.guild.get_role(role_id=630532857655328768)
if top_role > staff_role:
if message.content.startswith == "-clean":
pass
if str(message.channel) in channels:
if message.content.find("-hello") != -1:
await message.channel.send("Hi")
elif message.content == "-status":
await message.channel.send(f"""# of Members: {id.member_count}""")
else:
if message.author.bot is not 1:
print(f"""{message.author} tried to do command {message.content}""")
await message.channel.send(f"Error, {message.author.mention}. You Cannot Do That!")
client.loop.create_task(update_stats())
I'll respond in answer, because there are multiple mistakes in your code and it's hard to put into the comment. You can comment under this post if you get another error.
role = discord.utils.get(discord.Guild.roles, name="Member")
The error is where you retrieve the role by name Member. It's better to get the role by ID, you can do that using member.guild.get_role(630533613947060244). The error is that discord.Guild.roles is not an iterable property.
nick = discord.utils.get(str(member.nick))
Not sure what is your intention there, you can use nick = member.nick to get a string with member's nickname.
To edit the nickname you should use:
await member.edit(nick=f"[0] {member.display_name}")
AttributeError: 'User' object has no attribute 'top_role'
You get this error because you want to access top_role attribute on instance of discord.User, but only discord.Member has this attribute defined. When someone leaves the server you get the User instance instead of the Member instance.
if isinstance(message.author, discord.Member):
top_role = message.author.top_role
else:
top_role = None # top role not available, user has no roles