change role to all server members - python

I want to create a discord bot that, after receiving a message from the admin, changes the role of all server members (excluding the admin) from #everyone to #newrole.
I tried this code but there is an error:
role = discord.utils.get(server.roles, name="newrole")
AttributeError: 'NoneType' object has no attribute 'roles'
I use the latest version of discord and Python 3.6.
server = client.get_guild(int(server-id))
#client.event
async def on_message(message):
if message.content.startswith('change role'):
await message.author.send("Change the role from #everyone to #newrole")
role = discord.utils.get(server.roles, name="newrole")
for member in server.members:
await member.add_roles(role)

All members have the everyone role at all times. Members can have multiple roles, however, so you can also give them your new role. There is no coroutine for bulk assigning roles, so you have to do it member by member:
#client.event
async def on_message(message):
if message.content.startswith('change role'):
await message.author.send("Change the role from #everyone to #newrole")
role = discord.utils.get(message.guild.roles, name="newrole")
for member in message.guild.members:
await member.add_roles(role)

Related

How to check if the player has a role when the bot starts and sends the message "on_ready"

Blockquote
I have a bug, I created a bot that issues a role when entering the members server, but sometimes the bot is offline and cannot issue a role
Therefore, I wanted the bot to display a role when the bot is started if the member does not have a role, and to do nothing if the member already has a role
I tried it but it doesn't work and yes I work because of the cogenter image description here
#commands.Cog.listener()
async def on_ready(self, guild: discord.Guild):
role = discord.utils.get(guild.roles, id=775777298111791104)
for m in guild.members:
for r in role.guild.members:
if m.guild.roles != r.get_role(775777298111791104):
print("Ok")
await m.add_roles(role)
=======================================================================
async def setup(bot):
await bot.add_cog(JoinMemberMessages(bot))
I think there's a few fundamental issues with your code.
You're looping over the guild members and then for each guild member you're starting another loop where you're looping over the guild members again? Then you're checking if all the server's role is equal to one particular role?
Additionally, the on_ready event doesn't take guild as a parameter
Your code doesn't quite do what you suggest it's trying to do.
async def on_ready(self):
# if your client/bot is instantiated as another var - then change this
# perhaps if it's `client` or `self.bot` or whatever
guild = await bot.fetch_guild(YOUR_GUILD_ID)
role = discord.utils.get(guild.roles, id=MY_ROLE_ID)
for member in guild.members:
member_roles = member.roles
member_role_ids = [role.id for role in member_roles]
if MY_ROLE_ID in member_roles_ids:
# user already has our role
continue
await member.add_roles(role)
print(f"Given {member.name} the {role.name} role")
Replace CAPITAL_VARIABLES with yours or the relevant magic numbers.
Here, we loop over the members and check they don't have the existing role ID; and assign it to them if they don't.
Perhaps check the docs:
on_ready
discord.Guild
discord.Member

member receives role when joining discord

Got a simple code that gives a role to members when they join the server. For some reason, it doesn't work. Here is the code:
#client.event
async def on_member_join(member):
role = discord.utils.get(member.guild.roles, name="Players")
await member.add_roles(role)
Doesn't give any errors, am I missing some sort of perms?

Checking for Multiple Guild ID's - Discord.py

I'm trying to send a welcome DM to users that join my discord server, but I have the bot setup in multiple servers. I'm trying to check the guild then send a message based on which guild it is in, but it's not working. I've looked and the popular question like this on stackoverflow uses commands and ctx, which cannot be used in on_member_join().
#client.event
async def on_member_join(member):
guild = client.get_guild(762921541204705321)
if guild == 762921541204705321:
await member.create_dm()
await member.dm_channel.send("Welcome!")
According to the documentation, when you call get_guild() it doesn't return the guild ID, it returns a Guild object. From the source code, it appears that this guild class does have its comparison operator overloaded, so it cannot deal with comparisons between a Guild object and an integer ID.
The solution to your problem is to just compare the number ID with the Guild.id attribute:
#client.event
async def on_member_join(member):
# client.get_guild returns a Guild object!
guild = client.get_guild(762921541204705321)
# Get the ID from the 'id' attribute on the guild object and compare.
if guild.id == 762921541204705321:
await member.create_dm()
await member.dm_channel.send("Welcome!")

How to fetch actual users and exclude bots in discord.py?

I am trying to make a command that gives a specific role to every actual user in a guild , excluding bots.
code I have:
#commands.command()
#commands.has_permissions(manage_roles=True)
async def maddrole(self,ctx,role: discord.Role):
guild = ctx.guild
for member in guild.members:
await member.add_roles(role)
embed= discord.Embed(description=f'{role} have been given to all users.',color=discord.Color.red())
await ctx.channel.send(embed=embed)
this fetches everyone in the guild(bots too) . How do I exclude bots and fetch only real users?
The Member object has a bot attribute which will be true if the user is a bot, so
for member in guild.members:
if member.bot:
continue
await member.add_roles(role)
discord.Member objects have a bot attribute that returns either True or False depending if the member is a bot or not:
#commands.command()
#commands.has_permissions(manage_roles=True)
async def maddrole(self,ctx,role: discord.Role):
guild = ctx.guild
for member in guild.members:
if member.bot:
continue
await member.add_roles(role)
embed= discord.Embed(description=f'{role} have been given to all users.',color=discord.Color.red())
await ctx.channel.send(embed=embed)

'User' object has no attribute 'add_roles'

When trying to do await member.add_roles(role) where member is a User, it gives me the following error:
'User' object has no attribute 'add_roles'
However, when I look online, there is no mention of such an error, implying that this error isn't supposed to happen.
If it helps, this is the section of the code where this error happens:
#bot.event
async def on_raw_reaction_add(payload):
EMOJI = '✅'
guild = discord.utils.get(bot.guilds, name='The Molehill')
channel = bot.get_channel(740608959207047250)
member = await bot.fetch_user(payload.user_id)
message = await channel.fetch_message(payload.message_id)
MESSAGE = "{user.name} is now part of the Mole Workforce!"
rules_message = message=await channel.fetch_message(740891855666806866)
role = discord.utils.get(guild.roles, name="Worker Mole", id=739514340465705027)
if payload.emoji.name == EMOJI:
if message == rules_message:
await member.add_roles(role)
await bot.send(MESSAGE)
You are trying to add a role to a user object, however they can only be added to member objects. While a user represents a user on discord a member represents a member of a guild.
More information on members in the documentation
A user object is not directly linked with a guild. This is the reason it doesnt have functions to add roles to it. As roles are part of guild functionality.
If we want to fix this we need to get an object that is linked with a guild. The closest match is in this case the member object.
So instead of retrieving the user object and retrieving a member object instead should solve the problem:
#bot.event
async def on_raw_reaction_add(payload):
EMOJI = '✅'
guild = discord.utils.get(bot.guilds, name='The Molehill')
channel = bot.get_channel(740608959207047250)
member = await guild.get_member(payload.user_id)
message = await channel.fetch_message(payload.message_id)
MESSAGE = "{user.name} is now part of the Mole Workforce!"
rules_message = message=await channel.fetch_message(740891855666806866)
role = discord.utils.get(guild.roles, name="Worker Mole", id=739514340465705027)
if payload.emoji.name == EMOJI:
if message == rules_message:
await member.add_roles(role)
await bot.send(MESSAGE)
But when we read the documentation about the on_raw_reaction_add. We see that this can be much more efficient without needing lookups through the bot.
For example in the event documentation you see we get a payload object.
The payload object has the following data (and more just read the documentation):
a member object
guild id
channel id
user id
message id
Notice that we have a member object.
We can retrieve the following from it:
a guild object
So updating the old code to the following increases the performance as we dont need to look up stuff through the bot unnessecarily. Note: I removed some redundant code in this example, I assume you only run this bot in 1 guild, because you are using specific ID's that wont work in other guilds.
#bot.event
async def on_raw_reaction_add(payload):
EMOJI = '✅'
member = payload.member
guild = member.guild
# If you want to run your bot on multiple guilds. Then the code under this comment should be updated.
channel = guild.get_channel(740608959207047250)
MESSAGE = "{user.name} is now part of the Mole Workforce!"
role = guild.get_role(739514340465705027)
if payload.emoji.name == EMOJI:
await member.add_roles(role)
await bot.send(MESSAGE)

Categories