Reputation: 282
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
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.
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")
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
Reputation: 11
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
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
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
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
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
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