I've run into a problem with the following hybrid command group I'm trying to create in discord.py:
@commands.hybrid_group(name='event', description='Lists events attended by character')
@commands.guild_only()
async def character_events(self, ctx, event_type: str = None):
if event_type == None:
character_name = str(ctx.author.nick) or str(ctx.author.name)
await self.send_message_chunks(ctx, character_name.lower().title())
return
elif event_type is not None and str(event_type.lower()) not in ['start', 'end', 'add', 'delete', 'master']:
await self.send_message_chunks(ctx, event_type.lower().title())
return
@character_events.command(name='add', description='Adds a character event from a master record event, or manually adds raid ticks>')
@commands.has_permissions(administrator=True)
async def character_add_event(self, ctx, event_name: str = None, event_value: str = None, event_class: str = None):
if event_class is not None and event_class.lower() == 'channel' and ctx.author.guild_permissions.administrator:
await self.insert_event_channel(ctx, event_name, event_value, 'channel')
return
elif event_class is not None and event_class.lower() == 'split' and ctx.author.guild_permissions.administrator:
await self.insert_event_channel(ctx, event_name, event_value, 'split')
return
elif event_value.lower() == 'all':
await self.insert_event(ctx, event_name, event_value)
return
else:
await self.insert_event(ctx, event_name, event_value)
return
@character_events.command(name='delete', description='Deletes a character event: <character_name/all> <event_id>')
@commands.has_permissions(administrator=True)
async def character_delete_event(self, ctx, event_name: str = None, event_value: str = None):
if event_name.lower() == 'all':
await self.delete_event(ctx, event_name, event_value)
return
else:
print('delete detected')
await self.delete_event(ctx, event_name, event_value)
return
@character_events.command(name='start', description='Starts an event: <event_name> <event_value> <event_duration> <event_ticks>')
@commands.has_permissions(administrator=True)
async def start_timed_event(self, ctx, event_name: str = None, event_value: int = None, event_class: int = None, event_status: str = None, event_ticks: int = None):
print('start detected')
await self.event_channel_timer(ctx, event_name, event_value, event_class, event_status, event_ticks)
@character_events.command(name='master', description='Display or alter the master record: <add/delete> <event_name/event_id>')
async def master_modify(self, ctx, event_name: str = None, event_value: str = None):
if event_name == None:
await self.send_message_chunks_master(ctx, event_name)
elif event_name.lower() == 'add' and ctx.author.guild_permissions.administrator:
await self.master_record_modify(ctx, event_name, event_value, 'add')
elif event_name.lower() == 'delete' and ctx.author.guild_permissions.administrator:
await self.master_record_modify(ctx, event_name, event_value, 'delete')
async def setup(bot):
await bot.add_cog(Events(bot))
Basically 'event' is the parent command and add, delete, start, and master are the subcommands that I want to implement (example: /event add "New Event", etc). The prefix command works fine with the code as is, but I can't get it to register them as slash commands. In my main.py this is what I use to load all the cogs:
@bot.event
async def on_ready():
loaded_cogs = [] # Create a list to track loaded cogs
activity = discord.Game(name="EverQuest")
for filename in os.listdir("./cogs"):
if filename.endswith(".py"):
cog_name = "cogs.{0}".format(filename[:-3])
if cog_name not in loaded_cogs: # Check if the cog hasn't been loaded yet
try:
await bot.load_extension(cog_name)
loaded_cogs.append(cog_name) # Add the loaded cog to the list
print(f'"{cog_name}" Cog loaded')
except Exception as e:
print(f'Failed to load "{cog_name}" Cog: {e}')
I feel like I'm missing something obvious on how to register these (or maybe it's not possible in a hybrid command with nested commands?) From the discord.py documentation they say:
The following are currently not supported by hybrid commands:
Variable number of arguments. e.g. *arg: int Group commands with a depth greater than 1.
But my commands are within these parameters right?
To use slash commands you need to register them with Discord. It is not recommended that you do this in the on_ready event as you only need to sync your slash commands when you create a new one, remove one, or edit one. It's best practice to use a prefixed command that only you can use to sync these.
You can do something that looks like this:
@bot.command(name="Sync", description="Sync slash commands")
@commands.is_owner()
@commands.guild_only()
async def sync(ctx: Context):
ctx.bot.tree.clear_commands(guild=ctx.guild)
ctx.bot.tree.copy_global_to(guild=ctx.guild)
synced = await ctx.bot.tree.sync(guild=ctx.guild)
print(synced)
await ctx.reply(f"Synced {len(synced)} commands", mention_author=False)