Adamyoboy
Adamyoboy

Reputation: 282

How do i make a working slash command in discord.py

I am trying to make a slash command with discord.py I have tried a lot of stuff it doesn't seem to be working. Help would be appreciated.

Upvotes: 24

Views: 161079

Answers (6)

LoahL
LoahL

Reputation: 2613

Note: I will include a version for pycord at the end because I think it's much simpler, also it was the original answer.


discord.py version

First make sure that you have the newest version of discord.py installed. In your code, you first import the library:

import discord
from discord import app_commands

and then you define your client and tree:

intents = discord.Intents.default()
client = discord.Client(intents=intents)
tree = app_commands.CommandTree(client)

The tree holds all of your application commands. Then you can define your command:

# Add the guild ids in which the slash command will appear.
# If it should be in all, remove the argument, but note that
# it will take some time (up to an hour) to register the
# command if it's for all guilds.
@tree.command(
    name="commandname",
    description="My first application Command",
    guild=discord.Object(id=12417128931)
)
async def first_command(interaction):
    await interaction.response.send_message("Hello!")

Then you also have to sync your commands to discord once the client is ready, so we do that in the on_ready event:

@client.event
async def on_ready():
    await tree.sync(guild=discord.Object(id=Your guild id))
    print("Ready!")

And at the end we have to run our client:

client.run("token")

pycord version

To install py-cord, first run pip uninstall discord.py and then pip install py-cord. Then in your code, first import the library with

import discord
from discord.ext import commands

create your bot with

bot = commands.Bot()

and create your slash command with

# Add the guild ids in which the slash command will appear.
# If it should be in all, remove the argument, but note that
# it will take some time (up to an hour) to register the
# command if it's for all guilds.
@bot.slash_command(
  name="first_slash",
  guild_ids=[...]
)
async def first_slash(ctx): 
    await ctx.respond("You executed the slash command!")

and then run the bot with your token

bot.run(TOKEN)

Upvotes: 45

Tripping_Lettuce
Tripping_Lettuce

Reputation: 11

Slash Commands with discord.py (2.0)

While this is a new answer to an old question when I first started coding a bot I ran into this but non of the answers worked.

Some Context: There are 2 ways to code a slash command in discord.py 2.0

discord.Client, +Easy to Sync -No Prefix Commands

commands.Bot, -Harder to Sync +Prefix Commands

I will show one examples I am more confidant on the commands.Bot FYI

A great external source for discord.Client slash command examples is Rapptz-app_command_examples

commands.Bot Slash Command

from typing import Literal, Optional
import discord
from discord.ext.commands import Greedy, Context
from discord import app_commands
from discord.ext import commands

#------ Bot ------
# Can add command_prefix='!', in commands.Bot() for Prefix Commands
intents = discord.Intents.default()
intents.members = True
intents.message_content = True
bot = commands.Bot(intents=intents)
#--- Bot Startup
@bot.event
async def on_ready():
    print(f'Logged in as {bot.user}') #Bot Name
    print(bot.user.id) #Bot ID
#------ Slash Commands ------
#Parameters can be added in def help()
# Ex- async def help(interaction: discord.Interaction, left:int,right:int)
@bot.tree.command()
async def help(interaction: discord.Interaction):
    """Help""" #Description when viewing / commands
    await interaction.response.send_message("hello")

#------ Sync Tree ------
guild = discord.Object(id='guildID')
# Get Guild ID from right clicking on server icon
# Must have devloper mode on discord on setting>Advance>Developer Mode
#More info on tree can be found on discord.py Git Repo
@bot.command()
@commands.guild_only()
@commands.is_owner()
async def sync(
  ctx: Context, guilds: Greedy[discord.Object], spec: Optional[Literal["~", "*", "^"]] = None) -> None:
    if not guilds:
        if spec == "~":
            synced = await ctx.bot.tree.sync(guild=ctx.guild)
        elif spec == "*":
            ctx.bot.tree.copy_global_to(guild=ctx.guild)
            synced = await ctx.bot.tree.sync(guild=ctx.guild)
        elif spec == "^":
            ctx.bot.tree.clear_commands(guild=ctx.guild)
            await ctx.bot.tree.sync(guild=ctx.guild)
            synced = []
        else:
            synced = await ctx.bot.tree.sync()

        await ctx.send(
            f"Synced {len(synced)} commands {'globally' if spec is None else 'to the current guild.'}"
        )
        return

    ret = 0
    for guild in guilds:
        try:
            await ctx.bot.tree.sync(guild=guild)
        except discord.HTTPException:
            pass
        else:
            ret += 1

    await ctx.send(f"Synced the tree to {ret}/{len(guilds)}.")


bot.run('token')

!sync -> global/server sync (No ID) or (ID SET)

!sync ~ -> sync current guild (Bot In)

!sync * -> copies all global app commands to current guild and syncs

!sync ^ -> clears all commands from the current guild target and syncs (removes guild commands)

!sync id_1 id_2 -> syncs guilds with id 1 and 2

If I had made any errors please comment and I will fix them, goodluck on your discord bot journey

Upvotes: 1

Qoqnus-master
Qoqnus-master

Reputation: 11

Just do this

from discord import Interaction
from discord import app_commands

@app_commands.command(name="",description="")
async def ping(ctx: Interaction, have_account:bool, login_email:str=None, login_mobile:str=None):

Upvotes: 1

PhilPAlEskQ
PhilPAlEskQ

Reputation: 107

# This is new in the discord.py 2.0 update

# imports
import discord
import discord.ext

# setting up the bot
intents = discord.Intents.all() 
# if you don't want all intents you can do discord.Intents.default()
client = discord.Client(intents=intents)
tree = discord.app_commands.CommandTree(client)

# sync the slash command to your server
@client.event
async def on_ready():
    await tree.sync(guild=discord.Object(id=Your guild ID here))
    # print "ready" in the console when the bot is ready to work
    print("ready")

# make the slash command
@tree.command(name="name", description="description")
async def slash_command(interaction: discord.Interaction):    
    await interaction.response.send_message("command")

# run the bot
client.run("token")

Upvotes: 7

NotTraduce
NotTraduce

Reputation: 13

discord.py does not support slash commands. I recommend you use discord-py-interactions for slash commands. To install it is to do python3.exe -m pip install discord-py-interactions. It works well. Here is a sample code to base off:

import interactions

bot = interactions.Client(token="your_secret_bot_token")

@bot.command(
    name="my_first_command",
    description="This is the first command I made!",
    scope=the_id_of_your_guild,
)
async def my_first_command(ctx: interactions.CommandContext):
    await ctx.send("Hi there!")

bot.start()

Upvotes: -2

Jeffrey DeLucca
Jeffrey DeLucca

Reputation: 106

They're sort of in the middle of adding slash commands to discord.py but you can see a few examples in https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6 You seem to be using discord_slash, which I have not used.

The main documentation for this stuff is https://discordpy.readthedocs.io/en/master/interactions/api.html?highlight=dropdown#decorators but the main "how to" is that you've gotta make a "tree", attach commands to that tree, and sync your tree for the commands to show up. discord.ext.Bot makes its own tree, which is why I'm using that instead of client, which I think doesn't make a tree by default.

If you specify the guilds, the commands sync takes place instantly, but if you don't specify the guild, I think it takes an hour to update or something like that, so specify the guild until you're ready for deployment.

I'm not quite sure how to do it in cogs, because I have mine in groups but basically what I'm doing is a combination of @bot.tree.command() in the main bot file and a few groups in separate files.

So here's my main file

import discord
import simplegeneralgroup
from config import TOKEN
MY_GUILD = discord.Object(id=1234567890)

class MyBot(discord.ext.commands.Bot):
    async def on_ready(self):
        await self.tree.sync(guild=MY_GUILD)

bot: discord.ext.commands.Bot = MyBot

@bot.tree.command(guild=MY_GUILD)
async def slash(interaction: discord.Interaction, number: int, string: str):
    await interaction.response.send_message(f'Modify {number=} {string=}', ephemeral=True)

bot.tree.add_command(simplegeneralgroup.Generalgroup(bot), guild=MY_GUILD)

if __name__ == "__main__":
    bot.run(TOKEN)

and then the simplegeneralgroup file

import discord
from discord import app_commands as apc
class Generalgroup(apc.Group):
    """Manage general commands"""
    def __init__(self, bot: discord.ext.commands.Bot):
        super().__init__()
        self.bot = bot

    @apc.command()
    async def hello(self, interaction: discord.Interaction):
        await interaction.response.send_message('Hello')

    @apc.command()
    async def version(self, interaction: discord.Interaction):
        """tells you what version of the bot software is running."""
        await interaction.response.send_message('This is an untested test version')

There should be three commands: /slash, which will prompt the user for a number and string, /generalgroup hello, and /generalgroup version

Upvotes: 4

Related Questions