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)
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)
Related
So I have this to make a welcome message for new members.
#bot.event
async def on_member_join(member):
channel = bot.get_channel('channel_id')
await channel.send("insert message")
Does this work on bots? And will this work if the person joining is a real user?
Note: that bot.get_channel() takes int not str, if you've passed int then kindly check if you've enabled Intents for your bot in developers page and in your code.
On developers page: https://discord.com/developers/applications/{bot_id}/bot Enable server members intent in Privileged Gateway Intents.
On your code:
intents = discord.intents.default()
intents.members = True
bot = commands.bot(command_prefix=prefix, intents=intents)
Yes, it will respond to bots. Bots are actually a normal user, they just have a special status.
If you want to filter out bots, then just look at the member object, it contains a property that will tell you if it is a robot - member.bot.
So then you can write something like this:
#bot.event
async def on_member_join(member):
if not member.bot:
channel = bot.get_channel('channel_id')
await channel.send("insert message")
Edit PS:
I recommend making a test discord server if you don't have it yet, and you can test it directly.
And to test people's connections, simply leave it open to people without an account, and open the server invitation in an anonymous browser window.
So recently I've tried to create a bot that could change the voice channel's name based on how many members are on the server, but I end up getting this error: await memberchannel.edit(name = ">> 👥ᴍᴇᴍʙᴇʀꜱ: " + guild.member_count) AttributeError: 'NoneType' object has no attribute 'edit'
Here's my code, I cannot figure out how to access the .edit attribute:
async def on_member_join(member):
guild = member.guild
memberchannel : discord.VoiceChannel = get(guild.channels, id=MemberCounterChannel)
await memberchannel.edit(name = ">> 👥ᴍᴇᴍʙᴇʀꜱ: " + guild.member_count)
I did the same thing in the on_member_remove function.
Events that use on_member_join or others related to member events, must require member intents to be enabled. This works to allow these events to run as they are private and should be used carefully.
Intents can be enabled from Discord developer portal, from there you only need to make sure you have enabled Member in intents within the "Bot" category. You'd then need to define and use the intents in your bot code in the section you define your bot or client:
intents = discord.Intents.default()
intents.members = True
client = commands.Bot(command_prefix='your bot prefix', intents=intents)
After you have enabled intents, the member events would work. With your code, memberchannel also isn't defined, nor is it a Discord parameter.
This would now get the channel you want to edit by it's ID and edit whenever a user joined to the current member count of the guild the user joined.
async def on_member_join(member):
member_channel = client.get_channel(channel id)
await member_channel.edit(name=f"Members: {member.guild.member_count}")
I had to toggle all of the intents in my application using discord developers panel and left the code like this (ConfigFile is a json file containing all of the variables):
memberchannel: discord.VoiceChannel = get(guild.channels, id=ConfigFile["MemberCounterChannelID"])
membercount = guild.member_count - 1
await memberchannel.edit(name="{0} {1}".format(ConfigFile["MemberCounterChannelName"], membercount))
Also I did the membercount = guild.member_count - 1 part because I only use this bot on my server and it's not made for commercial use so I don't really need it to actually count member-bots
I want to make a profile command that shows member status(online, offline, etc.).
#client.command(passContent=True)
#commands.has_role("🍿║Участники")
async def профиль1(ctx, member: discord.Member = None):
await ctx.send(f'your status is {ctx.author.status}')
When someone uses this command he always appears offline. ("your status is offline")
You need to use Intents!
Intents are new in version 1.5 of discord.py
Activate Intents on the discord developer portal
Add this to the top of your code
intents = discord.Intents().all()
client = commands.Bot(command_prefix = '?',intents=intents)
# OR
bot = commands.Bot(command_prefix='?', intents=intents)
Then everything should work fine.
You can also join the discord.py server via this link
I want to retrieve a list with all people which are part of the discord server.
import discord
from discord.ext import commands
TOKEN = 'my_token'
bot = commands.Bot(command_prefix = '!')
#bot.command()
async def members(ctx):
for member in ctx.guild.members:
await ctx.send(member)
bot.run(TOKEN)
Whenever using !members I just get a List of all members which are currently in a voice channel or in some way active on the server where but I'd like to get those just shown as online or even offline.
Does someone have any idea?
Since last updates you have to enable intents. Enable them from the dev portal and code it self.
intents = discord.Intents().all()
bot = commands.Bot(command_prefix="$", intents=intents)
Remove that line with server = bot.get_guild(SERVER_ID)
Guild.members will return a list of members in the guild.
Since >=1.5.0 requires elevated intents for Member/Presence events, you must enable the Member intents in the developer portal and in your code.
You're also checking for the number of members in which the command is invoked, so you would want to use the guild_only() decorator and remove the line with bot.get_guild()
Reason for having the guild_only() decorator is because if you invoke !members in a DM, guild would be None and will raise an error saying that 'NoneType' object has no attribute called 'members'
I made a stupid discord bot a few months ago to change my friends name every minute, but I updated it today and now the get_member function is returning none.
#client.event
async def on_ready():
print('bot is ready!')
status = discord.Activity(name="Sam be a loser", type=discord.ActivityType.watching)
await client.change_presence(activity=status)
name_change.start()
#tasks.loop(minutes=1)
async def name_change():
server = client.get_guild(id=584112137132048387)
user = server.get_member(376388277302984714)
global english_words
global wordNumber
wordNumber = wordNumber + 1
#changes nickname to current word
await user.edit(nick=f"{english_words[wordNumber]} lookin' ass")
print(f'Word number {wordNumber}: {english_words[wordNumber]}')
#updates number in file
file = open("currentWord.txt", "w")
file.write(str(wordNumber))
file.close
I tried the same function with every user in the server, but it returned none for all of them except when I put the bot's id in. I have no clue why this is happening since I didn't even edit this part of the code.
This is most likely due to the recent discord.py 1.5 update. You are required to configure your intents when you're declaring your Bot.
What are intents?
Version 1.5 comes with the introduction of intents. This is a radical change in how bots are written. An intent basically allows a bot to subscribe into specific buckets of events. The events that correspond to each intent is documented in the individual attribute of the Intents documentation. Here's an example:
import discord
from discord.ext import commands
intents = discord.Intents.default()
intents.members = True # Subscribe to the privileged members intent.
bot = commands.Bot(command_prefix='!', intents=intents)
You will also have to enable privileged intents for guild related events: Here
You can read more about intents: Here
You may be able to not use Intents, Privileged or otherwise, by not using get_member() and instead use
guild.fetch_member()