Search code examples
pythondiscorddiscord.py

Is there a discord.py code that can let a certain role use the command?


So what I am looking for is a application commands/slash command for a certain role to use.

Current:

import discord
import os
import logging
from discord import app_commands
from discord import Member
from discord.ext import commands
from discord.ext.commands import has_permissions, MissingPermissions
from discord.ext import commands, tasks
from dotenv import load_dotenv
from discord.ext.commands import check
from keep_alive import keep_alive

prefix = os.environ['PREFIX']
intents = discord.Intents().all()
intents.message_content = True
client = discord.Client(intents=intents)
bot = commands.Bot(command_prefix=prefix, intents=intents)
tree = app_commands.CommandTree(client)


@client.event
async def on_ready():
  print(f'Logged in as {client.user} || Normal commands added')
  await client.change_presence(activity=discord.Activity(
    type=discord.ActivityType.watching, name='Nothing <3'))
  print(f'Logged in as {client.user} || Owner commands Failed to be included')
  await tree.sync()
  print("Next MAINTENANCE from 4:00PM-5:00PM EST")
  await tree.sync(guild=discord.Object(id=914595694424236083))
  print("Slash commands for 914595694424236083 has been added")

@tree.command(name="test2", description="test command", guild = discord.Object(id = 914595694424236083))
@discord.app_commands.checks.has_role(id == 1073244171541942283)
async def second_command(interaction):
  await interaction.response.send_message(
    "Currently another test command, there is nothing here.")

After testing the commands with and without the command, it works as expected, but when I don’t have the role, the command still executed.

  1. Activated The Program

  2. Added the role id to user (me)

  3. Tested Command (Passed)

  4. Removed the role id from user (me)

  5. Command still executed with no problem, I want to let only people with the role be able to execute the slash command.

Edits:

  1. I used Raymus’s answer.

  2. Ran test #8162

8a. Working with role? Yes

8b: Working without role? Yes

What I need help with, I want members with that role to be able to use the slash command, not all users in the guild to use the command. Any tips to fully fix it?


Solution

  • Your code has many issues, I'll mention them in order of importance.

    1. Using commands.bot and discord.Client at the same time.

    Reference: Confusion between commands.Bot and discord.Client | Which one should I use?

    The difference is that commands.Bot provides a lot more functionality (like Commands), which Client doesn't do. Bot is a subclass of Client, so it can do everything that a Client can do, but not the other way around.

    In the long run you should use the one that you need. If you want to use Bot features then use a Bot. If you don't care about Bot features then use a Client, or you can still use a Bot and just not use the extra features.

    TL;DR: You CANNOT use both of them at the same time, it doesn't work that way. It's better to use commands.bot for it's functionalities. commands.bot can do anything discord.Client can but not the other way around.

    1. Incorrect use of @discord.app_commands.checks.has_role()

    Like I had mentioned in my previous (now deleted) answer, this isn't how you use it. id == doesn't make sense because @discord.app_commands.checks.has_role() is not looking for that, it is looking for either an int or a str.

    If a string is specified, you must give the exact name of the role, including caps and spelling. If an integer is specified, you must give the exact snowflake ID of the role.

    Therefore, you should ONLY input an int or str, int being the role id either or str being the role name (ids are preferred because they cannot be changed unless role is deleted).

    @discord.app_commands.checks.has_role(1073244171541942283)
    
    1. Command tree syncing

    It is recommended to avoid syncing in an on_ready event because every time you restart your bot, it will sync and could cause a rate limit. Hence, you should put your await tree.sync() in a command (of course sync the command first or else the command won't appear).

    @client.event
    async def on_ready():
      print(f'Logged in as {client.user} || Normal commands added')
      await client.change_presence(activity=discord.Activity(
        type=discord.ActivityType.watching, name='Nothing <3'))
      print(f'Logged in as {client.user} || Owner commands Failed to be included')
    
    @tree.command(name="sync", description="Bot owner only")
    async def sync(interaction):
        if interaction.user.id == youridhere:
            await tree.sync()
            print("Next MAINTENANCE from 4:00PM-5:00PM EST")
            await tree.sync(guild=discord.Object(id=914595694424236083))
            print("Slash commands for 914595694424236083 has been added")
            await interaction.response.send_message("Synced!")
        else:
            await interaction.response.send_message("This command is not for you")