Detecting Multiple Guild IDs - Discord.py - python

This code works for sending a DM to a user who joined a guild, but it only executes the first if statement instead of actually checking to see what guild the member joined. I'll get the first DM from the bot whether I join guild1 or guild2.
#client.event
async def on_member_join(member):
guild1 = client.get_guild(762921541204705321)
guild2 = client.get_guild(593941391110045697)
if guild1.id == 762921541204705321:
await member.create_dm()
await member.dm_channel.send("Welcome to guild1!")
elif guild2.id == 593941391110045697:
await member.create_dm()
await member.dm_channel.send(f"Welcome to guild2!")

In your example, you are not actually checking the guild that the member is in.
In discord.py (and similar libraries), member objects are not unique to a user, but rather they represent a user's membership in a guild.
With discord.py, the guild is stored in a member as the property "guild":
guild_id = member.guild.id
You can then compare the member's guild with your other guild ids:
if guild_id == 762921541204705321:
# do stuff
elif guild_id == 1231254125151:
# do other stuff

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

How do I make a bot that joins a voice channel when a specific person joins a voice channel?

Very new to this. I've been reading the readthedocs API reference for discord.py and it's isn't making a lot of sense to me. So far I have
import os
import discord
#os.environ['targetID']
bot = discord.Client()
intents = discord.Intents.default()
intents.members = True
channel_id = os.environ['channelID']
voice_channel = bot.get_channel(channel_id)
async def on_ready():
print ("Ready")
channel_id = os.environ['channelID']
voice_channel = bot.get_channel(channel_id)
await voice_channel.connect()
#async def on_voice_state_update(Member, channel[None], channel['general']):
# print(client.member.id)
#move_to(None)
bot.run(os.environ['token'])
The goal is to get the bot to join the voice channel that the user with the targetID join, but I'm having trouble just getting the bot to join a channel in the first place.
Based on the answer of Nathan Marotte I will provide a code example.
You can use an on_voice_state_update function in order to check in which channel the member is.
Therefore take a look at the following code:
#bot.event
async def on_voice_state_update(member, before, after):
targetID = bot.get_user(TargetIDHere)
if before.channel is None and after.channel is not None and member.id == targetID.id: # Condition that must be fulfilled
await member.voice.channel.connect() # Connect to the channel
To explain the different functions in the code:
before.channel is None = Checks that the user is not in a channel/was not in a channel.
after.channel is not None = Checks the channel which the user joined and then grants the role.
member.id == targetID.id = Checks if the member.id that joined matches targetID.id.
on_voice_state_update is what you need. This event will be called when a change of voice state happens on the server, this includes
A member joins a voice channel.
A member leaves a voice channel.
A member is muted or deafened by their own accord.
A member is muted or deafened by a guild administrator.
This function takes 3 parameters, the member to which the update occurred, the state before, and the state after.
When this event is triggered, check that member.id == target_member.id. If it is the case, then await after.channel.connect()
You should also add checking if the bot is not already in this channel and other stuff but this should point you in the right direction

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