diff --git a/botbotbot/__init__.py b/botbotbot/__init__.py
index aca06b4..24265fc 100644
--- a/botbotbot/__init__.py
+++ b/botbotbot/__init__.py
@@ -1,13 +1,14 @@
 import logging
-import pickle
 import random
 import tomllib
 
 import discord
 
 from botbotbot.ai import AIBot
+from botbotbot.shuffle import Shuffler
 from botbotbot.text import TextBot
 from botbotbot.tts import CambAI
+from botbotbot.wordlist import Wordlist
 
 
 def main() -> None:
@@ -19,10 +20,7 @@ def main() -> None:
     with open("config.toml", "rb") as config_file:
         config = tomllib.load(config_file)
 
-    with open("wordlist.pickle", "rb") as word_file:
-        word_list = pickle.load(word_file)
     guild_ids = config.get("guild_ids")
-    delay = config.get("delay", 60)
 
     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.
@@ -50,123 +48,25 @@ def main() -> None:
     intents.voice_states = True
 
     bot = discord.Bot(description=description, intents=intents)
+    shf = Shuffler()
+    wl = Wordlist(bot)
 
-    text_bot = TextBot(bot, aibot, word_list)
+    text_bot = TextBot(bot, wl, aibot=aibot, shuffler=shf)
     text_bot.init_events()
 
-    shuffle_tasks = set()
-
     @bot.listen("on_ready")
     async def on_ready() -> None:
         logger.info(f"We have logged in as {bot.user}")
 
-    @bot.listen("on_reaction_add")
-    async def add_more_reaction(
-        reaction: discord.Reaction, user: discord.Member | discord.User
-    ) -> None:
-        if random.random() < 50 / 100:
-            logger.info(f"Copy reaction from {user}")
-            await reaction.message.add_reaction(reaction.emoji)
-
-    @bot.listen("on_message_edit")
-    async def react_message_edit(
-        before: discord.Message, after: discord.Message
-    ) -> None:
-        if (
-            before.content != after.content
-            and after.author != bot.user
-            and random.random() < 50 / 100
-        ):
-            logger.info(f"React to edit from {after.author}")
-            await after.add_reaction("👀")
-
-    @bot.listen("on_message")
-    async def rando_shuffle(message: discord.Message) -> None:
-        if not message.flags.ephemeral and random.random() < 5 / 100 and message.guild:
-            logger.info(f"Message shuffle after message from {message.author}")
-            await try_shuffle(message.guild)
-
-    def save_wordlist() -> None:
-        logger.info("Saving updated wordlist")
-        with open("wordlist.pickle", "wb") as word_file:
-            pickle.dump(word_list, word_file)
-
-    @bot.slash_command(
-        name="bibl", guild_ids=guild_ids, description="Ajouter une phrase"
-    )
-    async def bibl(ctx: discord.ApplicationContext, phrase: str) -> None:
-        logger.info(f"BIBL {ctx.author} {phrase}")
-        word_list.append(phrase)
-        embed = discord.Embed(
-            title="BIBL", description=phrase, color=discord.Colour.green()
-        )
-        await ctx.respond(embed=embed)
-        save_wordlist()
-        logger.info("FIN BIBL")
-
-    @bot.slash_command(
-        name="tabl", guild_ids=guild_ids, description="Lister les phrases"
-    )
-    async def tabl(ctx: discord.ApplicationContext) -> None:
-        logger.info(f"TABL {ctx.author}")
-        embed = discord.Embed(
-            title="TABL", description="\n".join(word_list), color=discord.Colour.green()
-        )
-        await ctx.respond(embed=embed, ephemeral=True, delete_after=delay)
-
-    @bot.slash_command(
-        name="enle", guild_ids=guild_ids, description="Enlever une phrase"
-    )
-    async def enle(ctx: discord.ApplicationContext, phrase: str) -> None:
-        logger.info(f"ENLE {ctx.author} {phrase}")
-        try:
-            word_list.remove(phrase)
-        except ValueError:
-            embed = discord.Embed(
-                title="ERRE ENLE", description=phrase, color=discord.Colour.red()
-            )
-            await ctx.respond(embed=embed)
-            logger.info("ERRE ENLE")
-        else:
-            embed = discord.Embed(
-                title="ENLE", description=f"~~{phrase}~~", color=discord.Colour.green()
-            )
-            await ctx.respond(embed=embed, ephemeral=True, delete_after=delay)
-            save_wordlist()
-            logger.info("FIN ENLE")
-
-    async def try_shuffle(guild: discord.Guild) -> bool:
-        if guild.id in shuffle_tasks:
-            return False
-
-        shuffle_tasks.add(guild.id)
-        await shuffle_nicks(guild)
-        shuffle_tasks.discard(guild.id)
-        return True
-
-    async def shuffle_nicks(guild: discord.Guild) -> None:
-        logger.info("Shuffle")
-        members = guild.members
-        if guild.owner:
-            members.remove(guild.owner)
-
-        nicks = [member.nick for member in members]
-
-        random.shuffle(nicks)
-        for member, nick in zip(members, nicks):
-            logger.info(f"{member} {nick}")
-            await member.edit(nick=nick)
-        logger.info("Shuffle done")
-
     @bot.slash_command(
         name="alea", guild_ids=guild_ids, description="Modifier les pseudos"
     )
     async def alea(ctx: discord.ApplicationContext) -> None:
         logger.info(f"ALEA {ctx.author}")
         await ctx.defer()
-        if await try_shuffle(ctx.guild):
+        if await shf.try_shuffle(ctx.guild):
             embed = discord.Embed(title="ALEA", color=discord.Colour.green())
-            await ctx.respond(embed=embed, ephemeral=True, delete_after=delay)
+            await ctx.respond(embed=embed, ephemeral=True, delete_after=30)
             logger.info("FIN ALEA")
         else:
             embed = discord.Embed(title="ERRE ALEA", color=discord.Colour.red())
@@ -177,10 +77,6 @@ def main() -> None:
     async def on_voice_state_update(
         member: discord.Member, before: discord.VoiceState, after: discord.VoiceState
     ) -> None:
-        if before.channel is None and random.random() < 5 / 100:
-            logger.info(f"Voice shuffle from {member}")
-            await try_shuffle(member.guild)
-
         logger.debug("Voice state update")
         logger.debug(before.channel)
         logger.debug(after.channel)
@@ -210,6 +106,10 @@ def main() -> None:
             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/shuffle.py b/botbotbot/shuffle.py
new file mode 100644
index 0000000..cd8786c
--- /dev/null
+++ b/botbotbot/shuffle.py
@@ -0,0 +1,34 @@
+import logging
+import random
+
+import discord
+
+logger = logging.getLogger(__name__)
+
+
+class Shuffler:
+    def __init__(self) -> None:
+        self.shuffle_tasks: set[int] = set()
+
+    async def try_shuffle(self, guild: discord.Guild) -> bool:
+        if guild.id in self.shuffle_tasks:
+            return False
+
+        self.shuffle_tasks.add(guild.id)
+        await self.shuffle_nicks(guild)
+        self.shuffle_tasks.discard(guild.id)
+        return True
+
+    async def shuffle_nicks(self, guild: discord.Guild) -> None:
+        logger.info("Shuffle")
+        members = guild.members
+        if guild.owner:
+            members.remove(guild.owner)
+
+        nicks = [member.nick for member in members]
+
+        random.shuffle(nicks)
+        for member, nick in zip(members, nicks):
+            logger.info(f"{member} {nick}")
+            await member.edit(nick=nick)
+        logger.info("Shuffle done")
diff --git a/botbotbot/text.py b/botbotbot/text.py
index a03161f..50a3cd6 100644
--- a/botbotbot/text.py
+++ b/botbotbot/text.py
@@ -6,6 +6,8 @@ import discord
 import emoji
 
 from botbotbot.ai import AIBot
+from botbotbot.shuffle import Shuffler
+from botbotbot.wordlist import Wordlist
 
 logger = logging.getLogger(__name__)
 
@@ -16,17 +18,22 @@ class TextBot:
     def __init__(
         self,
         bot: discord.Bot,
+        wordlist: Wordlist,
         aibot: AIBot | None = None,
-        wordlist: list[str] = [],
+        shuffler: Shuffler | None = None,
         rnd_weights: list[float] = [10, 5, 10],
     ) -> None:
         self.bot = bot
         self.aibot = aibot
-        self.word_list = wordlist
+        self.wl = wordlist
         self._rnd_weights = rnd_weights
+        self.shf = shuffler
 
     def init_events(self) -> None:
         self.bot.add_listener(self.on_message, "on_message")
+        self.bot.add_listener(self.add_more_reaction, "on_reaction_add")
+        self.bot.add_listener(self.react_message_edit, "on_message_edit")
+        self.bot.add_listener(self.rando_shuffle, "on_message")
 
     @property
     def rnd_weights(self) -> list[float]:
@@ -77,8 +84,8 @@ class TextBot:
         )[0]
         content = random.choice(
             (
-                f"{mention}, {random.choice(self.word_list)}",
-                f"{random.choice(self.word_list)}",
+                f"{mention}, {self.wl.random()}",
+                f"{self.wl.random()}",
             )
         )
 
@@ -144,3 +151,31 @@ class TextBot:
             webhook = await channel.create_webhook(name="BotbotbotHook")
 
         await webhook.send(content=content, username=name, avatar_url=avatar_url)
+
+    async def add_more_reaction(
+        self, reaction: discord.Reaction, user: discord.Member | discord.User
+    ) -> None:
+        if random.random() < 20 / 100:
+            logger.info(f"Copy reaction from {user}")
+            await reaction.message.add_reaction(reaction.emoji)
+
+    async def react_message_edit(
+        self, before: discord.Message, after: discord.Message
+    ) -> None:
+        if (
+            before.content != after.content
+            and after.author != self.bot.user
+            and random.random() < 20 / 100
+        ):
+            logger.info(f"React to edit from {after.author}")
+            await after.add_reaction("👀")
+
+    async def rando_shuffle(self, message: discord.Message) -> None:
+        if (
+            self.shf
+            and not message.flags.ephemeral
+            and random.random() < 5 / 100
+            and message.guild
+        ):
+            logger.info(f"Message shuffle after message from {message.author}")
+            await self.shf.try_shuffle(message.guild)
diff --git a/botbotbot/voice.py b/botbotbot/voice.py
new file mode 100644
index 0000000..e69de29
diff --git a/botbotbot/wordlist.py b/botbotbot/wordlist.py
new file mode 100644
index 0000000..e142408
--- /dev/null
+++ b/botbotbot/wordlist.py
@@ -0,0 +1,81 @@
+import logging
+import pathlib
+import pickle
+import random
+
+import discord
+
+logger = logging.getLogger(__name__)
+
+
+class Wordlist:
+    def __init__(
+        self, bot: discord.Bot, 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
+
+    def init_events(self) -> None:
+        self.bot.add_application_command(
+            discord.SlashCommand(
+                self.bibl, name="bibl", description="Ajouter une phrase"
+            )
+        )
+        self.bot.add_application_command(
+            discord.SlashCommand(
+                self.tabl, name="tabl", description="Lister les phrases"
+            )
+        )
+        self.bot.add_application_command(
+            discord.SlashCommand(
+                self.enle, name="enle", description="Enlever une phrase"
+            )
+        )
+
+    def random(self) -> str:
+        return random.choice(self.word_list)
+
+    def save(self) -> None:
+        logger.info("Saving updated wordlist")
+        with open(self.path, "wb") as w_file:
+            pickle.dump(self.word_list, w_file)
+
+    async def bibl(self, ctx: discord.ApplicationContext, phrase: str) -> None:
+        logger.info(f"BIBL {ctx.author} {phrase}")
+        self.word_list.append(phrase)
+        embed = discord.Embed(
+            title="BIBL", description=phrase, color=discord.Colour.green()
+        )
+        await ctx.respond(embed=embed)
+        self.save()
+        logger.info("FIN BIBL")
+
+    async def tabl(self, ctx: discord.ApplicationContext) -> None:
+        logger.info(f"TABL {ctx.author}")
+        embed = discord.Embed(
+            title="TABL",
+            description="\n".join(self.word_list),
+            color=discord.Colour.green(),
+        )
+        await ctx.respond(embed=embed, ephemeral=True, delete_after=30)
+
+    async def enle(self, ctx: discord.ApplicationContext, phrase: str) -> None:
+        logger.info(f"ENLE {ctx.author} {phrase}")
+        try:
+            self.word_list.remove(phrase)
+        except ValueError:
+            embed = discord.Embed(
+                title="ERRE ENLE", description=phrase, color=discord.Colour.red()
+            )
+            await ctx.respond(embed=embed)
+            logger.info("ERRE ENLE")
+        else:
+            embed = discord.Embed(
+                title="ENLE", description=f"~~{phrase}~~", color=discord.Colour.green()
+            )
+            await ctx.respond(embed=embed, ephemeral=True, delete_after=30)
+            self.save()
+            logger.info("FIN ENLE")