From d4bb50a162e5c69221ba8de4ab43dff4bd846aec Mon Sep 17 00:00:00 2001 From: Evelyn Date: Thu, 17 Jul 2025 14:50:30 -0700 Subject: [PATCH 1/2] feat: manual command sync --- README.md | 1 + README_MODULAR.md | 2 +- src/gitcord/bot.py | 3 +-- src/gitcord/cogs/general.py | 22 ++++++++++++++++++++++ src/gitcord/events.py | 4 ++-- 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f7ac8d2..12834ca 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Once it's ready, you'll have to link the **GitCord** bot to your own repository, - **Version-Controlled Configuration**: Store your Discord server configuration in a Git repository - **Automatic Sync**: Webhook-based synchronization when configuration changes are pushed to GitHub - **Manual Pull**: Use `/gitcord pull` command to manually sync configuration changes +- **Command Syncing**: Use `/synccommands` to manually synchronize slash commands - **Category and Channel Management**: Organize your server structure through YAML configuration files ## Project Status diff --git a/README_MODULAR.md b/README_MODULAR.md index f9cf642..0bf3ddd 100644 --- a/README_MODULAR.md +++ b/README_MODULAR.md @@ -40,7 +40,7 @@ gitcord/ ### Enhanced Features - **Rich Embeds**: Beautiful Discord embeds for responses - **Structured Logging**: Proper logging with formatting -- **Command Syncing**: Automatic slash command synchronization +- **Command Syncing**: Use the `/synccommands` slash command to synchronize application commands - **Error Recovery**: Graceful error handling and recovery ## 📦 Installation diff --git a/src/gitcord/bot.py b/src/gitcord/bot.py index e629d60..4b61e09 100644 --- a/src/gitcord/bot.py +++ b/src/gitcord/bot.py @@ -38,8 +38,7 @@ async def setup_hook(self) -> None: # Load cogs await self._load_cogs() - # Sync command tree - await self.tree.sync() + # Command syncing is now done manually using the `/synccommands` slash command. logger.info("Bot setup completed") diff --git a/src/gitcord/cogs/general.py b/src/gitcord/cogs/general.py index 6a85beb..8cb8267 100644 --- a/src/gitcord/cogs/general.py +++ b/src/gitcord/cogs/general.py @@ -312,6 +312,28 @@ async def slashping(self, interaction: discord.Interaction) -> None: ) await interaction.response.send_message(embed=embed) + @app_commands.command(name="synccommands", description="Manually sync slash commands") + @app_commands.checks.has_permissions(administrator=True) + async def synccommands(self, interaction: discord.Interaction) -> None: + """Synchronize application commands for this guild.""" + await interaction.response.defer(thinking=True, ephemeral=True) + try: + synced = await self.bot.tree.sync(guild=interaction.guild) + await interaction.followup.send( + f"Synced {len(synced)} command(s).", + ephemeral=True + ) + logger.info( + "Manually synced %d command(s) in guild: %s", + len(synced), + interaction.guild.name if interaction.guild else "N/A" + ) + except discord.DiscordException as e: + logger.error("Failed to sync commands: %s", e) + await interaction.followup.send( + f"Failed to sync commands: {e}", ephemeral=True + ) + @app_commands.command(name="createcategory", description="Create a category and its channels from YAML configuration") @app_commands.describe(yaml_path="Path to the category YAML file (optional)") async def createcategory_slash(self, interaction: discord.Interaction, yaml_path: str = None) -> None: diff --git a/src/gitcord/events.py b/src/gitcord/events.py index 9178fd7..350b546 100644 --- a/src/gitcord/events.py +++ b/src/gitcord/events.py @@ -30,8 +30,8 @@ async def on_ready(self) -> None: # Send restart message to guilds await self._send_restart_messages() - # Sync slash commands - await self._sync_commands() + # Slash commands are no longer automatically synced here. + # Use the `/synccommands` command to sync manually if needed. async def _send_restart_messages(self) -> None: """Send restart messages to available text channels.""" From 338efff59f881a103c14afd8be1dccdbd404959b Mon Sep 17 00:00:00 2001 From: Eve Date: Thu, 17 Jul 2025 15:13:22 -0700 Subject: [PATCH 2/2] fix: Prefix sync command --- README.md | 2 +- README_MODULAR.md | 2 +- src/gitcord/cogs/general.py | 47 +++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 12834ca..454febf 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Once it's ready, you'll have to link the **GitCord** bot to your own repository, - **Version-Controlled Configuration**: Store your Discord server configuration in a Git repository - **Automatic Sync**: Webhook-based synchronization when configuration changes are pushed to GitHub - **Manual Pull**: Use `/gitcord pull` command to manually sync configuration changes -- **Command Syncing**: Use `/synccommands` to manually synchronize slash commands +- **Command Syncing**: Use `/synccommands` (slash) or `!synccommands` (prefix) to manually synchronize slash commands - **Category and Channel Management**: Organize your server structure through YAML configuration files ## Project Status diff --git a/README_MODULAR.md b/README_MODULAR.md index 0bf3ddd..871f7e2 100644 --- a/README_MODULAR.md +++ b/README_MODULAR.md @@ -40,7 +40,7 @@ gitcord/ ### Enhanced Features - **Rich Embeds**: Beautiful Discord embeds for responses - **Structured Logging**: Proper logging with formatting -- **Command Syncing**: Use the `/synccommands` slash command to synchronize application commands +- **Command Syncing**: Use the `/synccommands` (slash) or `!synccommands` (prefix) command to synchronize application commands - **Error Recovery**: Graceful error handling and recovery ## 📦 Installation diff --git a/src/gitcord/cogs/general.py b/src/gitcord/cogs/general.py index 8cb8267..1a988ed 100644 --- a/src/gitcord/cogs/general.py +++ b/src/gitcord/cogs/general.py @@ -334,6 +334,53 @@ async def synccommands(self, interaction: discord.Interaction) -> None: f"Failed to sync commands: {e}", ephemeral=True ) + @commands.command(name='synccommands') + @commands.has_permissions(administrator=True) + async def synccommands_prefix(self, ctx: commands.Context) -> None: + """Prefix command to manually sync slash commands.""" + try: + # Send initial response + await ctx.send("🔄 Syncing slash commands...") + + synced = await self.bot.tree.sync(guild=ctx.guild) + + embed = create_embed( + title="✅ Commands Synced", + description=f"Successfully synced **{len(synced)}** command(s) to this guild.", + color=discord.Color.green() + ) + + await ctx.send(embed=embed) + + logger.info( + "Manually synced %d command(s) in guild: %s via prefix command", + len(synced), + ctx.guild.name if ctx.guild else "N/A" + ) + except discord.DiscordException as e: + embed = create_embed( + title="❌ Sync Failed", + description=f"Failed to sync commands: {str(e)}", + color=discord.Color.red() + ) + await ctx.send(embed=embed) + logger.error("Failed to sync commands via prefix command: %s", e) + + @synccommands_prefix.error + async def synccommands_prefix_error(self, ctx: commands.Context, + error: commands.CommandError) -> None: + """Handle errors for the synccommands prefix command.""" + if isinstance(error, commands.MissingPermissions): + embed = create_embed( + title="❌ Permission Denied", + description="You need the 'Administrator' permission to use this command.", + color=discord.Color.red() + ) + await ctx.send(embed=embed) + else: + logger.error("Error in synccommands prefix command: %s", error) + await ctx.send(f"An error occurred: {error}") + @app_commands.command(name="createcategory", description="Create a category and its channels from YAML configuration") @app_commands.describe(yaml_path="Path to the category YAML file (optional)") async def createcategory_slash(self, interaction: discord.Interaction, yaml_path: str = None) -> None: