From 3166661adc7e0829599139bb84d5a7133a3cb423 Mon Sep 17 00:00:00 2001
From: "Edgar P. Burkhart" <git@edgarpierre.fr>
Date: Sun, 23 Mar 2025 09:58:28 +0100
Subject: [PATCH] Enhance VoiceBot to accept guild IDs and implement join
 command for voice channel connection

---
 botbotbot/__init__.py |  2 +-
 botbotbot/voice.py    | 76 +++++++++++++++++++++++++++++++++----------
 2 files changed, 60 insertions(+), 18 deletions(-)

diff --git a/botbotbot/__init__.py b/botbotbot/__init__.py
index 575bce4..5f15202 100644
--- a/botbotbot/__init__.py
+++ b/botbotbot/__init__.py
@@ -59,7 +59,7 @@ def main() -> None:
     text_bot = TextBot(bot, wl, aibot=aibot, shuffler=shf)
     text_bot.init_events()
 
-    voice_bot = VoiceBot(bot, cambai, aibot=aibot, shuffler=shf)
+    voice_bot = VoiceBot(bot, cambai, aibot=aibot, shuffler=shf, guild_ids=guild_ids)
     voice_bot.init_events()
 
     @bot.listen("on_ready")
diff --git a/botbotbot/voice.py b/botbotbot/voice.py
index c3fdabe..00cf944 100644
--- a/botbotbot/voice.py
+++ b/botbotbot/voice.py
@@ -17,14 +17,72 @@ class VoiceBot:
         cambai: CambAI | None = None,
         aibot: AIBot | None = None,
         shuffler: Shuffler | None = None,
+        guild_ids: list[int] = [],
     ) -> None:
         self.bot = bot
         self.cambai = cambai
         self.shf = shuffler
         self.aibot = aibot
+        self.guild_ids = guild_ids
 
     def init_events(self) -> None:
         self.bot.add_listener(self.on_voice_state_update, "on_voice_state_update")
+        self.bot.add_application_command(
+            discord.SlashCommand(
+                self.join_voice,
+                name="join",
+                description="Rejoindre un channel vocal",
+                guild_ids=self.guild_ids,
+            )
+        )
+
+    async def connect_voice(
+        self, channel: discord.VoiceChannel | discord.StageChannel
+    ) -> None:
+        if self.cambai is None:
+            return
+
+        logger.info("Generating tts")
+        if len(channel.members) == 1:
+            member = channel.members[0].display_name
+        else:
+            member = (
+                ", ".join(member.display_name for member in channel.members[:-1])
+                + " et "
+                + channel.members[-1].display_name
+            )
+
+        script = None
+        if self.aibot is not None and random.random() < 20 / 100:
+            script = self.aibot.answer("Dis un truc aléatoire et original.")
+        if script is None:
+            script = random.choice(
+                [
+                    "Salut la jeunesse !",
+                    f"Salut {member}, ça va bien ?",
+                    "Allo ? À l'huile !",
+                ]
+            )
+        source = await discord.FFmpegOpusAudio.from_probe(self.cambai.tts(script))
+        vo: discord.VoiceClient = await channel.connect()
+
+        await vo.play(source, wait_finish=True)
+        await vo.disconnect()
+
+    async def join_voice(self, ctx: discord.ApplicationContext) -> None:
+        if ctx.user.voice:
+            await ctx.respond(
+                f"Connecting to voice channel {ctx.user.voice.channel}.",
+                ephemeral=True,
+                delete_after=30,
+            )
+            await self.connect_voice(ctx.user.voice.channel)
+        else:
+            await ctx.respond(
+                "You are not connected to a voice channel.",
+                ephemeral=True,
+                delete_after=30,
+            )
 
     async def on_voice_state_update(
         self,
@@ -47,23 +105,7 @@ class VoiceBot:
             and member.id != self.bot.user.id
             and random.random() < 5 / 100
         ):
-            logger.info("Generating tts")
-            script = None
-            if self.aibot is not None and random.random() < 20 / 100:
-                script = self.aibot.answer("Dis un truc aléatoire et original.")
-            if script is None:
-                script = random.choice(
-                    [
-                        "Salut la jeunesse !",
-                        f"Salut {member.display_name}, ça va bien ?",
-                        "Allo ? À l'huile !",
-                    ]
-                )
-            source = await discord.FFmpegOpusAudio.from_probe(self.cambai.tts(script))
-            vo: discord.VoiceClient = await after.channel.connect()
-
-            await vo.play(source, wait_finish=True)
-            await vo.disconnect()
+            await self.connect_voice(after.channel)
 
         if self.shf and before.channel is None and random.random() < 5 / 100:
             logger.info(f"Voice shuffle from {member}")