How to get member names on discord.py? - python

I want to get the member names from a connected discord server, but the code I have right now just prints out {"Security"}:
import discord
import os
client = discord.Client()
def get_member_names():
for guild in client.guilds:
for member in guild.members:
yield member.name
#client.event
async def on_ready():
print("We have logged in as {0.user}".format(client))
people = set(get_member_names())
print(people)
#client.event
async def on_message(message):
if message.author == client.user:
return
print(message.content[0] == '>')
client.run(os.environ["BOT_PASSWORD"])

use guild.fetch_members(limit=None) instead of guild.members.
See docs

You could try using the members property but if I recall correctly Discord removed this from their API.

The preferred method for doing this is through client.get_all_members(), which is an equivalent of the code you currently have, so I don't think this is an issue with your code. Your problem may be in what members your bot can actually see. If {"Security"} is all you're seeing, perhaps your bot can only see a member named Security. Make sure your bot has the proper permissions to view a channel that has members in it. Seeing members is reliant on the View Channel permission (For example, if someone doesn't have permission to view a channel, they won't appear in the member list, this works both ways)

Related

Discord.py Not recognising the member intent

I'm trying to make a discord bot in python which gives the user a role if they enter the correct text.
The weird thing is, I have a code which, for some reason, doesn't work. I have imported member from discord, but when I run this specific code, it says NameError: Member Not Defined.
Imports:
from discord import Member
Code:
#client.event
async def on_message(message):
verify_channel = client.get_channel(#idgoeshere)
verify_role = get(member.guild.roles, id='#idgoeshere')
if message.content == 'Exo' in verify_channel:
await member.add_roles(message.author, verify_role)
await message.send(f'{message.author}, You have gained access to the other channels!')
I really don't know what the problem is, I have searched up on stackoverflow but there isn't much of these problems associating with this. My other discord bots work with the member function and importation.
Well, it's because member isn't defined.
In your code, you have an on_message event, and you're getting the message. You can try defining member as member = message.author. You don't import member directly from discord. Because you are just importing the member class. I hope this helps answer your question.
P.S, in the line if message.content == 'Exo' in verify_channel: that is not how you check if it is in that channel.
You need to have something like if message.content == 'Exo' and message.channel verify_channel:. I hope this helps too
As your error states, you have not defined member. Member is usually used in commands and is defined, as seen here:
#client.command()
async def test(ctx, member:discord.Member):
await member.add_roles(verify_role)
However, since you are not using commands, this is not going to be your approach. It would be best to replace member with message.author instead, as this also gives you a discord.Member object. Have a look at the revised code below.
#client.event
async def on_message(message):
verify_channel = client.get_channel(#idgoeshere)
verify_role = get(member.guild.roles, id='#idgoeshere')
if message.content == 'Exo' in verify_channel:
await message.author.add_roles(verify_role)
await message.send(f'{message.author}, You have gained access to the other channels!')
# alternatively, you could add a separate variable such as
# member = message.author
# but using message.author on its own can be cleaner and clearer in this case

How to add a role to a specific member when he joins a discord server

I'm new to python, so can someone help me with my code, because it is not working properly. When the user that I want joins it doesn't give it a role. I want to make it work for a specific user only to give a role when joining discord server.
#client.event
async def on_member_join(member):
member = get(member.id, id=member_id)
role = get(member.guild.roles, id=role_id)
await member.id(member)
await member.add_roles(role)
I don't even know why you're making this so complicated.
Since you already have the member as an "argument" you can work with it and don't have to define member again.
We can get the ID of member very easily with member.id. If we want to compare this with a real ID, we do the following:
if member.id = TheIDHere:
# Do what you want to do
The function for the role is correct, yet I cannot find a use for await member.id(member). What is the point of this/has it any use?
How you add the role at the end is also correct, but the code must be indented properly and best you work with an if / else statement, otherwise the bot will still give an error at the end in the console if always the wrong member joins.
The whole code:
#client.event
async def on_member_join(member):
role = discord.utils.get(member.guild.roles, id=IDOfTheRole) # Get the role from member.guild and the id
if member.id == TheIDHere: # If the member.id matches
await member.add_roles(role) # Add the role for the specific user
else: # If it does not match
return # Do nothing
You may also need to enable the members Intent, here are some good posts on that:
https://discordpy.readthedocs.io/en/stable/intents.html
How do I get the discord.py intents to work?

How do you make your bot ignore reply mentions?

In my bot, I have an event for replying to when the bot is mentioned. The issue is, that it replies when u mention the bot through replying to it. How can I fix this? Here's my code:
#commands.Cog.listener()
async def on_message(self, msg):
guild = msg.guild
prefix = get_prefix(self.client, guild)
if msg.author == self.client.user:
return
if msg.mention_everyone:
return
if self.client.user.mentioned_in(msg):
embed = discord.Embed(description=f"The prefix for this server is `{prefix}` <:info:857962218150953000>", color=0x505050)
await msg.channel.send(embed=embed)
Change
if self.client.user.mentioned_in(msg):
to
if msg.guild.me.mention in msg.content:
Why this happens
discord messages use a special field in it's messages to specify if someone is mentioned or not, if a message has someone in that field then the message will ping that someone. mentioned_in works that way so you can figure out if a certain message pings a certain person. when we use the msg.guild.mention part, we manually check for the mention instead of discord telling us if someone was mentioned since discord counts replies as mentions
I've used the following code for similar applications.
Note - Replace 'client' in client.user.id with what you've used like bot.user.id
#client.event
async def on_message(message):
if message.content in [f'<#{client.user.id}', f'<#!{client.user.id}>']:
await message.channel.send("Hey! My prefix is ```,```")
await client.process_commands(message)

Discord Bot Delete Messages in Specific Channel

TIA for your help and apologies, I'm a newbie so this may be a foolish question. I've searched through and can't find anything specific on how to make a discord bot (in Python) delete messages only within a specific channel. I want all messages sent to a specific channel to be deleted, their contents sent via PM to the user and the user's role changed.
Is there a way to use on_message and specify in an specific channel?
#client.event
async def on_message(message):
user = message.author
if message.content.startswith("Cluebot:"):
await message.delete()
await user.send("Yes?")
await user.remove_roles(get(user.guild.roles, "Investigator"))
The problem I'm having is I'm also using commands which now no longer work because the bot only responds if the message begins with "Cluebot:" Can I have the bot only look for "Cluebot:" in a specific channel?
Is it possible to make this work through a command instead of an event?
Thanks for your help. :)
The problem I'm having is I'm also using commands which now no longer work because the bot only responds if the message begins with "Cluebot:" Can I have the bot only look for "Cluebot:" in a specific channel?
About this problem the clue is:
await bot.process_commands(message)
as docs says Without this coroutine, none of the commands will be triggered.
about the main question you could try using get_channel by ID and then purge it:
eg.
#client.event
async def on_message(message):
purgeChannel = client.get_channel([CHANNEL ID]])
await purgeChannel.purge(limit=1)
you can add check to purge() to check for deleting specific message:
eg.:
def check(message):
return message.author.id == [author's ID]
#client.event
async def on_message(message):
purgeChannel = client.get_channel([CHANNEL ID]])
await purgeChannel.purge(limit=1, check=check)

How to get User roles on discord.py rewrite

New discord.py-rewrite user here.
I'm coding a bot that has a discord interface: It is connected to more than one server (guild) and I currently need an auth system to limit its use.
I thought I could get all users roles and parse them later when needed. So I did:
#client.event
async def on_ready():
...
for guild in client.guilds:
for member in guild.members:
for role in member.roles:
if role.name == "Test":
print("USER_ID: %d - ROLE: %s" % (member.id, role.name))
but I don't like it. I have to store these and its not efficient. Also I have to refresh with a background co-routine to check if new members join/changed roles.
So my question: is there a simply way to check on the fly user roles on mutual guilds when receiving a message?
Scrolling the official API the only way to get user's mutual guilds is profile() but as a bot I get a Forbidden Error, like API says.
#client.event
async def on_message(message):
...
profile = await message.author.profile()
discord.errors.Forbidden: FORBIDDEN (status code: 403): Bots cannot use this endpoint
(update) ADDENDUM:
I need to check user's roles even in private messages so the need to get mutual_guilds
I have looked trough the Documentation, and I don't think there is simpler way to do this.
#commands.command(pass_context=True)
async def test(self, ctx):
for role in ctx.guild.roles:
if role.name == 'Your role name':
#Code
Simply when certain command is called, you check for each role on the guild the message was sent in, and if the role name matches the role name you pick, it will execute certain code.

Categories

Resources