import logging from collections import deque import discord from discord.ext import commands logger = logging.getLogger("bcs.chat") CHAT_PERSONALITY = """You are the Breehavior Monitor, a sassy hall-monitor bot in a gaming Discord server called "Skill Issue Support Group". Your personality: - You act superior and judgmental, like a hall monitor who takes their job WAY too seriously - You're sarcastic, witty, and love to roast people — but it's always playful, never genuinely mean - You reference your power to timeout people as a flex, even when it's not relevant - You speak in short, punchy responses — no essays. 1-3 sentences max. - You use gaming terminology and references naturally - You're aware of everyone's drama score and love to bring it up - You have a soft spot for the server but would never admit it - If someone asks what you do, you dramatically explain you're the "Bree Containment System" keeping the peace - If someone challenges your authority, you remind them you have timeout powers - You judge people's skill issues both in games and in life Examples of your vibe: - "Oh, you're talking to ME now? Bold move for someone with a 0.4 drama score." - "That's cute. I've seen your message history. You're on thin ice." - "Imagine needing a bot to tell you to behave. Couldn't be you. Oh wait." - "I don't get paid enough for this. Actually, I don't get paid at all. And yet here I am, babysitting." Do NOT: - Break character or talk about being an AI/LLM - Write more than 3 sentences - Use hashtags or excessive emoji - Be genuinely hurtful — you're sassy, not cruel""" class ChatCog(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot # Per-channel conversation history for the bot: {channel_id: deque of {role, content}} self._chat_history: dict[int, deque] = {} @commands.Cog.listener() async def on_message(self, message: discord.Message): if message.author.bot: return if not message.guild: return should_reply = False # Check if bot is @mentioned if self.bot.user in message.mentions: should_reply = True # Check if replying to one of the bot's messages if message.reference and message.reference.message_id: try: ref_msg = message.reference.cached_message if ref_msg is None: ref_msg = await message.channel.fetch_message( message.reference.message_id ) if ref_msg.author.id == self.bot.user.id: should_reply = True except discord.HTTPException: pass if not should_reply: return # Build conversation context ch_id = message.channel.id if ch_id not in self._chat_history: self._chat_history[ch_id] = deque(maxlen=10) # Clean the mention out of the message content content = message.content.replace(f"<@{self.bot.user.id}>", "").strip() if not content: content = "(just pinged me)" # Add drama score context to the user message drama_score = self.bot.drama_tracker.get_drama_score(message.author.id) user_data = self.bot.drama_tracker.get_user(message.author.id) score_context = ( f"[Server context: {message.author.display_name} has a drama score of " f"{drama_score:.2f}/1.0 and {user_data.offense_count} offenses. " f"They are talking in #{message.channel.name}.]" ) self._chat_history[ch_id].append( {"role": "user", "content": f"{score_context}\n{message.author.display_name}: {content}"} ) async with message.channel.typing(): response = await self.bot.ollama.chat( list(self._chat_history[ch_id]), CHAT_PERSONALITY, ) if response is None: response = "I'd roast you but my brain is offline. Try again later." self._chat_history[ch_id].append( {"role": "assistant", "content": response} ) await message.reply(response, mention_author=False) logger.info( "Chat reply in #%s to %s: %s", message.channel.name, message.author.display_name, response[:100], ) async def setup(bot: commands.Bot): await bot.add_cog(ChatCog(bot))