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.
Related
This is my code, but no matter what I try it's only tagging the bot? Do you know what I'm doing wrong? I've spent hours on this and I've not been able to figure it out.
#client.command(pass_context=True)
async def test(ctx):
user = random.choice(ctx.message.channel.guild.members)
await ctx.send(f'{user.mention} Youre the best')
I'm trying to get it to tag any random user.
Most likely, you did not give the bot permission to receive users information (SERVER MEMBERS INTENT) on the site Discord Developers in the Privileged Gateway Intents section.
code is only mentioning the bot, which is executing the command!
Try this:
#client.command(pass_context=True)
async def test(ctx):
members = [member for member in ctx.message.channel.guild.members if not member.bot]
if not members:
await ctx.send("There are no non-bot members in this guild.")
return
user = random.choice(members)
await ctx.send(f'{user.mention} You're the best')
As #DK404 has already mention, you probably didn't enable the Server Members Intent on Discord Developers.
Also check if you have enabled the intent for your bot too. You can do that by adding the intents parameter to your bot instance:
client = discord.Client(..., intents = discord.Intents.all())
After you do that try running the bot again.
By the way ctx.message.channel.guild.members is the same as ctx.guild.members
if message.content.startswith('$register'):
await message.channel.send('You are registered successfully')
userk = print(client.user.id)
I am using Discord.py and Iam trying to get the Discord user id of a user when they type into a channel. But I am not able to find the specific command for that current api of discord is not saying anything about that.the above code is only printing my bot's id.
Get the author of the message
You need to look the id of the author.
API:
discord.on_message(message): Get a message, a Message,
class discord.Message: look for author attribute, a Member,
class discord.Member: look id attribute.
if message.content.startswith('$register'):
await message.channel.send('You are registered successfully')
print(message.author.id)
Maybe a possible answer here:
Discord-py When a user is typing, how to make the bot to follow the typing and when the user stop, the bot also stop typing in a specific channel?
EDIT:
enabling intents.typing and turning on the intents within the
Discord developer portal can access the on_typing event, you can
just enable all intents from your code like:
discord.Client(intents=intents) ```
The typing event can be called simply using an ``on_typing`` event,
``` #client.event async def on_typing(channel, user, when):
print(f"{user} is typing message in {channel} {when}")
Here is an example:
#client.event
async def on_typing(channel, user, when):
print(f"{user.id=}")
Check the discord.on_typing(channel, user, when) documentation.
user parameter can be a User or a Member, but either way, it have an id attribute.
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)
I want make it so if a user leaves the server while they have the Muted or [Banned] role they get permanently banned.
This is the code that I tried:
#bot.event
async def on_member_remove(ctx, member, reason=None):
role="[Banned]"
guild = ctx.guild
if role in member.roles:
await guild.ban(discord.Object(id=member.id), reason="Leaved the server when soft banned")
*this is just a try with only the banned role.
The user doesn't get banned, there is also no error or anything that could help me troubleshoot it.
member.roles returns a List of Role
You need to get the Role object which one way you can use is:
role = discord.utils.find(lambda r: r.name == '[Banned]', member.guild.roles)
on_member_remove takes in Member. You cannot have reason or Context(ctx)
#bot.event
async def on_member_remove(member):
role = discord.utils.find(lambda r: r.name == '[Banned]', member.guild.roles)
guild = member.guild
if role in member.roles:
await guild.ban(discord.Object(id=member.id), reason="Leaved the server when soft banned")
Please also ensure you have the Members intent enabled. You can do this by going here then selecting Bot -> SERVER MEMBERS INTENT
You will need to do enable intents in your code by using:
intents = discord.Intents.default()
intents.members = True
bot = commands.Bot(command_prefix=".", intents=intents)
Your code seems fine.
Check that you have enabled the Intents.members on your Discord Developper portal and in your bot code, if you're using Discord API v8 (as intents are mandatory in this API version), as explained here in Discord.py docs.
For your information, by default, all intents are enabled except members and presence intents.
On Discord Developer Portal, enable this in the "Bot" section of your app :
How do I make a bot in Discord.py that will assign roles present in a role.json file, while using the same command to both remove and add the same role. For example, ?role <rolename> will both add and remove a role, depending on if the user has the role assigned. I'm a bit confused on how to achieve this.
My current bot uses ?roleadd <rolename> ?roleremove <rolename>.
I'm not sure where your role.json file comes into play, but here's how I would implement such a command
#bot.command(name="role")
async def _role(ctx, role: discord.Role):
if role in ctx.author.roles:
await ctx.author.remove_roles(role)
else:
await ctx.author.add_roles(role)
This uses the Role converter to automatically resolve the role object from its name, id, or mention.
This code basically just checks that if the command raiser is the owner of the server or not and then assigns the specified role to him.
#bot.command()
#commands.is_owner()
async def role(ctx, role:discord.Role):
"""Add a role to someone"""
user = ctx.message.mentions[0]
await user.add_roles(role)
await ctx.send(f"{user.name} has been assigned the role:{role.name}")
Let me break the code down:
#bot.command()
#commands.is_owner()
These are just plain function decorators. They are pretty much self-explanatory. But still let me tell.
#bot.command() just defines that it is a command.
#commands.is_owner() checks that the person who has raised that command is the owner.
async def role(ctx, role:discord.Role): > This line defines the function.
user = ctx.message.mentions[0] #I don't know about this line.
await user.add_roles(role) #This line adds the roles to the user.
await ctx.send(f"{user.name} has been assigned the role:{role.name}")
#It just sends a kind of notification that the role has been assigned