From e6fc040d786919b649b38221a748ce8b066f12b6 Mon Sep 17 00:00:00 2001
From: "Edgar P. Burkhart" <git@edgarpierre.fr>
Date: Sat, 22 Mar 2025 23:07:54 +0100
Subject: [PATCH] Add VoiceBot class for voice state handling; enhance Wordlist
 initialization with guild IDs

---
 botbotbot/__init__.py | 47 +++++++-------------------------
 botbotbot/voice.py    | 63 +++++++++++++++++++++++++++++++++++++++++++
 botbotbot/wordlist.py | 21 ++++++++++++---
 3 files changed, 89 insertions(+), 42 deletions(-)

diff --git a/botbotbot/__init__.py b/botbotbot/__init__.py
index 24265fc..995bbf3 100644
--- a/botbotbot/__init__.py
+++ b/botbotbot/__init__.py
@@ -8,6 +8,7 @@ from botbotbot.ai import AIBot
 from botbotbot.shuffle import Shuffler
 from botbotbot.text import TextBot
 from botbotbot.tts import CambAI
+from botbotbot.voice import VoiceBot
 from botbotbot.wordlist import Wordlist
 
 
@@ -21,6 +22,9 @@ def main() -> None:
         config = tomllib.load(config_file)
 
     guild_ids = config.get("guild_ids")
+    if not (isinstance(guild_ids, list) and all(isinstance(i, int) for i in guild_ids)):
+        logger.error("Guild IDs must be a list of integers.")
+        guild_ids = []
 
     system_prompt = """Tu es une intelligence artificelle qui répond en français.
     Tu dois faire un commentaire pertinent en lien avec ce qui te sera dit.
@@ -49,11 +53,15 @@ def main() -> None:
 
     bot = discord.Bot(description=description, intents=intents)
     shf = Shuffler()
-    wl = Wordlist(bot)
+    wl = Wordlist(bot, guild_ids)
+    wl.init_events()
 
     text_bot = TextBot(bot, wl, aibot=aibot, shuffler=shf)
     text_bot.init_events()
 
+    voice_bot = VoiceBot(bot, cambai, shuffler=shf)
+    voice_bot.init_events()
+
     @bot.listen("on_ready")
     async def on_ready() -> None:
         logger.info(f"We have logged in as {bot.user}")
@@ -73,43 +81,6 @@ def main() -> None:
             await ctx.respond(embed=embed)
             logger.info("ERRE ALEA")
 
-    @bot.listen("on_voice_state_update")
-    async def on_voice_state_update(
-        member: discord.Member, before: discord.VoiceState, after: discord.VoiceState
-    ) -> None:
-        logger.debug("Voice state update")
-        logger.debug(before.channel)
-        logger.debug(after.channel)
-        if after.channel:
-            logger.debug(after.channel.members)
-
-        if (
-            cambai is not None
-            and before.channel is None
-            and after.channel is not None
-            and bot not in after.channel.members
-            and bot.user
-            and member.id != bot.user.id
-            and random.random() < 5 / 100
-        ):
-            logger.info("Generating tts")
-            script = random.choice(
-                [
-                    "Salut la jeunesse !",
-                    f"Salut {member.display_name}, ça va bien ?",
-                    "Allo ? À l'huile !",
-                ]
-            )
-            source = await discord.FFmpegOpusAudio.from_probe(cambai.tts(script))
-            vo: discord.VoiceClient = await after.channel.connect()
-
-            await vo.play(source, wait_finish=True)
-            await vo.disconnect()
-
-        if before.channel is None and random.random() < 5 / 100:
-            logger.info(f"Voice shuffle from {member}")
-            await shf.try_shuffle(member.guild)
-
     @bot.slash_command(
         name="indu", guild_ids=guild_ids, description="Poser une question à MistralAI"
     )
diff --git a/botbotbot/voice.py b/botbotbot/voice.py
index e69de29..83b3317 100644
--- a/botbotbot/voice.py
+++ b/botbotbot/voice.py
@@ -0,0 +1,63 @@
+import logging
+import random
+
+import discord
+
+from botbotbot.shuffle import Shuffler
+from botbotbot.tts import CambAI
+
+logger = logging.getLogger(__name__)
+
+
+class VoiceBot:
+    def __init__(
+        self,
+        bot: discord.Bot,
+        cambai: CambAI | None = None,
+        shuffler: Shuffler | None = None,
+    ) -> None:
+        self.bot = bot
+        self.cambai = cambai
+        self.shf = shuffler
+
+    def init_events(self) -> None:
+        self.bot.add_listener(self.on_voice_state_update, "on_voice_state_update")
+
+    async def on_voice_state_update(
+        self,
+        member: discord.Member,
+        before: discord.VoiceState,
+        after: discord.VoiceState,
+    ) -> None:
+        logger.debug("Voice state update")
+        logger.debug(before.channel)
+        logger.debug(after.channel)
+        if after.channel:
+            logger.debug(after.channel.members)
+
+        if (
+            self.cambai is not None
+            and before.channel is None
+            and after.channel is not None
+            and self.bot not in after.channel.members
+            and self.bot.user
+            and member.id != self.bot.user.id
+            and random.random() < 5 / 100
+        ):
+            logger.info("Generating tts")
+            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()
+
+        if self.shf and before.channel is None and random.random() < 5 / 100:
+            logger.info(f"Voice shuffle from {member}")
+            await self.shf.try_shuffle(member.guild)
diff --git a/botbotbot/wordlist.py b/botbotbot/wordlist.py
index e142408..cffc3e8 100644
--- a/botbotbot/wordlist.py
+++ b/botbotbot/wordlist.py
@@ -10,28 +10,41 @@ logger = logging.getLogger(__name__)
 
 class Wordlist:
     def __init__(
-        self, bot: discord.Bot, path: pathlib.Path = pathlib.Path("wordlist.pickle")
+        self,
+        bot: discord.Bot,
+        guild_ids: list[int] = [],
+        path: pathlib.Path = pathlib.Path("wordlist.pickle"),
     ):
         self.path = path
         if self.path.exists():
             with self.path.open("rb") as w_file:
                 self.word_list: list[str] = pickle.load(w_file)
         self.bot = bot
+        self.guild_ids = guild_ids
 
     def init_events(self) -> None:
         self.bot.add_application_command(
             discord.SlashCommand(
-                self.bibl, name="bibl", description="Ajouter une phrase"
+                self.bibl,
+                name="bibl",
+                description="Ajouter une phrase",
+                guild_ids=self.guild_ids,
             )
         )
         self.bot.add_application_command(
             discord.SlashCommand(
-                self.tabl, name="tabl", description="Lister les phrases"
+                self.tabl,
+                name="tabl",
+                description="Lister les phrases",
+                guild_ids=self.guild_ids,
             )
         )
         self.bot.add_application_command(
             discord.SlashCommand(
-                self.enle, name="enle", description="Enlever une phrase"
+                self.enle,
+                name="enle",
+                description="Enlever une phrase",
+                guild_ids=self.guild_ids,
             )
         )