Discord.py set user id as an argument - python

I want to create a command where its using an user id as an argument after ctx to make the bot send the user mention. The problem is, i dont know whats the syntax for user id. Im already looking through the documentation but didnt find the answer there.
Heres the code.
#client.command()
async def userid(ctx, member: discord.Member.id):
await ctx.send(f'{member.mention})

You are nearly there.
The typehint converts usernames, mentions, ID and display_name into a Member object, this object contains all of the above.
#client.command()
async def userid(ctx, member: discord.Member):
await ctx.send(member.mention)

Related

How do I make my discord.py bot get a user's avatar?

I'm trying to make my discord.py bot be able to send a user's avatar into the chat when it is asked to. This is my current code:
if any(word in msg for word in avatar_words):
async def avatar(ctx,*,avamember:discord.Member=None):
userAvatarUrl = avamember.avatar_url
await ctx.send(userAvatarUrl)
This code doesn't work and I'm not exactly sure why. I would also like to give the bot the ability to have the bot get a mentioned user's avatar as opposed to just the author's, but yet again I'm unsure exactly how.
Yes, I have looked around beforehand and all of the solutions I found did not work. The one shown is the only one that did not produce error messages.
async def avatar(ctx, *, member: discord.Member = None):
if not member:
member = ctx.message.author
em = discord.Embed(title=str(member), color=0xAE0808)
em.set_image(url=member.avatar_url)
await ctx.send(embed=em)

Discord.py — Check if the user has specific roles?

I am trying to create a command that can ban people on the Server and those who are not on the server. But there is a problem: If I use async def ban(ctx, member: discord.Member, *, reason): to use the "roles" attribute, then it will not be able to ban those who are not on the server. If i use async def ban(ctx, member: discord.User, *, reason): i will not be able to use the "roles" attribute because it is not an attribute.
Why am I doing this? I am trying to make it so that Server Moderators cannot ban those who have Moderator roles
Code:
async def ban(ctx, member: discord.User = None, *, reason=None):
if get(ctx.author.roles, id=866038959980544050) or get(ctx.author.roles, id=866436325503008768) or get(
ctx.author.roles, id=866441730631008316) or ctx.author.guild_permissions.administrator: # Check if the author has the Role "Moderator", "Admin", etc.
if get(member.roles, id=867371024466968596) or get(member.roles, id=867132420489871411) and not ctx.author.guild_permissions.administrator: # Check if the member has the Role "Moderator", "Admin", etc.
await ctx.send("You cannot ban this user.")
Assuming that you use discord.ext.commands, you could use a typing.Union converter to ensure that the argument is either a user or a member.
import typing
[...]
async def ban(ctx, user: typing.Union[discord.Member, discord.User]):
Note that order matters: By having discord.Member first, it tries to apply this converter first before trying discord.User, thus prioritising conversion to a member over conversion to a user (which should be what you want).
To distinguish between the two cases, you can now check whether user is of type discord.Member and perform your checks on it.
if type(user) is discord.Member:
if YOUR_CHECKS:
await ctx.send('You cannot ban this user')
return
# Perform ban
await ctx.send('Ban successful')
When testing, I discovered that the command library will give you a numerical user id instead of a real user and shows
Failed fetching discord object! Passing ID instead. as a warning. If you need more than just the user id, you could convert it to a User object using
if type(user) is int:
user = await bot.fetch_user(user)
if user is None:
await ctx.send('User not found')
return
Note that fetch_user is an API call and you might want to avoid it. See the docs for more info.
One way of doing this would be to check if the given member is in the current guild. If this is True, you can create a new member object with their id or with another prefered method, otherwise you can assume that they do not have the Moderator role. For simplicity, I only included checking for a single role, but you can tweak this in the way you want to do it. Other than that, everything else is explained in further detail in the code below.
if member in ctx.guild.members: # checks if the provided member is in the current server
member = ctx.guild.get_member(member.id) # Get the member object of the user
if get(member.roles, id=866038959980544050): # Check if this role is in the member's roles
await ctx.send("This member has <#&866038959980544050>")
else:
await ctx.send("This member does not have <#&866038959980544050>")
return # returns, since member was in the server
# This happens if the provided member is not in the current server
await ctx.send("This member, who is not in this server, does not have <#&866038959980544050>")
You must use this
#bot.command(...)
#commands.has_any_role(role id)
...

'Object' object had no attitude 'name' discord.py

I am trying to make an id converter that converts any id to name.
#bot.command()
async def idconv(ctx, *, arg):
id=int(arg)
conv=discord.Object(id)
await ctx.send(conv.name)
It appears as though you are trying to get a users name from their ID.
discord.py offers a class called Member that does it for you
import discord
#bot.command()
async def idconv(ctx, member: discord.Member):
await ctx.send(member.name)
While creating a discord.Object with an id is useful for banning\unbanning a user who doesn't share a guild with your bot, it isn't useful for your case.
Here is the documentation for discord.Member.
Here the command idconv accepts arguments like user-id, name, nickname and tries to convert it into a Member object.
There might be instances where the ID of the member you provided may not share a server with the bot, and hence member ends up being None , resulting in any operation with member raising an error.
You can account for that by checking it beforehand
if member: #or if member is not None
await ctx.send(member.name)
else:
await ctx.send("Could not find a user with that ID")
If you use bot.fetch_user, you
can fetch any discord user by their ID, if found it returns an User object,
which is similar to Member but has overall lesser information.

Permission Check Discord.py Bot

I am working on a discord bot for basic moderation which does kick, ban and mute for now at least. But the problem is other members can use it too. I want only a few specified role who can use it.
Don't want to work on it depending on the #role either because the name of the roles across different servers aren't the same. Also wanting to keep the bot as simple as possible.
Now, I started out as this:
#client.command(name='ban')
async def mod_ban(member: discord.User):
try:
await client.ban(member, delete_message_days=0)
await client.say('**{0}** has been banned.'.format(str(member)))
except Exception as error:
await client.say(error)
But any member can use the commands then. So, tried follow this one = Permission System for Discord.py Bot and ended up with this:
#client.command(name='ban')
async def mod_ban(context, member: discord.User):
if context.message.author.server_premission.administrator:
try:
await client.ban(member, delete_message_days=0)
await client.say('**{0}** has been banned.'.format(str(member)))
except Exception as error:
await client.say(error)
else:
await client.say('Looks like you don\'t have the perm.')
Which lands me with this error: ;-;
raise MissingRequiredArgument('{0.name} is a required argument that is missing.'.format(param))
discord.ext.commands.errors.MissingRequiredArgument: member is a required argument that is missing.
Also, besides context.message.author.server_premission.administrator I don't only want the roles with Admin perm to use this command. I also want a few other roles with have few perms like manage message, manage roles etc. to use to command too.
Thanks in advance for the help! Also, sorry if I've missed anything stupid or silly ;-;
You aren't passing the context into the coroutine in your second example (and as #Andrei suggests, you can only ban members):
#client.command(name='ban', pass_context=True)
async def mod_ban(context, member: discord.Member):
...
Also, I should probably update my answer to that question. In the context of commands, you can use the very powerful checks built into discord.ext.commands to do a lot of this for you. has_permissions does exactly what you're looking for, validating that the user has any of the necessary permissions.
from discord.ext.commands import has_permissions, CheckFailure
#client.command(name='ban', pass_context=true)
#has_permissions(administrator=True, manage_messages=True, manage_roles=True)
async def mod_ban(ctx, member: discord.Member):
await client.ban(member, delete_message_days=0)
await client.say('**{0}** has been banned.'.format(str(member)))
#mod_ban.error
async def mod_ban_error(error, ctx):
if isinstance(error, CheckFailure):
await client.send_message(ctx.message.channel, "Looks like you don't have the perm.")
As far as I can see in the discord.py documentation discord.User is not the same as discord.Member.
Try to change
async def mod_ban(context, member: discord.User):
to
async def mod_ban(context, member: discord.Member):
If you are using discord.py rewrite, you can use checks (Discord.py rewrite checks)
Which (obviusly) checks for certain things suchs as roles or permissions on the command invoker
You can use both of this decorators, below your first decorator
#commands.has_role("rolename"/roleid)
#commands.has_any_role("rolename"/roleid,"rolename"/roleid,"rolename"/roleid ...)
Where rolename is a string containing the EXACT name of the role, letter by letter and space by space, and roleid is the id of the role, which, in case it's mentionable, you can get it by typing #rolename on any of your server chatrooms
Note how you must use the second decorator if you want to pass more than one role to check

How to mention a sender of a command? discord.py

I created a super simple .report <person> command. I have it so it will be sent to a certain channel when someone types it. What I wanted to do is have it display the name of the user who reported the other user. I don't know how to go about doing that. Does anyone know the best way?
#bot.command()
async def report(*, message):
await bot.delete(message)
await bot.send_message(bot.get_channel("479177111030988810"), message)
You could do something like this, where you take the context (ctx) and from it get the contents of the message and its author
#bot.command(pass_context=True)
async def report(ctx):
await bot.delete_message(ctx.message)
report = f"\"{ctx.message.content[8:]}\" sent by {ctx.message.author}"
await bot.send_message(bot.get_channel("479177111030988810"), report)
You can use ctx.author.mention for mentioning the user. The mention attribute (documented here) returns a string that you can use in the argument to send.
Example usage:
#bot.command("hello", help="Learn about this bot")
async def hello(ctx: discord.commands.Context):
await ctx.send(f"Hi {ctx.author.mention}! I'm a bot!")

Categories