Hereux
Hereux

Reputation: 45

discord.py | How do I check if users have a special role?

I want all users who have the role "notify" to receive a DM. But I would like to do that with a @client.event, but it gives me a lot of problems.

It is a voice support offered on e.g. the message "1" plays a file in a voice channel. If someone needs help from a supporter, all supporters should receive a direct message. The problem is that you can't use a ctx for a client.event.

@client.event
async def on_message(message):
    if message.content.startswith('1'):
        print('Hi')
        role = 'notify'
        msg = 'Hello World!'
        members = [m for m in '''What do I must put in here?''' if discord.guild.User in m.roles]
        for m in members:
            try:
                await m.send(msg)
                print(f":white_check_mark: Message sent to {m}")
            except:
                print(f":x: No DM could be sent to {m}")
                return
    else:
        print('Error')

Upvotes: 0

Views: 710

Answers (1)

Nurqm
Nurqm

Reputation: 4743

You should get the guild and the role with discord.utils.get or guild.get_role(), client.get_guild(). After that, you can iterate through the member's role and check if they have the role, if they have, you can send message.

@client.event
async def on_message(message):
    if message.content.startswith('1'):
        print('Hi')
        guild = client.get_guild(guild id)
        role = guild.get_role(role id)
        msg = 'Hello World!'
        members = [member for member in guild.members if role in member.roles]
        for m in members:
            try:
                await m.send(msg)
                print(f":white_check_mark: Message sent to {m}")
            except:
                print(f":x: No DM could be sent to {m}")
                return
    else:
        print('Error')

But this code is really inefficient because you're iterating through all the members every time someone sends a message. So you should add a on_ready event in your code and you should create the members list in there.

@client.event
async def on_ready():
    global members
    guild = client.get_guild(guild id)
    role = guild.get_role(role id)
    members = [member for member in guild.members if role in member.roles]

on_ready event runs only once, so if you add the specific role to someone after you run the bot, it won't send dm to that member. So you also need to create a task loop to check this every 120 seconds or more(if you're sure that you won't give that role to anybody else, you don't need to create a task).

@tasks.loop(seconds=120)
async def check_role():
    global members
    guild = client.get_guild(guild id)
    role = guild.get_role(role id)
    members = [member for member in guild.members if role in member.roles]
check_role.start()

So, finally, your code should seem like that:

@client.event
async def on_ready():
    global members
    guild = client.get_guild(guild id)
    role = guild.get_role(role id)
    members = [member for member in guild.members if role in member.roles]

@tasks.loop(seconds=120)
async def check_role():
    global members
    guild = client.get_guild(guild id)
    role = guild.get_role(role id)
    members = [member for member in guild.members if role in member.roles]

@client.event
async def on_message(message):
    if message.content.startswith('1'):
        print('Hi')
        for m in members:
            try:
                await m.send(msg)
                print(f":white_check_mark: Message sent to {m}")
            except:
                print(f":x: No DM could be sent to {m}")
                return
    else:
        print('Error')

Also, I'm not sure but you can try to use AuditLogs. I don't know how to use it very good but you can check the API References audit log data.

Upvotes: 1

Related Questions