hydroxide
hydroxide

Reputation: 23

Discord.py cannot send dm to member

The error code is:

member = message.guild.get_member(message.author.id)
await member.send(embed=level_up)

When trying to execute the second line, I get the error:

AttributeError: 'ClientUser' object has no attribute 'create_dm'

I read in the documentation that message.guild.get_member() should return a Member object, however it returns a ClientUser object for some reason, which you cannot send messages to. I want to send a dm to message.author

whole function code:

    @commands.Cog.listener()
    async def on_message(self, message):
        if not isinstance(message.channel, discord.channel.DMChannel) \
                and not message.content.startswith(yaml_data["Bot"]["Prefix"]):

            management = message.guild.get_role(yaml_data["Tickets"]["Management_Role"])
            operations = message.guild.get_role(yaml_data["Tickets"]["Operator_Role"])
            ownership = message.guild.get_role(yaml_data["Tickets"]["Owner_Role"])

            with open(arrays_folder + r"/members.json") as members_file:
                members_data = json.load(members_file)

            if random.random() < yaml_data["Xp"]["Xp_Chance"]:

                level_before = self.get_level(members_data["members"][str(message.author.id)]["Xp"])
                members_data["members"][str(message.author.id)]["Xp"] += 1
                level_after = self.get_level(members_data["members"][str(message.author.id)]["Xp"])

                with open(arrays_folder + r"/members.json", "w+") as f:
                    json.dump(members_data, f, indent=4)

                if level_after > level_before \
                        and not any(role in message.author.roles for role in (ownership, operations, management)):
                    if level_after < yaml_data["Xp"]["Levels"] and message.author.id != self.client.user.id:

                        level_up = discord.Embed(
                            description="You have leveled up!\n\n"
                                        f"You are now **Level {level_after}**!",
                            color=yaml_data["Customisation"]["General_Embed_Colour"])

                        new_role = discord.utils.get(message.guild.roles, name="Level " + str(level_after))

                    else:

                        level_up = discord.Embed(
                            description="You have leveled up!\n\n"
                                        f"You are now **{yaml_data['Xp']['Max_Level_Name']}**!",
                            color=yaml_data["Customisation"]["General_Embed_Colour"])

                        new_role = discord.utils.get(message.guild.roles, name=yaml_data['Xp']['Max_Level_Name'])

                    member = message.guild.get_member(message.author.id)
                    await member.send(embed=level_up)
                    await message.author.send(embed=level_up)
                    old_role = discord.utils.get(message.guild.roles, name="Level " + str(level_before))
                    await member.remove_roles(old_role)
                    await member.add_roles(new_role)

Upvotes: 2

Views: 646

Answers (1)

user11936470
user11936470

Reputation:

The problem is Privileged Gateway Intents. If you are not aware that Discord recently brought Gateway Intents. These intents are required for the bots that are tracking members of the server. As you are sending "a member" DM, You need the Members Intents. Without intents, the "get_member" function only returns the bot user.
To get the intents, Head to the developers portal and in bot section (where you have the bot's token). Scroll down till you see; Privileged Gateway Intents. Turn on the the Presence and Member's intents and save it. Once you are done, Go to your code. (Make sure you are using Discord.py 1.5+ as that version introduced intents.) So, In your code:

# after importing libraries or modules, where you are declaring client or bot variable;
client = commands.Bot(command_prefix="prefix", intents=discord.Intents.all())

# rest of the code with your command or function [...]

client.run("token")

This explanation may not be enough for you, Make sure you read the official documentation on that topic to get better explanation and steps to work with intents. Click here for documentation reference.

NOTE: If your bot is in 75+ servers, you will need to verify from discord to use intents, and also, With 75+ servers, you will also have to enable only the intents that you need like if you don't need presence intents you can't use it BUT if your bot is in less then 75 servers use the intents freely with no restrictions (for now, once bot reaches 75 servers, you will need to verify)

Upvotes: 1

Related Questions