I have a command where there is an asyncio event. Unfortunately this is lost when the bot restarts. Therefore I want to be able to exclude certain users from a command, respectively the bot should not react if they are entered in the list.
My attempt so far has been the following:
#commands.command
async def test(self, ctx):
#Shortened
user = discord.Member
userlist = [HereWePutTheUserIDs]
if user in userlist:
return await ctx.send("You are on the blocklist.")
Unfortunately, this did nothing. Is there anyway to prevent certain users, by ID/name, from executing the command until I remove them from the list?
You're assigning the user to a class, you don't even instantiate it, that's not how it works, the user variable should be ctx.author.id
user = ctx.author.id
Related
So pretty much as of now, my code checks if a user has nitro, on the user's avatar (like if it's a gif or not), although I want to make it so that it can also check without having to use the profile.
Is there any way around this I could do?
You can use user profile in discord.py to check if a user has nitro.
Example command:
#commands.command(name="nitro")
async def has_nitro(self, ctx):
user_to_check = ctx.author # you can specify any user (discord.User)
user_profile = await user_to_check.profile() # get user's profile
is_premium = user_profile.premium
await ctx.send(is_premium) # for example send a result, you can use it as you like
I would like to make a command that requires the user to have Administrator permission to execute the command.
An example is when a user first invited bot on the server, members must not be able to the use the so called "permissions" command. However members with the moderator role should have access to it and execute the rest of the command.
Would anyone be able to help with this in my command?
It's still not clear what you want to reserve who you want to command to be avaliable to however, the has_permissions decorator allows you to set what permissions a user can use to access a command. This can be set within the parameters
For example, if you just only want a member with Administrator permissions to have access to your command, you can add #commands.has_permissions(administrator = True) after the command decorator. Heres an example,
#bot.command()
#commands.has_permissions(administrator = True)
async def permission(ctx):
await ctx.send('You have administrator access...')
More information can be found in Discord's documentation:
https://discordpy.readthedocs.io/en/latest/ext/commands/api.html
EDIT:
However, using an if statement within a command can be done with:
if ctx.author.guild_permissions.administrator:
...
While this question is aimed at discord.py - this question came up when I was searching for how to do this with it's sort-of successor library Discord Interactions as discord.py is quite limited - so I'll let people know how to do this with interactions too.
So for those wondering, this is how you check if the calling user is a Server Administrator on interactions:
import interactions
bot = interactions.Client(token=TOKEN)
#bot.command(scope=SERVER_IDS)
async def my_command(ctx):
perms = (await ctx.author.get_guild_permissions(ctx.guild_id))
if interactions.Permissions.ADMINISTRATOR in perms:
return await ctx.send("You are an admin")
await ctx.send("You are NOT an admin")
Additionally, here's a function snippet which can be used within your commands to quickly check if the caller is a server admin:
async def is_server_admin(ctx: Union[CommandContext, ComponentContext]) -> bool:
"""Returns :bool:`True` if the calling user is a Discord Server Administrator"""
perms = (await ctx.author.get_guild_permissions(ctx.guild_id))
return interactions.Permissions.ADMINISTRATOR in perms
Example usage of that function:
#bot.command(scope=SERVER_IDS)
async def my_command(ctx):
if await is_server_admin(ctx):
return await ctx.send("You are an admin")
await ctx.send("You are NOT an admin")
I want a command that writes all of the roles for a user that writes this command and i can't figure out how to do that.
I have that command :
#client.command(name='role')
async def role(context):
roles = []
.... (fill the list with all the roles of the context.author)
await context.send(roles)
You can use the Member.roles attribute
#client.command(name='role')
async def role(context):
roles = context.author.roles # Is already a list of `discord.Role` instances
await context.send(roles)
Note: The command must be invoked in a guild, otherwise it's not gonna work
Reference:
Member.roles
I have a simple issue that I'm yet to figure out, how can I change my bot's own nickname, because I want to display information instead of its nickname continuously.
tried this :
await bot.user.edit(username=price)
but this actually changes the username which is not allowed to be done multiple times.
async def status_update():
while True:
price = str(get_BTC_price(ws))
await bot.user.edit(username=price)
await asyncio.sleep (2)
#bot.event
async def on_ready():
bot.loop.create_task(status_update())
Thanks
Nicknames are tied to Guild Members. In order to change your bot's nickname, you must
Get the Guild Member object for your bot
Use <Member>.edit(nick=nick)
Note that this will only change the nickname for one server. If you wanted it to be global you would have to loop through each guild and perform the operation (expensive). You may want to use the status box instead to convey this information.
So while we're all I'm surely aware of the entire copy and paste someone elses code, and magically it works, it looses some context and understanding when figuring out how this code actually works and functions.
I'm working with the Discord.py Rewrite, and a chunk of code called Reaction Light in order to create a bot that allows for self-assigning roles in my Discord Server. The bot is 100% functional and works as intended. Now, I have changed some things around from their code, so my methods are in different locations and are called from different areas.
Here's where I'm confused:
I have a method called isadmin() this is called whenever there needs to be a check completed to figure out if the user issuing the command is an admin. Admin roles are defined in the .env file which I'm retrieving using the dotenv module. Pretty straight forward stuff. (I'll rewrite that portion of it later and hopefully put all the admin role id's into a file and grab them from there.) However I'm confused on what exactly the third argument of this method does. msg=False
Whenever I wrote my cogs for this I'm calling this method as such without passing that 'msg' argument to it as illustrated below:
admin.py
# admin.py
# Simple ping pong command
#commands.command()
async def ping(self, ctx):
if helpers.isadmin(ctx):
print("Running Command from admin.py")
await ctx.send('Pong!')
Now in my on_message() listener method, it is passing the msg argument, then executing some code unrelated to the ping command but related to the functionality of the self-assigning role portion of the bot.
message.py
# message.py
#commands.Cog.listener()
async def on_message(self, message):
if helpers.isadmin(message, msg=True):
# Execute some code here for the self-assigning roles
The way this workflow works is this as far as I know, and I'll be using the ping command as an example which is called by the r.ping command.
on_message() listens for all messages being sent in the server
Ping Command Issued In Channel By User
on_message() hears the message & checks if the user is an admin, but also passes the msg argument
The ping command is called from admin.py and then checks (again?) if the user is an admin, and if he/she is, follows through with the command.
So, I'm trying to figure out when or when not to use this msg argument, and if it's already checking to see if the user is an admin in the listener do I have to check again in the actual command itself? Isn't that a bit redundant?
Here's the isadmin() method in the helpers.py file
# helpers.py
def isadmin(self, ctx, msg=False):
# Checks if command author has one of .env admin role IDs
try:
check = (
[role.id for role in ctx.author.roles]
if msg
else [role.id for role in ctx.message.author.roles]
)
if self.admin_a in check or self.admin_b in check or self.admin_c in check:
return True
return False
except AttributeError:
# Error raised from 'fake' users, such as webhooks
return False
To be entirely honest I'm not sure why that's there. If you have access to ctx.author you have access to ctx.message as ctx.author is simply the author of that message, seems redundent. However I strongly suggest you use checks for this. For example I have:
def is_owner():
def predicate(ctx):
return ctx.author.id in ctx.bot.config()["owners"]
return commands.check(predicate)
and I use this as a decorator
# utils/checks/checks.py
from utils.checks import checks
#checks.is_owner()
#commands.group(hidden=True, case_insensitive=True, description="Load a module")
async def load(self, ctx):
if not ctx.invoked_subcommand:
return await ctx.send_help(ctx.command)
For example you could have
def is_admin():
def predicate(ctx):
role_id = 123123123123123 # replace this with os.getenv("wherever your admin role is")
return role_id in [x.id for x in ctx.author.roles]
return commands.check(predicate)
It's just much cleaner and much easier to use/understand in my opinion.