From 0bd525a54ca026e86a4d92b682e22115b22ae544 Mon Sep 17 00:00:00 2001 From: CD Date: Sat, 7 Mar 2026 15:20:10 +0900 Subject: [PATCH] feat: Discord slash commands /stop /auto /send with guild sync --- bot.py | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/bot.py b/bot.py index 75d4f7b..4c5fc95 100644 --- a/bot.py +++ b/bot.py @@ -115,8 +115,59 @@ class GravityBot(commands.Bot): self.loop.create_task(self._process_events()) self.pending_approval_scanner.start() self.chat_snapshot_scanner.start() + self._register_slash_commands() logger.info("Bot setup complete") + def _register_slash_commands(self): + """Register Discord slash commands.""" + + @self.tree.command(name="stop", description="AI 작업 중지") + async def slash_stop(interaction: discord.Interaction): + project = self.channel_to_project.get(interaction.channel_id) + if not project: + await interaction.response.send_message("⚠️ 프로젝트 채널이 아닙니다.", ephemeral=True) + return + self.bridge.write_command(project, "!stop", project_name=project) + await interaction.response.send_message( + embed=discord.Embed( + title="⏹️ AI 작업 중지", + description=f"**{project}** IDE에 중지 요청 전달됨", + color=discord.Color.orange(), + ) + ) + + @self.tree.command(name="auto", description="자동 승인 토글") + async def slash_auto(interaction: discord.Interaction, mode: str): + project = self.channel_to_project.get(interaction.channel_id) + if not project: + await interaction.response.send_message("⚠️ 프로젝트 채널이 아닙니다.", ephemeral=True) + return + enabled = mode.lower() in ("on", "true", "1") + self.bridge.write_command(project, f"!auto {'on' if enabled else 'off'}", project_name=project) + emoji = "🟢" if enabled else "🔴" + await interaction.response.send_message( + embed=discord.Embed( + title=f"{emoji} {'자동 승인' if enabled else '수동 승인'} 모드", + description=f"프로젝트: **{project}**", + color=discord.Color.green() if enabled else discord.Color.red(), + ) + ) + + @self.tree.command(name="send", description="IDE 채팅에 메시지 전송") + async def slash_send(interaction: discord.Interaction, message: str): + project = self.channel_to_project.get(interaction.channel_id) + if not project: + await interaction.response.send_message("⚠️ 프로젝트 채널이 아닙니다.", ephemeral=True) + return + self.bridge.write_command(project, message, project_name=project) + await interaction.response.send_message( + embed=discord.Embed( + description=f"📨 → **{project}** IDE에 전달됨\n`{message[:100]}`", + color=discord.Color.blurple(), + ), + delete_after=10, + ) + async def on_ready(self): logger.info(f"Bot connected as {self.user} (ID: {self.user.id})") @@ -144,6 +195,14 @@ class GravityBot(commands.Bot): # Load conversation → project registrations from Extension self._load_registrations() + # Sync slash commands to guild + try: + self.tree.copy_global_to(guild=self.guild) + synced = await self.tree.sync(guild=self.guild) + logger.info(f"Synced {len(synced)} slash commands to guild") + except Exception as e: + logger.warning(f"Slash command sync failed: {e}") + # Open the gate self._ready_event.set() logger.info("Ready gate opened — event processing enabled")