how to fix add roles on voice channel join - python

i can't get my bot to add roles. what am i doing wrong here?
class MyClient(discord.Client):
async def on_voice_state_update(member, before, after):
role = get(member.server.roles, name="babbelaar")
if after.channel is None:
member.add_roles([role.id])
else:
member.remove_roles([role.id])
i want a user that joins a voice channel to get a certain role, and that role to be removed after the user leaves the voice channel

You need to await adding/removing roles, and pass the roles as an argument list of Role objects (instead of passing a list):
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

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

how to make a bot that gives role when we join a particular voice channel and removes when left

I am learning how to use discord.py and I want to make bot feature that give role when we join particular voice channel and removes the same role when user leaves the channel
#client.event
async def on_voice_state_update():
on_voice_state_update gives you after and before arguments, here's how to check when a member joined and left a voice channel
async def on_voice_state_update(member, before, after):
if before.channel is None and after.channel is not None:
# member joined a voice channel, add the roles here
elif before.channel is not None and after.channel is None:
# member left a voice channel, remove the roles here
To add roles, first you need to get a discord.Role object, then you can do member.add_roles(role)
role = member.guild.get_role(role_id)
await member.add_roles(role)
To remove a role is the same, but .remove_roles
await member.remove_roles(role)
EDIT:
async def on_voice_state_update(member, before, after):
channel = before.channel or after.channel
if channel.id == some_id:
if before.channel is None and after.channel is not None:
# member joined a voice channel, add the roles here
elif before.channel is not None and after.channel is None:
# member left a voice channel, remove the roles here
Reference:
on_voice_state_update
Guild.get_role
Member.add_roles
Member.remove_roles

Detecting Multiple Guild IDs - Discord.py

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

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!")

Categories