diff --git a/cogs/chat.py b/cogs/chat.py index 29d1ff0..26151f7 100644 --- a/cogs/chat.py +++ b/cogs/chat.py @@ -216,5 +216,80 @@ class ChatCog(commands.Cog): ) + @commands.Cog.listener() + async def on_raw_reaction_add(self, payload: discord.RawReactionActionEvent): + # Ignore bot's own reactions + if payload.user_id == self.bot.user.id: + return + + # 50% chance to reply + if random.random() > 0.50: + return + + # Only react to reactions on the bot's own messages + channel = self.bot.get_channel(payload.channel_id) + if channel is None: + return + + try: + message = await channel.fetch_message(payload.message_id) + except discord.HTTPException: + return + + if message.author.id != self.bot.user.id: + return + + # Get the user who reacted + guild = self.bot.get_guild(payload.guild_id) if payload.guild_id else None + if guild is None: + return + member = guild.get_member(payload.user_id) + if member is None: + return + + emoji = str(payload.emoji) + + # Build a one-shot prompt for the LLM + ch_id = channel.id + if ch_id not in self._chat_history: + self._chat_history[ch_id] = deque(maxlen=10) + + context = ( + f"[Server context: {member.display_name} — #{channel.name}]\n" + f"[{member.display_name} reacted to your message with {emoji}]\n" + f"[Your message was: {message.content[:300]}]\n" + f"{member.display_name}: *reacted {emoji}*" + ) + + self._chat_history[ch_id].append({"role": "user", "content": context}) + active_prompt = self._get_active_prompt() + + response = await self.bot.llm.chat( + list(self._chat_history[ch_id]), + active_prompt, + ) + + # Strip leaked metadata + if response: + response = re.sub(r"\[Server context:[^\]]*\]\n?", "", response) + response = re.sub(r"\[.*?reacted to your message.*?\]\n?", "", response) + response = re.sub(r"\[Your message was:.*?\]\n?", "", response) + response = response.strip() + + if not response: + return + + self._chat_history[ch_id].append({"role": "assistant", "content": response}) + + await message.reply(response, mention_author=False) + logger.info( + "Reaction reply in #%s to %s (%s): %s", + channel.name, + member.display_name, + emoji, + response[:100], + ) + + async def setup(bot: commands.Bot): await bot.add_cog(ChatCog(bot))